summaryrefslogtreecommitdiffstats
path: root/lib/class
diff options
context:
space:
mode:
authorPaul Arthur <paul.arthur@flowerysong.com>2013-01-26 03:00:32 -0500
committerPaul Arthur <paul.arthur@flowerysong.com>2013-01-26 03:38:46 -0500
commitef4d3660605efc7f1328d4533b0f4bfb6c1107e2 (patch)
treee4377fb129a899e65aaaf421f8c97098aecaedd5 /lib/class
parent8a750c3e875d590d351c3042570a134fcdf03e5d (diff)
downloadampache-ef4d3660605efc7f1328d4533b0f4bfb6c1107e2.tar.gz
ampache-ef4d3660605efc7f1328d4533b0f4bfb6c1107e2.tar.bz2
ampache-ef4d3660605efc7f1328d4533b0f4bfb6c1107e2.zip
Cosmetics: death to tabs
The refactoring I've been doing has reminded me of my strong preference for spaces, and I feel inclined to impose my will on the tree.
Diffstat (limited to 'lib/class')
-rw-r--r--lib/class/access.class.php1070
-rw-r--r--lib/class/ajax.class.php270
-rw-r--r--lib/class/album.class.php680
-rw-r--r--lib/class/ampache_mail.class.php364
-rw-r--r--lib/class/ampache_rss.class.php414
-rw-r--r--lib/class/api.class.php1214
-rw-r--r--lib/class/art.class.php2360
-rw-r--r--lib/class/artist.class.php462
-rw-r--r--lib/class/browse.class.php428
-rw-r--r--lib/class/catalog.class.php3968
-rw-r--r--lib/class/config.class.php180
-rw-r--r--lib/class/core.class.php270
-rw-r--r--lib/class/database_object.abstract.php156
-rw-r--r--lib/class/dba.class.php982
-rw-r--r--lib/class/democratic.class.php1040
-rw-r--r--lib/class/error.class.php162
-rw-r--r--lib/class/flag.class.php656
-rw-r--r--lib/class/localplay.class.php1016
-rw-r--r--lib/class/localplay_controller.abstract.php158
-rw-r--r--lib/class/media.interface.php70
-rw-r--r--lib/class/memory_object.class.php44
-rw-r--r--lib/class/playlist.class.php682
-rw-r--r--lib/class/playlist_object.abstract.php68
-rw-r--r--lib/class/plugin.class.php496
-rw-r--r--lib/class/preference.class.php718
-rw-r--r--lib/class/query.class.php2762
-rw-r--r--lib/class/radio.class.php288
-rw-r--r--lib/class/random.class.php754
-rw-r--r--lib/class/rating.class.php420
-rw-r--r--lib/class/recommendation.class.php344
-rw-r--r--lib/class/registration.class.php86
-rw-r--r--lib/class/scrobbler.class.php488
-rw-r--r--lib/class/search.class.php2108
-rw-r--r--lib/class/shoutbox.class.php304
-rw-r--r--lib/class/song.class.php1814
-rw-r--r--lib/class/stats.class.php396
-rw-r--r--lib/class/stream.class.php742
-rw-r--r--lib/class/stream_playlist.class.php842
-rw-r--r--lib/class/stream_url.class.php4
-rw-r--r--lib/class/tag.class.php852
-rw-r--r--lib/class/tmp_playlist.class.php506
-rw-r--r--lib/class/ui.class.php556
-rw-r--r--lib/class/update.class.php3298
-rw-r--r--lib/class/user.class.php1902
-rw-r--r--lib/class/vainfo.class.php2112
-rw-r--r--lib/class/vauth.class.php1302
-rw-r--r--lib/class/video.class.php150
-rw-r--r--lib/class/xml_data.class.php1248
48 files changed, 20603 insertions, 20603 deletions
diff --git a/lib/class/access.class.php b/lib/class/access.class.php
index ad4f4162..b72b7f3a 100644
--- a/lib/class/access.class.php
+++ b/lib/class/access.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,540 +29,540 @@
*/
class Access {
- // Variables from DB
-
- /**
- * User ID
- *
- * @var integer
- */
- public $id;
-
- /**
- *
- */
- public $name;
-
- /**
- *
- */
- public $start;
-
- /**
- *
- */
- public $end;
-
- /**
- *
- */
- public $level;
-
- /**
- *
- */
- public $user;
-
- /**
- *
- */
- public $type;
-
- /**
- *
- */
- public $enabled;
-
- /**
- * constructor
- *
- * Takes an ID of the access_id dealie :)
- *
- * @param integer $access_id ID of the access_id
- * @return boolean
- */
- public function __construct($access_id='') {
-
- if (!$access_id) { return false; }
-
- /* Assign id for use in get_info() */
- $this->id = intval($access_id);
-
- $info = $this->_get_info();
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
-
- return true;
-
- } // Constructor
-
- /**
- * _get_info
- *
- * get's the vars for $this out of the database
- * Taken from the object
- *
- * @return resource
- */
- private function _get_info() {
-
- /* Grab the basic information from the catalog and return it */
- $sql = "SELECT * FROM `access_list` WHERE `id`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
-
- return $results;
-
- } // _get_info
-
- /**
- * format
- *
- * This makes the Access object a nice fuzzy human readable object, spiffy ain't it.
- *
- * @return void
- */
- public function format() {
-
- $this->f_start = inet_ntop($this->start);
- $this->f_end = inet_ntop($this->end);
-
- $this->f_user = $this->get_user_name();
- $this->f_level = $this->get_level_name();
- $this->f_type = $this->get_type_name();
-
- } // format
-
- /**
- * update
- *
- * This function takes a named array as a datasource and updates the current access list entry
- *
- * @param array $data xxx
- * @return boolean
- */
- public function update($data) {
-
- /* We need to verify the incomming data a littlebit */
- $start = @inet_pton($data['start']);
- $end = @inet_pton($data['end']);
-
- if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') {
- Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered'));
- return false;
- }
- if (!$end) {
- Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered'));
- return false;
- }
-
- if (strlen(bin2hex($start)) != strlen(bin2hex($end))) {
- Error::add('start', T_('IP Address Version Mismatch'));
- Error::add('end', T_('IP Address Version Mismatch'));
- return false;
- }
-
- $name = Dba::escape($data['name']);
- $type = self::validate_type($data['type']);
- $start = Dba::escape(inet_pton($data['start']));
- $end = Dba::escape(inet_pton($data['end']));
- $level = Dba::escape($data['level']);
- $user = $data['user'] ? Dba::escape($data['user']) : '-1';
- $enabled = make_bool($data['enabled']) ? 1 : 0;
-
- $sql = "UPDATE `access_list` " .
- "SET `start`='$start', `end`='$end', `level`='$level', `user`='$user', " .
- "`name`='$name', `type`='$type',`enabled`='$enabled' WHERE `id`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // update
-
- /**
- * create
- *
- * This takes a key'd array of data and trys to insert it as a
- * new ACL entry
- *
- * @param array $data xxx
- * @return boolean
- */
- public static function create($data) {
-
- /* We need to verify the incomming data a littlebit */
- $start = @inet_pton($data['start']);
- $end = @inet_pton($data['end']);
-
- if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') {
- Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered'));
- return false;
- }
- if (!$end) {
- Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered'));
- return false;
- }
-
- if (strlen(bin2hex($start)) != strlen(bin2hex($end))) {
- Error::add('start', T_('IP Address Version Mismatch'));
- Error::add('end', T_('IP Address Version Mismatch'));
- return false;
- }
-
- // Check existing ACL's to make sure we're not duplicating values here
- if (self::exists($data)) {
- debug_event('ACL Create','Error: An ACL equal to the created one does already exist. Not adding another one: ' . $data['start'] . ' - ' . $data['end'],'1');
- Error::add('general', T_('Duplicate ACL defined'));
- return false;
- }
-
- $start = Dba::escape($start);
- $end = Dba::escape($end);
- $name = Dba::escape($data['name']);
- $user = $data['user'] ? Dba::escape($data['user']) : '-1';
- $level = intval($data['level']);
- $type = self::validate_type($data['type']);
- $enabled = make_bool($data['enabled']) ? 1 : 0;
-
- $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`user`,`type`,`enabled`) " .
- "VALUES ('$name','$level','$start','$end','$user','$type','$enabled')";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // create
-
- /**
- * exists
- *
- * this sees if the ACL that we've specified already exists, prevent duplicates. This ignores the name
- *
- * @param array $data xxx
- * @return boolean
- */
- public static function exists($data) {
-
- $start = Dba::escape(inet_pton($data['start']));
- $end = Dba::escape(inet_pton($data['end']));
- $type = self::validate_type($data['type']);
- $user = $data['user'] ? Dba::escape($data['user']) : '-1';
-
- $sql = "SELECT * FROM `access_list` WHERE `start`='$start' AND `end` = '$end' " .
- "AND `type`='$type' AND `user`='$user'";
- $db_results = Dba::read($sql);
-
- if (Dba::fetch_assoc($db_results)) {
- return true;
- }
-
- return false;
-
- } // exists
-
- /**
- * delete
- *
- * deletes the specified access_list entry
- *
- * @param integer $access_id xxx
- * @return void
- */
- public static function delete($access_id) {
-
- $sql = "DELETE FROM `access_list` WHERE `id`='" . Dba::escape($access_id) . "'";
- $db_results = Dba::write($sql);
-
- } // delete
-
- /**
- * check_function
- *
- * This checks if a specific functionality is enabled
- * it takes a type only
- *
- * @param string $type check type xxx
- * @return mixed boolean or config
- */
- public static function check_function($type) {
-
- switch ($type) {
- case 'download':
- return Config::get('download');
- break ;
- case 'batch_download':
- if (!function_exists('gzcompress')) {
- debug_event('gzcompress','ZLIB Extensions not loaded, batch download disabled','3');
- return false;
- }
- if (Config::get('allow_zip_download') AND $GLOBALS['user']->has_access('25')) {
- return Config::get('download');
- }
- break;
- default:
- return false;
- break;
- } // end switch
-
- } // check_function
-
- /**
- * check_network
- *
- * This takes a type, ip, user, level and key
- * and then returns true or false if they have access to this
- * the IP is passed as a dotted quad
- *
- * @param string $type Check type.
- * @param string $user User name.
- * @param integer $level Access level.
- * @param string $ip IP Address.
- * @return boolean
- */
- public static function check_network($type, $user, $level, $ip=null) {
-
- if (!Config::get('access_control')) {
- switch ($type) {
- case 'interface':
- case 'stream':
- return true;
- break;
- default:
- return false;
- } // end switch
- } // end if access control is turned off
-
- // Clean incoming variables
- $ip = $ip
- ? Dba::escape(inet_pton($ip))
- : Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']));
- $user = Dba::escape($user);
- $level = Dba::escape($level);
-
- switch ($type) {
- case 'init-api':
- if ($user) {
- $user = User::get_from_username($user);
- $user = $user->id;
- }
- case 'api':
- $type = 'rpc';
- case 'network':
- case 'interface':
- case 'stream':
- break;
- default:
- return false;
- break;
- } // end switch on type
-
- $sql = 'SELECT `id` FROM `access_list` ' .
- "WHERE `start` <= '$ip' AND `end` >= '$ip' " .
- "AND `level` >= '$level' AND `type` = '$type'";
-
- if (strlen($user) && $user != '-1') {
- $sql .= " AND `user` IN('$user', '-1')";
- }
- else {
- $sql .= " AND `user` = '-1'";
- }
-
- $db_results = Dba::read($sql);
-
- if (Dba::fetch_row($db_results)) {
- // Yah they have access they can use the mojo
- return true;
- }
-
- return false;
- } // check_network
-
- /**
- * check_access
- * This is the global 'has_access' function it can check for any 'type'
- * of object.
- * Everything uses the global 0,5,25,50,75,100 stuff. GLOBALS['user'] is
- * always used.
- */
- public static function check($type,$level) {
-
- if (Config::get('demo_mode')) { return true; }
- if (defined('INSTALL')) { return true; }
-
- $level = intval($level);
-
- // Switch on the type
- switch ($type) {
- case 'localplay':
- // Check their localplay_level
- if (Config::get('localplay_level') >= $level OR $GLOBALS['user']->access >= '100') {
- return true;
- }
- else {
- return false;
- }
- break;
- case 'interface':
- // Check their standard user level
- if ($GLOBALS['user']->access >= $level) {
- return true;
- }
- else {
- return false;
- }
- break;
- default:
- return false;
- break;
- } // end switch on type
-
- // Default false
- return false;
-
- } // check
-
- /**
- * validate_type
- * This cleans up and validates the specified type
- */
- public static function validate_type($type) {
-
- switch($type) {
- case 'rpc':
- case 'interface':
- case 'network':
- return $type;
- break;
- case 'xml-rpc':
- return 'rpc';
- break;
- default:
- return 'stream';
- break;
- } // end switch
-
- } // validate_type
-
- /**
- * get_access_lists
- * returns a full listing of all access rules on this server
- */
- public static function get_access_lists() {
-
- $sql = "SELECT `id` FROM `access_list`";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- // Man this is the wrong way to do it...
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- } // end while access list mojo
-
- return $results;
-
- } // get_access_lists
-
-
- /**
- * get_level_name
- * take the int level and return a named level
- */
- public function get_level_name() {
-
- if ($this->level >= '75') {
- return T_('All');
- }
- if ($this->level == '5') {
- return T_('View');
- }
- if ($this->level == '25') {
- return T_('Read');
- }
- if ($this->level == '50') {
- return T_('Read/Write');
- }
-
- } // get_level_name
-
- /**
- * get_user_name
- * Take a user and return their full name
- */
- public function get_user_name() {
-
- if ($this->user == '-1') { return T_('All'); }
-
- $user = new User($this->user);
- return $user->fullname . " (" . $user->username . ")";
-
- } // get_user_name
-
- /**
- * get_type_name
- * This function returns the pretty name for our current type
- */
- public function get_type_name() {
-
- switch ($this->type) {
- case 'xml-rpc':
- case 'rpc':
- return T_('API/RPC');
- break;
- case 'network':
- return T_('Local Network Definition');
- break;
- case 'interface':
- return T_('Web Interface');
- break;
- case 'stream':
- default:
- return T_('Stream Access');
- break;
- } // end switch
-
- } // get_type_name
-
- /**
- * session_exists
- * This checks to see if the specified session of the specified type
- * exists, it also provides an array of key'd data that may be required
- * based on the type
- */
- public static function session_exists($data,$key,$type) {
-
- // Switch on the type they pass
- switch ($type) {
- case 'api':
- $key = Dba::escape($key);
- $time = time();
- $sql = "SELECT * FROM `session_api` WHERE `id`='$key' AND `expire` > '$time'";
- $db_results = Dba::read($sql);
-
- if (Dba::num_rows($db_results)) {
- $time = $time + 3600;
- $sql = "UPDATE `session_api` WHERE `id`='$key' SET `expire`='$time'";
- $db_results = Dba::write($sql);
- return true;
- }
-
- return false;
-
- break;
- case 'stream':
-
- break;
- case 'interface':
-
- break;
- default:
- return false;
- break;
- } // type
-
-
- } // session_exists
+ // Variables from DB
+
+ /**
+ * User ID
+ *
+ * @var integer
+ */
+ public $id;
+
+ /**
+ *
+ */
+ public $name;
+
+ /**
+ *
+ */
+ public $start;
+
+ /**
+ *
+ */
+ public $end;
+
+ /**
+ *
+ */
+ public $level;
+
+ /**
+ *
+ */
+ public $user;
+
+ /**
+ *
+ */
+ public $type;
+
+ /**
+ *
+ */
+ public $enabled;
+
+ /**
+ * constructor
+ *
+ * Takes an ID of the access_id dealie :)
+ *
+ * @param integer $access_id ID of the access_id
+ * @return boolean
+ */
+ public function __construct($access_id='') {
+
+ if (!$access_id) { return false; }
+
+ /* Assign id for use in get_info() */
+ $this->id = intval($access_id);
+
+ $info = $this->_get_info();
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
+
+ return true;
+
+ } // Constructor
+
+ /**
+ * _get_info
+ *
+ * get's the vars for $this out of the database
+ * Taken from the object
+ *
+ * @return resource
+ */
+ private function _get_info() {
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT * FROM `access_list` WHERE `id`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+
+ return $results;
+
+ } // _get_info
+
+ /**
+ * format
+ *
+ * This makes the Access object a nice fuzzy human readable object, spiffy ain't it.
+ *
+ * @return void
+ */
+ public function format() {
+
+ $this->f_start = inet_ntop($this->start);
+ $this->f_end = inet_ntop($this->end);
+
+ $this->f_user = $this->get_user_name();
+ $this->f_level = $this->get_level_name();
+ $this->f_type = $this->get_type_name();
+
+ } // format
+
+ /**
+ * update
+ *
+ * This function takes a named array as a datasource and updates the current access list entry
+ *
+ * @param array $data xxx
+ * @return boolean
+ */
+ public function update($data) {
+
+ /* We need to verify the incomming data a littlebit */
+ $start = @inet_pton($data['start']);
+ $end = @inet_pton($data['end']);
+
+ if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') {
+ Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered'));
+ return false;
+ }
+ if (!$end) {
+ Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered'));
+ return false;
+ }
+
+ if (strlen(bin2hex($start)) != strlen(bin2hex($end))) {
+ Error::add('start', T_('IP Address Version Mismatch'));
+ Error::add('end', T_('IP Address Version Mismatch'));
+ return false;
+ }
+
+ $name = Dba::escape($data['name']);
+ $type = self::validate_type($data['type']);
+ $start = Dba::escape(inet_pton($data['start']));
+ $end = Dba::escape(inet_pton($data['end']));
+ $level = Dba::escape($data['level']);
+ $user = $data['user'] ? Dba::escape($data['user']) : '-1';
+ $enabled = make_bool($data['enabled']) ? 1 : 0;
+
+ $sql = "UPDATE `access_list` " .
+ "SET `start`='$start', `end`='$end', `level`='$level', `user`='$user', " .
+ "`name`='$name', `type`='$type',`enabled`='$enabled' WHERE `id`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // update
+
+ /**
+ * create
+ *
+ * This takes a key'd array of data and trys to insert it as a
+ * new ACL entry
+ *
+ * @param array $data xxx
+ * @return boolean
+ */
+ public static function create($data) {
+
+ /* We need to verify the incomming data a littlebit */
+ $start = @inet_pton($data['start']);
+ $end = @inet_pton($data['end']);
+
+ if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') {
+ Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered'));
+ return false;
+ }
+ if (!$end) {
+ Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered'));
+ return false;
+ }
+
+ if (strlen(bin2hex($start)) != strlen(bin2hex($end))) {
+ Error::add('start', T_('IP Address Version Mismatch'));
+ Error::add('end', T_('IP Address Version Mismatch'));
+ return false;
+ }
+
+ // Check existing ACL's to make sure we're not duplicating values here
+ if (self::exists($data)) {
+ debug_event('ACL Create','Error: An ACL equal to the created one does already exist. Not adding another one: ' . $data['start'] . ' - ' . $data['end'],'1');
+ Error::add('general', T_('Duplicate ACL defined'));
+ return false;
+ }
+
+ $start = Dba::escape($start);
+ $end = Dba::escape($end);
+ $name = Dba::escape($data['name']);
+ $user = $data['user'] ? Dba::escape($data['user']) : '-1';
+ $level = intval($data['level']);
+ $type = self::validate_type($data['type']);
+ $enabled = make_bool($data['enabled']) ? 1 : 0;
+
+ $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`user`,`type`,`enabled`) " .
+ "VALUES ('$name','$level','$start','$end','$user','$type','$enabled')";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // create
+
+ /**
+ * exists
+ *
+ * this sees if the ACL that we've specified already exists, prevent duplicates. This ignores the name
+ *
+ * @param array $data xxx
+ * @return boolean
+ */
+ public static function exists($data) {
+
+ $start = Dba::escape(inet_pton($data['start']));
+ $end = Dba::escape(inet_pton($data['end']));
+ $type = self::validate_type($data['type']);
+ $user = $data['user'] ? Dba::escape($data['user']) : '-1';
+
+ $sql = "SELECT * FROM `access_list` WHERE `start`='$start' AND `end` = '$end' " .
+ "AND `type`='$type' AND `user`='$user'";
+ $db_results = Dba::read($sql);
+
+ if (Dba::fetch_assoc($db_results)) {
+ return true;
+ }
+
+ return false;
+
+ } // exists
+
+ /**
+ * delete
+ *
+ * deletes the specified access_list entry
+ *
+ * @param integer $access_id xxx
+ * @return void
+ */
+ public static function delete($access_id) {
+
+ $sql = "DELETE FROM `access_list` WHERE `id`='" . Dba::escape($access_id) . "'";
+ $db_results = Dba::write($sql);
+
+ } // delete
+
+ /**
+ * check_function
+ *
+ * This checks if a specific functionality is enabled
+ * it takes a type only
+ *
+ * @param string $type check type xxx
+ * @return mixed boolean or config
+ */
+ public static function check_function($type) {
+
+ switch ($type) {
+ case 'download':
+ return Config::get('download');
+ break ;
+ case 'batch_download':
+ if (!function_exists('gzcompress')) {
+ debug_event('gzcompress','ZLIB Extensions not loaded, batch download disabled','3');
+ return false;
+ }
+ if (Config::get('allow_zip_download') AND $GLOBALS['user']->has_access('25')) {
+ return Config::get('download');
+ }
+ break;
+ default:
+ return false;
+ break;
+ } // end switch
+
+ } // check_function
+
+ /**
+ * check_network
+ *
+ * This takes a type, ip, user, level and key
+ * and then returns true or false if they have access to this
+ * the IP is passed as a dotted quad
+ *
+ * @param string $type Check type.
+ * @param string $user User name.
+ * @param integer $level Access level.
+ * @param string $ip IP Address.
+ * @return boolean
+ */
+ public static function check_network($type, $user, $level, $ip=null) {
+
+ if (!Config::get('access_control')) {
+ switch ($type) {
+ case 'interface':
+ case 'stream':
+ return true;
+ break;
+ default:
+ return false;
+ } // end switch
+ } // end if access control is turned off
+
+ // Clean incoming variables
+ $ip = $ip
+ ? Dba::escape(inet_pton($ip))
+ : Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']));
+ $user = Dba::escape($user);
+ $level = Dba::escape($level);
+
+ switch ($type) {
+ case 'init-api':
+ if ($user) {
+ $user = User::get_from_username($user);
+ $user = $user->id;
+ }
+ case 'api':
+ $type = 'rpc';
+ case 'network':
+ case 'interface':
+ case 'stream':
+ break;
+ default:
+ return false;
+ break;
+ } // end switch on type
+
+ $sql = 'SELECT `id` FROM `access_list` ' .
+ "WHERE `start` <= '$ip' AND `end` >= '$ip' " .
+ "AND `level` >= '$level' AND `type` = '$type'";
+
+ if (strlen($user) && $user != '-1') {
+ $sql .= " AND `user` IN('$user', '-1')";
+ }
+ else {
+ $sql .= " AND `user` = '-1'";
+ }
+
+ $db_results = Dba::read($sql);
+
+ if (Dba::fetch_row($db_results)) {
+ // Yah they have access they can use the mojo
+ return true;
+ }
+
+ return false;
+ } // check_network
+
+ /**
+ * check_access
+ * This is the global 'has_access' function it can check for any 'type'
+ * of object.
+ * Everything uses the global 0,5,25,50,75,100 stuff. GLOBALS['user'] is
+ * always used.
+ */
+ public static function check($type,$level) {
+
+ if (Config::get('demo_mode')) { return true; }
+ if (defined('INSTALL')) { return true; }
+
+ $level = intval($level);
+
+ // Switch on the type
+ switch ($type) {
+ case 'localplay':
+ // Check their localplay_level
+ if (Config::get('localplay_level') >= $level OR $GLOBALS['user']->access >= '100') {
+ return true;
+ }
+ else {
+ return false;
+ }
+ break;
+ case 'interface':
+ // Check their standard user level
+ if ($GLOBALS['user']->access >= $level) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ break;
+ } // end switch on type
+
+ // Default false
+ return false;
+
+ } // check
+
+ /**
+ * validate_type
+ * This cleans up and validates the specified type
+ */
+ public static function validate_type($type) {
+
+ switch($type) {
+ case 'rpc':
+ case 'interface':
+ case 'network':
+ return $type;
+ break;
+ case 'xml-rpc':
+ return 'rpc';
+ break;
+ default:
+ return 'stream';
+ break;
+ } // end switch
+
+ } // validate_type
+
+ /**
+ * get_access_lists
+ * returns a full listing of all access rules on this server
+ */
+ public static function get_access_lists() {
+
+ $sql = "SELECT `id` FROM `access_list`";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ // Man this is the wrong way to do it...
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ } // end while access list mojo
+
+ return $results;
+
+ } // get_access_lists
+
+
+ /**
+ * get_level_name
+ * take the int level and return a named level
+ */
+ public function get_level_name() {
+
+ if ($this->level >= '75') {
+ return T_('All');
+ }
+ if ($this->level == '5') {
+ return T_('View');
+ }
+ if ($this->level == '25') {
+ return T_('Read');
+ }
+ if ($this->level == '50') {
+ return T_('Read/Write');
+ }
+
+ } // get_level_name
+
+ /**
+ * get_user_name
+ * Take a user and return their full name
+ */
+ public function get_user_name() {
+
+ if ($this->user == '-1') { return T_('All'); }
+
+ $user = new User($this->user);
+ return $user->fullname . " (" . $user->username . ")";
+
+ } // get_user_name
+
+ /**
+ * get_type_name
+ * This function returns the pretty name for our current type
+ */
+ public function get_type_name() {
+
+ switch ($this->type) {
+ case 'xml-rpc':
+ case 'rpc':
+ return T_('API/RPC');
+ break;
+ case 'network':
+ return T_('Local Network Definition');
+ break;
+ case 'interface':
+ return T_('Web Interface');
+ break;
+ case 'stream':
+ default:
+ return T_('Stream Access');
+ break;
+ } // end switch
+
+ } // get_type_name
+
+ /**
+ * session_exists
+ * This checks to see if the specified session of the specified type
+ * exists, it also provides an array of key'd data that may be required
+ * based on the type
+ */
+ public static function session_exists($data,$key,$type) {
+
+ // Switch on the type they pass
+ switch ($type) {
+ case 'api':
+ $key = Dba::escape($key);
+ $time = time();
+ $sql = "SELECT * FROM `session_api` WHERE `id`='$key' AND `expire` > '$time'";
+ $db_results = Dba::read($sql);
+
+ if (Dba::num_rows($db_results)) {
+ $time = $time + 3600;
+ $sql = "UPDATE `session_api` WHERE `id`='$key' SET `expire`='$time'";
+ $db_results = Dba::write($sql);
+ return true;
+ }
+
+ return false;
+
+ break;
+ case 'stream':
+
+ break;
+ case 'interface':
+
+ break;
+ default:
+ return false;
+ break;
+ } // type
+
+
+ } // session_exists
} //end of access class
diff --git a/lib/class/ajax.class.php b/lib/class/ajax.class.php
index 04098861..e19301bf 100644
--- a/lib/class/ajax.class.php
+++ b/lib/class/ajax.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,185 +30,185 @@
*/
class Ajax {
- private static $include_override;
+ private static $include_override;
- /**
- * constructor
- * This is what is called when the class is loaded
- */
- public function __construct() {
+ /**
+ * constructor
+ * This is what is called when the class is loaded
+ */
+ public function __construct() {
- // Rien a faire
+ // Rien a faire
- } // constructor
-
- /**
- * observe
- * This returns a string with the correct and full ajax 'observe' stuff
- * from prototype
- */
- public static function observe($source,$method,$action,$post='') {
-
- $non_quoted = array('document','window');
+ } // constructor
+
+ /**
+ * observe
+ * This returns a string with the correct and full ajax 'observe' stuff
+ * from prototype
+ */
+ public static function observe($source,$method,$action,$post='') {
+
+ $non_quoted = array('document','window');
- if (in_array($source,$non_quoted)) {
- $source_txt = $source;
- }
- else {
- $source_txt = "'$source'";
- }
+ if (in_array($source,$non_quoted)) {
+ $source_txt = $source;
+ }
+ else {
+ $source_txt = "'$source'";
+ }
- // If it's a post then we need to stop events
- if ($post) {
- $action = 'Event.stop(e); ' . $action;
- }
+ // If it's a post then we need to stop events
+ if ($post) {
+ $action = 'Event.stop(e); ' . $action;
+ }
- $observe = "<script type=\"text/javascript\">";
- $observe .= "Event.observe($source_txt,'$method',function(e){" . $action . ";});";
- $observe .= "</script>";
+ $observe = "<script type=\"text/javascript\">";
+ $observe .= "Event.observe($source_txt,'$method',function(e){" . $action . ";});";
+ $observe .= "</script>";
- return $observe;
+ return $observe;
- } // observe
+ } // observe
- /**
- * url
- * This takes a string and makes an URL
- */
- public static function url($action) {
- return Config::get('ajax_url') . $action;
- }
+ /**
+ * url
+ * This takes a string and makes an URL
+ */
+ public static function url($action) {
+ return Config::get('ajax_url') . $action;
+ }
- /**
- * action
- * This takes the action, the source and the post (if passed) and
- * generates the full ajax link
- */
- public static function action($action,$source,$post='') {
+ /**
+ * action
+ * This takes the action, the source and the post (if passed) and
+ * generates the full ajax link
+ */
+ public static function action($action,$source,$post='') {
- $url = self::url($action);
+ $url = self::url($action);
- $non_quoted = array('document','window');
+ $non_quoted = array('document','window');
- if (in_array($source,$non_quoted)) {
- $source_txt = $source;
- }
- else {
- $source_txt = "'$source'";
- }
+ if (in_array($source,$non_quoted)) {
+ $source_txt = $source;
+ }
+ else {
+ $source_txt = "'$source'";
+ }
- if ($post) {
- $ajax_string = "ajaxPost('$url','$post',$source_txt)";
- }
- else {
- $ajax_string = "ajaxPut('$url',$source_txt)";
- }
-
- return $ajax_string;
+ if ($post) {
+ $ajax_string = "ajaxPost('$url','$post',$source_txt)";
+ }
+ else {
+ $ajax_string = "ajaxPut('$url',$source_txt)";
+ }
+
+ return $ajax_string;
- } // action
+ } // action
- /**
- * button
- * This prints out an img of the specified icon with the specified alt
- * text and then sets up the required ajax for it.
- */
- public static function button($action,$icon,$alt,$source='',$post='',$class='') {
+ /**
+ * button
+ * This prints out an img of the specified icon with the specified alt
+ * text and then sets up the required ajax for it.
+ */
+ public static function button($action,$icon,$alt,$source='',$post='',$class='') {
- // Get the correct action
- $ajax_string = self::action($action,$source,$post);
+ // Get the correct action
+ $ajax_string = self::action($action,$source,$post);
- // If they passed a span class
- if ($class) {
- $class = ' class="' . $class . '"';
- }
+ // If they passed a span class
+ if ($class) {
+ $class = ' class="' . $class . '"';
+ }
- $string = UI::get_icon($icon,$alt);
+ $string = UI::get_icon($icon,$alt);
- // Generate an <a> so that it's more compliant with older
- // browsers (ie :hover actions) and also to unify linkbuttons
- // (w/o ajax) display
- $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>".$string."</a>\n";
+ // Generate an <a> so that it's more compliant with older
+ // browsers (ie :hover actions) and also to unify linkbuttons
+ // (w/o ajax) display
+ $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>".$string."</a>\n";
- $string .= self::observe($source,'click',$ajax_string);
+ $string .= self::observe($source,'click',$ajax_string);
- return $string;
+ return $string;
- } // button
+ } // button
- /**
- * text
- * This prints out the specified text as a link and sets up the required
- * ajax for the link so it works correctly
- */
- public static function text($action,$text,$source,$post='',$class='') {
+ /**
+ * text
+ * This prints out the specified text as a link and sets up the required
+ * ajax for the link so it works correctly
+ */
+ public static function text($action,$text,$source,$post='',$class='') {
- // Format the string we wanna use
- $ajax_string = self::action($action,$source,$post);
+ // Format the string we wanna use
+ $ajax_string = self::action($action,$source,$post);
- // If they passed a span class
- if ($class) {
- $class = ' class="' . $class . '"';
- }
+ // If they passed a span class
+ if ($class) {
+ $class = ' class="' . $class . '"';
+ }
- // If we pass a source put it in the ID
- $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>$text</a>\n";
+ // If we pass a source put it in the ID
+ $string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>$text</a>\n";
- $string .= self::observe($source,'click',$ajax_string);
+ $string .= self::observe($source,'click',$ajax_string);
- return $string;
+ return $string;
- } // text
+ } // text
- /**
- * run
- * This runs the specified action no questions asked
- */
- public static function run($action) {
+ /**
+ * run
+ * This runs the specified action no questions asked
+ */
+ public static function run($action) {
- echo "<script type=\"text/javascript\"><!--\n";
- echo "$action";
- echo "\n--></script>";
+ echo "<script type=\"text/javascript\"><!--\n";
+ echo "$action";
+ echo "\n--></script>";
- } // run
+ } // run
- /**
- * set_include_override
- * This sets the including div override, used only one place. Kind of a
- * hack.
- */
- public static function set_include_override($value) {
+ /**
+ * set_include_override
+ * This sets the including div override, used only one place. Kind of a
+ * hack.
+ */
+ public static function set_include_override($value) {
- self::$include_override = make_bool($value);
+ self::$include_override = make_bool($value);
- } // set_include_override
+ } // set_include_override
- /**
- * start_container
- * This checks to see if we're AJAXin'. If we aren't then it echoes out
- * the html needed to start a container that can be replaced by Ajax.
- */
- public static function start_container($name) {
+ /**
+ * start_container
+ * This checks to see if we're AJAXin'. If we aren't then it echoes out
+ * the html needed to start a container that can be replaced by Ajax.
+ */
+ public static function start_container($name) {
- if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; }
+ if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; }
- echo '<div id="' . scrub_out($name) . '">';
+ echo '<div id="' . scrub_out($name) . '">';
- } // start_container
+ } // start_container
- /**
- * end_container
- * This ends the container if we're not doing the AJAX thing
- */
- public static function end_container() {
+ /**
+ * end_container
+ * This ends the container if we're not doing the AJAX thing
+ */
+ public static function end_container() {
- if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; }
+ if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; }
- echo "</div>";
+ echo "</div>";
- self::$include_override = false;
+ self::$include_override = false;
- } // end_container
+ } // end_container
} // end Ajax class
?>
diff --git a/lib/class/album.class.php b/lib/class/album.class.php
index c7b88dcf..56e458e8 100644
--- a/lib/class/album.class.php
+++ b/lib/class/album.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,345 +30,345 @@
*/
class Album extends database_object {
- /* Variables from DB */
- public $id;
- public $name;
- public $disk;
- public $year;
- public $prefix;
- public $mbid; // MusicBrainz ID
-
- public $full_name; // Prefix + Name, generated
-
- // cached information
- public $_songs=array();
-
- /**
- * __construct
- * Album constructor it loads everything relating
- * to this album from the database it does not
- * pull the album or thumb art by default or
- * get any of the counts.
- */
- public function __construct($id='') {
-
- if (!$id) { return false; }
-
- /* Get the information from the db */
- $info = $this->get_info($id);
-
- // Foreach what we've got
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
-
- // Little bit of formatting here
- $this->full_name = trim(trim($info['prefix']) . ' ' . trim($info['name']));
-
- return true;
-
- } // constructor
-
- /**
- * construct_from_array
- * This is often used by the metadata class, it fills out an album object from a
- * named array, _fake is set to true
- */
- public static function construct_from_array($data) {
-
- $album = new Album(0);
- foreach ($data as $key=>$value) {
- $album->$key = $value;
- }
-
- // Make sure that we tell em it's fake
- $album->_fake = true;
-
- return $album;
-
- } // construct_from_array
-
- /**
- * gc
- *
- * Cleans out unused albums
- */
- public static function gc() {
- Dba::write('DELETE FROM `album` USING `album` LEFT JOIN `song` ON `song`.`album` = `album`.`id` WHERE `song`.`id` IS NULL');
- }
-
- /**
- * build_cache
- * This takes an array of object ids and caches all of their information
- * with a single query
- */
- public static function build_cache($ids,$extra=false) {
-
- // Nothing to do if they pass us nothing
- if (!is_array($ids) OR !count($ids)) { return false; }
-
- $idlist = '(' . implode(',', $ids) . ')';
-
- $sql = "SELECT * FROM `album` WHERE `id` IN $idlist";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('album',$row['id'],$row);
- }
-
- // If we're extra'ing cache the extra info as well
- if ($extra) {
- $sql = "SELECT COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " .
- "COUNT(`song`.`id`) AS `song_count`, " .
- "`artist`.`name` AS `artist_name`, " .
- "`artist`.`prefix` AS `artist_prefix`, " .
- "`artist`.`id` AS `artist_id`, `song`.`album`" .
- "FROM `song` " .
- "INNER JOIN `artist` ON `artist`.`id`=`song`.`artist` " .
- "WHERE `song`.`album` IN $idlist GROUP BY `song`.`album`";
-
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $art = new Art($row['album'], 'album');
- $art->get_db();
- $row['has_art'] = make_bool($art->raw);
- $row['has_thumb'] = make_bool($art->thumb);
- parent::add_to_cache('album_extra',$row['album'],$row);
- } // while rows
- } // if extra
-
- return true;
-
- } // build_cache
-
- /**
- * _get_extra_info
- * This pulls the extra information from our tables, this is a 3 table join, which is why we don't normally
- * do it
- */
- private function _get_extra_info() {
-
- if (parent::is_cached('album_extra',$this->id)) {
- return parent::get_from_cache('album_extra',$this->id);
- }
-
- $sql = "SELECT " .
- "COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " .
- "COUNT(`song`.`id`) AS `song_count`, " .
- "`artist`.`name` AS `artist_name`, " .
- "`artist`.`prefix` AS `artist_prefix`, " .
- "`artist`.`id` AS `artist_id` " .
- "FROM `song` INNER JOIN `artist` " .
- "ON `artist`.`id`=`song`.`artist` " .
- "WHERE `song`.`album`='$this->id' " .
- "GROUP BY `song`.`album`";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
-
- $art = new Art($this->id, 'album');
- $art->get_db();
- $results['has_art'] = make_bool($art->raw);
- $results['has_thumb'] = make_bool($art->thumb);
-
- parent::add_to_cache('album_extra',$this->id,$results);
-
- return $results;
-
- } // _get_extra_info
-
- /**
- * get_songs
- * gets the songs for this album takes an optional limit
- * and an optional artist, if artist is passed it only gets
- * songs with this album + specified artist
- */
- public function get_songs($limit = 0,$artist='') {
-
- $results = array();
-
- $artist = Dba::escape($artist);
-
- $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' ";
- if ($artist) {
- $sql .= "AND `artist`='$artist'";
- }
- $sql .= "ORDER BY `track`, `title`";
- if ($limit) {
- $sql .= " LIMIT $limit";
- }
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['id'];
- }
-
- return $results;
-
- } // get_songs
-
- /**
- * has_track
- * This checks to see if this album has a track of the specified title
- */
- public function has_track($title) {
-
- $title = Dba::escape($title);
-
- $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' AND `title`='$title'";
- $db_results = Dba::read($sql);
-
- $data = Dba::fetch_assoc($db_results);
-
- return $data;
-
- } // has_track
-
- /**
- * format
- * This is the format function for this object. It sets cleaned up
- * album information with the base required
- * f_link, f_name
- */
- public function format() {
-
- $web_path = Config::get('web_path');
-
- /* Pull the advanced information */
- $data = $this->_get_extra_info();
- foreach ($data as $key=>$value) { $this->$key = $value; }
-
- /* Truncate the string if it's to long */
- $this->f_name = UI::truncate($this->full_name,Config::get('ellipse_threshold_album'));
-
- $this->f_name_link = "<a href=\"$web_path/albums.php?action=show&amp;album=" . scrub_out($this->id) . "\" title=\"" . scrub_out($this->full_name) . "\">" . scrub_out($this->f_name);
- // If we've got a disk append it
- if ($this->disk) {
- $this->f_name_link .= " <span class=\"discnb disc" .$this->disk. "\">[" . T_('Disk') . " " . $this->disk . "]</span>";
- }
- $this->f_name_link .="</a>";
-
- $this->f_link = $this->f_name_link;
- $this->f_title = $this->full_name; // FIXME: Legacy?
- if ($this->artist_count == '1') {
- $artist = trim(trim($this->artist_prefix) . ' ' . trim($this->artist_name));
- $this->f_artist_name = $artist;
- $artist = scrub_out(UI::truncate($artist), Config::get('ellipse_threshold_artist'));
- $this->f_artist_link = "<a href=\"$web_path/artists.php?action=show&amp;artist=" . $this->artist_id . "\" title=\"" . scrub_out($this->artist_name) . "\">" . $artist . "</a>";
- $this->f_artist = $artist;
- }
- else {
- $this->f_artist_link = "<span title=\"$this->artist_count " . T_('Artists') . "\">" . T_('Various') . "</span>";
- $this->f_artist = T_('Various');
- $this->f_artist_name = $this->f_artist;
- }
-
- if ($this->year == '0') {
- $this->year = "N/A";
- }
-
- $tags = Tag::get_top_tags('album',$this->id);
- $this->tags = $tags;
-
- $this->f_tags = Tag::get_display($tags,$this->id,'album');
-
- } // format
-
- /**
- * get_random_songs
- * gets a random number, and a random assortment of songs from this album
- */
- function get_random_songs() {
-
- $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' ORDER BY RAND()";
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_row($db_results)) {
- $results[] = $r['0'];
- }
-
- return $results;
-
- } // get_random_songs
-
- /**
- * update
- * This function takes a key'd array of data and updates this object
- * as needed, and then throws down with a flag
- */
- public function update($data) {
-
- $year = $data['year'];
- $artist = $data['artist'];
- $name = $data['name'];
- $disk = $data['disk'];
- $mbid = $data['mbid'];
-
- $current_id = $this->id;
-
- if ($artist != $this->artist_id AND $artist) {
- // Update every song
- $songs = $this->get_songs();
- foreach ($songs as $song_id) {
- Song::update_artist($artist,$song_id);
- }
- $updated = 1;
- Artist::gc();
- }
-
- $album_id = Catalog::check_album($name,$year,$disk,$mbid);
- if ($album_id != $this->id) {
- if (!is_array($songs)) { $songs = $this->get_songs(); }
- foreach ($songs as $song_id) {
- Song::update_album($album_id,$song_id);
- Song::update_year($year,$song_id);
- }
- $current_id = $album_id;
- $updated = 1;
- self::gc();
- }
-
- if ($updated) {
- // Flag all songs
- foreach ($songs as $song_id) {
- Flag::add($song_id,'song','retag','Interface Album Update');
- Song::update_utime($song_id);
- } // foreach song of album
- Stats::gc();
- Rating::gc();
- } // if updated
-
-
- return $current_id;
-
- } // update
-
- /**
- * get_random_albums
- * This returns a random number of albums from the catalogs
- * this is used by the index to return some 'potential' albums to play
- */
- public static function get_random_albums($count=6) {
-
- $sql = 'SELECT `id` FROM `album` ORDER BY RAND() LIMIT ' . ($count*2);
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $art = new Art($row['id'], 'album');
- $art->get_db();
- if ($art->raw) {
- $results[] = $row['id'];
- }
- }
-
- if (count($results) < $count) { return false; }
-
- $results = array_slice($results, 0, $count);
-
- return $results;
-
- } // get_random_albums
+ /* Variables from DB */
+ public $id;
+ public $name;
+ public $disk;
+ public $year;
+ public $prefix;
+ public $mbid; // MusicBrainz ID
+
+ public $full_name; // Prefix + Name, generated
+
+ // cached information
+ public $_songs=array();
+
+ /**
+ * __construct
+ * Album constructor it loads everything relating
+ * to this album from the database it does not
+ * pull the album or thumb art by default or
+ * get any of the counts.
+ */
+ public function __construct($id='') {
+
+ if (!$id) { return false; }
+
+ /* Get the information from the db */
+ $info = $this->get_info($id);
+
+ // Foreach what we've got
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
+
+ // Little bit of formatting here
+ $this->full_name = trim(trim($info['prefix']) . ' ' . trim($info['name']));
+
+ return true;
+
+ } // constructor
+
+ /**
+ * construct_from_array
+ * This is often used by the metadata class, it fills out an album object from a
+ * named array, _fake is set to true
+ */
+ public static function construct_from_array($data) {
+
+ $album = new Album(0);
+ foreach ($data as $key=>$value) {
+ $album->$key = $value;
+ }
+
+ // Make sure that we tell em it's fake
+ $album->_fake = true;
+
+ return $album;
+
+ } // construct_from_array
+
+ /**
+ * gc
+ *
+ * Cleans out unused albums
+ */
+ public static function gc() {
+ Dba::write('DELETE FROM `album` USING `album` LEFT JOIN `song` ON `song`.`album` = `album`.`id` WHERE `song`.`id` IS NULL');
+ }
+
+ /**
+ * build_cache
+ * This takes an array of object ids and caches all of their information
+ * with a single query
+ */
+ public static function build_cache($ids,$extra=false) {
+
+ // Nothing to do if they pass us nothing
+ if (!is_array($ids) OR !count($ids)) { return false; }
+
+ $idlist = '(' . implode(',', $ids) . ')';
+
+ $sql = "SELECT * FROM `album` WHERE `id` IN $idlist";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('album',$row['id'],$row);
+ }
+
+ // If we're extra'ing cache the extra info as well
+ if ($extra) {
+ $sql = "SELECT COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " .
+ "COUNT(`song`.`id`) AS `song_count`, " .
+ "`artist`.`name` AS `artist_name`, " .
+ "`artist`.`prefix` AS `artist_prefix`, " .
+ "`artist`.`id` AS `artist_id`, `song`.`album`" .
+ "FROM `song` " .
+ "INNER JOIN `artist` ON `artist`.`id`=`song`.`artist` " .
+ "WHERE `song`.`album` IN $idlist GROUP BY `song`.`album`";
+
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $art = new Art($row['album'], 'album');
+ $art->get_db();
+ $row['has_art'] = make_bool($art->raw);
+ $row['has_thumb'] = make_bool($art->thumb);
+ parent::add_to_cache('album_extra',$row['album'],$row);
+ } // while rows
+ } // if extra
+
+ return true;
+
+ } // build_cache
+
+ /**
+ * _get_extra_info
+ * This pulls the extra information from our tables, this is a 3 table join, which is why we don't normally
+ * do it
+ */
+ private function _get_extra_info() {
+
+ if (parent::is_cached('album_extra',$this->id)) {
+ return parent::get_from_cache('album_extra',$this->id);
+ }
+
+ $sql = "SELECT " .
+ "COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " .
+ "COUNT(`song`.`id`) AS `song_count`, " .
+ "`artist`.`name` AS `artist_name`, " .
+ "`artist`.`prefix` AS `artist_prefix`, " .
+ "`artist`.`id` AS `artist_id` " .
+ "FROM `song` INNER JOIN `artist` " .
+ "ON `artist`.`id`=`song`.`artist` " .
+ "WHERE `song`.`album`='$this->id' " .
+ "GROUP BY `song`.`album`";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+
+ $art = new Art($this->id, 'album');
+ $art->get_db();
+ $results['has_art'] = make_bool($art->raw);
+ $results['has_thumb'] = make_bool($art->thumb);
+
+ parent::add_to_cache('album_extra',$this->id,$results);
+
+ return $results;
+
+ } // _get_extra_info
+
+ /**
+ * get_songs
+ * gets the songs for this album takes an optional limit
+ * and an optional artist, if artist is passed it only gets
+ * songs with this album + specified artist
+ */
+ public function get_songs($limit = 0,$artist='') {
+
+ $results = array();
+
+ $artist = Dba::escape($artist);
+
+ $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' ";
+ if ($artist) {
+ $sql .= "AND `artist`='$artist'";
+ }
+ $sql .= "ORDER BY `track`, `title`";
+ if ($limit) {
+ $sql .= " LIMIT $limit";
+ }
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['id'];
+ }
+
+ return $results;
+
+ } // get_songs
+
+ /**
+ * has_track
+ * This checks to see if this album has a track of the specified title
+ */
+ public function has_track($title) {
+
+ $title = Dba::escape($title);
+
+ $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' AND `title`='$title'";
+ $db_results = Dba::read($sql);
+
+ $data = Dba::fetch_assoc($db_results);
+
+ return $data;
+
+ } // has_track
+
+ /**
+ * format
+ * This is the format function for this object. It sets cleaned up
+ * album information with the base required
+ * f_link, f_name
+ */
+ public function format() {
+
+ $web_path = Config::get('web_path');
+
+ /* Pull the advanced information */
+ $data = $this->_get_extra_info();
+ foreach ($data as $key=>$value) { $this->$key = $value; }
+
+ /* Truncate the string if it's to long */
+ $this->f_name = UI::truncate($this->full_name,Config::get('ellipse_threshold_album'));
+
+ $this->f_name_link = "<a href=\"$web_path/albums.php?action=show&amp;album=" . scrub_out($this->id) . "\" title=\"" . scrub_out($this->full_name) . "\">" . scrub_out($this->f_name);
+ // If we've got a disk append it
+ if ($this->disk) {
+ $this->f_name_link .= " <span class=\"discnb disc" .$this->disk. "\">[" . T_('Disk') . " " . $this->disk . "]</span>";
+ }
+ $this->f_name_link .="</a>";
+
+ $this->f_link = $this->f_name_link;
+ $this->f_title = $this->full_name; // FIXME: Legacy?
+ if ($this->artist_count == '1') {
+ $artist = trim(trim($this->artist_prefix) . ' ' . trim($this->artist_name));
+ $this->f_artist_name = $artist;
+ $artist = scrub_out(UI::truncate($artist), Config::get('ellipse_threshold_artist'));
+ $this->f_artist_link = "<a href=\"$web_path/artists.php?action=show&amp;artist=" . $this->artist_id . "\" title=\"" . scrub_out($this->artist_name) . "\">" . $artist . "</a>";
+ $this->f_artist = $artist;
+ }
+ else {
+ $this->f_artist_link = "<span title=\"$this->artist_count " . T_('Artists') . "\">" . T_('Various') . "</span>";
+ $this->f_artist = T_('Various');
+ $this->f_artist_name = $this->f_artist;
+ }
+
+ if ($this->year == '0') {
+ $this->year = "N/A";
+ }
+
+ $tags = Tag::get_top_tags('album',$this->id);
+ $this->tags = $tags;
+
+ $this->f_tags = Tag::get_display($tags,$this->id,'album');
+
+ } // format
+
+ /**
+ * get_random_songs
+ * gets a random number, and a random assortment of songs from this album
+ */
+ function get_random_songs() {
+
+ $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' ORDER BY RAND()";
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_row($db_results)) {
+ $results[] = $r['0'];
+ }
+
+ return $results;
+
+ } // get_random_songs
+
+ /**
+ * update
+ * This function takes a key'd array of data and updates this object
+ * as needed, and then throws down with a flag
+ */
+ public function update($data) {
+
+ $year = $data['year'];
+ $artist = $data['artist'];
+ $name = $data['name'];
+ $disk = $data['disk'];
+ $mbid = $data['mbid'];
+
+ $current_id = $this->id;
+
+ if ($artist != $this->artist_id AND $artist) {
+ // Update every song
+ $songs = $this->get_songs();
+ foreach ($songs as $song_id) {
+ Song::update_artist($artist,$song_id);
+ }
+ $updated = 1;
+ Artist::gc();
+ }
+
+ $album_id = Catalog::check_album($name,$year,$disk,$mbid);
+ if ($album_id != $this->id) {
+ if (!is_array($songs)) { $songs = $this->get_songs(); }
+ foreach ($songs as $song_id) {
+ Song::update_album($album_id,$song_id);
+ Song::update_year($year,$song_id);
+ }
+ $current_id = $album_id;
+ $updated = 1;
+ self::gc();
+ }
+
+ if ($updated) {
+ // Flag all songs
+ foreach ($songs as $song_id) {
+ Flag::add($song_id,'song','retag','Interface Album Update');
+ Song::update_utime($song_id);
+ } // foreach song of album
+ Stats::gc();
+ Rating::gc();
+ } // if updated
+
+
+ return $current_id;
+
+ } // update
+
+ /**
+ * get_random_albums
+ * This returns a random number of albums from the catalogs
+ * this is used by the index to return some 'potential' albums to play
+ */
+ public static function get_random_albums($count=6) {
+
+ $sql = 'SELECT `id` FROM `album` ORDER BY RAND() LIMIT ' . ($count*2);
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $art = new Art($row['id'], 'album');
+ $art->get_db();
+ if ($art->raw) {
+ $results[] = $row['id'];
+ }
+ }
+
+ if (count($results) < $count) { return false; }
+
+ $results = array_slice($results, 0, $count);
+
+ return $results;
+
+ } // get_random_albums
} //end of album class
diff --git a/lib/class/ampache_mail.class.php b/lib/class/ampache_mail.class.php
index 8c1d363b..6b8bc20f 100644
--- a/lib/class/ampache_mail.class.php
+++ b/lib/class/ampache_mail.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,187 +28,187 @@
*/
class Ampache_Mail {
- // The message, recipient and from
- public $message;
- public $subject;
- public $recipient;
- public $recipient_name;
- public $sender;
- public $sender_name;
-
- /**
- * Constructor
- *
- * This does nothing. Much like goggles.
- */
- public function __construct() {
-
- // Eh bien.
-
- } // Constructor
-
- /**
- * set_default_sender
- *
- * Does the config magic to figure out the "system" email sender and
- * sets it as the sender.
- */
- public function set_default_sender() {
- $user = Config::get('mail_user');
- if (!$user) {
- $user = 'info';
- }
-
- $domain = Config::get('mail_domain');
- if (!$domain) {
- $domain = 'example.com';
- }
-
- $fromname = Config::get('mail_name');
- if (!$fromname) {
- $fromname = 'Ampache';
- }
-
- $this->sender = $user . '@' . $domain;
- $this->sender_name = $fromname;
- } // set_default_sender
-
- /**
- * get_users
- * This returns an array of userids for people who have e-mail
- * addresses based on the passed filter
- */
- public static function get_users($filter) {
-
- switch ($filter) {
- default:
- case 'all':
- $sql = "SELECT * FROM `user` WHERE `email` IS NOT NULL";
- break;
- case 'users':
- $sql = "SELECT * FROM `user` WHERE `access`='25' AND `email` IS NOT NULL";
- break;
- case 'admins':
- $sql = "SELECT * FROM `user` WHERE `access`='100' AND `email` IS NOT NULL";
- break ;
- case 'inactive':
- $inactive = time() - (30*86400);
- $sql = "SELECT * FROM `user` WHERE `last_seen` <= '$inactive' AND `email` IS NOT NULL";
- break;
- } // end filter switch
-
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = array('id'=>$row['id'],'fullname'=>$row['fullname'],'email'=>$row['email']);
- }
-
- return $results;
-
- } // get_users
-
- /**
- * add_statistics
- * This should be run if we want to add some statistics to this e-mail,
- * appends to self::$message
- */
- public function add_statistics($methods) {
-
-
-
- } // add_statistics
-
- /**
- * send
- * This actually sends the mail, how amazing
- */
- public function send($phpmailer = null) {
-
- $mailtype = Config::get('mail_type');
-
- if ($phpmailer == null) {
- $mail = new PHPMailer();
-
- $recipient_name = $this->recipient_name;
- if(function_exists('mb_encode_mimeheader')) {
- $recipient_name = mb_encode_mimeheader($recipient_name);
- }
- $mail->AddAddress($this->recipient, $recipient_name);
- }
- else {
- $mail = $phpmailer;
- }
-
- $mail->CharSet = Config::get('site_charset');
- $mail->Encoding = 'base64';
- $mail->From = $this->sender;
- $mail->Sender = $this->sender;
- $mail->FromName = $this->sender_name;
- $mail->Subject = $this->subject;
-
- if(function_exists('mb_eregi_replace')) {
- $this->message = mb_eregi_replace("\r\n", "\n", $this->message);
- }
- $mail->Body = $this->message;
-
- $sendmail = Config::get('sendmail_path');
- $sendmail = $sendmail ? $sendmail : '/usr/sbin/sendmail';
- $mailhost = Config::get('mail_host');
- $mailhost = $mailhost ? $mailhost : 'localhost';
- $mailport = Config::get('mail_port');
- $mailport = $mailport ? $mailport : 25;
- $mailauth = Config::get('mail_auth');
- $mailuser = Config::get('mail_auth_user');
- $mailuser = $mailuser ? $mailuser : '';
- $mailpass = Config::get('mail_auth_pass');
- $mailpass = $mailpass ? $mailpass : '';
-
- switch($mailtype) {
- case 'smtp':
- $mail->IsSMTP();
- $mail->Host = $mailhost;
- $mail->Port = $mailport;
- if($mailauth == true) {
- $mail->SMTPAuth = true;
- $mail->Username = $mailuser;
- $mail->Password = $mailpass;
- }
- if ($mailsecure = Config::get('mail_secure_smtp')) {
- $mail->SMTPSecure = ($mailsecure == 'ssl') ? 'ssl' : 'tls';
- }
- break;
- case 'sendmail':
- $mail->IsSendmail();
- $mail->Sendmail = $sendmail;
- break;
- case 'php':
- default:
- $mail->IsMail();
- break;
- }
-
- $retval = $mail->send();
- if( $retval == true ) {
- return true;
- } else {
- return false;
- }
- } // send
-
- public function send_to_group($group_name) {
- $mail = new PHPMailer();
-
- foreach(self::get_users($group_name) as $member) {
- if(function_exists('mb_encode_mimeheader')) {
- $member['fullname'] = mb_encode_mimeheader($member['fullname']);
- }
- $mail->AddBCC($member['email'], $member['fullname']);
- }
-
- return $this->send($mail);
- }
+ // The message, recipient and from
+ public $message;
+ public $subject;
+ public $recipient;
+ public $recipient_name;
+ public $sender;
+ public $sender_name;
+
+ /**
+ * Constructor
+ *
+ * This does nothing. Much like goggles.
+ */
+ public function __construct() {
+
+ // Eh bien.
+
+ } // Constructor
+
+ /**
+ * set_default_sender
+ *
+ * Does the config magic to figure out the "system" email sender and
+ * sets it as the sender.
+ */
+ public function set_default_sender() {
+ $user = Config::get('mail_user');
+ if (!$user) {
+ $user = 'info';
+ }
+
+ $domain = Config::get('mail_domain');
+ if (!$domain) {
+ $domain = 'example.com';
+ }
+
+ $fromname = Config::get('mail_name');
+ if (!$fromname) {
+ $fromname = 'Ampache';
+ }
+
+ $this->sender = $user . '@' . $domain;
+ $this->sender_name = $fromname;
+ } // set_default_sender
+
+ /**
+ * get_users
+ * This returns an array of userids for people who have e-mail
+ * addresses based on the passed filter
+ */
+ public static function get_users($filter) {
+
+ switch ($filter) {
+ default:
+ case 'all':
+ $sql = "SELECT * FROM `user` WHERE `email` IS NOT NULL";
+ break;
+ case 'users':
+ $sql = "SELECT * FROM `user` WHERE `access`='25' AND `email` IS NOT NULL";
+ break;
+ case 'admins':
+ $sql = "SELECT * FROM `user` WHERE `access`='100' AND `email` IS NOT NULL";
+ break ;
+ case 'inactive':
+ $inactive = time() - (30*86400);
+ $sql = "SELECT * FROM `user` WHERE `last_seen` <= '$inactive' AND `email` IS NOT NULL";
+ break;
+ } // end filter switch
+
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = array('id'=>$row['id'],'fullname'=>$row['fullname'],'email'=>$row['email']);
+ }
+
+ return $results;
+
+ } // get_users
+
+ /**
+ * add_statistics
+ * This should be run if we want to add some statistics to this e-mail,
+ * appends to self::$message
+ */
+ public function add_statistics($methods) {
+
+
+
+ } // add_statistics
+
+ /**
+ * send
+ * This actually sends the mail, how amazing
+ */
+ public function send($phpmailer = null) {
+
+ $mailtype = Config::get('mail_type');
+
+ if ($phpmailer == null) {
+ $mail = new PHPMailer();
+
+ $recipient_name = $this->recipient_name;
+ if(function_exists('mb_encode_mimeheader')) {
+ $recipient_name = mb_encode_mimeheader($recipient_name);
+ }
+ $mail->AddAddress($this->recipient, $recipient_name);
+ }
+ else {
+ $mail = $phpmailer;
+ }
+
+ $mail->CharSet = Config::get('site_charset');
+ $mail->Encoding = 'base64';
+ $mail->From = $this->sender;
+ $mail->Sender = $this->sender;
+ $mail->FromName = $this->sender_name;
+ $mail->Subject = $this->subject;
+
+ if(function_exists('mb_eregi_replace')) {
+ $this->message = mb_eregi_replace("\r\n", "\n", $this->message);
+ }
+ $mail->Body = $this->message;
+
+ $sendmail = Config::get('sendmail_path');
+ $sendmail = $sendmail ? $sendmail : '/usr/sbin/sendmail';
+ $mailhost = Config::get('mail_host');
+ $mailhost = $mailhost ? $mailhost : 'localhost';
+ $mailport = Config::get('mail_port');
+ $mailport = $mailport ? $mailport : 25;
+ $mailauth = Config::get('mail_auth');
+ $mailuser = Config::get('mail_auth_user');
+ $mailuser = $mailuser ? $mailuser : '';
+ $mailpass = Config::get('mail_auth_pass');
+ $mailpass = $mailpass ? $mailpass : '';
+
+ switch($mailtype) {
+ case 'smtp':
+ $mail->IsSMTP();
+ $mail->Host = $mailhost;
+ $mail->Port = $mailport;
+ if($mailauth == true) {
+ $mail->SMTPAuth = true;
+ $mail->Username = $mailuser;
+ $mail->Password = $mailpass;
+ }
+ if ($mailsecure = Config::get('mail_secure_smtp')) {
+ $mail->SMTPSecure = ($mailsecure == 'ssl') ? 'ssl' : 'tls';
+ }
+ break;
+ case 'sendmail':
+ $mail->IsSendmail();
+ $mail->Sendmail = $sendmail;
+ break;
+ case 'php':
+ default:
+ $mail->IsMail();
+ break;
+ }
+
+ $retval = $mail->send();
+ if( $retval == true ) {
+ return true;
+ } else {
+ return false;
+ }
+ } // send
+
+ public function send_to_group($group_name) {
+ $mail = new PHPMailer();
+
+ foreach(self::get_users($group_name) as $member) {
+ if(function_exists('mb_encode_mimeheader')) {
+ $member['fullname'] = mb_encode_mimeheader($member['fullname']);
+ }
+ $mail->AddBCC($member['email'], $member['fullname']);
+ }
+
+ return $this->send($mail);
+ }
} // Ampache_Mail class
?>
diff --git a/lib/class/ampache_rss.class.php b/lib/class/ampache_rss.class.php
index 3056e9cf..8006d8be 100644
--- a/lib/class/ampache_rss.class.php
+++ b/lib/class/ampache_rss.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -27,227 +27,227 @@
*/
class Ampache_RSS {
- private $type;
- public $data;
+ private $type;
+ public $data;
- /**
- * Constructor
- * This takes a flagged.id and then pulls in the information for said flag entry
- */
- public function __construct($type) {
+ /**
+ * Constructor
+ * This takes a flagged.id and then pulls in the information for said flag entry
+ */
+ public function __construct($type) {
- $this->type = self::validate_type($type);
+ $this->type = self::validate_type($type);
- } // constructor
+ } // constructor
- /**
- * get_xml
- * This returns the xmldocument for the current rss type, it calls a sub function that gathers the data
- * and then uses the xmlDATA class to build the document
- */
- public function get_xml() {
+ /**
+ * get_xml
+ * This returns the xmldocument for the current rss type, it calls a sub function that gathers the data
+ * and then uses the xmlDATA class to build the document
+ */
+ public function get_xml() {
- // Function call name
- $data_function = 'load_' . $this->type;
- $pub_date_function = 'pubdate_' . $this->type;
+ // Function call name
+ $data_function = 'load_' . $this->type;
+ $pub_date_function = 'pubdate_' . $this->type;
- $data = call_user_func(array('Ampache_RSS',$data_function));
- $pub_date = call_user_func(array('Ampache_RSS',$pub_date_function));
-
- XML_Data::set_type('rss');
- $xml_document = XML_Data::rss_feed($data,$this->get_title(),$this->get_description(),$pub_date);
-
- return $xml_document;
-
- } // get_xml
+ $data = call_user_func(array('Ampache_RSS',$data_function));
+ $pub_date = call_user_func(array('Ampache_RSS',$pub_date_function));
+
+ XML_Data::set_type('rss');
+ $xml_document = XML_Data::rss_feed($data,$this->get_title(),$this->get_description(),$pub_date);
+
+ return $xml_document;
+
+ } // get_xml
- /**
- * get_title
- * This returns the standardized title for the rss feed based on this->type
- */
- public function get_title() {
-
- $titles = array('now_playing' => T_('Now Playing'),
- 'recently_played' => T_('Recently Played'),
- 'latest_album' => T_('Newest Albums'),
- 'latest_artist' => T_('Newest Artists'));
+ /**
+ * get_title
+ * This returns the standardized title for the rss feed based on this->type
+ */
+ public function get_title() {
+
+ $titles = array('now_playing' => T_('Now Playing'),
+ 'recently_played' => T_('Recently Played'),
+ 'latest_album' => T_('Newest Albums'),
+ 'latest_artist' => T_('Newest Artists'));
- return scrub_out(Config::get('site_title')) . ' - ' . $titles[$this->type];
+ return scrub_out(Config::get('site_title')) . ' - ' . $titles[$this->type];
- } // get_title
+ } // get_title
- /**
- * get_description
- * This returns the standardized description for the rss feed based on this->type
- */
- public function get_description() {
+ /**
+ * get_description
+ * This returns the standardized description for the rss feed based on this->type
+ */
+ public function get_description() {
- //FIXME: For now don't do any kind of translating
- return 'Ampache RSS Feeds';
+ //FIXME: For now don't do any kind of translating
+ return 'Ampache RSS Feeds';
- } // get_description
+ } // get_description
- /**
- * validate_type
- * this returns a valid type for an rss feed, if the specified type is invalid it returns a default value
- */
- public static function validate_type($type) {
+ /**
+ * validate_type
+ * this returns a valid type for an rss feed, if the specified type is invalid it returns a default value
+ */
+ public static function validate_type($type) {
- $valid_types = array('now_playing','recently_played','latest_album','latest_artist','latest_song',
- 'popular_song','popular_album','popular_artist');
+ $valid_types = array('now_playing','recently_played','latest_album','latest_artist','latest_song',
+ 'popular_song','popular_album','popular_artist');
- if (!in_array($type,$valid_types)) {
- return 'now_playing';
- }
+ if (!in_array($type,$valid_types)) {
+ return 'now_playing';
+ }
- return $type;
-
- } // validate_type
-
- /**
- * get_display
- * This dumps out some html and an icon for the type of rss that we specify
- */
- public static function get_display($type='now_playing') {
-
- // Default to now playing
- $type = self::validate_type($type);
-
- $string = '<a href="' . Config::get('web_path') . '/rss.php?type=' . $type . '">' . UI::get_icon('feed', T_('RSS Feed')) . '</a>';
-
- return $string;
-
- } // get_display
-
- // type specific functions below, these are called semi-dynamically based on the current type //
-
- /**
- * load_now_playing
- * This loads in the now playing information. This is just the raw data with key=>value pairs that could be turned
- * into an xml document if we so wished
- */
- public static function load_now_playing() {
-
- $data = Stream::get_now_playing();
-
- $results = array();
- $format = Config::get('rss_format') ?: '%t - %a - %A';
- $string_map = array(
- '%t' => 'title',
- '%a' => 'artist',
- '%A' => 'album'
- );
- foreach ($data as $element) {
- $song = $element['media'];
- $client = $element['user'];
- $title = $format;
- $description = $format;
- foreach($string_map as $search => $replace) {
- $trep = 'f_' . $replace;
- $drep = 'f_' . $replace . '_full';
- $title = str_replace($search, $song->$trep, $title);
- $description = str_replace($search, $song->$drep, $description);
- }
- $xml_array = array(
- 'title' => $title,
- 'link' => $song->link,
- 'description' => $description,
- 'comments' => $client->fullname . ' - ' . $element['agent'],
- 'pubDate' => date('r', $element['expire'])
- );
- $results[] = $xml_array;
- } // end foreach
-
- return $results;
-
- } // load_now_playing
-
- /**
- * pubdate_now_playing
- * this is the pub date we should use for the now playing information,
- * this is a little specific as it uses the 'newest' expire we can find
- */
- public static function pubdate_now_playing() {
-
- // Little redundent, should be fixed by an improvement in the get_now_playing stuff
- $data = Stream::get_now_playing();
-
- $element = array_shift($data);
-
- return $element['expire'];
-
- } // pubdate_now_playing
-
- /**
- * load_recently_played
- * This loads in the recently played information and formats it up real nice like
- */
- public static function load_recently_played() {
-
- //FIXME: The time stuff should be centralized, it's currently in two places, lame
-
- $time_unit = array('', T_('seconds ago'), T_('minutes ago'), T_('hours ago'), T_('days ago'), T_('weeks ago'), T_('months ago'), T_('years ago'));
- $data = Song::get_recently_played();
-
- $results = array();
-
- foreach ($data as $item) {
- $client = new User($item['user']);
- $song = new Song($item['object_id']);
- $song->format();
- $amount = intval(time() - $item['date']+2);
- $time_place = '0';
- while ($amount >= 1) {
- $final = $amount;
- $time_place++;
- if ($time_place <= 2) {
- $amount = floor($amount/60);
- }
- if ($time_place == '3') {
- $amount = floor($amount/24);
- }
- if ($time_place == '4') {
- $amount = floor($amount/7);
- }
- if ($time_place == '5') {
- $amount = floor($amount/4);
- }
- if ($time_place == '6') {
- $amount = floor ($amount/12);
- }
- if ($time_place > '6') {
- $final = $amount . '+';
- break;
- }
- } // end while
-
- $time_string = $final . ' ' . $time_unit[$time_place];
-
- $xml_array = array('title'=>$song->f_title . ' - ' . $song->f_artist . ' - ' . $song->f_album,
- 'link'=>str_replace('&amp;', '&', $song->link),
- 'description'=>$song->title . ' - ' . $song->f_artist_full . ' - ' . $song->f_album_full . ' - ' . $time_string,
- 'comments'=>$client->username,
- 'pubDate'=>date("r",$item['date']));
- $results[] = $xml_array;
-
- } // end foreach
-
- return $results;
-
- } // load_recently_played
-
- /**
- * pubdate_recently_played
- * This just returns the 'newest' recently played entry
- */
- public static function pubdate_recently_played() {
-
- $data = Song::get_recently_played();
-
- $element = array_shift($data);
-
- return $element['date'];
-
- } // pubdate_recently_played
+ return $type;
+
+ } // validate_type
+
+ /**
+ * get_display
+ * This dumps out some html and an icon for the type of rss that we specify
+ */
+ public static function get_display($type='now_playing') {
+
+ // Default to now playing
+ $type = self::validate_type($type);
+
+ $string = '<a href="' . Config::get('web_path') . '/rss.php?type=' . $type . '">' . UI::get_icon('feed', T_('RSS Feed')) . '</a>';
+
+ return $string;
+
+ } // get_display
+
+ // type specific functions below, these are called semi-dynamically based on the current type //
+
+ /**
+ * load_now_playing
+ * This loads in the now playing information. This is just the raw data with key=>value pairs that could be turned
+ * into an xml document if we so wished
+ */
+ public static function load_now_playing() {
+
+ $data = Stream::get_now_playing();
+
+ $results = array();
+ $format = Config::get('rss_format') ?: '%t - %a - %A';
+ $string_map = array(
+ '%t' => 'title',
+ '%a' => 'artist',
+ '%A' => 'album'
+ );
+ foreach ($data as $element) {
+ $song = $element['media'];
+ $client = $element['user'];
+ $title = $format;
+ $description = $format;
+ foreach($string_map as $search => $replace) {
+ $trep = 'f_' . $replace;
+ $drep = 'f_' . $replace . '_full';
+ $title = str_replace($search, $song->$trep, $title);
+ $description = str_replace($search, $song->$drep, $description);
+ }
+ $xml_array = array(
+ 'title' => $title,
+ 'link' => $song->link,
+ 'description' => $description,
+ 'comments' => $client->fullname . ' - ' . $element['agent'],
+ 'pubDate' => date('r', $element['expire'])
+ );
+ $results[] = $xml_array;
+ } // end foreach
+
+ return $results;
+
+ } // load_now_playing
+
+ /**
+ * pubdate_now_playing
+ * this is the pub date we should use for the now playing information,
+ * this is a little specific as it uses the 'newest' expire we can find
+ */
+ public static function pubdate_now_playing() {
+
+ // Little redundent, should be fixed by an improvement in the get_now_playing stuff
+ $data = Stream::get_now_playing();
+
+ $element = array_shift($data);
+
+ return $element['expire'];
+
+ } // pubdate_now_playing
+
+ /**
+ * load_recently_played
+ * This loads in the recently played information and formats it up real nice like
+ */
+ public static function load_recently_played() {
+
+ //FIXME: The time stuff should be centralized, it's currently in two places, lame
+
+ $time_unit = array('', T_('seconds ago'), T_('minutes ago'), T_('hours ago'), T_('days ago'), T_('weeks ago'), T_('months ago'), T_('years ago'));
+ $data = Song::get_recently_played();
+
+ $results = array();
+
+ foreach ($data as $item) {
+ $client = new User($item['user']);
+ $song = new Song($item['object_id']);
+ $song->format();
+ $amount = intval(time() - $item['date']+2);
+ $time_place = '0';
+ while ($amount >= 1) {
+ $final = $amount;
+ $time_place++;
+ if ($time_place <= 2) {
+ $amount = floor($amount/60);
+ }
+ if ($time_place == '3') {
+ $amount = floor($amount/24);
+ }
+ if ($time_place == '4') {
+ $amount = floor($amount/7);
+ }
+ if ($time_place == '5') {
+ $amount = floor($amount/4);
+ }
+ if ($time_place == '6') {
+ $amount = floor ($amount/12);
+ }
+ if ($time_place > '6') {
+ $final = $amount . '+';
+ break;
+ }
+ } // end while
+
+ $time_string = $final . ' ' . $time_unit[$time_place];
+
+ $xml_array = array('title'=>$song->f_title . ' - ' . $song->f_artist . ' - ' . $song->f_album,
+ 'link'=>str_replace('&amp;', '&', $song->link),
+ 'description'=>$song->title . ' - ' . $song->f_artist_full . ' - ' . $song->f_album_full . ' - ' . $time_string,
+ 'comments'=>$client->username,
+ 'pubDate'=>date("r",$item['date']));
+ $results[] = $xml_array;
+
+ } // end foreach
+
+ return $results;
+
+ } // load_recently_played
+
+ /**
+ * pubdate_recently_played
+ * This just returns the 'newest' recently played entry
+ */
+ public static function pubdate_recently_played() {
+
+ $data = Song::get_recently_played();
+
+ $element = array_shift($data);
+
+ return $element['date'];
+
+ } // pubdate_recently_played
} // end Ampache_RSS class
diff --git a/lib/class/api.class.php b/lib/class/api.class.php
index 841d3534..f289e98b 100644
--- a/lib/class/api.class.php
+++ b/lib/class/api.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,689 +30,689 @@
*/
class Api {
- public static $version = '350001';
-
- private static $browse = null;
-
- /**
- * constructor
- * This really isn't anything to do here, so it's private
- */
- private function __construct() {
-
- // Rien a faire
-
- } // constructor
-
- /**
- * _auto_init
- * Automatically called when this class is loaded.
- */
- public static function _auto_init() {
- if (is_null(self::$browse)) {
- self::$browse = new Browse();
- }
- }
-
- /**
- * set_filter
- * This is a play on the browse function, it's different as we expose
- * the filters in a slightly different and vastly simpler way to the
- * end users--so we have to do a little extra work to make them work
- * internally.
- */
- public static function set_filter($filter,$value) {
-
- if (!strlen($value)) { return false; }
-
- switch ($filter) {
- case 'add':
- // Check for a range, if no range default to gt
- if (strpos($value,'/')) {
- $elements = explode('/',$value);
- self::$browse->set_filter('add_lt',strtotime($elements['1']));
- self::$browse->set_filter('add_gt',strtotime($elements['0']));
- }
- else {
- self::$browse->set_filter('add_gt',strtotime($value));
- }
- break;
- case 'update':
- // Check for a range, if no range default to gt
- if (strpos($value,'/')) {
- $elements = explode('/',$value);
- self::$browse->set_filter('update_lt',strtotime($elements['1']));
- self::$browse->set_filter('update_gt',strtotime($elements['0']));
- }
- else {
- self::$browse->set_filter('update_gt',strtotime($value));
- }
- break;
- case 'alpha_match':
- self::$browse->set_filter('alpha_match',$value);
- break;
- case 'exact_match':
- self::$browse->set_filter('exact_match',$value);
- break;
- default:
- // Rien a faire
- break;
- } // end filter
-
- return true;
-
- } // set_filter
-
- /**
- * handshake
- *
- * This is the function that handles verifying a new handshake
- * Takes a timestamp, auth key, and username.
- */
- public static function handshake($input) {
-
- $timestamp = preg_replace('/[^0-9]/', '', $input['timestamp']);
- $passphrase = $input['auth'];
- $ip = $_SERVER['REMOTE_ADDR'];
- $username = $input['user'];
- $version = $input['version'];
-
- // Log the attempt
- debug_event('API', "Handshake Attempt, IP:$ip User:$username Version:$version", 5);
-
- if (intval($version) < self::$version) {
- debug_event('API', 'Login Failed: version too old', 1);
- Error::add('api', T_('Login Failed: version too old'));
- return false;
- }
-
- // If the timestamp isn't within 30 minutes sucks to be them
- if (($timestamp < (time() - 1800)) ||
- ($timestamp > (time() + 1800))) {
- debug_event('API', 'Login Failed: timestamp out of range', 1);
- Error::add('api', T_('Login Failed: timestamp out of range'));
- return false;
- }
-
- // Grab the correct userid
- // FIXME: Does this if/else make sense with the new ACLs?
- if (!trim($username)) {
- $user_id = '-1';
- }
- else {
- $client = User::get_from_username($username);
- $user_id = $client->id;
- }
- $user_id = Dba::escape($user_id);
-
- // Log this attempt
- debug_event('API', "Login Attempt, IP:$ip Time: $timestamp User:$username ($user_id) Auth:$passphrase", 1);
-
- if (Access::check_network('api', $user_id, 5, $ip)) {
- // Now we're sure that there is an ACL line that matches
- // this user or ALL USERS, pull the user's password and
- // then see what we come out with
- $sql = "SELECT * FROM `user` WHERE `id`='$user_id'";
- $db_results = Dba::read($sql);
-
- $row = Dba::fetch_assoc($db_results);
-
- if (!$row['password']) {
- debug_event('API', 'Unable to find user with userid of ' . $user_id, 1);
- Error::add('api', T_('Invalid Username/Password'));
- return false;
- }
-
- $sha1pass = hash('sha256', $timestamp . $row['password']);
-
- if ($sha1pass === $passphrase) {
- // Create the session
- // FIXME: needs to be moved to the correct class
- $data['username'] = $client->username;
- $data['type'] = 'api';
- $data['value'] = $timestamp;
- $token = vauth::session_create($data);
-
- // Insert the token into the streamer
- Stream::insert_session($token,$client->id);
- debug_event('API', 'Login Success, passphrase matched', 1);
-
- // We need to also get the 'last update' of the
- // catalog information in an RFC 2822 Format
- $sql = "SELECT MAX(`last_update`) AS `update`,MAX(`last_add`) AS `add`, MAX(`last_clean`) AS `clean` FROM `catalog`";
- $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
-
- // Now we need to quickly get the song totals
- $sql = 'SELECT COUNT(`id`) AS `song`, ' .
- 'COUNT(DISTINCT(`album`)) AS `album`, '.
- 'COUNT(DISTINCT(`artist`)) AS `artist` ' .
- 'FROM `song`';
- $db_results = Dba::read($sql);
- $counts = Dba::fetch_assoc($db_results);
-
- // Next the video counts
- $sql = "SELECT COUNT(`id`) AS `video` FROM `video`";
- $db_results = Dba::read($sql);
- $vcounts = Dba::fetch_assoc($db_results);
-
- $sql = "SELECT COUNT(`id`) AS `playlist` FROM `playlist`";
- $db_results = Dba::read($sql);
- $playlist = Dba::fetch_assoc($db_results);
-
- $sql = "SELECT COUNT(`id`) AS `catalog` FROM `catalog` WHERE `catalog_type`='local'";
- $db_results = Dba::read($sql);
- $catalog = Dba::fetch_assoc($db_results);
-
- echo XML_Data::keyed_array(array('auth'=>$token,
- 'api'=>self::$version,
- 'session_expire'=>date("c",time()+Config::get('session_length')-60),
- 'update'=>date("c",$row['update']),
- 'add'=>date("c",$row['add']),
- 'clean'=>date("c",$row['clean']),
- 'songs'=>$counts['song'],
- 'albums'=>$counts['album'],
- 'artists'=>$counts['artist'],
- 'playlists'=>$playlist['playlist'],
- 'videos'=>$vcounts['video'],
- 'catalogs'=>$catalog['catalog']));
- return true;
- } // match
-
- } // end while
-
- debug_event('API','Login Failed, unable to match passphrase','1');
- XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password'));
-
- } // handshake
-
- /**
- * ping
- * This can be called without being authenticated, it is useful for determining if what the status
- * of the server is, and what version it is running/compatible with
- */
- public static function ping($input) {
-
- $xmldata = array('server'=>Config::get('version'),'version'=>Api::$version,'compatible'=>'350001');
-
- // Check and see if we should extend the api sessions (done if valid sess is passed)
- if (vauth::session_exists('api', $input['auth'])) {
- vauth::session_extend($input['auth']);
- $xmldata = array_merge(array('session_expire'=>date("c",time()+Config::get('session_length')-60)),$xmldata);
- }
-
- debug_event('API','Ping Received from ' . $_SERVER['REMOTE_ADDR'] . ' :: ' . $input['auth'],'5');
-
- ob_end_clean();
- echo XML_Data::keyed_array($xmldata);
-
- } // ping
-
- /**
- * artists
- * This takes a collection of inputs and returns
- * artist objects. This function is deprecated!
- * //DEPRECATED
- */
- public static function artists($input) {
-
- self::$browse->reset_filters();
- self::$browse->set_type('artist');
- self::$browse->set_sort('name','ASC');
-
- $method = $input['exact'] ? 'exact_match' : 'alpha_match';
- Api::set_filter($method,$input['filter']);
- Api::set_filter('add',$input['add']);
- Api::set_filter('update',$input['update']);
-
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
-
- $artists = self::$browse->get_objects();
- // echo out the resulting xml document
- ob_end_clean();
- echo XML_Data::artists($artists);
-
- } // artists
-
- /**
- * artist
- * This returns a single artist based on the UID of said artist
- * //DEPRECATED
- */
- public static function artist($input) {
-
- $uid = scrub_in($input['filter']);
- echo XML_Data::artists(array($uid));
-
- } // artist
-
- /**
- * artist_albums
- * This returns the albums of an artist
- */
- public static function artist_albums($input) {
-
- $artist = new Artist($input['filter']);
-
- $albums = $artist->get_albums();
-
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::albums($albums);
-
- } // artist_albums
-
- /**
- * artist_songs
- * This returns the songs of the specified artist
- */
- public static function artist_songs($input) {
+ public static $version = '350001';
+
+ private static $browse = null;
+
+ /**
+ * constructor
+ * This really isn't anything to do here, so it's private
+ */
+ private function __construct() {
+
+ // Rien a faire
+
+ } // constructor
+
+ /**
+ * _auto_init
+ * Automatically called when this class is loaded.
+ */
+ public static function _auto_init() {
+ if (is_null(self::$browse)) {
+ self::$browse = new Browse();
+ }
+ }
+
+ /**
+ * set_filter
+ * This is a play on the browse function, it's different as we expose
+ * the filters in a slightly different and vastly simpler way to the
+ * end users--so we have to do a little extra work to make them work
+ * internally.
+ */
+ public static function set_filter($filter,$value) {
+
+ if (!strlen($value)) { return false; }
+
+ switch ($filter) {
+ case 'add':
+ // Check for a range, if no range default to gt
+ if (strpos($value,'/')) {
+ $elements = explode('/',$value);
+ self::$browse->set_filter('add_lt',strtotime($elements['1']));
+ self::$browse->set_filter('add_gt',strtotime($elements['0']));
+ }
+ else {
+ self::$browse->set_filter('add_gt',strtotime($value));
+ }
+ break;
+ case 'update':
+ // Check for a range, if no range default to gt
+ if (strpos($value,'/')) {
+ $elements = explode('/',$value);
+ self::$browse->set_filter('update_lt',strtotime($elements['1']));
+ self::$browse->set_filter('update_gt',strtotime($elements['0']));
+ }
+ else {
+ self::$browse->set_filter('update_gt',strtotime($value));
+ }
+ break;
+ case 'alpha_match':
+ self::$browse->set_filter('alpha_match',$value);
+ break;
+ case 'exact_match':
+ self::$browse->set_filter('exact_match',$value);
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end filter
+
+ return true;
+
+ } // set_filter
+
+ /**
+ * handshake
+ *
+ * This is the function that handles verifying a new handshake
+ * Takes a timestamp, auth key, and username.
+ */
+ public static function handshake($input) {
+
+ $timestamp = preg_replace('/[^0-9]/', '', $input['timestamp']);
+ $passphrase = $input['auth'];
+ $ip = $_SERVER['REMOTE_ADDR'];
+ $username = $input['user'];
+ $version = $input['version'];
+
+ // Log the attempt
+ debug_event('API', "Handshake Attempt, IP:$ip User:$username Version:$version", 5);
+
+ if (intval($version) < self::$version) {
+ debug_event('API', 'Login Failed: version too old', 1);
+ Error::add('api', T_('Login Failed: version too old'));
+ return false;
+ }
+
+ // If the timestamp isn't within 30 minutes sucks to be them
+ if (($timestamp < (time() - 1800)) ||
+ ($timestamp > (time() + 1800))) {
+ debug_event('API', 'Login Failed: timestamp out of range', 1);
+ Error::add('api', T_('Login Failed: timestamp out of range'));
+ return false;
+ }
+
+ // Grab the correct userid
+ // FIXME: Does this if/else make sense with the new ACLs?
+ if (!trim($username)) {
+ $user_id = '-1';
+ }
+ else {
+ $client = User::get_from_username($username);
+ $user_id = $client->id;
+ }
+ $user_id = Dba::escape($user_id);
+
+ // Log this attempt
+ debug_event('API', "Login Attempt, IP:$ip Time: $timestamp User:$username ($user_id) Auth:$passphrase", 1);
+
+ if (Access::check_network('api', $user_id, 5, $ip)) {
+ // Now we're sure that there is an ACL line that matches
+ // this user or ALL USERS, pull the user's password and
+ // then see what we come out with
+ $sql = "SELECT * FROM `user` WHERE `id`='$user_id'";
+ $db_results = Dba::read($sql);
+
+ $row = Dba::fetch_assoc($db_results);
+
+ if (!$row['password']) {
+ debug_event('API', 'Unable to find user with userid of ' . $user_id, 1);
+ Error::add('api', T_('Invalid Username/Password'));
+ return false;
+ }
+
+ $sha1pass = hash('sha256', $timestamp . $row['password']);
+
+ if ($sha1pass === $passphrase) {
+ // Create the session
+ // FIXME: needs to be moved to the correct class
+ $data['username'] = $client->username;
+ $data['type'] = 'api';
+ $data['value'] = $timestamp;
+ $token = vauth::session_create($data);
+
+ // Insert the token into the streamer
+ Stream::insert_session($token,$client->id);
+ debug_event('API', 'Login Success, passphrase matched', 1);
+
+ // We need to also get the 'last update' of the
+ // catalog information in an RFC 2822 Format
+ $sql = "SELECT MAX(`last_update`) AS `update`,MAX(`last_add`) AS `add`, MAX(`last_clean`) AS `clean` FROM `catalog`";
+ $db_results = Dba::read($sql);
+ $row = Dba::fetch_assoc($db_results);
+
+ // Now we need to quickly get the song totals
+ $sql = 'SELECT COUNT(`id`) AS `song`, ' .
+ 'COUNT(DISTINCT(`album`)) AS `album`, '.
+ 'COUNT(DISTINCT(`artist`)) AS `artist` ' .
+ 'FROM `song`';
+ $db_results = Dba::read($sql);
+ $counts = Dba::fetch_assoc($db_results);
+
+ // Next the video counts
+ $sql = "SELECT COUNT(`id`) AS `video` FROM `video`";
+ $db_results = Dba::read($sql);
+ $vcounts = Dba::fetch_assoc($db_results);
+
+ $sql = "SELECT COUNT(`id`) AS `playlist` FROM `playlist`";
+ $db_results = Dba::read($sql);
+ $playlist = Dba::fetch_assoc($db_results);
+
+ $sql = "SELECT COUNT(`id`) AS `catalog` FROM `catalog` WHERE `catalog_type`='local'";
+ $db_results = Dba::read($sql);
+ $catalog = Dba::fetch_assoc($db_results);
+
+ echo XML_Data::keyed_array(array('auth'=>$token,
+ 'api'=>self::$version,
+ 'session_expire'=>date("c",time()+Config::get('session_length')-60),
+ 'update'=>date("c",$row['update']),
+ 'add'=>date("c",$row['add']),
+ 'clean'=>date("c",$row['clean']),
+ 'songs'=>$counts['song'],
+ 'albums'=>$counts['album'],
+ 'artists'=>$counts['artist'],
+ 'playlists'=>$playlist['playlist'],
+ 'videos'=>$vcounts['video'],
+ 'catalogs'=>$catalog['catalog']));
+ return true;
+ } // match
+
+ } // end while
+
+ debug_event('API','Login Failed, unable to match passphrase','1');
+ XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password'));
+
+ } // handshake
+
+ /**
+ * ping
+ * This can be called without being authenticated, it is useful for determining if what the status
+ * of the server is, and what version it is running/compatible with
+ */
+ public static function ping($input) {
+
+ $xmldata = array('server'=>Config::get('version'),'version'=>Api::$version,'compatible'=>'350001');
+
+ // Check and see if we should extend the api sessions (done if valid sess is passed)
+ if (vauth::session_exists('api', $input['auth'])) {
+ vauth::session_extend($input['auth']);
+ $xmldata = array_merge(array('session_expire'=>date("c",time()+Config::get('session_length')-60)),$xmldata);
+ }
+
+ debug_event('API','Ping Received from ' . $_SERVER['REMOTE_ADDR'] . ' :: ' . $input['auth'],'5');
+
+ ob_end_clean();
+ echo XML_Data::keyed_array($xmldata);
+
+ } // ping
+
+ /**
+ * artists
+ * This takes a collection of inputs and returns
+ * artist objects. This function is deprecated!
+ * //DEPRECATED
+ */
+ public static function artists($input) {
+
+ self::$browse->reset_filters();
+ self::$browse->set_type('artist');
+ self::$browse->set_sort('name','ASC');
+
+ $method = $input['exact'] ? 'exact_match' : 'alpha_match';
+ Api::set_filter($method,$input['filter']);
+ Api::set_filter('add',$input['add']);
+ Api::set_filter('update',$input['update']);
+
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
+
+ $artists = self::$browse->get_objects();
+ // echo out the resulting xml document
+ ob_end_clean();
+ echo XML_Data::artists($artists);
+
+ } // artists
+
+ /**
+ * artist
+ * This returns a single artist based on the UID of said artist
+ * //DEPRECATED
+ */
+ public static function artist($input) {
+
+ $uid = scrub_in($input['filter']);
+ echo XML_Data::artists(array($uid));
+
+ } // artist
+
+ /**
+ * artist_albums
+ * This returns the albums of an artist
+ */
+ public static function artist_albums($input) {
+
+ $artist = new Artist($input['filter']);
+
+ $albums = $artist->get_albums();
+
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
+ ob_end_clean();
+ echo XML_Data::albums($albums);
+
+ } // artist_albums
+
+ /**
+ * artist_songs
+ * This returns the songs of the specified artist
+ */
+ public static function artist_songs($input) {
- $artist = new Artist($input['filter']);
- $songs = $artist->get_songs();
+ $artist = new Artist($input['filter']);
+ $songs = $artist->get_songs();
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::songs($songs);
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
+ ob_end_clean();
+ echo XML_Data::songs($songs);
- } // artist_songs
+ } // artist_songs
- /**
- * albums
- * This returns albums based on the provided search filters
- */
- public static function albums($input) {
+ /**
+ * albums
+ * This returns albums based on the provided search filters
+ */
+ public static function albums($input) {
- self::$browse->reset_filters();
- self::$browse->set_type('album');
- self::$browse->set_sort('name','ASC');
- $method = $input['exact'] ? 'exact_match' : 'alpha_match';
- Api::set_filter($method,$input['filter']);
- Api::set_filter('add',$input['add']);
- Api::set_filter('update',$input['update']);
+ self::$browse->reset_filters();
+ self::$browse->set_type('album');
+ self::$browse->set_sort('name','ASC');
+ $method = $input['exact'] ? 'exact_match' : 'alpha_match';
+ Api::set_filter($method,$input['filter']);
+ Api::set_filter('add',$input['add']);
+ Api::set_filter('update',$input['update']);
- $albums = self::$browse->get_objects();
+ $albums = self::$browse->get_objects();
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::albums($albums);
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
+ ob_end_clean();
+ echo XML_Data::albums($albums);
- } // albums
+ } // albums
- /**
- * album
- * This returns a single album based on the UID provided
- */
- public static function album($input) {
+ /**
+ * album
+ * This returns a single album based on the UID provided
+ */
+ public static function album($input) {
- $uid = scrub_in($input['filter']);
- echo XML_Data::albums(array($uid));
+ $uid = scrub_in($input['filter']);
+ echo XML_Data::albums(array($uid));
- } // album
+ } // album
- /**
- * album_songs
- * This returns the songs of a specified album
- */
- public static function album_songs($input) {
+ /**
+ * album_songs
+ * This returns the songs of a specified album
+ */
+ public static function album_songs($input) {
- $album = new Album($input['filter']);
- $songs = $album->get_songs();
+ $album = new Album($input['filter']);
+ $songs = $album->get_songs();
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::songs($songs);
+ ob_end_clean();
+ echo XML_Data::songs($songs);
- } // album_songs
+ } // album_songs
- /**
- * tags
- * This returns the tags based on the specified filter
- */
- public static function tags($input) {
+ /**
+ * tags
+ * This returns the tags based on the specified filter
+ */
+ public static function tags($input) {
- self::$browse->reset_filters();
- self::$browse->set_type('tag');
- self::$browse->set_sort('name','ASC');
+ self::$browse->reset_filters();
+ self::$browse->set_type('tag');
+ self::$browse->set_sort('name','ASC');
- $method = $input['exact'] ? 'exact_match' : 'alpha_match';
- Api::set_filter($method,$input['filter']);
- $tags = self::$browse->get_objects();
+ $method = $input['exact'] ? 'exact_match' : 'alpha_match';
+ Api::set_filter($method,$input['filter']);
+ $tags = self::$browse->get_objects();
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::tags($tags);
+ ob_end_clean();
+ echo XML_Data::tags($tags);
- } // tags
+ } // tags
- /**
- * tag
- * This returns a single tag based on UID
- */
- public static function tag($input) {
+ /**
+ * tag
+ * This returns a single tag based on UID
+ */
+ public static function tag($input) {
- $uid = scrub_in($input['filter']);
- ob_end_clean();
- echo XML_Data::tags(array($uid));
+ $uid = scrub_in($input['filter']);
+ ob_end_clean();
+ echo XML_Data::tags(array($uid));
- } // tag
+ } // tag
- /**
- * tag_artists
- * This returns the artists associated with the tag in question as defined by the UID
- */
- public static function tag_artists($input) {
+ /**
+ * tag_artists
+ * This returns the artists associated with the tag in question as defined by the UID
+ */
+ public static function tag_artists($input) {
- $artists = Tag::get_tag_objects('artist',$input['filter']);
+ $artists = Tag::get_tag_objects('artist',$input['filter']);
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::artists($artists);
+ ob_end_clean();
+ echo XML_Data::artists($artists);
- } // tag_artists
+ } // tag_artists
- /**
- * tag_albums
- * This returns the albums associated with the tag in question
- */
- public static function tag_albums($input) {
+ /**
+ * tag_albums
+ * This returns the albums associated with the tag in question
+ */
+ public static function tag_albums($input) {
- $albums = Tag::get_tag_objects('album',$input['filter']);
+ $albums = Tag::get_tag_objects('album',$input['filter']);
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::albums($albums);
+ ob_end_clean();
+ echo XML_Data::albums($albums);
- } // tag_albums
+ } // tag_albums
- /**
- * tag_songs
- * returns the songs for this tag
- */
- public static function tag_songs($input) {
+ /**
+ * tag_songs
+ * returns the songs for this tag
+ */
+ public static function tag_songs($input) {
- $songs = Tag::get_tag_objects('song',$input['filter']);
+ $songs = Tag::get_tag_objects('song',$input['filter']);
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::songs($songs);
+ ob_end_clean();
+ echo XML_Data::songs($songs);
- } // tag_songs
+ } // tag_songs
- /**
- * songs
- * Returns songs based on the specified filter
- */
- public static function songs($input) {
+ /**
+ * songs
+ * Returns songs based on the specified filter
+ */
+ public static function songs($input) {
- self::$browse->reset_filters();
- self::$browse->set_type('song');
- self::$browse->set_sort('title','ASC');
+ self::$browse->reset_filters();
+ self::$browse->set_type('song');
+ self::$browse->set_sort('title','ASC');
- $method = $input['exact'] ? 'exact_match' : 'alpha_match';
- Api::set_filter($method,$input['filter']);
- Api::set_filter('add',$input['add']);
- Api::set_filter('update',$input['update']);
+ $method = $input['exact'] ? 'exact_match' : 'alpha_match';
+ Api::set_filter($method,$input['filter']);
+ Api::set_filter('add',$input['add']);
+ Api::set_filter('update',$input['update']);
- $songs = self::$browse->get_objects();
+ $songs = self::$browse->get_objects();
- // Set the offset
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ // Set the offset
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::songs($songs);
+ ob_end_clean();
+ echo XML_Data::songs($songs);
- } // songs
+ } // songs
- /**
- * song
- * returns a single song
- */
- public static function song($input) {
+ /**
+ * song
+ * returns a single song
+ */
+ public static function song($input) {
- $uid = scrub_in($input['filter']);
+ $uid = scrub_in($input['filter']);
- ob_end_clean();
- echo XML_Data::songs(array($uid));
+ ob_end_clean();
+ echo XML_Data::songs(array($uid));
- } // song
+ } // song
- /**
- * url_to_song
- * This takes a url and returns the song object in question
- */
- public static function url_to_song($input) {
+ /**
+ * url_to_song
+ * This takes a url and returns the song object in question
+ */
+ public static function url_to_song($input) {
- // Don't scrub, the function needs her raw and juicy
- $song_id = Song::parse_song_url($input['url']);
+ // Don't scrub, the function needs her raw and juicy
+ $song_id = Song::parse_song_url($input['url']);
- ob_end_clean();
- echo XML_Data::songs(array($song_id));
+ ob_end_clean();
+ echo XML_Data::songs(array($song_id));
- } // url_to_song
+ } // url_to_song
- /**
- * playlists
- * This returns playlists based on the specified filter
- */
- public static function playlists($input) {
+ /**
+ * playlists
+ * This returns playlists based on the specified filter
+ */
+ public static function playlists($input) {
- self::$browse->reset_filters();
- self::$browse->set_type('playlist');
- self::$browse->set_sort('name','ASC');
+ self::$browse->reset_filters();
+ self::$browse->set_type('playlist');
+ self::$browse->set_sort('name','ASC');
- $method = $input['exact'] ? 'exact_match' : 'alpha_match';
- Api::set_filter($method,$input['filter']);
+ $method = $input['exact'] ? 'exact_match' : 'alpha_match';
+ Api::set_filter($method,$input['filter']);
- $playlist_ids = self::$browse->get_objects();
+ $playlist_ids = self::$browse->get_objects();
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::playlists($playlist_ids);
+ ob_end_clean();
+ echo XML_Data::playlists($playlist_ids);
- } // playlists
+ } // playlists
- /**
- * playlist
- * This returns a single playlist
- */
- public static function playlist($input) {
+ /**
+ * playlist
+ * This returns a single playlist
+ */
+ public static function playlist($input) {
- $uid = scrub_in($input['filter']);
+ $uid = scrub_in($input['filter']);
- ob_end_clean();
- echo XML_Data::playlists(array($uid));
+ ob_end_clean();
+ echo XML_Data::playlists(array($uid));
- } // playlist
+ } // playlist
- /**
- * playlist_songs
- * This returns the songs for a playlist
- */
- public static function playlist_songs($input) {
+ /**
+ * playlist_songs
+ * This returns the songs for a playlist
+ */
+ public static function playlist_songs($input) {
- $playlist = new Playlist($input['filter']);
- $items = $playlist->get_items();
+ $playlist = new Playlist($input['filter']);
+ $items = $playlist->get_items();
- foreach ($items as $object) {
- if ($object['object_type'] == 'song') {
- $songs[] = $object['object_id'];
- }
- } // end foreach
+ foreach ($items as $object) {
+ if ($object['object_type'] == 'song') {
+ $songs[] = $object['object_id'];
+ }
+ } // end foreach
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
- ob_end_clean();
- echo XML_Data::songs($songs);
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
+ ob_end_clean();
+ echo XML_Data::songs($songs);
- } // playlist_songs
+ } // playlist_songs
- /**
- * search_songs
- * This searches the songs and returns... songs
- */
- public static function search_songs($input) {
- $array['type'] = 'song';
- $array['rule_1'] = 'anywhere';
- $array['rule_1_input'] = $input['filter'];
- $array['rule_1_operator'] = 0;
+ /**
+ * search_songs
+ * This searches the songs and returns... songs
+ */
+ public static function search_songs($input) {
+ $array['type'] = 'song';
+ $array['rule_1'] = 'anywhere';
+ $array['rule_1_input'] = $input['filter'];
+ $array['rule_1_operator'] = 0;
- ob_end_clean();
+ ob_end_clean();
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
- $results = Search::run($array);
-
- echo XML_Data::songs($results);
+ $results = Search::run($array);
+
+ echo XML_Data::songs($results);
- } // search_songs
+ } // search_songs
- /**
- * videos
- * This returns video objects!
- */
- public static function videos($input) {
-
- self::$browse->reset_filters();
- self::$browse->set_type('video');
- self::$browse->set_sort('title','ASC');
-
- $method = $input['exact'] ? 'exact_match' : 'alpha_match';
- Api::set_filter($method,$input['filter']);
-
- $video_ids = self::$browse->get_objects();
-
- XML_Data::set_offset($input['offset']);
- XML_Data::set_limit($input['limit']);
-
- echo XML_Data::videos($video_ids);
-
- } // videos
-
- /**
- * video
- * This returns a single video
- */
- public static function video($input) {
-
- $video_id = scrub_in($input['filter']);
-
- echo XML_Data::videos(array($video_id));
-
-
- } // video
-
- /**
- * localplay
- * This is for controling localplay
- */
- public static function localplay($input) {
-
- // Load their localplay instance
- $localplay = new Localplay(Config::get('localplay_controller'));
- $localplay->connect();
-
- switch ($input['command']) {
- case 'next':
- case 'prev':
- case 'play':
- case 'stop':
- $result_status = $localplay->$input['command']();
- $xml_array = array('localplay'=>array('command'=>array($input['command']=>make_bool($result_status))));
- echo XML_Data::keyed_array($xml_array);
- break;
- default:
- // They are doing it wrong
- echo XML_Data::error('405', T_('Invalid Request'));
- break;
- } // end switch on command
-
- } // localplay
-
- /**
- * democratic
- * This is for controlling democratic play
- */
- public static function democratic($input) {
-
- // Load up democratic information
- $democratic = Democratic::get_current_playlist();
- $democratic->set_parent();
-
- switch ($input['method']) {
- case 'vote':
- $type = 'song';
- $media = new $type($input['oid']);
- if (!$media->id) {
- echo XML_Data::error('400', T_('Media Object Invalid or Not Specified'));
- break;
- }
- $democratic->add_vote(array(
- array(
- 'object_type' => 'song',
- 'object_id' => $media->id
- )
- ));
-
- // If everything was ok
- $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true);
- echo XML_Data::keyed_array($xml_array);
- break;
- case 'devote':
- $type = 'song';
- $media = new $type($input['oid']);
- if (!$media->id) {
- echo XML_Data::error('400', T_('Media Object Invalid or Not Specified'));
- }
-
- $uid = $democratic->get_uid_from_object_id($media->id,$type);
- $democratic->remove_vote($uid);
-
- // Everything was ok
- $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true);
- echo XML_Data::keyed_array($xml_array);
- break;
- case 'playlist':
- $objects = $democratic->get_items();
- Song::build_cache($democratic->object_ids);
- Democratic::build_vote_cache($democratic->vote_ids);
- XML_Data::democratic($objects);
- break;
- case 'play':
- $url = $democratic->play_url();
- $xml_array = array('url'=>$url);
- echo XML_Data::keyed_array($xml_array);
- break;
- default:
- echo XML_Data::error('405', T_('Invalid Request'));
- break;
- } // switch on method
-
- } // democratic
+ /**
+ * videos
+ * This returns video objects!
+ */
+ public static function videos($input) {
+
+ self::$browse->reset_filters();
+ self::$browse->set_type('video');
+ self::$browse->set_sort('title','ASC');
+
+ $method = $input['exact'] ? 'exact_match' : 'alpha_match';
+ Api::set_filter($method,$input['filter']);
+
+ $video_ids = self::$browse->get_objects();
+
+ XML_Data::set_offset($input['offset']);
+ XML_Data::set_limit($input['limit']);
+
+ echo XML_Data::videos($video_ids);
+
+ } // videos
+
+ /**
+ * video
+ * This returns a single video
+ */
+ public static function video($input) {
+
+ $video_id = scrub_in($input['filter']);
+
+ echo XML_Data::videos(array($video_id));
+
+
+ } // video
+
+ /**
+ * localplay
+ * This is for controling localplay
+ */
+ public static function localplay($input) {
+
+ // Load their localplay instance
+ $localplay = new Localplay(Config::get('localplay_controller'));
+ $localplay->connect();
+
+ switch ($input['command']) {
+ case 'next':
+ case 'prev':
+ case 'play':
+ case 'stop':
+ $result_status = $localplay->$input['command']();
+ $xml_array = array('localplay'=>array('command'=>array($input['command']=>make_bool($result_status))));
+ echo XML_Data::keyed_array($xml_array);
+ break;
+ default:
+ // They are doing it wrong
+ echo XML_Data::error('405', T_('Invalid Request'));
+ break;
+ } // end switch on command
+
+ } // localplay
+
+ /**
+ * democratic
+ * This is for controlling democratic play
+ */
+ public static function democratic($input) {
+
+ // Load up democratic information
+ $democratic = Democratic::get_current_playlist();
+ $democratic->set_parent();
+
+ switch ($input['method']) {
+ case 'vote':
+ $type = 'song';
+ $media = new $type($input['oid']);
+ if (!$media->id) {
+ echo XML_Data::error('400', T_('Media Object Invalid or Not Specified'));
+ break;
+ }
+ $democratic->add_vote(array(
+ array(
+ 'object_type' => 'song',
+ 'object_id' => $media->id
+ )
+ ));
+
+ // If everything was ok
+ $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true);
+ echo XML_Data::keyed_array($xml_array);
+ break;
+ case 'devote':
+ $type = 'song';
+ $media = new $type($input['oid']);
+ if (!$media->id) {
+ echo XML_Data::error('400', T_('Media Object Invalid or Not Specified'));
+ }
+
+ $uid = $democratic->get_uid_from_object_id($media->id,$type);
+ $democratic->remove_vote($uid);
+
+ // Everything was ok
+ $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true);
+ echo XML_Data::keyed_array($xml_array);
+ break;
+ case 'playlist':
+ $objects = $democratic->get_items();
+ Song::build_cache($democratic->object_ids);
+ Democratic::build_vote_cache($democratic->vote_ids);
+ XML_Data::democratic($objects);
+ break;
+ case 'play':
+ $url = $democratic->play_url();
+ $xml_array = array('url'=>$url);
+ echo XML_Data::keyed_array($xml_array);
+ break;
+ default:
+ echo XML_Data::error('405', T_('Invalid Request'));
+ break;
+ } // switch on method
+
+ } // democratic
} // API class
?>
diff --git a/lib/class/art.class.php b/lib/class/art.class.php
index 0e23463f..4b896e7f 100644
--- a/lib/class/art.class.php
+++ b/lib/class/art.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,1184 +29,1184 @@
*/
class Art extends database_object {
- public $type;
- public $uid; // UID of the object not ID because it's not the ART.ID
- public $raw; // Raw art data
- public $raw_mime;
-
- public $thumb;
- public $thumb_mime;
-
- private static $enabled;
-
- /**
- * Constructor
- * Art constructor, takes the UID of the object and the
- * object type.
- */
- public function __construct($uid, $type = 'album') {
-
- $this->type = Art::validate_type($type);
- $this->uid = $uid;
-
- } // constructor
-
- /**
- * build_cache
- * This attempts to reduce # of queries by asking for everything in the
- * browse all at once and storing it in the cache, this can help if the
- * db connection is the slow point
- */
- public static function build_cache($object_ids) {
-
- if (!is_array($object_ids) || !count($object_ids)) { return false; }
- $uidlist = '(' . implode(',', $object_ids) . ')';
- $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_id` IN $uidlist";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('art', $row['object_type'] .
- $row['object_id'] . $row['size'], $row);
- }
-
- return true;
- } // build_cache
-
-
- /**
- * _auto_init
- * Called on creation of the class
- */
- public static function _auto_init() {
- if (!isset($_SESSION['art_enabled'])) {
- $_SESSION['art_enabled'] = (Config::get('bandwidth') > 25);
- }
- self::$enabled = make_bool($_SESSION['art_enabled']);
- }
-
- /**
- * is_enabled
- * Checks whether the user currently wants art
- */
- public static function is_enabled() {
- if (self::$enabled) {
- return true;
- }
-
- return false;
- }
-
- /**
- * set_enabled
- * Changes the value of enabled
- */
- public static function set_enabled($value = null) {
- if (is_null($value)) {
- self::$enabled = self::$enabled ? false : true;
- }
- else {
- self::$enabled = make_bool($value);
- }
-
- $_SESSION['art_enabled'] = self::$enabled;
- }
-
- /**
- * validate_type
- * This validates the type
- */
- public static function validate_type($type) {
-
- switch ($type) {
- case 'album':
- case 'artist':
- case 'video':
- return $type;
- break;
- default:
- return 'album';
- break;
- }
-
- } // validate_type
-
- /**
- * extension
- * This returns the file extension for the currently loaded art
- */
- public static function extension($mime) {
-
- $data = explode("/", $mime);
- $extension = $data['1'];
-
- if ($extension == 'jpeg') { $extension = 'jpg'; }
-
- return $extension;
-
- } // extension
-
- /**
- * test_image
- * Runs some sanity checks on the putative image
- */
- public static function test_image($source) {
- if (strlen($source) < 10) {
- debug_event('Art', 'Invalid image passed', 1);
- return false;
- }
-
- // Check to make sure PHP:GD exists. If so, we can sanity check
- // the image.
- if (function_exists('ImageCreateFromString')) {
- $image = ImageCreateFromString($source);
- if (!$image || imagesx($image) < 5 || imagesy($image) < 5) {
- debug_event('Art', 'Image failed PHP-GD test',1);
- return false;
- }
- }
-
- return true;
- } //test_image
-
- /**
- * get
- * This returns the art for our current object, this can
- * look in the database and will return the thumb if it
- * exists, if it doesn't depending on settings it will try
- * to create it.
- */
- public function get($raw=false) {
-
- // Get the data either way
- if (!$this->get_db()) {
- return false;
- }
-
- if ($raw || !$this->thumb) {
- return $this->raw;
- }
- else {
- return $this->thumb;
- }
-
- } // get
-
-
- /**
- * get_db
- * This pulls the information out from the database, depending
- * on if we want to resize and if there is not a thumbnail go
- * ahead and try to resize
- */
- public function get_db() {
-
- $type = Dba::escape($this->type);
- $id = Dba::escape($this->uid);
-
- $sql = "SELECT `image`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$id'";
- $db_results = Dba::read($sql);
-
- while ($results = Dba::fetch_assoc($db_results)) {
- if ($results['size'] == 'original') {
- $this->raw = $results['image'];
- $this->raw_mime = $results['mime'];
- }
- else if (Config::get('resize_images') &&
- $results['size'] == '275x275') {
- $this->thumb = $results['image'];
- $this->raw_mime = $results['mime'];
- }
- }
- // If we get nothing return false
- if (!$this->raw) { return false; }
-
- // If there is no thumb and we want thumbs
- if (!$this->thumb && Config::get('resize_images')) {
- $data = $this->generate_thumb($this->raw, array('width' => 275, 'height' => 275), $this->raw_mime);
- // If it works save it!
- if ($data) {
- $this->save_thumb($data['thumb'], $data['thumb_mime'], '275x275');
- $this->thumb = $data['thumb'];
- $this->thumb_mime = $data['thumb_mime'];
- }
- else {
- debug_event('Art','Unable to retrieve or generate thumbnail for ' . $type . '::' . $id,1);
- }
- } // if no thumb, but art and we want to resize
-
- return true;
-
- } // get_db
-
- /**
- * insert
- * This takes the string representation of an image and inserts it into
- * the database. You must also pass the mime type.
- */
- public function insert($source, $mime) {
-
- // Disabled in demo mode cause people suck and upload porn
- if (Config::get('demo_mode')) { return false; }
-
- // Check to make sure we like this image
- if (!self::test_image($source)) {
- debug_event('Art', 'Not inserting image, invalid data passed', 1);
- return false;
- }
-
- // Default to image/jpeg if they don't pass anything
- $mime = $mime ? $mime : 'image/jpeg';
-
- $image = Dba::escape($source);
- $mime = Dba::escape($mime);
- $uid = Dba::escape($this->uid);
- $type = Dba::escape($this->type);
-
- // Blow it away!
- $this->reset();
-
- // Insert it!
- $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$image', '$mime', 'original', '$type', '$uid')";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // insert
-
- /**
- * reset
- * This resets the art in the database
- */
- public function reset() {
-
- $type = Dba::escape($this->type);
- $uid = Dba::escape($this->uid);
-
- $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type'";
- $db_results = Dba::write($sql);
-
- } // reset
-
- /**
- * save_thumb
- * This saves the thumbnail that we're passed
- */
- public function save_thumb($source, $mime, $size) {
-
- // Quick sanity check
- if (!self::test_image($source)) {
- debug_event('Art', 'Not inserting thumbnail, invalid data passed', 1);
- return false;
- }
-
- $source = Dba::escape($source);
- $mime = Dba::escape($mime);
- $size = Dba::escape($size);
- $uid = Dba::escape($this->uid);
- $type = Dba::escape($this->type);
-
- $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type' AND `size`='$size'";
- $db_results = Dba::write($sql);
-
- $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$source', '$mime', '$size', '$type', '$uid')";
- $db_results = Dba::write($sql);
-
- } // save_thumb
-
- /**
- * get_thumb
- * Returns the specified resized image. If the requested size doesn't
- * already exist, create and cache it.
- */
- public function get_thumb($size) {
- $sizetext = $size['width'] . 'x' . $size['height'];
- $sizetext = Dba::escape($sizetext);
- $type = Dba::escape($this->type);
- $uid = Dba::escape($this->uid);
-
- $sql = "SELECT `image`, `mime` FROM `image` WHERE `size`='$sizetext' AND `object_type`='$type' AND `object_id`='$uid'";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
- if (count($results)) {
- return array('thumb' => $results['image'],
- 'thumb_mime' => $results['mime']);
- }
-
- // If we didn't get a result
- $results = $this->generate_thumb($this->raw, $size, $this->raw_mime);
- if ($results) {
- $this->save_thumb($results['thumb'], $results['thumb_mime'], $sizetext);
- }
-
- return $results;
- } // get_thumb
-
- /**
- * generate_thumb
- * Automatically resizes the image for thumbnail viewing.
- * Only works on gif/jpg/png/bmp. Fails if PHP-GD isn't available
- * or lacks support for the requested image type.
- */
- public function generate_thumb($image,$size,$mime) {
-
- $data = explode("/",$mime);
- $type = strtolower($data['1']);
-
- if (!self::test_image($image)) {
- debug_event('Art', 'Not trying to generate thumbnail, invalid data passed', 1);
- return false;
- }
-
- if (!function_exists('gd_info')) {
- debug_event('Art','PHP-GD Not found - unable to resize art',1);
- return false;
- }
-
- // Check and make sure we can resize what you've asked us to
- if (($type == 'jpg' OR $type == 'jpeg') AND !(imagetypes() & IMG_JPG)) {
- debug_event('Art','PHP-GD Does not support JPGs - unable to resize',1);
- return false;
- }
- if ($type == 'png' AND !imagetypes() & IMG_PNG) {
- debug_event('Art','PHP-GD Does not support PNGs - unable to resize',1);
- return false;
- }
- if ($type == 'gif' AND !imagetypes() & IMG_GIF) {
- debug_event('Art','PHP-GD Does not support GIFs - unable to resize',1);
- return false;
- }
- if ($type == 'bmp' AND !imagetypes() & IMG_WBMP) {
- debug_event('Art','PHP-GD Does not support BMPs - unable to resize',1);
- return false;
- }
-
- $source = imagecreatefromstring($image);
-
- if (!$source) {
- debug_event('Art','Failed to create Image from string - Source Image is damaged / malformed',1);
- return false;
- }
-
- $source_size = array('height' => imagesy($source), 'width' => imagesx($source));
-
- // Create a new blank image of the correct size
- $thumbnail = imagecreatetruecolor($size['width'], $size['height']);
-
- if (!imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $size['width'], $size['height'], $source_size['width'], $source_size['height'])) {
- debug_event('Art','Unable to create resized image',1);
- return false;
- }
-
- // Start output buffer
- ob_start();
-
- // Generate the image to our OB
- switch ($type) {
- case 'jpg':
- case 'jpeg':
- imagejpeg($thumbnail, null, 75);
- $mime_type = image_type_to_mime_type(IMAGETYPE_JPEG);
- break;
- case 'gif':
- imagegif($thumbnail);
- $mime_type = image_type_to_mime_type(IMAGETYPE_GIF);
- break;
- // Turn bmps into pngs
- case 'bmp':
- $type = 'png';
- case 'png':
- imagepng($thumbnail);
- $mime_type = image_type_to_mime_type(IMAGETYPE_PNG);
- break;
- } // resized
-
- $data = ob_get_contents();
- ob_end_clean();
-
- if (!strlen($data)) {
- debug_event('Art', 'Unknown Error resizing art', 1);
- return false;
- }
-
- return array('thumb' => $data, 'thumb_mime' => $mime_type);
-
- } // generate_thumb
-
- /**
- * get_from_source
- * This gets an image for the album art from a source as
- * defined in the passed array. Because we don't know where
- * it's coming from we are a passed an array that can look like
- * ['url'] = URL *** OPTIONAL ***
- * ['file'] = FILENAME *** OPTIONAL ***
- * ['raw'] = Actual Image data, already captured
- */
- public static function get_from_source($data, $type = 'album') {
-
- // Already have the data, this often comes from id3tags
- if (isset($data['raw'])) {
- return $data['raw'];
- }
-
- // If it came from the database
- if (isset($data['db'])) {
- // Repull it
- $uid = Dba::escape($data['db']);
- $type = Dba::escape($type);
-
- $sql = "SELECT * FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid' AND `size`='original'";
- $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
- return $row['art'];
- } // came from the db
-
- // Check to see if it's a URL
- if (isset($data['url'])) {
- $snoopy = new Snoopy();
- if(Config::get('proxy_host') AND Config::get('proxy_port')) {
- $snoopy->proxy_user = Config::get('proxy_host');
- $snoopy->proxy_port = Config::get('proxy_port');
- $snoopy->proxy_user = Config::get('proxy_user');
- $snoopy->proxy_pass = Config::get('proxy_pass');
- }
- $snoopy->fetch($data['url']);
- return $snoopy->results;
- }
-
- // Check to see if it's a FILE
- if (isset($data['file'])) {
- $handle = fopen($data['file'],'rb');
- $image_data = fread($handle,filesize($data['file']));
- fclose($handle);
- return $image_data;
- }
-
- // Check to see if it is embedded in id3 of a song
- if (isset($data['song'])) {
- // If we find a good one, stop looking
- $getID3 = new getID3();
- $id3 = $getID3->analyze($data['song']);
-
- if ($id3['format_name'] == "WMA") {
- return $id3['asf']['extended_content_description_object']['content_descriptors']['13']['data'];
- }
- elseif (isset($id3['id3v2']['APIC'])) {
- // Foreach in case they have more then one
- foreach ($id3['id3v2']['APIC'] as $image) {
- return $image['data'];
- }
- }
- } // if data song
-
- return false;
-
- } // get_from_source
-
- /**
- * url
- * This returns the constructed URL for the art in question
- */
- public static function url($uid,$type,$sid=false) {
-
- $sid = $sid ? scrub_out($sid) : scrub_out(session_id());
- $type = self::validate_type($type);
-
- $key = $type . $uid;
- if (parent::is_cached('art', $key . '275x275') && Config::get('resize_images')) {
- $row = parent::get_from_cache('art', $key . '275x275');
- $mime = $row['mime'];
- }
- if (parent::is_cached('art', $key . 'original')) {
- $row = parent::get_from_cache('art', $key . 'original');
- $thumb_mime = $row['mime'];
- }
- if (!$mime && !$thumb_mime) {
-
- $type = Dba::escape($type);
- $uid = Dba::escape($uid);
-
- $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid'";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('art', $key . $row['size'], $row);
- if ($row['size'] == 'original') {
- $mime = $row['mime'];
- }
- else if ($row['size'] == '275x275' && Config::get('resize_images')) {
- $thumb_mime = $row['mime'];
- }
- }
- }
-
- $mime = $thumb_mime ? $thumb_mime : $mime;
- $extension = self::extension($mime);
-
- $name = 'art.' . $extension;
- $url = Config::get('web_path') . '/image.php?id=' . scrub_out($uid) . '&object_type=' . scrub_out($type) . '&auth=' . $sid . '&name=' . $name;
-
- return $url;
-
- } // url
-
-
- /**
- * gc
- * This cleans up art that no longer has a corresponding object
- */
- public static function gc() {
- // iterate over our types and delete the images
- foreach (array('album', 'artist') as $type) {
- $sql = "DELETE FROM `image` USING `image` LEFT JOIN `" .
- $type . "` ON `" . $type . "`.`id`=" .
- "`image`.`object_id` WHERE `object_type`='" .
- $type . "' AND `" . $type . "`.`id` IS NULL";
- $db_results = Dba::write($sql);
- } // foreach
- }
-
- /**
- * gather
- * This tries to get the art in question
- */
- public function gather($options = array(), $limit = false) {
-
- // Define vars
- $results = array();
-
- switch ($this->type) {
- case 'album':
- $allowed_methods = array('db','lastfm','folder','amazon','google','musicbrainz','tags');
- break;
- case 'artist':
- $allowed_methods = array();
- break;
- case 'video':
- $allowed_methods = array();
- break;
- }
-
- $config = Config::get('art_order');
- $methods = get_class_methods('Art');
-
- /* If it's not set */
- if (empty($config)) {
- // They don't want art!
- debug_event('Art', 'art_order is empty, skipping art gathering', 3);
- return array();
- }
- elseif (!is_array($config)) {
- $config = array($config);
- }
-
- debug_event('Art','Searching using:' . json_encode($config), 3);
-
- foreach ($config as $method) {
-
- $data = array();
-
- if (!in_array($method, $allowed_methods)) {
- debug_event('Art', "$method not in allowed_methods, skipping", 3);
- continue;
- }
-
- $method_name = "gather_" . $method;
-
- if (in_array($method_name, $methods)) {
- debug_event('Art', "Method used: $method_name", 3);
- // Some of these take options!
- switch ($method_name) {
- case 'gather_amazon':
- $data = $this->{$method_name}($limit, $options['keyword']);
- break;
- case 'gather_lastfm':
- $data = $this->{$method_name}($limit, $options);
- break;
- default:
- $data = $this->{$method_name}($limit);
- break;
- }
-
- // Add the results we got to the current set
- $results = array_merge($results, (array)$data);
-
- if ($limit && count($results) >= $limit) {
- return array_slice($results, 0, $limit);
- }
-
- } // if the method exists
- else {
- debug_event("Art", "$method_name not defined", 1);
- }
-
- } // end foreach
-
- return $results;
-
- } // gather
-
-
- ///////////////////////////////////////////////////////////////////////
- // Art Methods
- ///////////////////////////////////////////////////////////////////////
-
- /**
- * gather_db
- * This function retrieves art that's already in the database
- */
- public function gather_db($limit = null) {
- if ($this->get_db()) {
- return array('db' => true);
- }
- return array();
- }
-
- /**
- * gather_musicbrainz
- * This function retrieves art based on MusicBrainz' Advanced
- * Relationships
- */
- public function gather_musicbrainz($limit = 5) {
- $images = array();
- $num_found = 0;
-
- if ($this->type == 'album') {
- $album = new Album($this->uid);
- }
- else {
- return $images;
- }
-
- if ($album->mbid) {
- debug_event('mbz-gatherart', "Album MBID: " . $album->mbid, '5');
- }
- else {
- return $images;
- }
-
- $mbquery = new MusicBrainzQuery();
- $includes = new mbReleaseIncludes();
- try {
- $release = $mbquery->getReleaseByID($album->mbid, $includes->urlRelations());
- } catch (Exception $e) {
- return $images;
- }
-
- $asin = $release->getAsin();
-
- if ($asin) {
- debug_event('mbz-gatherart', "Found ASIN: " . $asin, '5');
- $base_urls = array(
- "01" => "ec1.images-amazon.com",
- "02" => "ec1.images-amazon.com",
- "03" => "ec2.images-amazon.com",
- "08" => "ec1.images-amazon.com",
- "09" => "ec1.images-amazon.com",
- );
- foreach ($base_urls as $server_num => $base_url) {
- // to avoid complicating things even further, we only look for large cover art
- $url = 'http://' . $base_url . '/images/P/' . $asin . '.' . $server_num . '.LZZZZZZZ.jpg';
- debug_event('mbz-gatherart', "Evaluating Amazon URL: " . $url, '5');
- $snoopy = new Snoopy();
- if(Config::get('proxy_host') AND Config::get('proxy_port')) {
- $snoopy->proxy_user = Config::get('proxy_host');
- $snoopy->proxy_port = Config::get('proxy_port');
- $snoopy->proxy_user = Config::get('proxy_user');
- $snoopy->proxy_pass = Config::get('proxy_pass');
- }
- if ($snoopy->fetch($url)) {
- $num_found++;
- debug_event('mbz-gatherart', "Amazon URL added: " . $url, '5');
- $images[] = array(
- 'url' => $url,
- 'mime' => 'image/jpeg',
- );
- if ($num_found >= $limit) {
- return $images;
- }
- }
- }
- }
- // The next bit is based directly on the MusicBrainz server code
- // that displays cover art.
- // I'm leaving in the releaseuri info for the moment, though
- // it's not going to be used.
- $coverartsites[] = array(
- 'name' => "CD Baby",
- 'domain' => "cdbaby.com",
- 'regexp' => '@http://cdbaby\.com/cd/(\w)(\w)(\w*)@',
- 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[1]$matches[2]$matches[3].jpg',
- 'releaseuri' => 'http://cdbaby.com/cd/$matches[1]$matches[2]$matches[3]/from/musicbrainz',
- );
- $coverartsites[] = array(
- 'name' => "CD Baby",
- 'domain' => "cdbaby.name",
- 'regexp' => "@http://cdbaby\.name/([a-z0-9])/([a-z0-9])/([A-Za-z0-9]*).jpg@",
- 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[3].jpg',
- 'releaseuri' => 'http://cdbaby.com/cd/$matches[3]/from/musicbrainz',
- );
- $coverartsites[] = array(
- 'name' => 'archive.org',
- 'domain' => 'archive.org',
- 'regexp' => '/^(.*\.(jpg|jpeg|png|gif))$/',
- 'imguri' => '$matches[1]',
- 'releaseuri' => '',
- );
- $coverartsites[] = array(
- 'name' => "Jamendo",
- 'domain' => "www.jamendo.com",
- 'regexp' => '/http://www\.jamendo\.com/(\w\w/)?album/(\d+)/',
- 'imguri' => 'http://img.jamendo.com/albums/$matches[2]/covers/1.200.jpg',
- 'releaseuri' => 'http://www.jamendo.com/album/$matches[2]',
- );
- $coverartsites[] = array(
- 'name' => '8bitpeoples.com',
- 'domain' => '8bitpeoples.com',
- 'regexp' => '/^(.*)$/',
- 'imguri' => '$matches[1]',
- 'releaseuri' => '',
- );
- $coverartsites[] = array(
- 'name' => 'Encyclopédisque',
- 'domain' => 'encyclopedisque.fr',
- 'regexp' => '/http://www.encyclopedisque.fr/images/imgdb/(thumb250|main)/(\d+).jpg/',
- 'imguri' => 'http://www.encyclopedisque.fr/images/imgdb/thumb250/$matches[2].jpg',
- 'releaseuri' => 'http://www.encyclopedisque.fr/',
- );
- $coverartsites[] = array(
- 'name' => 'Thastrom',
- 'domain' => 'www.thastrom.se',
- 'regexp' => '/^(.*)$/',
- 'imguri' => '$matches[1]',
- 'releaseuri' => '',
- );
- $coverartsites[] = array(
- 'name' => 'Universal Poplab',
- 'domain' => 'www.universalpoplab.com',
- 'regexp' => '/^(.*)$/',
- 'imguri' => '$matches[1]',
- 'releaseuri' => '',
- );
- foreach ($release->getRelations(mbRelation::TO_URL) as $ar) {
- $arurl = $ar->getTargetId();
- debug_event('mbz-gatherart', "Found URL AR: " . $arurl , '5');
- foreach ($coverartsites as $casite) {
- if (strpos($arurl, $casite['domain']) !== false) {
- debug_event('mbz-gatherart', "Matched coverart site: " . $casite['name'], '5');
- if (preg_match($casite['regexp'], $arurl, $matches)) {
- $num_found++;
- eval("\$url = \"$casite[imguri]\";");
- debug_event('mbz-gatherart', "Generated URL added: " . $url, '5');
- $images[] = array(
- 'url' => $url,
- 'mime' => 'image/jpeg',
- );
- if ($num_found >= $limit) {
- return $images;
- }
- }
- }
- } // end foreach coverart sites
- } // end foreach
-
- return $images;
-
- } // gather_musicbrainz
-
- /**
- * gather_amazon
- * This takes keywords and performs a search of the Amazon website
- * for the art. It returns an array of found objects with mime/url keys
- */
- public function gather_amazon($limit = 5, $keywords = '') {
-
- $images = array();
- $final_results = array();
- $possible_keys = array(
- 'LargeImage',
- 'MediumImage',
- 'SmallImage'
- );
-
- // Prevent the script from timing out
- set_time_limit(0);
-
- if (empty($keywords)) {
- $keywords = $this->full_name;
- /* If this isn't a various album combine with artist name */
- if ($this->artist_count == '1') { $keywords .= ' ' . $this->artist_name; }
- }
-
- /* Attempt to retrieve the album art order */
- $amazon_base_urls = Config::get('amazon_base_urls');
-
- /* If it's not set */
- if (!count($amazon_base_urls)) {
- $amazon_base_urls = array('http://webservices.amazon.com');
- }
-
- /* Foreach through the base urls that we should check */
- foreach ($amazon_base_urls as $amazon_base) {
-
- // Create the Search Object
- $amazon = new AmazonSearch(Config::get('amazon_developer_public_key'), Config::get('amazon_developer_private_key'), $amazon_base);
- if(Config::get('proxy_host') AND Config::get('proxy_port')) {
- $proxyhost = Config::get('proxy_host');
- $proxyport = Config::get('proxy_port');
- $proxyuser = Config::get('proxy_user');
- $proxypass = Config::get('proxy_pass');
- debug_event('amazon', 'setProxy', 5);
- $amazon->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass);
- }
-
- $search_results = array();
-
- /* Set up the needed variables */
- $max_pages_to_search = max(Config::get('max_amazon_results_pages'),$amazon->_default_results_pages);
- $pages_to_search = $max_pages_to_search; //init to max until we know better.
- // while we have pages to search
- do {
- $raw_results = $amazon->search(array('artist'=>$artist,'album'=>$albumname,'keywords'=>$keywords));
-
- $total = count($raw_results) + count($search_results);
-
- // If we've gotten more then we wanted
- if ($limit && $total > $limit) {
- $raw_results = array_slice($raw_results, 0, -($total - $limit), true);
-
- debug_event('amazon-xml', "Found $total, limit $limit; reducing and breaking from loop", 5);
- // Merge the results and BREAK!
- $search_results = array_merge($search_results,$raw_results);
- break;
- } // if limit defined
-
- $search_results = array_merge($search_results,$raw_results);
- $pages_to_search = min($max_pages_to_search, $amazon->_maxPage);
- debug_event('amazon-xml', "Searched results page " . ($amazon->_currentPage+1) . "/" . $pages_to_search,'5');
- $amazon->_currentPage++;
-
- } while ($amazon->_currentPage < $pages_to_search);
-
-
- // Only do the second search if the first actually returns something
- if (count($search_results)) {
- $final_results = $amazon->lookup($search_results);
- }
-
- /* Log this if we're doin debug */
- debug_event('amazon-xml',"Searched using $keywords with " . Config::get('amazon_developer_key') . " as key, results: " . count($final_results), 5);
-
- // If we've hit our limit
- if (!empty($limit) && count($final_results) >= $limit) {
- break;
- }
-
- } // end foreach
-
- /* Foreach through what we've found */
- foreach ($final_results as $result) {
-
- /* Recurse through the images found */
- foreach ($possible_keys as $key) {
- if (strlen($result[$key])) {
- break;
- }
- } // foreach
-
- // Rudimentary image type detection, only JPG and GIF allowed.
- if (substr($result[$key], -4 == '.jpg')) {
- $mime = "image/jpeg";
- }
- elseif (substr($result[$key], -4 == '.gif')) {
- $mime = "image/gif";
- }
- elseif (substr($result[$key], -4 == '.png')) {
- $mime = "image/png";
- }
- else {
- /* Just go to the next result */
- continue;
- }
-
- $data['url'] = $result[$key];
- $data['mime'] = $mime;
-
- $images[] = $data;
-
- if (!empty($limit)) {
- if (count($images) >= $limit) {
- return $images;
- }
- }
-
- } // if we've got something
-
- return $images;
-
- } // gather_amazon
-
- /**
- * gather_folder
- * This returns the art from the folder of the files
- * If a limit is passed or the preferred filename is found the current
- * results set is returned
- */
- public function gather_folder($limit = 5) {
-
- $media = new Album($this->uid);
- $songs = $media->get_songs();
- $results = array();
- $preferred = false;
- // For storing which directories we've already done
- $processed = array();
-
- /* See if we are looking for a specific filename */
- $preferred_filename = Config::get('album_art_preferred_filename');
-
- // Array of valid extensions
- $image_extensions = array(
- 'bmp',
- 'gif',
- 'jp2',
- 'jpeg',
- 'jpg',
- 'png'
- );
-
- foreach ($songs as $song_id) {
- $data = array();
- $song = new Song($song_id);
- $dir = dirname($song->file);
-
- if (isset($processed[$dir])) {
- continue;
- }
-
- debug_event('folder_art', "Opening $dir and checking for Album Art", 3);
-
- /* Open up the directory */
- $handle = opendir($dir);
-
- if (!$handle) {
- Error::add('general', T_('Error: Unable to open') . ' ' . $dir);
- debug_event('folder_art', "Error: Unable to open $dir for album art read", 2);
- continue;
- }
-
- $processed[$dir] = true;
-
- // Recurse through this dir and create the files array
- while ($file = readdir($handle)) {
- $extension = pathinfo($file);
- $extension = $extension['extension'];
-
- // Make sure it looks like an image file
- if (!in_array($extension, $image_extensions)) {
- continue;
- }
-
- $full_filename = $dir . '/' . $file;
-
- // Make sure it's got something in it
- if (!filesize($full_filename)) {
- debug_event('folder_art', "Empty file, rejecting $file", 5);
- continue;
- }
-
- // Regularise for mime type
- if ($extension == 'jpg') {
- $extension = 'jpeg';
- }
-
- // Take an md5sum so we don't show duplicate
- // files.
- $index = md5($full_filename);
-
- if ($file == $preferred_filename) {
- // We found the preferred filename and
- // so we're done.
- debug_event('folder_art', "Found preferred image file: $file", 5);
- $preferred[$index] = array(
- 'file' => $full_filename,
- 'mime' => 'image/' . $extension
- );
- break;
- }
-
- debug_event('folder_art', "Found image file: $file", 5);
- $results[$index] = array(
- 'file' => $full_filename,
- 'mime' => 'image/' . $extension
- );
-
- } // end while reading dir
- closedir($handle);
-
- } // end foreach songs
-
- if (is_array($preferred)) {
- // We found our favourite filename somewhere, so we need
- // to dump the other, less sexy ones.
- $results = $preferred;
- }
-
- debug_event('folder_art', 'Results: ' . json_encode($results), 5);
- if ($limit && count($results) > $limit) {
- $results = array_slice($results, 0, $limit);
- }
-
- return array_values($results);
-
- } // gather_folder
-
- /**
- * gather_tags
- * This looks for the art in the meta-tags of the file
- * itself
- */
- public function gather_tags($limit = 5) {
-
- // We need the filenames
- $album = new Album($this->uid);
-
- // grab the songs and define our results
- $songs = $album->get_songs();
- $data = array();
-
- // Foreach songs in this album
- foreach ($songs as $song_id) {
- $song = new Song($song_id);
- // If we find a good one, stop looking
- $getID3 = new getID3();
- try { $id3 = $getID3->analyze($song->file); }
- catch (Exception $error) {
- debug_event('getid3', $error->message, 1);
- }
-
- if (isset($id3['asf']['extended_content_description_object']['content_descriptors']['13'])) {
- $image = $id3['asf']['extended_content_description_object']['content_descriptors']['13'];
- $data[] = array(
- 'song' => $song->file,
- 'raw' => $image['data'],
- 'mime' => $image['mime']);
- }
-
- if (isset($id3['id3v2']['APIC'])) {
- // Foreach in case they have more then one
- foreach ($id3['id3v2']['APIC'] as $image) {
- $data[] = array(
- 'song' => $song->file,
- 'raw' => $image['data'],
- 'mime' => $image['mime']);
- }
- }
-
- if ($limit && count($data) >= $limit) {
- return array_slice($data, 0, $limit);
- }
-
- } // end foreach
-
- return $data;
-
- } // gather_tags
-
- /**
- * gather_google
- * Raw google search to retrieve the art, not very reliable
- */
- public function gather_google($limit = 5) {
-
- $images = array();
- $media = new $this->type($this->uid);
- $media->format();
-
- $search = $media->full_name;
-
- if ($media->artist_count == '1')
- $search = $media->artist_name . ', ' . $search;
-
- $search = rawurlencode($search);
-
- $size = '&imgsz=m'; // Medium
- //$size = '&imgsz=l'; // Large
-
- $html = file_get_contents("http://images.google.com/images?source=hp&q=$search&oq=&um=1&ie=UTF-8&sa=N&tab=wi&start=0&tbo=1$size");
-
- if(preg_match_all("|\ssrc\=\"(http.+?)\"|", $html, $matches, PREG_PATTERN_ORDER))
- foreach ($matches[1] as $match) {
- $extension = "image/jpeg";
-
- if (strrpos($extension, '.') !== false) $extension = substr($extension, strrpos($extension, '.') + 1);
-
- $images[] = array('url' => $match, 'mime' => $extension);
- }
-
- return $images;
-
- } // gather_google
-
- /**
- * gather_lastfm
- * This returns the art from lastfm. It doesn't currently require an
- * account but may in the future.
- */
- public function gather_lastfm($limit, $options = false) {
-
- // Create the parser object
- $lastfm = new LastFMSearch();
-
- switch ($this->type) {
- case 'album':
- if (is_array($options)) {
- $artist = $options['artist'];
- $album = $options['album_name'];
- }
- else {
- $media = new Album($this->uid);
- $media->format();
- $artist = $media->artist_name;
- $album = $media->full_name;
- }
- break;
- }
-
- if(Config::get('proxy_host') AND Config::get('proxy_port')) {
- $proxyhost = Config::get('proxy_host');
- $proxyport = Config::get('proxy_port');
- $proxyuser = Config::get('proxy_user');
- $proxypass = Config::get('proxy_pass');
- debug_event('LastFM', 'proxy set', 5);
- $lastfm->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass);
- }
-
- $raw_data = $lastfm->album_search($artist, $album);
-
- if (!count($raw_data)) { return array(); }
-
- $coverart = $raw_data['coverart'];
- if (!is_array($coverart)) { return array(); }
-
- ksort($coverart);
- foreach ($coverart as $url) {
- // We need to check the URL for the /noimage/ stuff
- if (strpos($url, '/noimage/') !== false) {
- debug_event('LastFM', 'Detected as noimage, skipped ' . $url, 3);
- continue;
- }
-
- // HACK: we shouldn't rely on the extension to determine file type
- $results = pathinfo($url);
- $mime = 'image/' . $results['extension'];
- $data[] = array('url' => $url, 'mime' => $mime);
- if ($limit && count($data) >= $limit) {
- return $data;
- }
- } // end foreach
-
- return $data;
-
- } // gather_lastfm
+ public $type;
+ public $uid; // UID of the object not ID because it's not the ART.ID
+ public $raw; // Raw art data
+ public $raw_mime;
+
+ public $thumb;
+ public $thumb_mime;
+
+ private static $enabled;
+
+ /**
+ * Constructor
+ * Art constructor, takes the UID of the object and the
+ * object type.
+ */
+ public function __construct($uid, $type = 'album') {
+
+ $this->type = Art::validate_type($type);
+ $this->uid = $uid;
+
+ } // constructor
+
+ /**
+ * build_cache
+ * This attempts to reduce # of queries by asking for everything in the
+ * browse all at once and storing it in the cache, this can help if the
+ * db connection is the slow point
+ */
+ public static function build_cache($object_ids) {
+
+ if (!is_array($object_ids) || !count($object_ids)) { return false; }
+ $uidlist = '(' . implode(',', $object_ids) . ')';
+ $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_id` IN $uidlist";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('art', $row['object_type'] .
+ $row['object_id'] . $row['size'], $row);
+ }
+
+ return true;
+ } // build_cache
+
+
+ /**
+ * _auto_init
+ * Called on creation of the class
+ */
+ public static function _auto_init() {
+ if (!isset($_SESSION['art_enabled'])) {
+ $_SESSION['art_enabled'] = (Config::get('bandwidth') > 25);
+ }
+ self::$enabled = make_bool($_SESSION['art_enabled']);
+ }
+
+ /**
+ * is_enabled
+ * Checks whether the user currently wants art
+ */
+ public static function is_enabled() {
+ if (self::$enabled) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * set_enabled
+ * Changes the value of enabled
+ */
+ public static function set_enabled($value = null) {
+ if (is_null($value)) {
+ self::$enabled = self::$enabled ? false : true;
+ }
+ else {
+ self::$enabled = make_bool($value);
+ }
+
+ $_SESSION['art_enabled'] = self::$enabled;
+ }
+
+ /**
+ * validate_type
+ * This validates the type
+ */
+ public static function validate_type($type) {
+
+ switch ($type) {
+ case 'album':
+ case 'artist':
+ case 'video':
+ return $type;
+ break;
+ default:
+ return 'album';
+ break;
+ }
+
+ } // validate_type
+
+ /**
+ * extension
+ * This returns the file extension for the currently loaded art
+ */
+ public static function extension($mime) {
+
+ $data = explode("/", $mime);
+ $extension = $data['1'];
+
+ if ($extension == 'jpeg') { $extension = 'jpg'; }
+
+ return $extension;
+
+ } // extension
+
+ /**
+ * test_image
+ * Runs some sanity checks on the putative image
+ */
+ public static function test_image($source) {
+ if (strlen($source) < 10) {
+ debug_event('Art', 'Invalid image passed', 1);
+ return false;
+ }
+
+ // Check to make sure PHP:GD exists. If so, we can sanity check
+ // the image.
+ if (function_exists('ImageCreateFromString')) {
+ $image = ImageCreateFromString($source);
+ if (!$image || imagesx($image) < 5 || imagesy($image) < 5) {
+ debug_event('Art', 'Image failed PHP-GD test',1);
+ return false;
+ }
+ }
+
+ return true;
+ } //test_image
+
+ /**
+ * get
+ * This returns the art for our current object, this can
+ * look in the database and will return the thumb if it
+ * exists, if it doesn't depending on settings it will try
+ * to create it.
+ */
+ public function get($raw=false) {
+
+ // Get the data either way
+ if (!$this->get_db()) {
+ return false;
+ }
+
+ if ($raw || !$this->thumb) {
+ return $this->raw;
+ }
+ else {
+ return $this->thumb;
+ }
+
+ } // get
+
+
+ /**
+ * get_db
+ * This pulls the information out from the database, depending
+ * on if we want to resize and if there is not a thumbnail go
+ * ahead and try to resize
+ */
+ public function get_db() {
+
+ $type = Dba::escape($this->type);
+ $id = Dba::escape($this->uid);
+
+ $sql = "SELECT `image`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$id'";
+ $db_results = Dba::read($sql);
+
+ while ($results = Dba::fetch_assoc($db_results)) {
+ if ($results['size'] == 'original') {
+ $this->raw = $results['image'];
+ $this->raw_mime = $results['mime'];
+ }
+ else if (Config::get('resize_images') &&
+ $results['size'] == '275x275') {
+ $this->thumb = $results['image'];
+ $this->raw_mime = $results['mime'];
+ }
+ }
+ // If we get nothing return false
+ if (!$this->raw) { return false; }
+
+ // If there is no thumb and we want thumbs
+ if (!$this->thumb && Config::get('resize_images')) {
+ $data = $this->generate_thumb($this->raw, array('width' => 275, 'height' => 275), $this->raw_mime);
+ // If it works save it!
+ if ($data) {
+ $this->save_thumb($data['thumb'], $data['thumb_mime'], '275x275');
+ $this->thumb = $data['thumb'];
+ $this->thumb_mime = $data['thumb_mime'];
+ }
+ else {
+ debug_event('Art','Unable to retrieve or generate thumbnail for ' . $type . '::' . $id,1);
+ }
+ } // if no thumb, but art and we want to resize
+
+ return true;
+
+ } // get_db
+
+ /**
+ * insert
+ * This takes the string representation of an image and inserts it into
+ * the database. You must also pass the mime type.
+ */
+ public function insert($source, $mime) {
+
+ // Disabled in demo mode cause people suck and upload porn
+ if (Config::get('demo_mode')) { return false; }
+
+ // Check to make sure we like this image
+ if (!self::test_image($source)) {
+ debug_event('Art', 'Not inserting image, invalid data passed', 1);
+ return false;
+ }
+
+ // Default to image/jpeg if they don't pass anything
+ $mime = $mime ? $mime : 'image/jpeg';
+
+ $image = Dba::escape($source);
+ $mime = Dba::escape($mime);
+ $uid = Dba::escape($this->uid);
+ $type = Dba::escape($this->type);
+
+ // Blow it away!
+ $this->reset();
+
+ // Insert it!
+ $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$image', '$mime', 'original', '$type', '$uid')";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // insert
+
+ /**
+ * reset
+ * This resets the art in the database
+ */
+ public function reset() {
+
+ $type = Dba::escape($this->type);
+ $uid = Dba::escape($this->uid);
+
+ $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type'";
+ $db_results = Dba::write($sql);
+
+ } // reset
+
+ /**
+ * save_thumb
+ * This saves the thumbnail that we're passed
+ */
+ public function save_thumb($source, $mime, $size) {
+
+ // Quick sanity check
+ if (!self::test_image($source)) {
+ debug_event('Art', 'Not inserting thumbnail, invalid data passed', 1);
+ return false;
+ }
+
+ $source = Dba::escape($source);
+ $mime = Dba::escape($mime);
+ $size = Dba::escape($size);
+ $uid = Dba::escape($this->uid);
+ $type = Dba::escape($this->type);
+
+ $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type' AND `size`='$size'";
+ $db_results = Dba::write($sql);
+
+ $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$source', '$mime', '$size', '$type', '$uid')";
+ $db_results = Dba::write($sql);
+
+ } // save_thumb
+
+ /**
+ * get_thumb
+ * Returns the specified resized image. If the requested size doesn't
+ * already exist, create and cache it.
+ */
+ public function get_thumb($size) {
+ $sizetext = $size['width'] . 'x' . $size['height'];
+ $sizetext = Dba::escape($sizetext);
+ $type = Dba::escape($this->type);
+ $uid = Dba::escape($this->uid);
+
+ $sql = "SELECT `image`, `mime` FROM `image` WHERE `size`='$sizetext' AND `object_type`='$type' AND `object_id`='$uid'";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+ if (count($results)) {
+ return array('thumb' => $results['image'],
+ 'thumb_mime' => $results['mime']);
+ }
+
+ // If we didn't get a result
+ $results = $this->generate_thumb($this->raw, $size, $this->raw_mime);
+ if ($results) {
+ $this->save_thumb($results['thumb'], $results['thumb_mime'], $sizetext);
+ }
+
+ return $results;
+ } // get_thumb
+
+ /**
+ * generate_thumb
+ * Automatically resizes the image for thumbnail viewing.
+ * Only works on gif/jpg/png/bmp. Fails if PHP-GD isn't available
+ * or lacks support for the requested image type.
+ */
+ public function generate_thumb($image,$size,$mime) {
+
+ $data = explode("/",$mime);
+ $type = strtolower($data['1']);
+
+ if (!self::test_image($image)) {
+ debug_event('Art', 'Not trying to generate thumbnail, invalid data passed', 1);
+ return false;
+ }
+
+ if (!function_exists('gd_info')) {
+ debug_event('Art','PHP-GD Not found - unable to resize art',1);
+ return false;
+ }
+
+ // Check and make sure we can resize what you've asked us to
+ if (($type == 'jpg' OR $type == 'jpeg') AND !(imagetypes() & IMG_JPG)) {
+ debug_event('Art','PHP-GD Does not support JPGs - unable to resize',1);
+ return false;
+ }
+ if ($type == 'png' AND !imagetypes() & IMG_PNG) {
+ debug_event('Art','PHP-GD Does not support PNGs - unable to resize',1);
+ return false;
+ }
+ if ($type == 'gif' AND !imagetypes() & IMG_GIF) {
+ debug_event('Art','PHP-GD Does not support GIFs - unable to resize',1);
+ return false;
+ }
+ if ($type == 'bmp' AND !imagetypes() & IMG_WBMP) {
+ debug_event('Art','PHP-GD Does not support BMPs - unable to resize',1);
+ return false;
+ }
+
+ $source = imagecreatefromstring($image);
+
+ if (!$source) {
+ debug_event('Art','Failed to create Image from string - Source Image is damaged / malformed',1);
+ return false;
+ }
+
+ $source_size = array('height' => imagesy($source), 'width' => imagesx($source));
+
+ // Create a new blank image of the correct size
+ $thumbnail = imagecreatetruecolor($size['width'], $size['height']);
+
+ if (!imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $size['width'], $size['height'], $source_size['width'], $source_size['height'])) {
+ debug_event('Art','Unable to create resized image',1);
+ return false;
+ }
+
+ // Start output buffer
+ ob_start();
+
+ // Generate the image to our OB
+ switch ($type) {
+ case 'jpg':
+ case 'jpeg':
+ imagejpeg($thumbnail, null, 75);
+ $mime_type = image_type_to_mime_type(IMAGETYPE_JPEG);
+ break;
+ case 'gif':
+ imagegif($thumbnail);
+ $mime_type = image_type_to_mime_type(IMAGETYPE_GIF);
+ break;
+ // Turn bmps into pngs
+ case 'bmp':
+ $type = 'png';
+ case 'png':
+ imagepng($thumbnail);
+ $mime_type = image_type_to_mime_type(IMAGETYPE_PNG);
+ break;
+ } // resized
+
+ $data = ob_get_contents();
+ ob_end_clean();
+
+ if (!strlen($data)) {
+ debug_event('Art', 'Unknown Error resizing art', 1);
+ return false;
+ }
+
+ return array('thumb' => $data, 'thumb_mime' => $mime_type);
+
+ } // generate_thumb
+
+ /**
+ * get_from_source
+ * This gets an image for the album art from a source as
+ * defined in the passed array. Because we don't know where
+ * it's coming from we are a passed an array that can look like
+ * ['url'] = URL *** OPTIONAL ***
+ * ['file'] = FILENAME *** OPTIONAL ***
+ * ['raw'] = Actual Image data, already captured
+ */
+ public static function get_from_source($data, $type = 'album') {
+
+ // Already have the data, this often comes from id3tags
+ if (isset($data['raw'])) {
+ return $data['raw'];
+ }
+
+ // If it came from the database
+ if (isset($data['db'])) {
+ // Repull it
+ $uid = Dba::escape($data['db']);
+ $type = Dba::escape($type);
+
+ $sql = "SELECT * FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid' AND `size`='original'";
+ $db_results = Dba::read($sql);
+ $row = Dba::fetch_assoc($db_results);
+ return $row['art'];
+ } // came from the db
+
+ // Check to see if it's a URL
+ if (isset($data['url'])) {
+ $snoopy = new Snoopy();
+ if(Config::get('proxy_host') AND Config::get('proxy_port')) {
+ $snoopy->proxy_user = Config::get('proxy_host');
+ $snoopy->proxy_port = Config::get('proxy_port');
+ $snoopy->proxy_user = Config::get('proxy_user');
+ $snoopy->proxy_pass = Config::get('proxy_pass');
+ }
+ $snoopy->fetch($data['url']);
+ return $snoopy->results;
+ }
+
+ // Check to see if it's a FILE
+ if (isset($data['file'])) {
+ $handle = fopen($data['file'],'rb');
+ $image_data = fread($handle,filesize($data['file']));
+ fclose($handle);
+ return $image_data;
+ }
+
+ // Check to see if it is embedded in id3 of a song
+ if (isset($data['song'])) {
+ // If we find a good one, stop looking
+ $getID3 = new getID3();
+ $id3 = $getID3->analyze($data['song']);
+
+ if ($id3['format_name'] == "WMA") {
+ return $id3['asf']['extended_content_description_object']['content_descriptors']['13']['data'];
+ }
+ elseif (isset($id3['id3v2']['APIC'])) {
+ // Foreach in case they have more then one
+ foreach ($id3['id3v2']['APIC'] as $image) {
+ return $image['data'];
+ }
+ }
+ } // if data song
+
+ return false;
+
+ } // get_from_source
+
+ /**
+ * url
+ * This returns the constructed URL for the art in question
+ */
+ public static function url($uid,$type,$sid=false) {
+
+ $sid = $sid ? scrub_out($sid) : scrub_out(session_id());
+ $type = self::validate_type($type);
+
+ $key = $type . $uid;
+ if (parent::is_cached('art', $key . '275x275') && Config::get('resize_images')) {
+ $row = parent::get_from_cache('art', $key . '275x275');
+ $mime = $row['mime'];
+ }
+ if (parent::is_cached('art', $key . 'original')) {
+ $row = parent::get_from_cache('art', $key . 'original');
+ $thumb_mime = $row['mime'];
+ }
+ if (!$mime && !$thumb_mime) {
+
+ $type = Dba::escape($type);
+ $uid = Dba::escape($uid);
+
+ $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid'";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('art', $key . $row['size'], $row);
+ if ($row['size'] == 'original') {
+ $mime = $row['mime'];
+ }
+ else if ($row['size'] == '275x275' && Config::get('resize_images')) {
+ $thumb_mime = $row['mime'];
+ }
+ }
+ }
+
+ $mime = $thumb_mime ? $thumb_mime : $mime;
+ $extension = self::extension($mime);
+
+ $name = 'art.' . $extension;
+ $url = Config::get('web_path') . '/image.php?id=' . scrub_out($uid) . '&object_type=' . scrub_out($type) . '&auth=' . $sid . '&name=' . $name;
+
+ return $url;
+
+ } // url
+
+
+ /**
+ * gc
+ * This cleans up art that no longer has a corresponding object
+ */
+ public static function gc() {
+ // iterate over our types and delete the images
+ foreach (array('album', 'artist') as $type) {
+ $sql = "DELETE FROM `image` USING `image` LEFT JOIN `" .
+ $type . "` ON `" . $type . "`.`id`=" .
+ "`image`.`object_id` WHERE `object_type`='" .
+ $type . "' AND `" . $type . "`.`id` IS NULL";
+ $db_results = Dba::write($sql);
+ } // foreach
+ }
+
+ /**
+ * gather
+ * This tries to get the art in question
+ */
+ public function gather($options = array(), $limit = false) {
+
+ // Define vars
+ $results = array();
+
+ switch ($this->type) {
+ case 'album':
+ $allowed_methods = array('db','lastfm','folder','amazon','google','musicbrainz','tags');
+ break;
+ case 'artist':
+ $allowed_methods = array();
+ break;
+ case 'video':
+ $allowed_methods = array();
+ break;
+ }
+
+ $config = Config::get('art_order');
+ $methods = get_class_methods('Art');
+
+ /* If it's not set */
+ if (empty($config)) {
+ // They don't want art!
+ debug_event('Art', 'art_order is empty, skipping art gathering', 3);
+ return array();
+ }
+ elseif (!is_array($config)) {
+ $config = array($config);
+ }
+
+ debug_event('Art','Searching using:' . json_encode($config), 3);
+
+ foreach ($config as $method) {
+
+ $data = array();
+
+ if (!in_array($method, $allowed_methods)) {
+ debug_event('Art', "$method not in allowed_methods, skipping", 3);
+ continue;
+ }
+
+ $method_name = "gather_" . $method;
+
+ if (in_array($method_name, $methods)) {
+ debug_event('Art', "Method used: $method_name", 3);
+ // Some of these take options!
+ switch ($method_name) {
+ case 'gather_amazon':
+ $data = $this->{$method_name}($limit, $options['keyword']);
+ break;
+ case 'gather_lastfm':
+ $data = $this->{$method_name}($limit, $options);
+ break;
+ default:
+ $data = $this->{$method_name}($limit);
+ break;
+ }
+
+ // Add the results we got to the current set
+ $results = array_merge($results, (array)$data);
+
+ if ($limit && count($results) >= $limit) {
+ return array_slice($results, 0, $limit);
+ }
+
+ } // if the method exists
+ else {
+ debug_event("Art", "$method_name not defined", 1);
+ }
+
+ } // end foreach
+
+ return $results;
+
+ } // gather
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // Art Methods
+ ///////////////////////////////////////////////////////////////////////
+
+ /**
+ * gather_db
+ * This function retrieves art that's already in the database
+ */
+ public function gather_db($limit = null) {
+ if ($this->get_db()) {
+ return array('db' => true);
+ }
+ return array();
+ }
+
+ /**
+ * gather_musicbrainz
+ * This function retrieves art based on MusicBrainz' Advanced
+ * Relationships
+ */
+ public function gather_musicbrainz($limit = 5) {
+ $images = array();
+ $num_found = 0;
+
+ if ($this->type == 'album') {
+ $album = new Album($this->uid);
+ }
+ else {
+ return $images;
+ }
+
+ if ($album->mbid) {
+ debug_event('mbz-gatherart', "Album MBID: " . $album->mbid, '5');
+ }
+ else {
+ return $images;
+ }
+
+ $mbquery = new MusicBrainzQuery();
+ $includes = new mbReleaseIncludes();
+ try {
+ $release = $mbquery->getReleaseByID($album->mbid, $includes->urlRelations());
+ } catch (Exception $e) {
+ return $images;
+ }
+
+ $asin = $release->getAsin();
+
+ if ($asin) {
+ debug_event('mbz-gatherart', "Found ASIN: " . $asin, '5');
+ $base_urls = array(
+ "01" => "ec1.images-amazon.com",
+ "02" => "ec1.images-amazon.com",
+ "03" => "ec2.images-amazon.com",
+ "08" => "ec1.images-amazon.com",
+ "09" => "ec1.images-amazon.com",
+ );
+ foreach ($base_urls as $server_num => $base_url) {
+ // to avoid complicating things even further, we only look for large cover art
+ $url = 'http://' . $base_url . '/images/P/' . $asin . '.' . $server_num . '.LZZZZZZZ.jpg';
+ debug_event('mbz-gatherart', "Evaluating Amazon URL: " . $url, '5');
+ $snoopy = new Snoopy();
+ if(Config::get('proxy_host') AND Config::get('proxy_port')) {
+ $snoopy->proxy_user = Config::get('proxy_host');
+ $snoopy->proxy_port = Config::get('proxy_port');
+ $snoopy->proxy_user = Config::get('proxy_user');
+ $snoopy->proxy_pass = Config::get('proxy_pass');
+ }
+ if ($snoopy->fetch($url)) {
+ $num_found++;
+ debug_event('mbz-gatherart', "Amazon URL added: " . $url, '5');
+ $images[] = array(
+ 'url' => $url,
+ 'mime' => 'image/jpeg',
+ );
+ if ($num_found >= $limit) {
+ return $images;
+ }
+ }
+ }
+ }
+ // The next bit is based directly on the MusicBrainz server code
+ // that displays cover art.
+ // I'm leaving in the releaseuri info for the moment, though
+ // it's not going to be used.
+ $coverartsites[] = array(
+ 'name' => "CD Baby",
+ 'domain' => "cdbaby.com",
+ 'regexp' => '@http://cdbaby\.com/cd/(\w)(\w)(\w*)@',
+ 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[1]$matches[2]$matches[3].jpg',
+ 'releaseuri' => 'http://cdbaby.com/cd/$matches[1]$matches[2]$matches[3]/from/musicbrainz',
+ );
+ $coverartsites[] = array(
+ 'name' => "CD Baby",
+ 'domain' => "cdbaby.name",
+ 'regexp' => "@http://cdbaby\.name/([a-z0-9])/([a-z0-9])/([A-Za-z0-9]*).jpg@",
+ 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[3].jpg',
+ 'releaseuri' => 'http://cdbaby.com/cd/$matches[3]/from/musicbrainz',
+ );
+ $coverartsites[] = array(
+ 'name' => 'archive.org',
+ 'domain' => 'archive.org',
+ 'regexp' => '/^(.*\.(jpg|jpeg|png|gif))$/',
+ 'imguri' => '$matches[1]',
+ 'releaseuri' => '',
+ );
+ $coverartsites[] = array(
+ 'name' => "Jamendo",
+ 'domain' => "www.jamendo.com",
+ 'regexp' => '/http://www\.jamendo\.com/(\w\w/)?album/(\d+)/',
+ 'imguri' => 'http://img.jamendo.com/albums/$matches[2]/covers/1.200.jpg',
+ 'releaseuri' => 'http://www.jamendo.com/album/$matches[2]',
+ );
+ $coverartsites[] = array(
+ 'name' => '8bitpeoples.com',
+ 'domain' => '8bitpeoples.com',
+ 'regexp' => '/^(.*)$/',
+ 'imguri' => '$matches[1]',
+ 'releaseuri' => '',
+ );
+ $coverartsites[] = array(
+ 'name' => 'Encyclopédisque',
+ 'domain' => 'encyclopedisque.fr',
+ 'regexp' => '/http://www.encyclopedisque.fr/images/imgdb/(thumb250|main)/(\d+).jpg/',
+ 'imguri' => 'http://www.encyclopedisque.fr/images/imgdb/thumb250/$matches[2].jpg',
+ 'releaseuri' => 'http://www.encyclopedisque.fr/',
+ );
+ $coverartsites[] = array(
+ 'name' => 'Thastrom',
+ 'domain' => 'www.thastrom.se',
+ 'regexp' => '/^(.*)$/',
+ 'imguri' => '$matches[1]',
+ 'releaseuri' => '',
+ );
+ $coverartsites[] = array(
+ 'name' => 'Universal Poplab',
+ 'domain' => 'www.universalpoplab.com',
+ 'regexp' => '/^(.*)$/',
+ 'imguri' => '$matches[1]',
+ 'releaseuri' => '',
+ );
+ foreach ($release->getRelations(mbRelation::TO_URL) as $ar) {
+ $arurl = $ar->getTargetId();
+ debug_event('mbz-gatherart', "Found URL AR: " . $arurl , '5');
+ foreach ($coverartsites as $casite) {
+ if (strpos($arurl, $casite['domain']) !== false) {
+ debug_event('mbz-gatherart', "Matched coverart site: " . $casite['name'], '5');
+ if (preg_match($casite['regexp'], $arurl, $matches)) {
+ $num_found++;
+ eval("\$url = \"$casite[imguri]\";");
+ debug_event('mbz-gatherart', "Generated URL added: " . $url, '5');
+ $images[] = array(
+ 'url' => $url,
+ 'mime' => 'image/jpeg',
+ );
+ if ($num_found >= $limit) {
+ return $images;
+ }
+ }
+ }
+ } // end foreach coverart sites
+ } // end foreach
+
+ return $images;
+
+ } // gather_musicbrainz
+
+ /**
+ * gather_amazon
+ * This takes keywords and performs a search of the Amazon website
+ * for the art. It returns an array of found objects with mime/url keys
+ */
+ public function gather_amazon($limit = 5, $keywords = '') {
+
+ $images = array();
+ $final_results = array();
+ $possible_keys = array(
+ 'LargeImage',
+ 'MediumImage',
+ 'SmallImage'
+ );
+
+ // Prevent the script from timing out
+ set_time_limit(0);
+
+ if (empty($keywords)) {
+ $keywords = $this->full_name;
+ /* If this isn't a various album combine with artist name */
+ if ($this->artist_count == '1') { $keywords .= ' ' . $this->artist_name; }
+ }
+
+ /* Attempt to retrieve the album art order */
+ $amazon_base_urls = Config::get('amazon_base_urls');
+
+ /* If it's not set */
+ if (!count($amazon_base_urls)) {
+ $amazon_base_urls = array('http://webservices.amazon.com');
+ }
+
+ /* Foreach through the base urls that we should check */
+ foreach ($amazon_base_urls as $amazon_base) {
+
+ // Create the Search Object
+ $amazon = new AmazonSearch(Config::get('amazon_developer_public_key'), Config::get('amazon_developer_private_key'), $amazon_base);
+ if(Config::get('proxy_host') AND Config::get('proxy_port')) {
+ $proxyhost = Config::get('proxy_host');
+ $proxyport = Config::get('proxy_port');
+ $proxyuser = Config::get('proxy_user');
+ $proxypass = Config::get('proxy_pass');
+ debug_event('amazon', 'setProxy', 5);
+ $amazon->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass);
+ }
+
+ $search_results = array();
+
+ /* Set up the needed variables */
+ $max_pages_to_search = max(Config::get('max_amazon_results_pages'),$amazon->_default_results_pages);
+ $pages_to_search = $max_pages_to_search; //init to max until we know better.
+ // while we have pages to search
+ do {
+ $raw_results = $amazon->search(array('artist'=>$artist,'album'=>$albumname,'keywords'=>$keywords));
+
+ $total = count($raw_results) + count($search_results);
+
+ // If we've gotten more then we wanted
+ if ($limit && $total > $limit) {
+ $raw_results = array_slice($raw_results, 0, -($total - $limit), true);
+
+ debug_event('amazon-xml', "Found $total, limit $limit; reducing and breaking from loop", 5);
+ // Merge the results and BREAK!
+ $search_results = array_merge($search_results,$raw_results);
+ break;
+ } // if limit defined
+
+ $search_results = array_merge($search_results,$raw_results);
+ $pages_to_search = min($max_pages_to_search, $amazon->_maxPage);
+ debug_event('amazon-xml', "Searched results page " . ($amazon->_currentPage+1) . "/" . $pages_to_search,'5');
+ $amazon->_currentPage++;
+
+ } while ($amazon->_currentPage < $pages_to_search);
+
+
+ // Only do the second search if the first actually returns something
+ if (count($search_results)) {
+ $final_results = $amazon->lookup($search_results);
+ }
+
+ /* Log this if we're doin debug */
+ debug_event('amazon-xml',"Searched using $keywords with " . Config::get('amazon_developer_key') . " as key, results: " . count($final_results), 5);
+
+ // If we've hit our limit
+ if (!empty($limit) && count($final_results) >= $limit) {
+ break;
+ }
+
+ } // end foreach
+
+ /* Foreach through what we've found */
+ foreach ($final_results as $result) {
+
+ /* Recurse through the images found */
+ foreach ($possible_keys as $key) {
+ if (strlen($result[$key])) {
+ break;
+ }
+ } // foreach
+
+ // Rudimentary image type detection, only JPG and GIF allowed.
+ if (substr($result[$key], -4 == '.jpg')) {
+ $mime = "image/jpeg";
+ }
+ elseif (substr($result[$key], -4 == '.gif')) {
+ $mime = "image/gif";
+ }
+ elseif (substr($result[$key], -4 == '.png')) {
+ $mime = "image/png";
+ }
+ else {
+ /* Just go to the next result */
+ continue;
+ }
+
+ $data['url'] = $result[$key];
+ $data['mime'] = $mime;
+
+ $images[] = $data;
+
+ if (!empty($limit)) {
+ if (count($images) >= $limit) {
+ return $images;
+ }
+ }
+
+ } // if we've got something
+
+ return $images;
+
+ } // gather_amazon
+
+ /**
+ * gather_folder
+ * This returns the art from the folder of the files
+ * If a limit is passed or the preferred filename is found the current
+ * results set is returned
+ */
+ public function gather_folder($limit = 5) {
+
+ $media = new Album($this->uid);
+ $songs = $media->get_songs();
+ $results = array();
+ $preferred = false;
+ // For storing which directories we've already done
+ $processed = array();
+
+ /* See if we are looking for a specific filename */
+ $preferred_filename = Config::get('album_art_preferred_filename');
+
+ // Array of valid extensions
+ $image_extensions = array(
+ 'bmp',
+ 'gif',
+ 'jp2',
+ 'jpeg',
+ 'jpg',
+ 'png'
+ );
+
+ foreach ($songs as $song_id) {
+ $data = array();
+ $song = new Song($song_id);
+ $dir = dirname($song->file);
+
+ if (isset($processed[$dir])) {
+ continue;
+ }
+
+ debug_event('folder_art', "Opening $dir and checking for Album Art", 3);
+
+ /* Open up the directory */
+ $handle = opendir($dir);
+
+ if (!$handle) {
+ Error::add('general', T_('Error: Unable to open') . ' ' . $dir);
+ debug_event('folder_art', "Error: Unable to open $dir for album art read", 2);
+ continue;
+ }
+
+ $processed[$dir] = true;
+
+ // Recurse through this dir and create the files array
+ while ($file = readdir($handle)) {
+ $extension = pathinfo($file);
+ $extension = $extension['extension'];
+
+ // Make sure it looks like an image file
+ if (!in_array($extension, $image_extensions)) {
+ continue;
+ }
+
+ $full_filename = $dir . '/' . $file;
+
+ // Make sure it's got something in it
+ if (!filesize($full_filename)) {
+ debug_event('folder_art', "Empty file, rejecting $file", 5);
+ continue;
+ }
+
+ // Regularise for mime type
+ if ($extension == 'jpg') {
+ $extension = 'jpeg';
+ }
+
+ // Take an md5sum so we don't show duplicate
+ // files.
+ $index = md5($full_filename);
+
+ if ($file == $preferred_filename) {
+ // We found the preferred filename and
+ // so we're done.
+ debug_event('folder_art', "Found preferred image file: $file", 5);
+ $preferred[$index] = array(
+ 'file' => $full_filename,
+ 'mime' => 'image/' . $extension
+ );
+ break;
+ }
+
+ debug_event('folder_art', "Found image file: $file", 5);
+ $results[$index] = array(
+ 'file' => $full_filename,
+ 'mime' => 'image/' . $extension
+ );
+
+ } // end while reading dir
+ closedir($handle);
+
+ } // end foreach songs
+
+ if (is_array($preferred)) {
+ // We found our favourite filename somewhere, so we need
+ // to dump the other, less sexy ones.
+ $results = $preferred;
+ }
+
+ debug_event('folder_art', 'Results: ' . json_encode($results), 5);
+ if ($limit && count($results) > $limit) {
+ $results = array_slice($results, 0, $limit);
+ }
+
+ return array_values($results);
+
+ } // gather_folder
+
+ /**
+ * gather_tags
+ * This looks for the art in the meta-tags of the file
+ * itself
+ */
+ public function gather_tags($limit = 5) {
+
+ // We need the filenames
+ $album = new Album($this->uid);
+
+ // grab the songs and define our results
+ $songs = $album->get_songs();
+ $data = array();
+
+ // Foreach songs in this album
+ foreach ($songs as $song_id) {
+ $song = new Song($song_id);
+ // If we find a good one, stop looking
+ $getID3 = new getID3();
+ try { $id3 = $getID3->analyze($song->file); }
+ catch (Exception $error) {
+ debug_event('getid3', $error->message, 1);
+ }
+
+ if (isset($id3['asf']['extended_content_description_object']['content_descriptors']['13'])) {
+ $image = $id3['asf']['extended_content_description_object']['content_descriptors']['13'];
+ $data[] = array(
+ 'song' => $song->file,
+ 'raw' => $image['data'],
+ 'mime' => $image['mime']);
+ }
+
+ if (isset($id3['id3v2']['APIC'])) {
+ // Foreach in case they have more then one
+ foreach ($id3['id3v2']['APIC'] as $image) {
+ $data[] = array(
+ 'song' => $song->file,
+ 'raw' => $image['data'],
+ 'mime' => $image['mime']);
+ }
+ }
+
+ if ($limit && count($data) >= $limit) {
+ return array_slice($data, 0, $limit);
+ }
+
+ } // end foreach
+
+ return $data;
+
+ } // gather_tags
+
+ /**
+ * gather_google
+ * Raw google search to retrieve the art, not very reliable
+ */
+ public function gather_google($limit = 5) {
+
+ $images = array();
+ $media = new $this->type($this->uid);
+ $media->format();
+
+ $search = $media->full_name;
+
+ if ($media->artist_count == '1')
+ $search = $media->artist_name . ', ' . $search;
+
+ $search = rawurlencode($search);
+
+ $size = '&imgsz=m'; // Medium
+ //$size = '&imgsz=l'; // Large
+
+ $html = file_get_contents("http://images.google.com/images?source=hp&q=$search&oq=&um=1&ie=UTF-8&sa=N&tab=wi&start=0&tbo=1$size");
+
+ if(preg_match_all("|\ssrc\=\"(http.+?)\"|", $html, $matches, PREG_PATTERN_ORDER))
+ foreach ($matches[1] as $match) {
+ $extension = "image/jpeg";
+
+ if (strrpos($extension, '.') !== false) $extension = substr($extension, strrpos($extension, '.') + 1);
+
+ $images[] = array('url' => $match, 'mime' => $extension);
+ }
+
+ return $images;
+
+ } // gather_google
+
+ /**
+ * gather_lastfm
+ * This returns the art from lastfm. It doesn't currently require an
+ * account but may in the future.
+ */
+ public function gather_lastfm($limit, $options = false) {
+
+ // Create the parser object
+ $lastfm = new LastFMSearch();
+
+ switch ($this->type) {
+ case 'album':
+ if (is_array($options)) {
+ $artist = $options['artist'];
+ $album = $options['album_name'];
+ }
+ else {
+ $media = new Album($this->uid);
+ $media->format();
+ $artist = $media->artist_name;
+ $album = $media->full_name;
+ }
+ break;
+ }
+
+ if(Config::get('proxy_host') AND Config::get('proxy_port')) {
+ $proxyhost = Config::get('proxy_host');
+ $proxyport = Config::get('proxy_port');
+ $proxyuser = Config::get('proxy_user');
+ $proxypass = Config::get('proxy_pass');
+ debug_event('LastFM', 'proxy set', 5);
+ $lastfm->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass);
+ }
+
+ $raw_data = $lastfm->album_search($artist, $album);
+
+ if (!count($raw_data)) { return array(); }
+
+ $coverart = $raw_data['coverart'];
+ if (!is_array($coverart)) { return array(); }
+
+ ksort($coverart);
+ foreach ($coverart as $url) {
+ // We need to check the URL for the /noimage/ stuff
+ if (strpos($url, '/noimage/') !== false) {
+ debug_event('LastFM', 'Detected as noimage, skipped ' . $url, 3);
+ continue;
+ }
+
+ // HACK: we shouldn't rely on the extension to determine file type
+ $results = pathinfo($url);
+ $mime = 'image/' . $results['extension'];
+ $data[] = array('url' => $url, 'mime' => $mime);
+ if ($limit && count($data) >= $limit) {
+ return $data;
+ }
+ } // end foreach
+
+ return $data;
+
+ } // gather_lastfm
} // Art
diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php
index d971e33a..caf24335 100644
--- a/lib/class/artist.class.php
+++ b/lib/class/artist.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,293 +22,293 @@
class Artist extends database_object {
- /* Variables from DB */
- public $id;
- public $name;
- public $songs;
- public $albums;
- public $prefix;
- public $mbid; // MusicBrainz ID
- public $catalog_id;
+ /* Variables from DB */
+ public $id;
+ public $name;
+ public $songs;
+ public $albums;
+ public $prefix;
+ public $mbid; // MusicBrainz ID
+ public $catalog_id;
- // Constructed vars
- public $_fake = false; // Set if construct_from_array() used
+ // Constructed vars
+ public $_fake = false; // Set if construct_from_array() used
- /**
- * Artist
- * Artist class, for modifing a artist
- * Takes the ID of the artist and pulls the info from the db
- */
- public function __construct($id='',$catalog_init=0) {
+ /**
+ * Artist
+ * Artist class, for modifing a artist
+ * Takes the ID of the artist and pulls the info from the db
+ */
+ public function __construct($id='',$catalog_init=0) {
- /* If they failed to pass in an id, just run for it */
- if (!$id) { return false; }
+ /* If they failed to pass in an id, just run for it */
+ if (!$id) { return false; }
- $this->catalog_id = $catalog_init;
- /* Get the information from the db */
- $info = $this->get_info($id);
+ $this->catalog_id = $catalog_init;
+ /* Get the information from the db */
+ $info = $this->get_info($id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- } // foreach info
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ } // foreach info
- return true;
+ return true;
- } //constructor
+ } //constructor
- /**
- * construct_from_array
- * This is used by the metadata class specifically but fills out a Artist object
- * based on a key'd array, it sets $_fake to true
- */
- public static function construct_from_array($data) {
+ /**
+ * construct_from_array
+ * This is used by the metadata class specifically but fills out a Artist object
+ * based on a key'd array, it sets $_fake to true
+ */
+ public static function construct_from_array($data) {
- $artist = new Artist(0);
- foreach ($data as $key=>$value) {
- $artist->$key = $value;
- }
+ $artist = new Artist(0);
+ foreach ($data as $key=>$value) {
+ $artist->$key = $value;
+ }
- //Ack that this is not a real object from the DB
- $artist->_fake = true;
+ //Ack that this is not a real object from the DB
+ $artist->_fake = true;
- return $artist;
+ return $artist;
- } // construct_from_array
+ } // construct_from_array
- /**
- * gc
- *
- * This cleans out unused artists
- */
- public static function gc() {
- Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` WHERE `song`.`id` IS NULL');
- }
+ /**
+ * gc
+ *
+ * This cleans out unused artists
+ */
+ public static function gc() {
+ Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` WHERE `song`.`id` IS NULL');
+ }
- /**
- * this attempts to build a cache of the data from the passed albums all in one query
- */
- public static function build_cache($ids,$extra=false) {
- if(!is_array($ids) OR !count($ids)) { return false; }
+ /**
+ * this attempts to build a cache of the data from the passed albums all in one query
+ */
+ public static function build_cache($ids,$extra=false) {
+ if(!is_array($ids) OR !count($ids)) { return false; }
- $idlist = '(' . implode(',', $ids) . ')';
+ $idlist = '(' . implode(',', $ids) . ')';
- $sql = "SELECT * FROM `artist` WHERE `id` IN $idlist";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `artist` WHERE `id` IN $idlist";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('artist',$row['id'],$row);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('artist',$row['id'],$row);
+ }
- // If we need to also pull the extra information, this is normally only used when we are doing the human display
- if ($extra) {
- $sql = "SELECT `song`.`artist`, COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist` IN $idlist GROUP BY `song`.`artist`";
-
- debug_event("Artist", "build_cache sql: " . $sql, "6");
- $db_results = Dba::read($sql);
+ // If we need to also pull the extra information, this is normally only used when we are doing the human display
+ if ($extra) {
+ $sql = "SELECT `song`.`artist`, COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist` IN $idlist GROUP BY `song`.`artist`";
+
+ debug_event("Artist", "build_cache sql: " . $sql, "6");
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('artist_extra',$row['artist'],$row);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('artist_extra',$row['artist'],$row);
+ }
- } // end if extra
+ } // end if extra
- return true;
+ return true;
- } // build_cache
+ } // build_cache
- /**
- * get_from_name
- * This gets an artist object based on the artist name
- */
- public static function get_from_name($name) {
+ /**
+ * get_from_name
+ * This gets an artist object based on the artist name
+ */
+ public static function get_from_name($name) {
- $name = Dba::escape($name);
- $sql = "SELECT `id` FROM `artist` WHERE `name`='$name'";
- $db_results = Dba::write($sql);
+ $name = Dba::escape($name);
+ $sql = "SELECT `id` FROM `artist` WHERE `name`='$name'";
+ $db_results = Dba::write($sql);
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- $object = new Artist($row['id']);
+ $object = new Artist($row['id']);
- return $object;
+ return $object;
- } // get_from_name
+ } // get_from_name
- /**
- * get_albums
- * gets the album ids that this artist is a part
- * of
- */
- public function get_albums($catalog = null) {
+ /**
+ * get_albums
+ * gets the album ids that this artist is a part
+ * of
+ */
+ public function get_albums($catalog = null) {
- if($catalog) {
- $catalog_join = "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
- $catalog_where = "AND `catalog`.`id` = '$catalog'";
- }
+ if($catalog) {
+ $catalog_join = "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
+ $catalog_where = "AND `catalog`.`id` = '$catalog'";
+ }
- $results = array();
+ $results = array();
- $sql = "SELECT `album`.`id` FROM album LEFT JOIN `song` ON `song`.`album`=`album`.`id` $catalog_join " .
- "WHERE `song`.`artist`='$this->id' $catalog_where GROUP BY `album`.`id` ORDER BY `album`.`name`,`album`.`disk`,`album`.`year`";
+ $sql = "SELECT `album`.`id` FROM album LEFT JOIN `song` ON `song`.`album`=`album`.`id` $catalog_join " .
+ "WHERE `song`.`artist`='$this->id' $catalog_where GROUP BY `album`.`id` ORDER BY `album`.`name`,`album`.`disk`,`album`.`year`";
- debug_event("Artist", "$sql", "6");
- $db_results = Dba::read($sql);
+ debug_event("Artist", "$sql", "6");
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['id'];
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['id'];
+ }
- return $results;
+ return $results;
- } // get_albums
+ } // get_albums
- /**
- * get_songs
- * gets the songs for this artist
- */
- public function get_songs() {
+ /**
+ * get_songs
+ * gets the songs for this artist
+ */
+ public function get_songs() {
- $sql = "SELECT `song`.`id` FROM `song` WHERE `song`.`artist`='" . Dba::escape($this->id) . "' ORDER BY album, track";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `song`.`id` FROM `song` WHERE `song`.`artist`='" . Dba::escape($this->id) . "' ORDER BY album, track";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['id'];
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['id'];
+ }
- return $results;
+ return $results;
- } // get_songs
+ } // get_songs
- /**
- * get_random_songs
- * Gets the songs from this artist in a random order
- */
- public function get_random_songs() {
+ /**
+ * get_random_songs
+ * Gets the songs from this artist in a random order
+ */
+ public function get_random_songs() {
- $results = array();
+ $results = array();
- $sql = "SELECT `id` FROM `song` WHERE `artist`='$this->id' ORDER BY RAND()";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `song` WHERE `artist`='$this->id' ORDER BY RAND()";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['id'];
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['id'];
+ }
- return $results;
+ return $results;
- } // get_random_songs
+ } // get_random_songs
- /**
- * _get_extra info
- * This returns the extra information for the artist, this means totals etc
- */
- private function _get_extra_info($catalog=FALSE) {
+ /**
+ * _get_extra info
+ * This returns the extra information for the artist, this means totals etc
+ */
+ private function _get_extra_info($catalog=FALSE) {
- // Try to find it in the cache and save ourselves the trouble
- if (parent::is_cached('artist_extra',$this->id) ) {
- $row = parent::get_from_cache('artist_extra',$this->id);
- }
- else {
- $uid = Dba::escape($this->id);
- $sql = "SELECT `song`.`artist`,COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist`='$uid' ";
- if ($catalog) {
- $sql .= "AND (`song`.`catalog` = '$catalog') ";
- }
+ // Try to find it in the cache and save ourselves the trouble
+ if (parent::is_cached('artist_extra',$this->id) ) {
+ $row = parent::get_from_cache('artist_extra',$this->id);
+ }
+ else {
+ $uid = Dba::escape($this->id);
+ $sql = "SELECT `song`.`artist`,COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist`='$uid' ";
+ if ($catalog) {
+ $sql .= "AND (`song`.`catalog` = '$catalog') ";
+ }
- $sql .= "GROUP BY `song`.`artist`";
-
- $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
- parent::add_to_cache('artist_extra',$row['artist'],$row);
- }
+ $sql .= "GROUP BY `song`.`artist`";
+
+ $db_results = Dba::read($sql);
+ $row = Dba::fetch_assoc($db_results);
+ parent::add_to_cache('artist_extra',$row['artist'],$row);
+ }
- /* Set Object Vars */
- $this->songs = $row['song_count'];
- $this->albums = $row['album_count'];
- $this->time = $row['time'];
+ /* Set Object Vars */
+ $this->songs = $row['song_count'];
+ $this->albums = $row['album_count'];
+ $this->time = $row['time'];
- return $row;
+ return $row;
- } // _get_extra_info
+ } // _get_extra_info
- /**
- * format
- * this function takes an array of artist
- * information and reformats the relevent values
- * so they can be displayed in a table for example
- * it changes the title into a full link.
- */
- public function format() {
+ /**
+ * format
+ * this function takes an array of artist
+ * information and reformats the relevent values
+ * so they can be displayed in a table for example
+ * it changes the title into a full link.
+ */
+ public function format() {
- /* Combine prefix and name, trim then add ... if needed */
- $name = UI::truncate(trim($this->prefix . " " . $this->name),Config::get('ellipse_threshold_artist'));
- $this->f_name = $name;
- $this->f_full_name = trim(trim($this->prefix) . ' ' . trim($this->name));
+ /* Combine prefix and name, trim then add ... if needed */
+ $name = UI::truncate(trim($this->prefix . " " . $this->name),Config::get('ellipse_threshold_artist'));
+ $this->f_name = $name;
+ $this->f_full_name = trim(trim($this->prefix) . ' ' . trim($this->name));
- // If this is a fake object, we're done here
- if ($this->_fake) { return true; }
+ // If this is a fake object, we're done here
+ if ($this->_fake) { return true; }
- if ($this->catalog_id) {
- $this->f_name_link = "<a href=\"" . Config::get('web_path') . "/artists.php?action=show&amp;catalog=" . $this->catalog_id . "&amp;artist=" . $this->id . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
- $this->f_link = Config::get('web_path') . '/artists.php?action=show&amp;catalog=' . $this->catalog_id . '&amp;artist=' . $this->id;
- } else {
- $this->f_name_link = "<a href=\"" . Config::get('web_path') . "/artists.php?action=show&amp;artist=" . $this->id . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
- $this->f_link = Config::get('web_path') . '/artists.php?action=show&amp;artist=' . $this->id;
- }
- // Get the counts
- $extra_info = $this->_get_extra_info($this->catalog_id);
-
- //Format the new time thingy that we just got
- $min = sprintf("%02d",(floor($extra_info['time']/60)%60));
-
- $sec = sprintf("%02d",($extra_info['time']%60));
- $hours = floor($extra_info['time']/3600);
-
- $this->f_time = ltrim($hours . ':' . $min . ':' . $sec,'0:');
-
- $this->tags = Tag::get_top_tags('artist',$this->id);
-
- $this->f_tags = Tag::get_display($this->tags,$this->id,'artist');
-
- return true;
-
- } // format
-
- /**
- * update
- * This takes a key'd array of data and updates the current artist
- * it will flag songs as neeed
- */
- public function update($data) {
-
- // Save our current ID
- $current_id = $this->id;
-
- $artist_id = Catalog::check_artist($data['name'], $this->mbid);
-
- // If it's changed we need to update
- if ($artist_id != $this->id) {
- $songs = $this->get_songs();
- foreach ($songs as $song_id) {
- Song::update_artist($artist_id,$song_id);
- }
- $updated = 1;
- $current_id = $artist_id;
- self::gc();
- } // end if it changed
-
- if ($updated) {
- foreach ($songs as $song_id) {
- Flag::add($song_id,'song','retag','Interface Artist Update');
- Song::update_utime($song_id);
- }
- Stats::gc();
- Rating::gc();
- } // if updated
-
- return $current_id;
-
- } // update
+ if ($this->catalog_id) {
+ $this->f_name_link = "<a href=\"" . Config::get('web_path') . "/artists.php?action=show&amp;catalog=" . $this->catalog_id . "&amp;artist=" . $this->id . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
+ $this->f_link = Config::get('web_path') . '/artists.php?action=show&amp;catalog=' . $this->catalog_id . '&amp;artist=' . $this->id;
+ } else {
+ $this->f_name_link = "<a href=\"" . Config::get('web_path') . "/artists.php?action=show&amp;artist=" . $this->id . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
+ $this->f_link = Config::get('web_path') . '/artists.php?action=show&amp;artist=' . $this->id;
+ }
+ // Get the counts
+ $extra_info = $this->_get_extra_info($this->catalog_id);
+
+ //Format the new time thingy that we just got
+ $min = sprintf("%02d",(floor($extra_info['time']/60)%60));
+
+ $sec = sprintf("%02d",($extra_info['time']%60));
+ $hours = floor($extra_info['time']/3600);
+
+ $this->f_time = ltrim($hours . ':' . $min . ':' . $sec,'0:');
+
+ $this->tags = Tag::get_top_tags('artist',$this->id);
+
+ $this->f_tags = Tag::get_display($this->tags,$this->id,'artist');
+
+ return true;
+
+ } // format
+
+ /**
+ * update
+ * This takes a key'd array of data and updates the current artist
+ * it will flag songs as neeed
+ */
+ public function update($data) {
+
+ // Save our current ID
+ $current_id = $this->id;
+
+ $artist_id = Catalog::check_artist($data['name'], $this->mbid);
+
+ // If it's changed we need to update
+ if ($artist_id != $this->id) {
+ $songs = $this->get_songs();
+ foreach ($songs as $song_id) {
+ Song::update_artist($artist_id,$song_id);
+ }
+ $updated = 1;
+ $current_id = $artist_id;
+ self::gc();
+ } // end if it changed
+
+ if ($updated) {
+ foreach ($songs as $song_id) {
+ Flag::add($song_id,'song','retag','Interface Artist Update');
+ Song::update_utime($song_id);
+ }
+ Stats::gc();
+ Rating::gc();
+ } // if updated
+
+ return $current_id;
+
+ } // update
} // end of artist class
?>
diff --git a/lib/class/browse.class.php b/lib/class/browse.class.php
index ce22728e..e747430a 100644
--- a/lib/class/browse.class.php
+++ b/lib/class/browse.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -31,218 +31,218 @@
*/
class Browse extends Query {
- /**
- * set_simple_browse
- * This sets the current browse object to a 'simple' browse method
- * which means use the base query provided and expand from there
- */
- public function set_simple_browse($value) {
-
- $this->set_is_simple($value);
-
- } // set_simple_browse
-
- /**
- * add_supplemental_object
- * Legacy function, need to find a better way to do that
- */
- public function add_supplemental_object($class, $uid) {
-
- $_SESSION['browse']['supplemental'][$this->id][$class] = intval($uid);
-
- return true;
-
- } // add_supplemental_object
-
- /**
- * get_supplemental_objects
- * This returns an array of 'class','id' for additional objects that
- * need to be created before we start this whole browsing thing.
- */
- public function get_supplemental_objects() {
-
- $objects = $_SESSION['browse']['supplemental'][$this->id];
-
- if (!is_array($objects)) { $objects = array(); }
-
- return $objects;
-
- } // get_supplemental_objects
-
- /**
- * show_objects
- * This takes an array of objects
- * and requires the correct template based on the
- * type that we are currently browsing
- */
- public function show_objects($object_ids = null) {
-
- if ($this->is_simple() || ! is_array($object_ids)) {
- $object_ids = $this->get_saved();
- }
- else {
- $this->save_objects($object_ids);
- }
-
- // Limit is based on the user's preferences if this is not a
- // simple browse because we've got too much here
- if ((count($object_ids) > $this->get_start()) &&
- ! $this->is_simple() &&
- ! $this->is_static_content()) {
- $object_ids = array_slice(
- $object_ids,
- $this->get_start(),
- $this->get_offset(),
- true
- );
- }
-
- // Load any additional object we need for this
- $extra_objects = $this->get_supplemental_objects();
- $browse = $this;
-
- foreach ($extra_objects as $class_name => $id) {
- ${$class_name} = new $class_name($id);
- }
-
- $match = '';
- // Format any matches we have so we can show them to the masses
- if ($filter_value = $this->get_filter('alpha_match')) {
- $match = ' (' . $filter_value . ')';
- }
- elseif ($filter_value = $this->get_filter('starts_with')) {
- $match = ' (' . $filter_value . ')';
- } elseif ($filter_value = $this->get_filter('catalog')) {
- // Get the catalog title
- $catalog = new Catalog($filter_value);
- $match = ' (' . $catalog->name . ')';
- }
-
- $type = $this->get_type();
-
- // Set the correct classes based on type
- $class = "box browse_" . $type;
-
- Ajax::start_container('browse_content');
- // Switch on the type of browsing we're doing
- switch ($type) {
- case 'song':
- UI::show_box_top(T_('Songs') . $match, $class);
- Song::build_cache($object_ids);
- require_once Config::get('prefix') . '/templates/show_songs.inc.php';
- UI::show_box_bottom();
- break;
- case 'album':
- UI::show_box_top(T_('Albums') . $match, $class);
- Album::build_cache($object_ids,'extra');
- require_once Config::get('prefix') . '/templates/show_albums.inc.php';
- UI::show_box_bottom();
- break;
- case 'user':
- UI::show_box_top(T_('Manage Users') . $match, $class);
- require_once Config::get('prefix') . '/templates/show_users.inc.php';
- UI::show_box_bottom();
- break;
- case 'artist':
- UI::show_box_top(T_('Artists') . $match, $class);
- Artist::build_cache($object_ids,'extra');
- require_once Config::get('prefix') . '/templates/show_artists.inc.php';
- UI::show_box_bottom();
- break;
- case 'live_stream':
- require_once Config::get('prefix') . '/templates/show_live_stream.inc.php';
- UI::show_box_top(T_('Radio Stations') . $match, $class);
- require_once Config::get('prefix') . '/templates/show_live_streams.inc.php';
- UI::show_box_bottom();
- break;
- case 'playlist':
- Playlist::build_cache($object_ids);
- UI::show_box_top(T_('Playlists') . $match, $class);
- require_once Config::get('prefix') . '/templates/show_playlists.inc.php';
- UI::show_box_bottom();
- break;
- case 'playlist_song':
- UI::show_box_top(T_('Playlist Songs') . $match,$class);
- require_once Config::get('prefix') . '/templates/show_playlist_songs.inc.php';
- UI::show_box_bottom();
- break;
- case 'playlist_localplay':
- UI::show_box_top(T_('Current Playlist'));
- require_once Config::get('prefix') . '/templates/show_localplay_playlist.inc.php';
- UI::show_box_bottom();
- break;
- case 'smartplaylist':
- UI::show_box_top(T_('Smart Playlists') . $match, $class);
- require_once Config::get('prefix') . '/templates/show_smartplaylists.inc.php';
- UI::show_box_bottom();
- break;
- case 'catalog':
- UI::show_box_top(T_('Catalogs'), $class);
- require_once Config::get('prefix') . '/templates/show_catalogs.inc.php';
- UI::show_box_bottom();
- break;
- case 'shoutbox':
- UI::show_box_top(T_('Shoutbox Records'),$class);
- require_once Config::get('prefix') . '/templates/show_manage_shoutbox.inc.php';
- UI::show_box_bottom();
- break;
- case 'flagged':
- UI::show_box_top(T_('Flagged Records'),$class);
- require_once Config::get('prefix') . '/templates/show_flagged.inc.php';
- UI::show_box_bottom();
- break;
- case 'tag':
- Tag::build_cache($tags);
- UI::show_box_top(T_('Tag Cloud'),$class);
- require_once Config::get('prefix') . '/templates/show_tagcloud.inc.php';
- UI::show_box_bottom();
- break;
- case 'video':
- Video::build_cache($object_ids);
- UI::show_box_top(T_('Videos'),$class);
- require_once Config::get('prefix') . '/templates/show_videos.inc.php';
- UI::show_box_bottom();
- break;
- case 'democratic':
- UI::show_box_top(T_('Democratic Playlist'),$class);
- require_once Config::get('prefix') . '/templates/show_democratic_playlist.inc.php';
- UI::show_box_bottom();
- default:
- // Rien a faire
- break;
- } // end switch on type
- echo '<script type="text/javascript">';
- echo Ajax::action('?page=browse&action=get_filters&browse_id=' . $this->id, '');
- echo ';</script>';
-
- Ajax::end_container();
-
- } // show_object
-
- /**
- * set_filter_from_request
- * //FIXME
- */
- public function set_filter_from_request($request) {
- foreach($request as $key => $value) {
- //reinterpret v as a list of int
- $list = explode(',', $value);
- $ok = true;
- foreach($list as $item) {
- if (!is_numeric($item)) {
- $ok = false;
- break;
- }
- }
- if ($ok) {
- if (sizeof($list) == 1) {
- $this->set_filter($key, $list[0]);
- }
- }
- else {
- $this->set_filter($key, $list);
- }
- }
- } // set_filter_from_request
+ /**
+ * set_simple_browse
+ * This sets the current browse object to a 'simple' browse method
+ * which means use the base query provided and expand from there
+ */
+ public function set_simple_browse($value) {
+
+ $this->set_is_simple($value);
+
+ } // set_simple_browse
+
+ /**
+ * add_supplemental_object
+ * Legacy function, need to find a better way to do that
+ */
+ public function add_supplemental_object($class, $uid) {
+
+ $_SESSION['browse']['supplemental'][$this->id][$class] = intval($uid);
+
+ return true;
+
+ } // add_supplemental_object
+
+ /**
+ * get_supplemental_objects
+ * This returns an array of 'class','id' for additional objects that
+ * need to be created before we start this whole browsing thing.
+ */
+ public function get_supplemental_objects() {
+
+ $objects = $_SESSION['browse']['supplemental'][$this->id];
+
+ if (!is_array($objects)) { $objects = array(); }
+
+ return $objects;
+
+ } // get_supplemental_objects
+
+ /**
+ * show_objects
+ * This takes an array of objects
+ * and requires the correct template based on the
+ * type that we are currently browsing
+ */
+ public function show_objects($object_ids = null) {
+
+ if ($this->is_simple() || ! is_array($object_ids)) {
+ $object_ids = $this->get_saved();
+ }
+ else {
+ $this->save_objects($object_ids);
+ }
+
+ // Limit is based on the user's preferences if this is not a
+ // simple browse because we've got too much here
+ if ((count($object_ids) > $this->get_start()) &&
+ ! $this->is_simple() &&
+ ! $this->is_static_content()) {
+ $object_ids = array_slice(
+ $object_ids,
+ $this->get_start(),
+ $this->get_offset(),
+ true
+ );
+ }
+
+ // Load any additional object we need for this
+ $extra_objects = $this->get_supplemental_objects();
+ $browse = $this;
+
+ foreach ($extra_objects as $class_name => $id) {
+ ${$class_name} = new $class_name($id);
+ }
+
+ $match = '';
+ // Format any matches we have so we can show them to the masses
+ if ($filter_value = $this->get_filter('alpha_match')) {
+ $match = ' (' . $filter_value . ')';
+ }
+ elseif ($filter_value = $this->get_filter('starts_with')) {
+ $match = ' (' . $filter_value . ')';
+ } elseif ($filter_value = $this->get_filter('catalog')) {
+ // Get the catalog title
+ $catalog = new Catalog($filter_value);
+ $match = ' (' . $catalog->name . ')';
+ }
+
+ $type = $this->get_type();
+
+ // Set the correct classes based on type
+ $class = "box browse_" . $type;
+
+ Ajax::start_container('browse_content');
+ // Switch on the type of browsing we're doing
+ switch ($type) {
+ case 'song':
+ UI::show_box_top(T_('Songs') . $match, $class);
+ Song::build_cache($object_ids);
+ require_once Config::get('prefix') . '/templates/show_songs.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'album':
+ UI::show_box_top(T_('Albums') . $match, $class);
+ Album::build_cache($object_ids,'extra');
+ require_once Config::get('prefix') . '/templates/show_albums.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'user':
+ UI::show_box_top(T_('Manage Users') . $match, $class);
+ require_once Config::get('prefix') . '/templates/show_users.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'artist':
+ UI::show_box_top(T_('Artists') . $match, $class);
+ Artist::build_cache($object_ids,'extra');
+ require_once Config::get('prefix') . '/templates/show_artists.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'live_stream':
+ require_once Config::get('prefix') . '/templates/show_live_stream.inc.php';
+ UI::show_box_top(T_('Radio Stations') . $match, $class);
+ require_once Config::get('prefix') . '/templates/show_live_streams.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'playlist':
+ Playlist::build_cache($object_ids);
+ UI::show_box_top(T_('Playlists') . $match, $class);
+ require_once Config::get('prefix') . '/templates/show_playlists.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'playlist_song':
+ UI::show_box_top(T_('Playlist Songs') . $match,$class);
+ require_once Config::get('prefix') . '/templates/show_playlist_songs.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'playlist_localplay':
+ UI::show_box_top(T_('Current Playlist'));
+ require_once Config::get('prefix') . '/templates/show_localplay_playlist.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'smartplaylist':
+ UI::show_box_top(T_('Smart Playlists') . $match, $class);
+ require_once Config::get('prefix') . '/templates/show_smartplaylists.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'catalog':
+ UI::show_box_top(T_('Catalogs'), $class);
+ require_once Config::get('prefix') . '/templates/show_catalogs.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'shoutbox':
+ UI::show_box_top(T_('Shoutbox Records'),$class);
+ require_once Config::get('prefix') . '/templates/show_manage_shoutbox.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'flagged':
+ UI::show_box_top(T_('Flagged Records'),$class);
+ require_once Config::get('prefix') . '/templates/show_flagged.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'tag':
+ Tag::build_cache($tags);
+ UI::show_box_top(T_('Tag Cloud'),$class);
+ require_once Config::get('prefix') . '/templates/show_tagcloud.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'video':
+ Video::build_cache($object_ids);
+ UI::show_box_top(T_('Videos'),$class);
+ require_once Config::get('prefix') . '/templates/show_videos.inc.php';
+ UI::show_box_bottom();
+ break;
+ case 'democratic':
+ UI::show_box_top(T_('Democratic Playlist'),$class);
+ require_once Config::get('prefix') . '/templates/show_democratic_playlist.inc.php';
+ UI::show_box_bottom();
+ default:
+ // Rien a faire
+ break;
+ } // end switch on type
+ echo '<script type="text/javascript">';
+ echo Ajax::action('?page=browse&action=get_filters&browse_id=' . $this->id, '');
+ echo ';</script>';
+
+ Ajax::end_container();
+
+ } // show_object
+
+ /**
+ * set_filter_from_request
+ * //FIXME
+ */
+ public function set_filter_from_request($request) {
+ foreach($request as $key => $value) {
+ //reinterpret v as a list of int
+ $list = explode(',', $value);
+ $ok = true;
+ foreach($list as $item) {
+ if (!is_numeric($item)) {
+ $ok = false;
+ break;
+ }
+ }
+ if ($ok) {
+ if (sizeof($list) == 1) {
+ $this->set_filter($key, $list[0]);
+ }
+ }
+ else {
+ $this->set_filter($key, $list);
+ }
+ }
+ } // set_filter_from_request
} // browse
diff --git a/lib/class/catalog.class.php b/lib/class/catalog.class.php
index 3833d329..df5229a4 100644
--- a/lib/class/catalog.class.php
+++ b/lib/class/catalog.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,2079 +29,2079 @@
*/
class Catalog extends database_object {
- public $name;
- public $last_update;
- public $last_add;
- public $last_clean;
- public $key;
- public $rename_pattern;
- public $sort_pattern;
- public $catalog_type;
- public $path;
+ public $name;
+ public $last_update;
+ public $last_add;
+ public $last_clean;
+ public $key;
+ public $rename_pattern;
+ public $sort_pattern;
+ public $catalog_type;
+ public $path;
- /* This is a private var that's used during catalog builds */
- private $_playlists = array();
+ /* This is a private var that's used during catalog builds */
+ private $_playlists = array();
- // Cache all files in catalog for quick lookup during add
- private $_filecache = array();
+ // Cache all files in catalog for quick lookup during add
+ private $_filecache = array();
- // Used in functions
- private static $albums = array();
- private static $artists = array();
- private static $tags = array();
- private static $_art_albums = array();
+ // Used in functions
+ private static $albums = array();
+ private static $artists = array();
+ private static $tags = array();
+ private static $_art_albums = array();
- /**
- * Constructor
- * Catalog class constructor, pulls catalog information
- * $catalog_id The ID of the catalog you want to build information from
- */
- public function __construct($catalog_id = '') {
-
- if (!$catalog_id) { return false; }
-
- /* Assign id for use in get_info() */
- $this->id = intval($catalog_id);
+ /**
+ * Constructor
+ * Catalog class constructor, pulls catalog information
+ * $catalog_id The ID of the catalog you want to build information from
+ */
+ public function __construct($catalog_id = '') {
+
+ if (!$catalog_id) { return false; }
+
+ /* Assign id for use in get_info() */
+ $this->id = intval($catalog_id);
- /* Get the information from the db */
- $info = $this->get_info($catalog_id);
+ /* Get the information from the db */
+ $info = $this->get_info($catalog_id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
- } //constructor
+ } //constructor
- /**
- * _create_filecache
- * This poplates an array (filecache) on this object from the database
- * it is used to speed up the add process
- */
- private function _create_filecache() {
+ /**
+ * _create_filecache
+ * This poplates an array (filecache) on this object from the database
+ * it is used to speed up the add process
+ */
+ private function _create_filecache() {
- if (count($this->_filecache) == 0) {
- $catalog_id = Dba::escape($this->id);
- // Get _EVERYTHING_
- $sql = "SELECT `id`,`file` FROM `song` WHERE `catalog`='$catalog_id'";
- $db_results = Dba::read($sql);
-
- // Populate the filecache
- while ($results = Dba::fetch_assoc($db_results)) {
- $this->_filecache[strtolower($results['file'])] = $results['id'];
- }
+ if (count($this->_filecache) == 0) {
+ $catalog_id = Dba::escape($this->id);
+ // Get _EVERYTHING_
+ $sql = "SELECT `id`,`file` FROM `song` WHERE `catalog`='$catalog_id'";
+ $db_results = Dba::read($sql);
+
+ // Populate the filecache
+ while ($results = Dba::fetch_assoc($db_results)) {
+ $this->_filecache[strtolower($results['file'])] = $results['id'];
+ }
- $sql = "SELECT `id`,`file` FROM `video` WHERE `catalog`='$catalog_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id`,`file` FROM `video` WHERE `catalog`='$catalog_id'";
+ $db_results = Dba::read($sql);
- while ($results = Dba::fetch_assoc($db_results)) {
- $this->_filecache[strtolower($results['file'])] = 'v_' . $results['id'];
- }
- } // end if empty filecache
+ while ($results = Dba::fetch_assoc($db_results)) {
+ $this->_filecache[strtolower($results['file'])] = 'v_' . $results['id'];
+ }
+ } // end if empty filecache
- return true;
+ return true;
- } // _create_filecache
+ } // _create_filecache
- /**
- * get_from_path
- * Try to figure out which catalog path most closely resembles this one
- * This is useful when creating a new catalog to make sure we're not
- * doubling up here.
- */
- public static function get_from_path($path) {
+ /**
+ * get_from_path
+ * Try to figure out which catalog path most closely resembles this one
+ * This is useful when creating a new catalog to make sure we're not
+ * doubling up here.
+ */
+ public static function get_from_path($path) {
- // First pull a list of all of the paths for the different catalogs
- $sql = "SELECT `id`,`path` FROM `catalog` WHERE `catalog_type`='local'";
- $db_results = Dba::read($sql);
+ // First pull a list of all of the paths for the different catalogs
+ $sql = "SELECT `id`,`path` FROM `catalog` WHERE `catalog_type`='local'";
+ $db_results = Dba::read($sql);
- $catalog_paths = array();
- $component_path = $path;
+ $catalog_paths = array();
+ $component_path = $path;
- while ($row = Dba::fetch_assoc($db_results)) {
- $catalog_paths[$row['path']] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $catalog_paths[$row['path']] = $row['id'];
+ }
- // Break it down into its component parts and start looking for a catalog
- do {
- if ($catalog_paths[$component_path]) {
- return $catalog_paths[$component_path];
- }
+ // Break it down into its component parts and start looking for a catalog
+ do {
+ if ($catalog_paths[$component_path]) {
+ return $catalog_paths[$component_path];
+ }
- // Keep going until the path stops changing
- $old_path = $component_path;
- $component_path = realpath($component_path . '/../');
+ // Keep going until the path stops changing
+ $old_path = $component_path;
+ $component_path = realpath($component_path . '/../');
- } while (strcmp($component_path,$old_path) != 0);
+ } while (strcmp($component_path,$old_path) != 0);
- return false;
+ return false;
- } // get_from_path
+ } // get_from_path
- /**
- * format
- * This makes the object human readable
- */
- public function format() {
+ /**
+ * format
+ * This makes the object human readable
+ */
+ public function format() {
- $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title'));
- $this->f_name_link = '<a href="' . Config::get('web_path') . '/admin/catalog.php?action=show_customize_catalog&catalog_id=' . $this->id . '" title="' . scrub_out($this->name) . '">' . scrub_out($this->f_name) . '</a>';
- $this->f_path = UI::truncate($this->path,Config::get('ellipse_threshold_title'));
- $this->f_update = $this->last_update ? date('d/m/Y h:i',$this->last_update) : T_('Never');
- $this->f_add = $this->last_add ? date('d/m/Y h:i',$this->last_add) : T_('Never');
- $this->f_clean = $this->last_clean ? date('d/m/Y h:i',$this->last_clean) : T_('Never');
+ $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title'));
+ $this->f_name_link = '<a href="' . Config::get('web_path') . '/admin/catalog.php?action=show_customize_catalog&catalog_id=' . $this->id . '" title="' . scrub_out($this->name) . '">' . scrub_out($this->f_name) . '</a>';
+ $this->f_path = UI::truncate($this->path,Config::get('ellipse_threshold_title'));
+ $this->f_update = $this->last_update ? date('d/m/Y h:i',$this->last_update) : T_('Never');
+ $this->f_add = $this->last_add ? date('d/m/Y h:i',$this->last_add) : T_('Never');
+ $this->f_clean = $this->last_clean ? date('d/m/Y h:i',$this->last_clean) : T_('Never');
- } // format
+ } // format
- /**
- * get_catalogs
- * Pull all the current catalogs and return an array of ids
- * of what you find
- */
- public static function get_catalogs() {
+ /**
+ * get_catalogs
+ * Pull all the current catalogs and return an array of ids
+ * of what you find
+ */
+ public static function get_catalogs() {
- $sql = "SELECT `id` FROM `catalog` ORDER BY `name`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `catalog` ORDER BY `name`";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_catalogs
-
- /**
- * get_stats
- * This returns an hash with the #'s for the different
- * objects that are associated with this catalog. This is used
- * to build the stats box, it also calculates time.
- */
- public static function get_stats($catalog_id = null) {
-
- $results = self::count_songs($catalog_id);
- $results = array_merge(self::count_users($catalog_id), $results);
- $results['tags'] = self::count_tags();
- $results = array_merge(self::count_videos($catalog_id), $results);
+ } // get_catalogs
+
+ /**
+ * get_stats
+ * This returns an hash with the #'s for the different
+ * objects that are associated with this catalog. This is used
+ * to build the stats box, it also calculates time.
+ */
+ public static function get_stats($catalog_id = null) {
+
+ $results = self::count_songs($catalog_id);
+ $results = array_merge(self::count_users($catalog_id), $results);
+ $results['tags'] = self::count_tags();
+ $results = array_merge(self::count_videos($catalog_id), $results);
- $hours = floor($results['time'] / 3600);
+ $hours = floor($results['time'] / 3600);
- $results['formatted_size'] = UI::format_bytes($results['size']);
+ $results['formatted_size'] = UI::format_bytes($results['size']);
- $days = floor($hours / 24);
- $hours = $hours % 24;
+ $days = floor($hours / 24);
+ $hours = $hours % 24;
- $time_text = "$days ";
- $time_text .= T_ngettext('day','days',$days);
- $time_text .= ", $hours ";
- $time_text .= T_ngettext('hour','hours',$hours);
+ $time_text = "$days ";
+ $time_text .= T_ngettext('day','days',$days);
+ $time_text .= ", $hours ";
+ $time_text .= T_ngettext('hour','hours',$hours);
- $results['time_text'] = $time_text;
+ $results['time_text'] = $time_text;
- return $results;
+ return $results;
- } // get_stats
-
- /**
- * create
- * This creates a new catalog entry and then returns the insert id
- * it checks to make sure this path is not already used before creating
- * the catalog
- */
- public static function create($data) {
+ } // get_stats
+
+ /**
+ * create
+ * This creates a new catalog entry and then returns the insert id
+ * it checks to make sure this path is not already used before creating
+ * the catalog
+ */
+ public static function create($data) {
- // Clean up the path just in case
- $data['path'] = rtrim(rtrim(trim($data['path']),'/'),'\\');
+ // Clean up the path just in case
+ $data['path'] = rtrim(rtrim(trim($data['path']),'/'),'\\');
- $path = Dba::escape($data['path']);
+ $path = Dba::escape($data['path']);
- // Make sure the path is readable/exists
- if ($data['type'] == 'local') {
- $handle = opendir($path);
- if ($handle === false) {
- Error::add('general', sprintf(T_('Error: %s is not readable or does not exist'), scrub_out($data['path'])));
- return false;
- }
- closedir($handle);
- }
+ // Make sure the path is readable/exists
+ if ($data['type'] == 'local') {
+ $handle = opendir($path);
+ if ($handle === false) {
+ Error::add('general', sprintf(T_('Error: %s is not readable or does not exist'), scrub_out($data['path'])));
+ return false;
+ }
+ closedir($handle);
+ }
- // Make sure this path isn't already in use by an existing catalog
- $sql = "SELECT `id` FROM `catalog` WHERE `path`='$path'";
- $db_results = Dba::read($sql);
+ // Make sure this path isn't already in use by an existing catalog
+ $sql = "SELECT `id` FROM `catalog` WHERE `path`='$path'";
+ $db_results = Dba::read($sql);
- if (Dba::num_rows($db_results)) {
- Error::add('general', sprintf(T_('Error: Catalog with %s already exists'), $path));
- return false;
- }
+ if (Dba::num_rows($db_results)) {
+ Error::add('general', sprintf(T_('Error: Catalog with %s already exists'), $path));
+ return false;
+ }
- $name = Dba::escape($data['name']);
- $catalog_type = Dba::escape($data['type']);
- $rename_pattern = Dba::escape($data['rename_pattern']);
- $sort_pattern = Dba::escape($data['sort_pattern']);
- $gather_types = 'NULL';
- $remote_username = 'NULL';
- $remote_password = 'NULL';
+ $name = Dba::escape($data['name']);
+ $catalog_type = Dba::escape($data['type']);
+ $rename_pattern = Dba::escape($data['rename_pattern']);
+ $sort_pattern = Dba::escape($data['sort_pattern']);
+ $gather_types = 'NULL';
+ $remote_username = 'NULL';
+ $remote_password = 'NULL';
- // Don't save these if it isn't a remote catalog
- if ($catalog_type == 'remote') {
- $remote_username = "'" . Dba::escape($data['remote_username']) . "'";
- $remote_password = "'" . Dba::escape($data['remote_password']) . "'";
- }
+ // Don't save these if it isn't a remote catalog
+ if ($catalog_type == 'remote') {
+ $remote_username = "'" . Dba::escape($data['remote_username']) . "'";
+ $remote_password = "'" . Dba::escape($data['remote_password']) . "'";
+ }
- // Ok we're good to go ahead and insert this record
- $sql = "INSERT INTO `catalog` (`name`,`path`,`catalog_type`,`remote_username`,`remote_password`,`rename_pattern`,`sort_pattern`,`gather_types`) " .
- "VALUES ('$name','$path','$catalog_type',$remote_username,$remote_password,'$rename_pattern','$sort_pattern',$gather_types)";
- $db_results = Dba::write($sql);
+ // Ok we're good to go ahead and insert this record
+ $sql = "INSERT INTO `catalog` (`name`,`path`,`catalog_type`,`remote_username`,`remote_password`,`rename_pattern`,`sort_pattern`,`gather_types`) " .
+ "VALUES ('$name','$path','$catalog_type',$remote_username,$remote_password,'$rename_pattern','$sort_pattern',$gather_types)";
+ $db_results = Dba::write($sql);
- $insert_id = Dba::insert_id();
+ $insert_id = Dba::insert_id();
- if (!$insert_id) {
- Error::add('general', T_('Catalog Insert Failed check debug logs'));
- debug_event('catalog','SQL Failed:' . $sql,'3');
- return false;
- }
+ if (!$insert_id) {
+ Error::add('general', T_('Catalog Insert Failed check debug logs'));
+ debug_event('catalog','SQL Failed:' . $sql,'3');
+ return false;
+ }
- return $insert_id;
+ return $insert_id;
- } // create
+ } // create
- /**
- * run_add
- * This runs the add to catalog function
- * it includes the javascript refresh stuff and then starts rolling
- * throught the path for this catalog
- */
- public function run_add($options) {
-
- if ($this->catalog_type == 'remote') {
- UI::show_box_top(T_('Running Remote Sync') . '. . .');
- $this->get_remote_catalog($type=0);
- UI::show_box_bottom();
- return true;
- }
+ /**
+ * run_add
+ * This runs the add to catalog function
+ * it includes the javascript refresh stuff and then starts rolling
+ * throught the path for this catalog
+ */
+ public function run_add($options) {
+
+ if ($this->catalog_type == 'remote') {
+ UI::show_box_top(T_('Running Remote Sync') . '. . .');
+ $this->get_remote_catalog($type=0);
+ UI::show_box_bottom();
+ return true;
+ }
- // Catalog Add start
- $start_time = time();
+ // Catalog Add start
+ $start_time = time();
- require Config::get('prefix') . '/templates/show_adds_catalog.inc.php';
- flush();
-
- // Prevent the script from timing out and flush what we've got
- set_time_limit(0);
-
- $this->add_files($this->path,$options);
-
- // If they have checked the box then go ahead and gather the art
- if ($options['gather_art']) {
- $catalog_id = $this->id;
- require Config::get('prefix') . '/templates/show_gather_art.inc.php';
- flush();
- $this->get_art('',1);
- }
-
- if ($options['parse_m3u'] AND count($this->_playlists)) {
- foreach ($this->_playlists as $playlist_file) {
- $result = $this->import_m3u($playlist_file);
- }
- } // if we need to do some m3u-age
-
- return true;
-
- } // run_add
-
- /**
- * count_videos
- * This returns the current # of video files we've got in the db
- */
- public static function count_videos($catalog_id = null) {
-
- $catalog_search = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : '';
-
- $sql = 'SELECT COUNT(`id`) AS `videos` FROM `video` ';
- if ($catalog_id) {
- $sql .= "WHERE `catalog`='" . Dba::escape($catalog_id) . "'";
- }
- $db_results = Dba::read($sql);
-
- $row = Dba::fetch_assoc($db_results);
-
- return $row;
-
- } // count_videos
-
- /**
- * count_tags
- * This returns the current # of unique tags that exist in the database
- */
- public static function count_tags($catalog_id = null) {
-
- // FIXME: Ignores catalog_id
- $sql = "SELECT COUNT(`id`) FROM `tag`";
- $db_results = Dba::read($sql);
-
- $info = Dba::fetch_row($db_results);
-
- return $info['0'];
-
- } // count_tags
-
- /**
- * count_songs
- * This returns the current # of songs, albums, artists
- * in this catalog
- */
- public static function count_songs($catalog_id = null) {
-
- $where_sql = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : '';
-
- $sql = "SELECT COUNT(`id`),SUM(`time`),SUM(`size`) FROM `song` $where_sql";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_row($db_results);
- $songs = $data['0'];
- $time = $data['1'];
- $size = $data['2'];
-
- $sql = "SELECT COUNT(DISTINCT(`album`)) FROM `song` $where_sql";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_row($db_results);
- $albums = $data['0'];
-
- $sql = "SELECT COUNT(DISTINCT(`artist`)) FROM `song` $where_sql";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_row($db_results);
- $artists = $data['0'];
-
- $results['songs'] = $songs;
- $results['albums'] = $albums;
- $results['artists'] = $artists;
- $results['size'] = $size;
- $results['time'] = $time;
-
- return $results;
-
- } // count_songs
-
- /**
- * count_users
- * This returns the total number of users in the ampache instance
- */
- public static function count_users($catalog_id = null) {
-
- // Count total users
- $sql = "SELECT COUNT(`id`) FROM `user`";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_row($db_results);
- $results['users'] = $data['0'];
-
- // Get the connected users
- $time = time();
- $last_seen_time = $time - 1200;
- $sql = 'SELECT COUNT(DISTINCT `session`.`username`) ' .
- 'FROM `session` INNER JOIN `user` ' .
- 'ON `session`.`username` = `user`.`username` ' .
- "WHERE `session`.`expire` > '$time' " .
- "AND `user`.`last_seen` > '$last_seen_time'";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_row($db_results);
-
- $results['connected'] = $data['0'];
-
- return $results;
-
- } // count_users
-
- /**
- * add_files
- * Recurses through $this->path and pulls out all mp3s and returns the
- * full path in an array. Passes gather_type to determine if we need to
- * check id3 information against the db.
- */
- public function add_files($path, $options) {
-
- // Profile the memory a bit
- debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5);
-
- // See if we want a non-root path for the add
- if (isset($options['subdirectory'])) {
- $path = $options['subdirectory'];
- unset($options['subdirectory']);
- }
-
- // Correctly detect the slash we need to use here
- if (strpos($path, '/') !== false) {
- $slash_type = '/';
- }
- else {
- $slash_type = '\\';
- }
-
- /* Open up the directory */
- $handle = opendir($path);
-
- if (!is_resource($handle)) {
- debug_event('read', "Unable to open $path", 5,'ampache-catalog');
- Error::add('catalog_add', sprintf(T_('Error: Unable to open %s'), $path));
- return false;
- }
-
- /* Change the dir so is_dir works correctly */
- if (!chdir($path)) {
- debug_event('read', "Unable to chdir $path", 2,'ampache-catalog');
- Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path));
- return false;
- }
-
- // Ensure that we've got our cache
- $this->_create_filecache();
-
- debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5);
-
- /* Recurse through this dir and create the files array */
- while ( false !== ( $file = readdir($handle) ) ) {
-
- /* Skip to next if we've got . or .. */
- if (substr($file,0,1) == '.') { continue; }
-
- debug_event('read',"Starting work on $file inside $path",'5','ampache-catalog');
- debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5);
-
- /* Create the new path */
- $full_file = $path.$slash_type.$file;
-
- /* First thing first, check if file is already in catalog.
- * This check is very quick, so it should be performed before any other checks to save time
- */
- if (isset($this->_filecache[strtolower($full_file)])) {
- continue;
- }
-
- // Incase this is the second time through clear this variable
- // if it was set the day before
- unset($failed_check);
-
- if (Config::get('no_symlinks')) {
- if (is_link($full_file)) {
- debug_event('read',"Skipping Symbolic Link $path",'5','ampache-catalog');
- continue;
- }
- }
-
- /* If it's a dir run this function again! */
- if (is_dir($full_file)) {
- $this->add_files($full_file,$options);
-
- /* Change the dir so is_dir works correctly */
- if (!chdir($path)) {
- debug_event('read',"Unable to chdir $path",'2','ampache-catalog');
- Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path));
- }
-
- /* Skip to the next file */
- continue;
- } //it's a directory
-
- /* If it's not a dir let's roll with it
- * next we need to build the pattern that we will use
- * to detect if it's an audio file
- */
- $pattern = "/\.(" . Config::get('catalog_file_pattern');
- if ($options['parse_m3u']) {
- $pattern .= "|m3u)$/i";
- }
- else {
- $pattern .= ")$/i";
- }
-
- $is_audio_file = preg_match($pattern,$file);
-
- // Define the Video file pattern
- if (!$is_audio_file AND Config::get('catalog_video_pattern')) {
- $video_pattern = "/\.(" . Config::get('catalog_video_pattern') . ")$/i";
- $is_video_file = preg_match($video_pattern,$file);
- }
-
- /* see if this is a valid audio file or playlist file */
- if ($is_audio_file OR $is_video_file) {
-
- /* Now that we're sure its a file get filesize */
- $file_size = filesize($full_file);
-
- if (!$file_size) {
- debug_event('read',"Unable to get filesize for $full_file",'2','ampache-catalog');
- /* HINT: FullFile */
- Error::add('catalog_add', sprintf(T_('Error: Unable to get filesize for %s'), $full_file));
- } // file_size check
-
- if (!is_readable($full_file)) {
- // not readable, warn user
- debug_event('read',"$full_file is not readable by ampache",'2','ampache-catalog');
- /* HINT: FullFile */
- Error::add('catalog_add', sprintf(T_('%s is not readable by ampache'), $full_file));
- continue;
- }
-
- // Check to make sure the filename is of the expected charset
- if (function_exists('iconv')) {
- if (strcmp($full_file,iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file)) != '0') {
- debug_event('read',$full_file . ' has non-' . Config::get('site_charset') . ' characters and can not be indexed, converted filename:' . iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file),'1');
- /* HINT: FullFile */
- Error::add('catalog_add', sprintf(T_('%s does not match site charset'), $full_file));
- continue;
- }
- } // end if iconv
-
- if ($options['parse_m3u'] AND substr($file,-3,3) == 'm3u') {
- $this->_playlists[] = $full_file;
- } // if it's an m3u
-
- else {
- if ($is_audio_file) { $this->insert_local_song($full_file,$file_size); }
- else { $this->insert_local_video($full_file,$file_size); }
-
- $this->count++;
- $file = str_replace(array('(',')','\''),'',$full_file);
- if(UI::check_ticker()) {
- UI::update_text('add_count_' . $this->id, $this->count);
- UI::update_text('add_dir_' . $this->id, scrub_out($file));
- } // update our current state
-
- } // if it's not an m3u
-
- } //if it matches the pattern
- else {
- debug_event('read',"$full_file ignored, non audio file or 0 bytes",'5','ampache-catalog');
- } // else not an audio file
-
- } // end while reading directory
-
- debug_event('closedir',"Finished reading $path closing handle",'5','ampache-catalog');
-
- // This should only happen on the last run
- if ($path == $this->path) {
- UI::update_text('add_count_' . $this->id, $this->count);
- UI::update_text('add_dir_' . $this->id, scrub_out($file));
- }
-
-
- /* Close the dir handle */
- @closedir($handle);
-
- } // add_files
-
- /**
- * get_album_ids
- * This returns an array of ids of albums that have songs in this
- * catalog
- */
- public function get_album_ids() {
-
- $id = Dba::escape($this->id);
- $results = array();
-
- $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$id'";
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['album'];
- }
-
- return $results;
-
- } // get_album_ids
-
- /**
- * get_art
- * This runs through all of the needs art albums and trys
- * to find the art for them from the mp3s
- */
- public function get_art($catalog_id = null, $all = false) {
-
- // Make sure they've actually got methods
- $art_order = Config::get('art_order');
- if (!count($art_order)) {
- debug_event('gather_art', 'art_order not set, Catalog::get_art aborting', 3);
- return true;
- }
-
- // Prevent the script from timing out
- set_time_limit(0);
-
- // If not passed use $this
- $catalog_id = $catalog_id ? $catalog_id : $this->id;
-
- if ($all) {
- $albums = $this->get_album_ids();
- }
- else {
- $albums = array_keys(self::$_art_albums);
- }
-
- // Run through them an get the art!
- foreach ($albums as $album_id) {
-
- // Create the object
- $art = new Art($album_id, 'album');
- $album = new Album($album_id);
- // We're going to need the name here
- $album->format();
-
- debug_event('gather_art', 'Gathering art for ' . $album->name, 5);
-
- // Define the options we want to use for the find art function
- $options = array(
- 'album_name' => $album->full_name,
- 'artist' => $album->artist_name,
- 'keyword' => $album->artist_name . ' ' . $album->full_name
- );
+ require Config::get('prefix') . '/templates/show_adds_catalog.inc.php';
+ flush();
+
+ // Prevent the script from timing out and flush what we've got
+ set_time_limit(0);
+
+ $this->add_files($this->path,$options);
+
+ // If they have checked the box then go ahead and gather the art
+ if ($options['gather_art']) {
+ $catalog_id = $this->id;
+ require Config::get('prefix') . '/templates/show_gather_art.inc.php';
+ flush();
+ $this->get_art('',1);
+ }
+
+ if ($options['parse_m3u'] AND count($this->_playlists)) {
+ foreach ($this->_playlists as $playlist_file) {
+ $result = $this->import_m3u($playlist_file);
+ }
+ } // if we need to do some m3u-age
+
+ return true;
+
+ } // run_add
+
+ /**
+ * count_videos
+ * This returns the current # of video files we've got in the db
+ */
+ public static function count_videos($catalog_id = null) {
+
+ $catalog_search = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : '';
+
+ $sql = 'SELECT COUNT(`id`) AS `videos` FROM `video` ';
+ if ($catalog_id) {
+ $sql .= "WHERE `catalog`='" . Dba::escape($catalog_id) . "'";
+ }
+ $db_results = Dba::read($sql);
+
+ $row = Dba::fetch_assoc($db_results);
+
+ return $row;
+
+ } // count_videos
+
+ /**
+ * count_tags
+ * This returns the current # of unique tags that exist in the database
+ */
+ public static function count_tags($catalog_id = null) {
+
+ // FIXME: Ignores catalog_id
+ $sql = "SELECT COUNT(`id`) FROM `tag`";
+ $db_results = Dba::read($sql);
+
+ $info = Dba::fetch_row($db_results);
+
+ return $info['0'];
+
+ } // count_tags
+
+ /**
+ * count_songs
+ * This returns the current # of songs, albums, artists
+ * in this catalog
+ */
+ public static function count_songs($catalog_id = null) {
+
+ $where_sql = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : '';
+
+ $sql = "SELECT COUNT(`id`),SUM(`time`),SUM(`size`) FROM `song` $where_sql";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_row($db_results);
+ $songs = $data['0'];
+ $time = $data['1'];
+ $size = $data['2'];
+
+ $sql = "SELECT COUNT(DISTINCT(`album`)) FROM `song` $where_sql";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_row($db_results);
+ $albums = $data['0'];
+
+ $sql = "SELECT COUNT(DISTINCT(`artist`)) FROM `song` $where_sql";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_row($db_results);
+ $artists = $data['0'];
+
+ $results['songs'] = $songs;
+ $results['albums'] = $albums;
+ $results['artists'] = $artists;
+ $results['size'] = $size;
+ $results['time'] = $time;
+
+ return $results;
+
+ } // count_songs
+
+ /**
+ * count_users
+ * This returns the total number of users in the ampache instance
+ */
+ public static function count_users($catalog_id = null) {
+
+ // Count total users
+ $sql = "SELECT COUNT(`id`) FROM `user`";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_row($db_results);
+ $results['users'] = $data['0'];
+
+ // Get the connected users
+ $time = time();
+ $last_seen_time = $time - 1200;
+ $sql = 'SELECT COUNT(DISTINCT `session`.`username`) ' .
+ 'FROM `session` INNER JOIN `user` ' .
+ 'ON `session`.`username` = `user`.`username` ' .
+ "WHERE `session`.`expire` > '$time' " .
+ "AND `user`.`last_seen` > '$last_seen_time'";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_row($db_results);
+
+ $results['connected'] = $data['0'];
+
+ return $results;
+
+ } // count_users
+
+ /**
+ * add_files
+ * Recurses through $this->path and pulls out all mp3s and returns the
+ * full path in an array. Passes gather_type to determine if we need to
+ * check id3 information against the db.
+ */
+ public function add_files($path, $options) {
+
+ // Profile the memory a bit
+ debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5);
+
+ // See if we want a non-root path for the add
+ if (isset($options['subdirectory'])) {
+ $path = $options['subdirectory'];
+ unset($options['subdirectory']);
+ }
+
+ // Correctly detect the slash we need to use here
+ if (strpos($path, '/') !== false) {
+ $slash_type = '/';
+ }
+ else {
+ $slash_type = '\\';
+ }
+
+ /* Open up the directory */
+ $handle = opendir($path);
+
+ if (!is_resource($handle)) {
+ debug_event('read', "Unable to open $path", 5,'ampache-catalog');
+ Error::add('catalog_add', sprintf(T_('Error: Unable to open %s'), $path));
+ return false;
+ }
+
+ /* Change the dir so is_dir works correctly */
+ if (!chdir($path)) {
+ debug_event('read', "Unable to chdir $path", 2,'ampache-catalog');
+ Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path));
+ return false;
+ }
+
+ // Ensure that we've got our cache
+ $this->_create_filecache();
+
+ debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5);
+
+ /* Recurse through this dir and create the files array */
+ while ( false !== ( $file = readdir($handle) ) ) {
+
+ /* Skip to next if we've got . or .. */
+ if (substr($file,0,1) == '.') { continue; }
+
+ debug_event('read',"Starting work on $file inside $path",'5','ampache-catalog');
+ debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5);
+
+ /* Create the new path */
+ $full_file = $path.$slash_type.$file;
+
+ /* First thing first, check if file is already in catalog.
+ * This check is very quick, so it should be performed before any other checks to save time
+ */
+ if (isset($this->_filecache[strtolower($full_file)])) {
+ continue;
+ }
+
+ // Incase this is the second time through clear this variable
+ // if it was set the day before
+ unset($failed_check);
+
+ if (Config::get('no_symlinks')) {
+ if (is_link($full_file)) {
+ debug_event('read',"Skipping Symbolic Link $path",'5','ampache-catalog');
+ continue;
+ }
+ }
+
+ /* If it's a dir run this function again! */
+ if (is_dir($full_file)) {
+ $this->add_files($full_file,$options);
+
+ /* Change the dir so is_dir works correctly */
+ if (!chdir($path)) {
+ debug_event('read',"Unable to chdir $path",'2','ampache-catalog');
+ Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path));
+ }
+
+ /* Skip to the next file */
+ continue;
+ } //it's a directory
+
+ /* If it's not a dir let's roll with it
+ * next we need to build the pattern that we will use
+ * to detect if it's an audio file
+ */
+ $pattern = "/\.(" . Config::get('catalog_file_pattern');
+ if ($options['parse_m3u']) {
+ $pattern .= "|m3u)$/i";
+ }
+ else {
+ $pattern .= ")$/i";
+ }
+
+ $is_audio_file = preg_match($pattern,$file);
+
+ // Define the Video file pattern
+ if (!$is_audio_file AND Config::get('catalog_video_pattern')) {
+ $video_pattern = "/\.(" . Config::get('catalog_video_pattern') . ")$/i";
+ $is_video_file = preg_match($video_pattern,$file);
+ }
+
+ /* see if this is a valid audio file or playlist file */
+ if ($is_audio_file OR $is_video_file) {
+
+ /* Now that we're sure its a file get filesize */
+ $file_size = filesize($full_file);
+
+ if (!$file_size) {
+ debug_event('read',"Unable to get filesize for $full_file",'2','ampache-catalog');
+ /* HINT: FullFile */
+ Error::add('catalog_add', sprintf(T_('Error: Unable to get filesize for %s'), $full_file));
+ } // file_size check
+
+ if (!is_readable($full_file)) {
+ // not readable, warn user
+ debug_event('read',"$full_file is not readable by ampache",'2','ampache-catalog');
+ /* HINT: FullFile */
+ Error::add('catalog_add', sprintf(T_('%s is not readable by ampache'), $full_file));
+ continue;
+ }
+
+ // Check to make sure the filename is of the expected charset
+ if (function_exists('iconv')) {
+ if (strcmp($full_file,iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file)) != '0') {
+ debug_event('read',$full_file . ' has non-' . Config::get('site_charset') . ' characters and can not be indexed, converted filename:' . iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file),'1');
+ /* HINT: FullFile */
+ Error::add('catalog_add', sprintf(T_('%s does not match site charset'), $full_file));
+ continue;
+ }
+ } // end if iconv
+
+ if ($options['parse_m3u'] AND substr($file,-3,3) == 'm3u') {
+ $this->_playlists[] = $full_file;
+ } // if it's an m3u
+
+ else {
+ if ($is_audio_file) { $this->insert_local_song($full_file,$file_size); }
+ else { $this->insert_local_video($full_file,$file_size); }
+
+ $this->count++;
+ $file = str_replace(array('(',')','\''),'',$full_file);
+ if(UI::check_ticker()) {
+ UI::update_text('add_count_' . $this->id, $this->count);
+ UI::update_text('add_dir_' . $this->id, scrub_out($file));
+ } // update our current state
+
+ } // if it's not an m3u
+
+ } //if it matches the pattern
+ else {
+ debug_event('read',"$full_file ignored, non audio file or 0 bytes",'5','ampache-catalog');
+ } // else not an audio file
+
+ } // end while reading directory
+
+ debug_event('closedir',"Finished reading $path closing handle",'5','ampache-catalog');
+
+ // This should only happen on the last run
+ if ($path == $this->path) {
+ UI::update_text('add_count_' . $this->id, $this->count);
+ UI::update_text('add_dir_' . $this->id, scrub_out($file));
+ }
+
+
+ /* Close the dir handle */
+ @closedir($handle);
+
+ } // add_files
+
+ /**
+ * get_album_ids
+ * This returns an array of ids of albums that have songs in this
+ * catalog
+ */
+ public function get_album_ids() {
+
+ $id = Dba::escape($this->id);
+ $results = array();
+
+ $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$id'";
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['album'];
+ }
+
+ return $results;
+
+ } // get_album_ids
+
+ /**
+ * get_art
+ * This runs through all of the needs art albums and trys
+ * to find the art for them from the mp3s
+ */
+ public function get_art($catalog_id = null, $all = false) {
+
+ // Make sure they've actually got methods
+ $art_order = Config::get('art_order');
+ if (!count($art_order)) {
+ debug_event('gather_art', 'art_order not set, Catalog::get_art aborting', 3);
+ return true;
+ }
+
+ // Prevent the script from timing out
+ set_time_limit(0);
+
+ // If not passed use $this
+ $catalog_id = $catalog_id ? $catalog_id : $this->id;
+
+ if ($all) {
+ $albums = $this->get_album_ids();
+ }
+ else {
+ $albums = array_keys(self::$_art_albums);
+ }
+
+ // Run through them an get the art!
+ foreach ($albums as $album_id) {
+
+ // Create the object
+ $art = new Art($album_id, 'album');
+ $album = new Album($album_id);
+ // We're going to need the name here
+ $album->format();
+
+ debug_event('gather_art', 'Gathering art for ' . $album->name, 5);
+
+ // Define the options we want to use for the find art function
+ $options = array(
+ 'album_name' => $album->full_name,
+ 'artist' => $album->artist_name,
+ 'keyword' => $album->artist_name . ' ' . $album->full_name
+ );
- // Return results
- $results = $art->gather($options, 1);
+ // Return results
+ $results = $art->gather($options, 1);
- if (count($results)) {
- // Pull the string representation from the source
- $image = Art::get_from_source($results['0'], 'album');
- if (strlen($image) > '5') {
- $art->insert($image, $results['0']['mime']);
- // If they've enabled resizing of images generate the thumbnail now
- if (Config::get('resize_images')) {
- $thumb = $art->generate_thumb($image,array('width'=>275,'height'=>275),$results['0']['mime']);
- if (is_array($thumb)) { $art->save_thumb($thumb['thumb'], $thumb['thumb_mime'], '275x275'); }
- }
-
- }
- else {
- debug_event('gather_art', 'Image less than 5 chars, not inserting', 3);
- }
- $art_found++;
- }
+ if (count($results)) {
+ // Pull the string representation from the source
+ $image = Art::get_from_source($results['0'], 'album');
+ if (strlen($image) > '5') {
+ $art->insert($image, $results['0']['mime']);
+ // If they've enabled resizing of images generate the thumbnail now
+ if (Config::get('resize_images')) {
+ $thumb = $art->generate_thumb($image,array('width'=>275,'height'=>275),$results['0']['mime']);
+ if (is_array($thumb)) { $art->save_thumb($thumb['thumb'], $thumb['thumb_mime'], '275x275'); }
+ }
+
+ }
+ else {
+ debug_event('gather_art', 'Image less than 5 chars, not inserting', 3);
+ }
+ $art_found++;
+ }
- /* Stupid little cutesie thing */
- $search_count++;
- if (UI::check_ticker()) {
- UI::update_text('count_art_' . $this->id, $search_count);
- UI::update_text('read_art_' . $this->id, scrub_out($album->name));
- } //echos song count
+ /* Stupid little cutesie thing */
+ $search_count++;
+ if (UI::check_ticker()) {
+ UI::update_text('count_art_' . $this->id, $search_count);
+ UI::update_text('read_art_' . $this->id, scrub_out($album->name));
+ } //echos song count
- unset($found);
- } // foreach albums
+ unset($found);
+ } // foreach albums
- // One last time for good measure
- UI::update_text('count_art_' . $this->id, $search_count);
- UI::update_text('read_art_' . $this->id, scrub_out($album->name));
-
- self::$_art_albums = array();
-
- } // get_art
+ // One last time for good measure
+ UI::update_text('count_art_' . $this->id, $search_count);
+ UI::update_text('read_art_' . $this->id, scrub_out($album->name));
+
+ self::$_art_albums = array();
+
+ } // get_art
- /**
- * generate_thumbnails
- * This generates the thumbnails from the images for object
- * of this catalog
- */
- public function generate_thumbnails() {
-
- // Albums first
- $albums = $this->get_album_ids();
-
- $thumb_count = 0;
-
- foreach ($albums as $album) {
- $art = new Art($album, 'album');
- $image = $art->get();
-
- /* Stupid little cutesie thing */
- $thumb_count++;
- if (UI::check_ticker()) {
- UI::update_text('count_thumb_' . $this->id, $search_count);
- } //echos thumb count
-
- } // end foreach albums
-
- UI::update_text('count_thumb_' . $this->id, $search_count);
-
- } // generate_thumbnails
-
- /**
- * get_catalog_albums()
- * Returns an array of the albums from a catalog
- */
- public static function get_catalog_albums($catalog_id) {
-
- $results = array();
-
- $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$catalog_id'";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['album'];
- }
-
- return $results;
-
- } // get_catalog_albums
-
-
- /**
- * get_catalog_files
- * Returns an array of song objects from a catalog, used by sort_files script
- */
- public function get_catalog_files($catalog_id=0) {
-
- $results = array();
-
- /* Use $this->id if nothing passed */
- $catalog_id = $catalog_id ? Dba::escape($catalog_id) : Dba::escape($this->id);
-
- $sql = "SELECT `id` FROM `song` WHERE `catalog`='$catalog_id' AND `enabled`='1'";
- $db_results = Dba::read($sql);
-
- $results = array(); // return an emty array instead of nothing if no objects
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = new Song($r['id']);
- } //end while
-
- return $results;
-
- } //get_catalog_files
-
- /**
- * dump_album_art
- * This runs through all of the albums and tries to dump the
- * art for them into the 'folder.jpg' file in the appropriate dir
- */
- public static function dump_album_art($catalog_id, $methods=array()) {
+ /**
+ * generate_thumbnails
+ * This generates the thumbnails from the images for object
+ * of this catalog
+ */
+ public function generate_thumbnails() {
+
+ // Albums first
+ $albums = $this->get_album_ids();
+
+ $thumb_count = 0;
+
+ foreach ($albums as $album) {
+ $art = new Art($album, 'album');
+ $image = $art->get();
+
+ /* Stupid little cutesie thing */
+ $thumb_count++;
+ if (UI::check_ticker()) {
+ UI::update_text('count_thumb_' . $this->id, $search_count);
+ } //echos thumb count
+
+ } // end foreach albums
+
+ UI::update_text('count_thumb_' . $this->id, $search_count);
+
+ } // generate_thumbnails
+
+ /**
+ * get_catalog_albums()
+ * Returns an array of the albums from a catalog
+ */
+ public static function get_catalog_albums($catalog_id) {
+
+ $results = array();
+
+ $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$catalog_id'";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['album'];
+ }
+
+ return $results;
+
+ } // get_catalog_albums
+
+
+ /**
+ * get_catalog_files
+ * Returns an array of song objects from a catalog, used by sort_files script
+ */
+ public function get_catalog_files($catalog_id=0) {
+
+ $results = array();
+
+ /* Use $this->id if nothing passed */
+ $catalog_id = $catalog_id ? Dba::escape($catalog_id) : Dba::escape($this->id);
+
+ $sql = "SELECT `id` FROM `song` WHERE `catalog`='$catalog_id' AND `enabled`='1'";
+ $db_results = Dba::read($sql);
+
+ $results = array(); // return an emty array instead of nothing if no objects
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = new Song($r['id']);
+ } //end while
+
+ return $results;
+
+ } //get_catalog_files
+
+ /**
+ * dump_album_art
+ * This runs through all of the albums and tries to dump the
+ * art for them into the 'folder.jpg' file in the appropriate dir
+ */
+ public static function dump_album_art($catalog_id, $methods=array()) {
- // Get all of the albums in this catalog
- $albums = self::get_catalog_albums($catalog_id);
+ // Get all of the albums in this catalog
+ $albums = self::get_catalog_albums($catalog_id);
- echo "Starting Dump Album Art...\n";
+ echo "Starting Dump Album Art...\n";
- // Run through them and get the art!
- foreach ($albums as $album_id) {
+ // Run through them and get the art!
+ foreach ($albums as $album_id) {
- $album = new Album($album_id);
- $art = new Art($album_id, 'album');
-
- // If no art, skip
- if ( ! $art->get_db() ) { continue; }
+ $album = new Album($album_id);
+ $art = new Art($album_id, 'album');
+
+ // If no art, skip
+ if ( ! $art->get_db() ) { continue; }
- // Get the first song in the album
- $songs = $album->get_songs(1);
- $song = new Song($songs[0]);
- $dir = dirname($song->file);
+ // Get the first song in the album
+ $songs = $album->get_songs(1);
+ $song = new Song($songs[0]);
+ $dir = dirname($song->file);
- $extension = Art::extension($art->raw_mime);
-
- // Try the preferred filename, if that fails use folder.???
- $preferred_filename = Config::get('album_art_preferred_filename');
- if (!$preferred_filename ||
- strpos($preferred_filename, '%') !== false) {
- $preferred_filename = "folder.$extension";
- }
+ $extension = Art::extension($art->raw_mime);
+
+ // Try the preferred filename, if that fails use folder.???
+ $preferred_filename = Config::get('album_art_preferred_filename');
+ if (!$preferred_filename ||
+ strpos($preferred_filename, '%') !== false) {
+ $preferred_filename = "folder.$extension";
+ }
- $file = "$dir/$preferred_filename";
- if ($file_handle = fopen($file,"w")) {
- if (fwrite($file_handle, $art->raw)) {
+ $file = "$dir/$preferred_filename";
+ if ($file_handle = fopen($file,"w")) {
+ if (fwrite($file_handle, $art->raw)) {
- // Also check and see if we should write
- // out some metadata
- if ($methods['metadata']) {
- switch ($methods['metadata']) {
- case 'windows':
- $meta_file = $dir . '/desktop.ini';
- $string = "[.ShellClassInfo]\nIconFile=$file\nIconIndex=0\nInfoTip=$album->full_name";
- break;
- default:
- case 'linux':
- $meta_file = $dir . '/.directory';
- $string = "Name=$album->full_name\nIcon=$file";
- break;
- } // end switch
+ // Also check and see if we should write
+ // out some metadata
+ if ($methods['metadata']) {
+ switch ($methods['metadata']) {
+ case 'windows':
+ $meta_file = $dir . '/desktop.ini';
+ $string = "[.ShellClassInfo]\nIconFile=$file\nIconIndex=0\nInfoTip=$album->full_name";
+ break;
+ default:
+ case 'linux':
+ $meta_file = $dir . '/.directory';
+ $string = "Name=$album->full_name\nIcon=$file";
+ break;
+ } // end switch
- $meta_handle = fopen($meta_file,"w");
- fwrite($meta_handle,$string);
- fclose($meta_handle);
-
- } // end metadata
- $i++;
- if (!($i%100)) {
- echo "Written: $i. . .\n";
- debug_event('art_write',"$album->name Art written to $file",'5');
- }
- } // end if fopen
- else {
- debug_event('art_write',"Unable to open $file for writting",'5');
- echo "Error unable to open file for writting [$file]\n";
- }
- } // end if fopen worked
-
- fclose($file_handle);
-
-
- } // end foreach
-
- echo "Album Art Dump Complete\n";
-
- } // dump_album_art
-
- /**
- * update_last_update
- * updates the last_update of the catalog
- */
- private function update_last_update() {
-
- $date = time();
- $sql = "UPDATE `catalog` SET `last_update`='$date' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- } // update_last_update
-
- /**
- * update_last_add
- * updates the last_add of the catalog
- */
- public function update_last_add() {
-
- $date = time();
- $sql = "UPDATE `catalog` SET `last_add`='$date' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- } // update_last_add
-
- /**
- * update_last_clean
- * This updates the last clean information
- */
- public function update_last_clean() {
-
- $date = time();
- $sql = "UPDATE `catalog` SET `last_clean`='$date' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- } // update_last_clean
-
- /**
- * update_settings
- * This function updates the basic setting of the catalog
- */
- public static function update_settings($data) {
-
- $id = Dba::escape($data['catalog_id']);
- $name = Dba::escape($data['name']);
- $rename = Dba::escape($data['rename_pattern']);
- $sort = Dba::escape($data['sort_pattern']);
- $remote_username = Dba::escape($data['remote_username']);
- $remote_password = Dba::escape($data['remote_password']);
-
- $sql = "UPDATE `catalog` SET `name`='$name', `rename_pattern`='$rename', " .
- "`sort_pattern`='$sort', `remote_username`='$remote_username', `remote_password`='$remote_password' WHERE `id` = '$id'";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // update_settings
-
- /**
- * update_single_item
- * updates a single album,artist,song from the tag data
- * this can be done by 75+
- */
- public static function update_single_item($type,$id) {
-
- // Because single items are large numbers of things too
- set_time_limit(0);
-
- $songs = array();
-
- switch ($type) {
- case 'album':
- $album = new Album($id);
- $songs = $album->get_songs();
- break;
- case 'artist':
- $artist = new Artist($id);
- $songs = $artist->get_songs();
- break;
- case 'song':
- $songs[] = $id;
- break;
- } // end switch type
-
- foreach($songs as $song_id) {
- $song = new Song($song_id);
- $info = self::update_media_from_tags($song,'','');
-
- if ($info['change']) {
- $file = scrub_out($song->file);
- echo "<dl>\n\t<dd>";
- echo "<strong>$file " . T_('Updated') . "</strong>\n";
- echo $info['text'];
- echo "\t</dd>\n</dl><hr align=\"left\" width=\"50%\" />";
- flush();
- } // if change
- else {
- echo"<dl>\n\t<dd>";
- echo "<strong>" . scrub_out($song->file) . "</strong><br />" . T_('No Update Needed') . "\n";
- echo "\t</dd>\n</dl><hr align=\"left\" width=\"50%\" />";
- flush();
- }
- } // foreach songs
-
- self::gc();
-
- } // update_single_item
-
- /**
- * update_media_from_tags
- * This is a 'wrapper' function calls the update function for the media
- * type in question
- */
- public static function update_media_from_tags($media, $sort_pattern='', $rename_pattern='') {
-
- // Check for patterns
- if (!$sort_pattern OR !$rename_pattern) {
- $catalog = new Catalog($media->catalog);
- $sort_pattern = $catalog->sort_pattern;
- $rename_pattern = $catalog->rename_pattern;
- }
-
- debug_event('tag-read','Reading tags from ' . $media->file,'5','ampache-catalog');
-
- $vainfo = new vainfo($media->file,'','','',$sort_pattern,$rename_pattern);
- $vainfo->get_info();
-
- $key = vainfo::get_tag_type($vainfo->tags);
-
- $results = vainfo::clean_tag_info($vainfo->tags,$key,$media->file);
-
- // Figure out what type of object this is and call the right
- // function, giving it the stuff we've figured out above
- $name = (get_class($media) == 'Song') ? 'song' : 'video';
-
- $function = 'update_' . $name . '_from_tags';
-
- $return = call_user_func(array('Catalog',$function),$results,$media);
-
- return $return;
-
- } // update_media_from_tags
-
- /**
- * update_video_from_tags
- * Updates the video info based on tags
- */
- public static function update_video_from_tags($results,$video) {
-
- // Pretty sweet function here
- return $results;
-
- } // update_video_from_tags
-
- /**
- * update_song_from_tags
- * Updates the song info based on tags; this is called from a bunch of
- * different places and passes in a full fledged song object, so it's a
- * static function.
- * FIXME: This is an ugly mess, this really needs to be consolidated and
- * cleaned up.
- */
- public static function update_song_from_tags($results,$song) {
-
- /* Setup the vars */
- $new_song = new Song();
- $new_song->file = $results['file'];
- $new_song->title = $results['title'];
- $new_song->year = $results['year'];
- $new_song->comment = $results['comment'];
- $new_song->language = $results['language'];
- $new_song->lyrics = $results['lyrics'];
- $new_song->bitrate = $results['bitrate'];
- $new_song->rate = $results['rate'];
- $new_song->mode = ($results['mode'] == 'cbr') ? 'cbr' : 'vbr';
- $new_song->size = $results['size'];
- $new_song->time = $results['time'];
- $new_song->mime = $results['mime'];
- $new_song->track = intval($results['track']);
- $new_song->mbid = $results['mb_trackid'];
- $artist = $results['artist'];
- $artist_mbid = $results['mb_artistid'];
- $album = $results['album'];
- $album_mbid = $results['mb_albumid'];
- $disk = $results['disk'];
- $tags = $results['genre']; // multiple genre support makes this an array
-
- /*
- * We have the artist/genre/album name need to check it in the tables
- * If found then add & return id, else return id
- */
- $new_song->artist = self::check_artist($artist,$artist_mbid);
- $new_song->f_artist = $artist;
- $new_song->album = self::check_album($album,$new_song->year,$disk,$album_mbid);
- $new_song->f_album = $album . " - " . $new_song->year;
- $new_song->title = self::check_title($new_song->title,$new_song->file);
-
- // Nothing to assign here this is a multi-value doodly
- // multiple genre support
- foreach ($tags as $tag) {
- $tag = trim($tag);
- self::check_tag($tag,$song->id);
- self::check_tag($tag,$new_song->album,'album');
- self::check_tag($tag,$new_song->artist,'artist');
- }
-
- /* Since we're doing a full compare make sure we fill the extended information */
- $song->fill_ext_info();
-
- $info = Song::compare_song_information($song,$new_song);
-
- if ($info['change']) {
- debug_event('update',"$song->file difference found, updating database",'5','ampache-catalog');
- $song->update_song($song->id,$new_song);
- // Refine our reference
- $song = $new_song;
- }
- else {
- debug_event('update',"$song->file no difference found returning",'5','ampache-catalog');
- }
-
- return $info;
-
- } // update_song_from_tags
-
- /**
- * add_to_catalog
- * this function adds new files to an
- * existing catalog
- */
- public function add_to_catalog() {
-
- if ($this->catalog_type == 'remote') {
- UI::show_box_top(T_('Running Remote Update') . '. . .');
- $this->get_remote_catalog($type=0);
- UI::show_box_bottom();
- return true;
- }
-
- require Config::get('prefix') . '/templates/show_adds_catalog.inc.php';
- flush();
-
- /* Set the Start time */
- $start_time = time();
-
- // Make sure the path doesn't end in a / or \
- $this->path = rtrim($this->path,'/');
- $this->path = rtrim($this->path,'\\');
-
- // Prevent the script from timing out and flush what we've got
- set_time_limit(0);
-
- /* Get the songs and then insert them into the db */
- $this->add_files($this->path,$type,0,$verbose);
-
- // Foreach Playlists we found
- foreach ($this->_playlists as $full_file) {
- $result = $this->import_m3u($full_file);
- if ($result['success']) {
- $file = basename($full_file);
- if ($verbose) {
- echo "&nbsp;&nbsp;&nbsp;" . T_('Added Playlist From') . " $file . . . .<br />\n";
- flush();
- }
- } // end if import worked
- } // end foreach playlist files
-
- /* Do a little stats mojo here */
- $current_time = time();
-
- $catalog_id = $this->id;
- require Config::get('prefix') . '/templates/show_gather_art.inc.php';
- flush();
- $this->get_art();
-
- /* Update the Catalog last_update */
- $this->update_last_add();
-
- $time_diff = ($current_time - $start_time) ?: 0;
- $rate = intval($this->count / $time_diff) ?: T_('N/A');
-
- UI::show_box_top();
- echo "\n<br />" .
- printf(T_('Catalog Update Finished. Total Time: [%s] Total Songs: [%s] Songs Per Second: [%s]'),
- date('i:s', $time_diff), $this->count, $rate);
- echo '<br /><br />';
- UI::show_box_bottom();
-
- } // add_to_catalog
-
- /**
- * get_remote_catalog
- * get a remote catalog and runs update if needed this requires
- * this uses the AmpacheAPI library provided, replaces legacy XMLRPC
- */
- public function get_remote_catalog($type=0) {
-
- try {
- $remote_handle = new AmpacheApi(array('username'=>$this->remote_username,'password'=>$this->remote_password,'server'=>$this->path,'debug'=>true));
- } catch (Exception $e) {
- Error::add('general',$e->getMessage());
- Error::display('general');
- flush();
- return false;
- }
-
- if ($remote_handle->state() != 'CONNECTED') {
- debug_event('APICLIENT','Error Unable to make API client ready','1');
- Error::add('general', T_('Error Connecting to Remote Server'));
- Error::display('general');
- return false;
- }
-
- // Figure out how many songs, more information etc
- $remote_catalog_info = $remote_handle->info();
-
- // Tell em what we've found johnny!
- printf(T_('%u remote catalog(s) found (%u songs)'),$remote_catalog_info['catalogs'],$remote_catalog_info['songs']);
- flush();
-
- // Hardcoded for now
- $step = '500';
- $current = '0';
- $total = $remote_catalog_info['songs'];
-
- while ($total > $current) {
- $start = $current;
- $current += $step;
- // It uses exceptions so lets try this
- try {
- $remote_handle->parse_response($remote_handle->send_command('songs',array('offset'=>$start,'limit'=>$step)));
- $songs = $remote_handle->get_response();
- } catch (Exception $e) {
- Error::add('general',$e->getMessage());
- Error::display('general');
- flush();
- }
- // itterate the songs we retrieved and insert them
- foreach ($songs as $data) {
- if (!$this->insert_remote_song($data['song'])) {
- debug_event('REMOTE_INSERT','Remote Insert failed, see previous log messages -' . $data['song']['self']['id'],'1');
- Error::add('general', T_('Unable to Insert Song - %s'),$data['song']['title']);
- Error::display('general');
- flush();
- }
- } // end foreach
- } // end while
-
- echo "<p>" . T_('Completed updating remote catalog(s)') . ".</p><hr />\n";
- flush();
-
- // Update the last update value
- $this->update_last_update();
-
- return true;
-
- } // get_remote_catalog
-
- /**
- * update_remote_catalog
- * actually updates from the remote data, takes an array of songs that are base64 encoded and parses them
- */
- public function update_remote_catalog($data,$root_path) {
-
- // Going to leave this be for now
- //FIXME: Implement
-
- return true;
-
- } // update_remote_catalog
-
- /**
- * clean_catalog
- * Cleans the catalog of files that no longer exist.
- */
- public function clean_catalog() {
-
- // We don't want to run out of time
- set_time_limit(0);
-
- debug_event('clean', 'Starting on ' . $this->name, 5, 'ampache-catalog');
-
- require_once Config::get('prefix') . '/templates/show_clean_catalog.inc.php';
- ob_flush();
- flush();
-
- // Do a quick check to make sure that the root of the catalog is
- // readable. This will minimize the loss of catalog data if
- // mount points fail
- if ($this->catalog_type == 'local' && !is_readable($this->path)) {
- debug_event('catalog', 'Catalog path:' . $this->path . ' unreadable, clean failed', 1);
- Error::add('general', T_('Catalog Root unreadable, stopping clean'));
- Error::display('general');
- return false;
- }
-
-
- $dead_total = 0;
- $stats = self::get_stats($this->id);
- foreach(array('video', 'song') as $media_type) {
- $total = $stats[$media_type . 's']; // UGLY
- if ($total == 0) {
- continue;
- }
- $chunks = floor($total / 10000);
- $dead = array();
- foreach(range(0, $chunks) as $chunk) {
- $dead = array_merge($dead, $this->_clean_chunk($media_type, $chunk, 10000));
- }
-
- $dead_count = count($dead);
- // The AlmightyOatmeal sanity check
- // Never remove everything; it might be a dead mount
- if ($dead_count >= $total) {
- debug_event('catalog', 'All files would be removed. Doing nothing.', 1);
- Error::add('general', T_('All files would be removed. Doing nothing'));
- continue;
- }
- if ($dead_count) {
- $dead_total += $dead_count;
- $sql = "DELETE FROM `$media_type` WHERE `id` IN " .
- '(' . implode(',',$dead) . ')';
- $db_results = Dba::write($sql);
- }
- debug_event('clean', "$media_type finished, $dead_count removed from " .
- $this->name, 5, 'ampache-catalog');
- }
-
- // Remove any orphaned artists/albums/etc.
- self::gc();
-
- UI::show_box_top();
- echo "<strong>";
- printf (T_ngettext('Catalog Clean Done. %d file removed.', 'Catalog Clean Done. %d files removed.', $dead_total), $dead_total);
- echo "</strong><br />\n";
- UI::show_box_bottom();
- ob_flush();
- flush();
-
- $this->update_last_clean();
- } // clean_catalog
-
-
- /**
- * _clean_chunk
- * This is the clean function, its broken into
- * said chunks to try to save a little memory
- */
- private function _clean_chunk($media_type, $chunk, $chunk_size) {
- debug_event('clean', "Starting chunk $chunk", 5, 'ampache-catalog');
- $dead = array();
- $count = $chunk * $chunk_size;
-
- $sql = "SELECT `id`, `file` FROM `$media_type` " .
- "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size";
- $db_results = Dba::read($sql);
-
- while ($results = Dba::fetch_assoc($db_results)) {
- debug_event('clean', 'Starting work on ' . $results['file'] . '(' . $results['id'] . ')', 5, 'ampache-catalog');
- $count++;
- if (UI::check_ticker()) {
- $file = str_replace(array('(',')', '\''), '', $results['file']);
- UI::update_text('clean_count_' . $this->id, $count);
- UI::update_text('clean_dir_' . $this->id, scrub_out($file));
- }
- if($this->catalog_type == 'local') {
- $file_info = filesize($results['file']);
- if (!file_exists($results['file']) || $file_info < 1) {
- debug_event('clean', 'File not found or empty: ' . $results['file'], 5, 'ampache-catalog');
- Error::add('general', sprintf(T_('Error File Not Found or 0 Bytes: %s'), $results['file']));
-
-
- // Store it in an array we'll delete it later...
- $dead[] = $results['id'];
-
- } //if error
- else if (!is_readable($results['file'])) {
- debug_event('clean', $results['file'] . ' is not readable, but does exist', 1, 'ampache-catalog');
- }
- } // if localtype
- else {
- //do remote url check
- $file_info = $this->check_remote_song($results['file']);
-
- if ($file_info == false) {
- /* Add Error */
- Error::add('general', sprintf(T_('Error Remote File Not Found or 0 Bytes: %s'), $results['file']));
-
-
- // Store it in an array we'll delete it later...
- $dead[] = $results['id'];
-
- } //if error
- } // remote catalog
-
- } //while gettings songs
- return $dead;
-
- } //_clean_chunk
-
- /**
- * verify_catalog
- * This function compares the DB's information with the ID3 tags
- */
- public function verify_catalog() {
-
- debug_event('verify', 'Starting on ' . $this->name, 5, 'ampache-catalog');
- set_time_limit(0);
-
- $stats = self::get_stats($this->id);
- $number = $stats['videos'] + $stats['songs'];
- $total_updated = 0;
-
- require_once Config::get('prefix') . '/templates/show_verify_catalog.inc.php';
-
- foreach(array('video', 'song') as $media_type) {
- $total = $stats[$media_type . 's']; // UGLY
- if ($total == 0) {
- continue;
- }
- $chunks = floor($total / 10000);
- foreach(range(0, $chunks) as $chunk) {
- // Try to be nice about memory usage
- if ($chunk > 0) {
- $media_type::clear_cache();
- }
- $total_updated += $this->_verify_chunk($media_type, $chunk, 10000);
- }
- }
-
- debug_event('verify', "Finished, $total_updated updated in " . $this->name, 5, 'ampache-catalog');
-
- self::gc();
- $this->update_last_update();
-
- UI::show_box_top();
- echo '<strong>';
- printf(T_('Catalog Verify Done. %d of %d files updated.'), $total_updated, $number);
- echo "</strong><br />\n";
- UI::show_box_bottom();
- ob_flush();
- flush();
-
- return true;
-
- } // verify_catalog
-
- /**
- * _verify_chunk
- * This verifies a chunk of the catalog, done to save
- * memory
- */
- private function _verify_chunk($media_type, $chunk, $chunk_size) {
- debug_event('verify', "Starting chunk $chunk", 5, 'ampache-catalog');
- $count = $chunk * $chunk_size;
- $changed = 0;
-
- $sql = "SELECT `id`, `file` FROM `$media_type` " .
- "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size";
- $db_results = Dba::read($sql);
-
- if (Config::get('memory_cache')) {
- while ($row = Dba::fetch_assoc($db_results, false)) {
- $media_ids[] = $row['id'];
- }
- $media_type::build_cache($media_ids);
- Dba::seek($db_results, 0);
- }
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $count++;
- if (UI::check_ticker()) {
- $file = str_replace(array('(',')','\''), '', $row['file']);
- UI::update_text('verify_count_' . $this->id, $count);
- UI::update_text('verify_dir_' . $this->id, scrub_out($file));
- }
-
- if (!is_readable($row['file'])) {
- Error::add('general', sprintf(T_('%s does not exist or is not readable'), $row['file']));
- debug_event('read', $row['file'] . ' does not exist or is not readable', 5,'ampache-catalog');
- continue;
- }
-
- $media = new $media_type($row['id']);
-
- if (Flag::has_flag($media->id, $type)) {
- debug_event('verify', "$media->file is flagged, skipping", 5, 'ampache-catalog');
- continue;
- }
-
- $info = self::update_media_from_tags($media, $this->sort_pattern,$this->rename_pattern);
- if ($info['change']) {
- $changed++;
- }
- unset($info);
- }
-
- UI::update_text('verify_count_' . $this->id, $count);
- return $changed;
-
- } // _verfiy_chunk
-
- /**
- * gc
- *
- * This is a wrapper function for all of the different cleaning
- * functions, it runs them in an order that resembles correct
- */
- public static function gc() {
-
- debug_event('catalog', 'Database cleanup started', 5, 'ampache-catalog');
- Song::gc();
- Album::gc();
- Artist::gc();
- Art::gc();
- Flag::gc();
- Stats::gc();
- Rating::gc();
- Playlist::gc();
- Tmp_Playlist::gc();
- Shoutbox::gc();
- Tag::gc();
- debug_event('catalog', 'Database cleanup ended', 5, 'ampache-catalog');
-
- }
-
- /**
- * trim_prefix
- * Splits the prefix from the string
- */
- public static function trim_prefix($string) {
- $prefix_pattern = '/^(' . implode('\\s|',explode('|',Config::get('catalog_prefix_pattern'))) . '\\s)(.*)/i';
- preg_match($prefix_pattern, $string, $matches);
-
- if (count($matches)) {
- $string = trim($matches[2]);
- $prefix = trim($matches[1]);
- }
- else {
- $prefix = null;
- }
-
- return array('string' => $string, 'prefix' => $prefix);
- } // trim_prefix
-
- /**
- * check_artist
- * $artist checks if there then return id else insert and return id
- * If readonly is passed then don't create, return false on not found
- */
- public static function check_artist($artist,$mbid='',$readonly='') {
-
- /* Clean up the artist */
- $artist = trim($artist);
- $artist = Dba::escape($artist);
-
- /* Ohh no the artist has lost it's mojo! */
- if (!$artist) {
- $artist = T_('Unknown (Orphaned)');
- }
-
- // Remove the prefix so we can sort it correctly
- $trimmed = Catalog::trim_prefix($artist);
- $artist = $trimmed['string'];
- $prefix = $trimmed['prefix'];
-
- // Check to see if we've seen this artist before
- if (isset(self::$artists[$artist][$mbid])) {
- return self::$artists[$artist][$mbid];
- } // if we've seen this artist before
-
- $exists = false;
-
- $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'";
- $db_results = Dba::read($sql);
-
- // Check for results
- if ($r = Dba::fetch_assoc($db_results)) {
- $artist_id = $r['id'];
- $exists = true;
- }
-
- else { // No exact match based on MBID
- $sql = "SELECT `id`, `mbid` FROM `artist` WHERE `name` LIKE '$artist'";
- $db_results = Dba::read($sql);
-
-
- /* If we have results */
- while ($r = Dba::fetch_assoc($db_results)) {
- $key = is_null($r['mbid']) ? 'null' : $r['mbid'];
- $id_array[$key] = $r['id'];
- } // while
-
- /* Choose one */
- if (isset($id_array)) {
- if ($mbid == '') { // Prefer null entry, otherwise pick the first
- if (isset($id_array['null'])) {
- $key = 'null';
- }
- else {
- $keys = array_keys($id_array);
- $key = array_shift($keys);
- }
- $artist_id = $id_array[$key];
- $exists = true;
- }
- elseif (isset($id_array['null'])) {
- $artist_id = $id_array['null'];
- $exists = true;
- if (!$readonly) {
- $sql = "UPDATE `artist` SET `mbid`='$mbid' WHERE `id`='$artist_id'";
- $db_results = Dba::write($sql);
- if (!$db_results) {
- Error::add('general', sprintf(T_('Updating Artist: %s'), $artist));
- }
- }
- }
- unset($id_array);
- }
- } // fuzzy matching
-
- /* If not found create */
- if (!$readonly && !$exists) {
-
- $prefix_txt = $prefix ? "'$prefix'" : 'NULL';
-
- $mbid = $mbid == '' ? 'NULL' : "'$mbid'";
-
- $sql = "INSERT INTO `artist` (`name`, `prefix`, `mbid`) " .
- "VALUES ('$artist',$prefix_txt,$mbid)";
- $db_results = Dba::write($sql);
- $artist_id = Dba::insert_id();
-
- if (!$db_results) {
- Error::add('general', sprintf(T_('Inserting Artist: %s'), $artist));
- }
-
- } // not found
- // If readonly, and not found return false
- elseif (!$exists) {
- return false;
- }
-
- self::$artists[$artist][$mbid] = $artist_id;
-
- return $artist_id;
-
- } // check_artist
-
- /**
- * check_album
- * Searches for album; if found returns id else inserts and returns id
- */
- public static function check_album($album, $album_year = 0,
- $album_disk = 0, $mbid = '', $readonly = false) {
-
- /* Clean up the values */
- $album = trim($album);
- $album = Dba::escape($album);
- // Not even sure if these can be negative, but better safe than
- // llama.
- $album_year = abs(intval($album_year));
- $album_disk = abs(intval($album_disk));
-
- /* Ohh no the album has lost its mojo */
- if (!$album) {
- $album = T_('Unknown (Orphaned)');
- unset($album_year, $album_disk);
- }
-
- // Remove the prefix so we can sort it correctly
- $trimmed = Catalog::trim_prefix($album);
- $album = $trimmed['string'];
- $prefix = $trimmed['prefix'];
-
- // Check to see if we've seen this album before
- if (isset(self::$albums[$album][$album_year][$album_disk][$mbid])) {
- return self::$albums[$album][$album_year][$album_disk][$mbid];
- }
-
- /* Set up the Query */
- $sql = "SELECT `id` FROM `album` WHERE `name` = '$album'" .
- " AND `disk`='$album_disk' AND `year`='$album_year'" .
- " AND `mbid`" . ($mbid ? "='$mbid'" : ' IS NULL') .
- " AND `prefix`" . ($prefix ? "='$prefix'" : ' IS NULL');
-
- $db_results = Dba::read($sql);
-
- /* If it's found */
- if ($r = Dba::fetch_assoc($db_results)) {
- $album_id = $r['id'];
-
- // If we don't have art put it in the 'needs me some
- // art' array
- $art = new Art($r['id'], 'album');
- $art->get_db();
- if (!$art->raw) {
- $key = $r['id'];
- self::$_art_albums[$key] = $key;
- }
-
- } //if found
- elseif (!$readonly) { // If not found, create
-
- $prefix = $prefix ? "'$prefix'" : 'NULL';
- $mbid = $mbid ? "'$mbid'" : 'NULL';
-
- $sql = "INSERT INTO `album` (`name`, `prefix`,`year`,`disk`,`mbid`) " .
- "VALUES ('$album',$prefix,'$album_year','$album_disk',$mbid)";
- $db_results = Dba::write($sql);
- $album_id = Dba::insert_id();
-
- if (!$db_results) {
- debug_event('album',"Error Unable to insert Album:$album",'2');
- return false;
- }
-
- // Add it to the I needs me some album art array
- self::$_art_albums[$album_id] = $album_id;
-
- } //not found
- else {
- // readonly and not found
- return false;
- }
-
- // Save the cache
- self::$albums[$album][$album_year][$album_disk][$mbid] = $album_id;
-
- return $album_id;
-
- } // check_album
-
- /**
- * check_tag
- * This checks the tag we've been passed (name)
- * and sees if it exists, and if so if it's mapped
- * to this object, this is only done for songs for now
- */
- public static function check_tag($value,$object_id,$object_type='song') {
-
- $map_id = Tag::add($object_type,$object_id,$value,'0');
-
- return $map_id;
-
- } // check_tag
-
- /**
- * check_title
- * this checks to make sure something is
- * set on the title, if it isn't it looks at the
- * filename and trys to set the title based on that
- */
- public static function check_title($title,$file=0) {
-
- if (strlen(trim($title)) < 1) {
- $title = Dba::escape($file);
- }
-
- return $title;
-
- } // check_title
-
- /**
- * insert_local_song
- * Insert a song that isn't already in the database this
- * function is in here so we don't have to create a song object
- */
- public function insert_local_song($file,$file_info) {
-
- /* Create the vainfo object and get info */
- $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern);
- $vainfo->get_info();
-
- $key = vainfo::get_tag_type($vainfo->tags);
-
- /* Clean Up the tags */
- $results = vainfo::clean_tag_info($vainfo->tags,$key,$file);
-
- /* Set the vars here... so we don't have to do the '" . $blah['asd'] . "' */
- $title = Dba::escape($results['title']);
- $artist = $results['artist'];
- $album = $results['album'];
- $bitrate = $results['bitrate'];
- $rate = $results['rate'];
- $mode = $results['mode'];
- $size = $results['size'];
- $song_time = $results['time'];
- $track = $results['track'];
- $track_mbid = $results['mb_trackid'];
- $album_mbid = $results['mb_albumid'];
- $artist_mbid= $results['mb_artistid'];
- $disk = $results['disk'];
- $year = $results['year'];
- $comment = $results['comment'];
- $tags = $results['genre']; // multiple genre support makes this an array
- $current_time = time();
- $lyrics = ' ';
-
- /*
- * We have the artist/genre/album name need to check it in the tables
- * If found then add & return id, else return id
- */
- $artist_id = self::check_artist($artist,$artist_mbid);
- $album_id = self::check_album($album,$year,$disk,$album_mbid);
- $title = self::check_title($title,$file);
- $add_file = Dba::escape($file);
-
- $sql = "INSERT INTO `song` (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,addition_time,year,mbid)" .
- " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$track_mbid')";
- $db_results = Dba::write($sql);
-
- if (!$db_results) {
- debug_event('insert',"Unable to insert $file -- $sql" . Dba::error(),'5','ampache-catalog');
- Error::add('catalog_add', sprintf(T_('SQL Error Adding %s'), $file));
- }
-
- $song_id = Dba::insert_id();
-
- // multiple genre support
- foreach ($tags as $tag) {
- $tag = trim($tag);
- self::check_tag($tag,$song_id);
- self::check_tag($tag,$album_id,'album');
- self::check_tag($tag,$artist_id,'artist');
- }
-
-
- /* Add the EXT information */
- $sql = "INSERT INTO `song_data` (`song_id`,`comment`,`lyrics`) " .
- " VALUES ('$song_id','$comment','$lyrics')";
- $db_results = Dba::write($sql);
-
- if (!$db_results) {
- debug_event('insert',"Unable to insert EXT Info for $file -- $sql",'5','ampache-catalog');
- }
-
- } // insert_local_song
-
- /**
- * insert_remote_song
- * takes the information gotten from XML-RPC and
- * inserts it into the local database. The filename
- * ends up being the url.
- */
- public function insert_remote_song($song) {
-
- /* Limitations:
- * Missing Following Metadata
- * Disk,Rate
- */
-
- // Strip the SSID off of the url, we will need to regenerate this every time
- $url = preg_replace("/ssid=.*&/","",$song['url']);
- $title = Dba::escape($song['title']);
- $album = self::check_album($song['album'],$song['year'],null,$song['album_mbid']);
- $artist = self::check_artist($song['artist'],$song['artist_mbid']);
- $bitrate = Dba::escape($song['bitrate']);
- $size = Dba::escape($song['size']);
- $song_time = Dba::escape($song['time']);
- $track = Dba::escape($song['track']);
- $year = Dba::escape($song['year']);
- $title = Dba::escape($song['title']);
- $mbid = Dba::escape($song['mbid']);
- $mode = Dba::escape($song['mode']);
- $current_time = time();
- $catalog_id = Dba::escape($this->id);
-
- $sql = "INSERT INTO `song` (`file`,`catalog`,`album`,`artist`,`title`,`bitrate`,`rate`,`mode`,`size`,`time`,`track`,`addition_time`,`year`,`mbid`)" .
- " VALUES ('$url','$catalog_id','$album','$artist','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$mbid')";
- $db_results = Dba::write($sql);
-
- if (!$db_results) {
- debug_event('insert',"Unable to Add Remote $url -- $sql",'5','ampache-catalog');
- return false;
- }
-
- // Weird to do this here, but we have the information - see if the album has art, if it doesn't then use the remote
- // art url
- $art = new Art($album, 'album');
- // If it doesn't have art...
- if (!$art->get()) {
- // Get the mime out
- $get_vars = parse_url($song['art']);
- $extension = substr($get_vars['query'],strlen($get_vars['query'])-3,3);
- // Pull the image
- $raw = Art::get_from_source(
- array('url' => $song['art']), 'album');
- $inserted = $art->insert($raw,'image/' . $extension);
- }
-
- return true;
-
- } // insert_remote_song
-
- /**
- * insert_local_video
- * This inserts a video file into the video file table the tag
- * information we can get is super sketchy so it's kind of a crap shoot
- * here
- */
- public function insert_local_video($file,$filesize) {
-
- /* Create the vainfo object and get info */
- $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern);
- $vainfo->get_info();
-
- $tag_name = vainfo::get_tag_type($vainfo->tags);
- $results = vainfo::clean_tag_info($vainfo->tags,$tag_name,$file);
-
-
- $file = Dba::escape($file);
- $catalog_id = Dba::escape($this->id);
- $title = Dba::escape($results['title']);
- $vcodec = $results['video_codec'];
- $acodec = $results['audio_codec'];
- $rezx = intval($results['resolution_x']);
- $rezy = intval($results['resolution_y']);
- $filesize = Dba::escape($filesize);
- $time = Dba::escape($results['time']);
- $mime = Dba::escape($results['mime']);
- // UNUSED CURRENTLY
- $comment = Dba::escape($results['comment']);
- $year = Dba::escape($results['year']);
- $disk = Dba::escape($results['disk']);
-
- $sql = "INSERT INTO `video` (`file`,`catalog`,`title`,`video_codec`,`audio_codec`,`resolution_x`,`resolution_y`,`size`,`time`,`mime`) " .
- " VALUES ('$file','$catalog_id','$title','$vcodec','$acodec','$rezx','$rezy','$filesize','$time','$mime')";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // insert_local_video
-
- /**
- * check_remote_song
- * checks to see if a remote song exists in the database or not
- * if it find a song it returns the UID
- */
- public function check_remote_song($url) {
-
- $url = Dba::escape($url);
-
- $sql = "SELECT `id` FROM `song` WHERE `file`='$url'";
- $db_results = Dba::read($sql);
-
- if ($results = Dba::fetch_assoc($db_results)) {
- return $results['id'];
- }
-
- return false;
-
- } // check_remote_song
-
- /**
- * check_local_mp3
- * Checks the song to see if it's there already returns true if found, false if not
- */
- public function check_local_mp3($full_file, $gather_type='') {
-
- $file_date = filemtime($full_file);
- if ($file_date < $this->last_add) {
- debug_event('Check','Skipping ' . $full_file . ' File modify time before last add run','3');
- return true;
- }
-
- $full_file = Dba::escape($full_file);
+ $meta_handle = fopen($meta_file,"w");
+ fwrite($meta_handle,$string);
+ fclose($meta_handle);
+
+ } // end metadata
+ $i++;
+ if (!($i%100)) {
+ echo "Written: $i. . .\n";
+ debug_event('art_write',"$album->name Art written to $file",'5');
+ }
+ } // end if fopen
+ else {
+ debug_event('art_write',"Unable to open $file for writting",'5');
+ echo "Error unable to open file for writting [$file]\n";
+ }
+ } // end if fopen worked
+
+ fclose($file_handle);
+
+
+ } // end foreach
+
+ echo "Album Art Dump Complete\n";
+
+ } // dump_album_art
+
+ /**
+ * update_last_update
+ * updates the last_update of the catalog
+ */
+ private function update_last_update() {
+
+ $date = time();
+ $sql = "UPDATE `catalog` SET `last_update`='$date' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ } // update_last_update
+
+ /**
+ * update_last_add
+ * updates the last_add of the catalog
+ */
+ public function update_last_add() {
+
+ $date = time();
+ $sql = "UPDATE `catalog` SET `last_add`='$date' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ } // update_last_add
+
+ /**
+ * update_last_clean
+ * This updates the last clean information
+ */
+ public function update_last_clean() {
+
+ $date = time();
+ $sql = "UPDATE `catalog` SET `last_clean`='$date' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ } // update_last_clean
+
+ /**
+ * update_settings
+ * This function updates the basic setting of the catalog
+ */
+ public static function update_settings($data) {
+
+ $id = Dba::escape($data['catalog_id']);
+ $name = Dba::escape($data['name']);
+ $rename = Dba::escape($data['rename_pattern']);
+ $sort = Dba::escape($data['sort_pattern']);
+ $remote_username = Dba::escape($data['remote_username']);
+ $remote_password = Dba::escape($data['remote_password']);
+
+ $sql = "UPDATE `catalog` SET `name`='$name', `rename_pattern`='$rename', " .
+ "`sort_pattern`='$sort', `remote_username`='$remote_username', `remote_password`='$remote_password' WHERE `id` = '$id'";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // update_settings
+
+ /**
+ * update_single_item
+ * updates a single album,artist,song from the tag data
+ * this can be done by 75+
+ */
+ public static function update_single_item($type,$id) {
+
+ // Because single items are large numbers of things too
+ set_time_limit(0);
+
+ $songs = array();
+
+ switch ($type) {
+ case 'album':
+ $album = new Album($id);
+ $songs = $album->get_songs();
+ break;
+ case 'artist':
+ $artist = new Artist($id);
+ $songs = $artist->get_songs();
+ break;
+ case 'song':
+ $songs[] = $id;
+ break;
+ } // end switch type
+
+ foreach($songs as $song_id) {
+ $song = new Song($song_id);
+ $info = self::update_media_from_tags($song,'','');
+
+ if ($info['change']) {
+ $file = scrub_out($song->file);
+ echo "<dl>\n\t<dd>";
+ echo "<strong>$file " . T_('Updated') . "</strong>\n";
+ echo $info['text'];
+ echo "\t</dd>\n</dl><hr align=\"left\" width=\"50%\" />";
+ flush();
+ } // if change
+ else {
+ echo"<dl>\n\t<dd>";
+ echo "<strong>" . scrub_out($song->file) . "</strong><br />" . T_('No Update Needed') . "\n";
+ echo "\t</dd>\n</dl><hr align=\"left\" width=\"50%\" />";
+ flush();
+ }
+ } // foreach songs
+
+ self::gc();
+
+ } // update_single_item
+
+ /**
+ * update_media_from_tags
+ * This is a 'wrapper' function calls the update function for the media
+ * type in question
+ */
+ public static function update_media_from_tags($media, $sort_pattern='', $rename_pattern='') {
+
+ // Check for patterns
+ if (!$sort_pattern OR !$rename_pattern) {
+ $catalog = new Catalog($media->catalog);
+ $sort_pattern = $catalog->sort_pattern;
+ $rename_pattern = $catalog->rename_pattern;
+ }
+
+ debug_event('tag-read','Reading tags from ' . $media->file,'5','ampache-catalog');
+
+ $vainfo = new vainfo($media->file,'','','',$sort_pattern,$rename_pattern);
+ $vainfo->get_info();
+
+ $key = vainfo::get_tag_type($vainfo->tags);
+
+ $results = vainfo::clean_tag_info($vainfo->tags,$key,$media->file);
+
+ // Figure out what type of object this is and call the right
+ // function, giving it the stuff we've figured out above
+ $name = (get_class($media) == 'Song') ? 'song' : 'video';
+
+ $function = 'update_' . $name . '_from_tags';
+
+ $return = call_user_func(array('Catalog',$function),$results,$media);
+
+ return $return;
+
+ } // update_media_from_tags
+
+ /**
+ * update_video_from_tags
+ * Updates the video info based on tags
+ */
+ public static function update_video_from_tags($results,$video) {
+
+ // Pretty sweet function here
+ return $results;
+
+ } // update_video_from_tags
+
+ /**
+ * update_song_from_tags
+ * Updates the song info based on tags; this is called from a bunch of
+ * different places and passes in a full fledged song object, so it's a
+ * static function.
+ * FIXME: This is an ugly mess, this really needs to be consolidated and
+ * cleaned up.
+ */
+ public static function update_song_from_tags($results,$song) {
+
+ /* Setup the vars */
+ $new_song = new Song();
+ $new_song->file = $results['file'];
+ $new_song->title = $results['title'];
+ $new_song->year = $results['year'];
+ $new_song->comment = $results['comment'];
+ $new_song->language = $results['language'];
+ $new_song->lyrics = $results['lyrics'];
+ $new_song->bitrate = $results['bitrate'];
+ $new_song->rate = $results['rate'];
+ $new_song->mode = ($results['mode'] == 'cbr') ? 'cbr' : 'vbr';
+ $new_song->size = $results['size'];
+ $new_song->time = $results['time'];
+ $new_song->mime = $results['mime'];
+ $new_song->track = intval($results['track']);
+ $new_song->mbid = $results['mb_trackid'];
+ $artist = $results['artist'];
+ $artist_mbid = $results['mb_artistid'];
+ $album = $results['album'];
+ $album_mbid = $results['mb_albumid'];
+ $disk = $results['disk'];
+ $tags = $results['genre']; // multiple genre support makes this an array
+
+ /*
+ * We have the artist/genre/album name need to check it in the tables
+ * If found then add & return id, else return id
+ */
+ $new_song->artist = self::check_artist($artist,$artist_mbid);
+ $new_song->f_artist = $artist;
+ $new_song->album = self::check_album($album,$new_song->year,$disk,$album_mbid);
+ $new_song->f_album = $album . " - " . $new_song->year;
+ $new_song->title = self::check_title($new_song->title,$new_song->file);
+
+ // Nothing to assign here this is a multi-value doodly
+ // multiple genre support
+ foreach ($tags as $tag) {
+ $tag = trim($tag);
+ self::check_tag($tag,$song->id);
+ self::check_tag($tag,$new_song->album,'album');
+ self::check_tag($tag,$new_song->artist,'artist');
+ }
+
+ /* Since we're doing a full compare make sure we fill the extended information */
+ $song->fill_ext_info();
+
+ $info = Song::compare_song_information($song,$new_song);
+
+ if ($info['change']) {
+ debug_event('update',"$song->file difference found, updating database",'5','ampache-catalog');
+ $song->update_song($song->id,$new_song);
+ // Refine our reference
+ $song = $new_song;
+ }
+ else {
+ debug_event('update',"$song->file no difference found returning",'5','ampache-catalog');
+ }
+
+ return $info;
+
+ } // update_song_from_tags
+
+ /**
+ * add_to_catalog
+ * this function adds new files to an
+ * existing catalog
+ */
+ public function add_to_catalog() {
+
+ if ($this->catalog_type == 'remote') {
+ UI::show_box_top(T_('Running Remote Update') . '. . .');
+ $this->get_remote_catalog($type=0);
+ UI::show_box_bottom();
+ return true;
+ }
+
+ require Config::get('prefix') . '/templates/show_adds_catalog.inc.php';
+ flush();
+
+ /* Set the Start time */
+ $start_time = time();
+
+ // Make sure the path doesn't end in a / or \
+ $this->path = rtrim($this->path,'/');
+ $this->path = rtrim($this->path,'\\');
+
+ // Prevent the script from timing out and flush what we've got
+ set_time_limit(0);
+
+ /* Get the songs and then insert them into the db */
+ $this->add_files($this->path,$type,0,$verbose);
+
+ // Foreach Playlists we found
+ foreach ($this->_playlists as $full_file) {
+ $result = $this->import_m3u($full_file);
+ if ($result['success']) {
+ $file = basename($full_file);
+ if ($verbose) {
+ echo "&nbsp;&nbsp;&nbsp;" . T_('Added Playlist From') . " $file . . . .<br />\n";
+ flush();
+ }
+ } // end if import worked
+ } // end foreach playlist files
+
+ /* Do a little stats mojo here */
+ $current_time = time();
+
+ $catalog_id = $this->id;
+ require Config::get('prefix') . '/templates/show_gather_art.inc.php';
+ flush();
+ $this->get_art();
+
+ /* Update the Catalog last_update */
+ $this->update_last_add();
+
+ $time_diff = ($current_time - $start_time) ?: 0;
+ $rate = intval($this->count / $time_diff) ?: T_('N/A');
+
+ UI::show_box_top();
+ echo "\n<br />" .
+ printf(T_('Catalog Update Finished. Total Time: [%s] Total Songs: [%s] Songs Per Second: [%s]'),
+ date('i:s', $time_diff), $this->count, $rate);
+ echo '<br /><br />';
+ UI::show_box_bottom();
+
+ } // add_to_catalog
+
+ /**
+ * get_remote_catalog
+ * get a remote catalog and runs update if needed this requires
+ * this uses the AmpacheAPI library provided, replaces legacy XMLRPC
+ */
+ public function get_remote_catalog($type=0) {
+
+ try {
+ $remote_handle = new AmpacheApi(array('username'=>$this->remote_username,'password'=>$this->remote_password,'server'=>$this->path,'debug'=>true));
+ } catch (Exception $e) {
+ Error::add('general',$e->getMessage());
+ Error::display('general');
+ flush();
+ return false;
+ }
+
+ if ($remote_handle->state() != 'CONNECTED') {
+ debug_event('APICLIENT','Error Unable to make API client ready','1');
+ Error::add('general', T_('Error Connecting to Remote Server'));
+ Error::display('general');
+ return false;
+ }
+
+ // Figure out how many songs, more information etc
+ $remote_catalog_info = $remote_handle->info();
+
+ // Tell em what we've found johnny!
+ printf(T_('%u remote catalog(s) found (%u songs)'),$remote_catalog_info['catalogs'],$remote_catalog_info['songs']);
+ flush();
+
+ // Hardcoded for now
+ $step = '500';
+ $current = '0';
+ $total = $remote_catalog_info['songs'];
+
+ while ($total > $current) {
+ $start = $current;
+ $current += $step;
+ // It uses exceptions so lets try this
+ try {
+ $remote_handle->parse_response($remote_handle->send_command('songs',array('offset'=>$start,'limit'=>$step)));
+ $songs = $remote_handle->get_response();
+ } catch (Exception $e) {
+ Error::add('general',$e->getMessage());
+ Error::display('general');
+ flush();
+ }
+ // itterate the songs we retrieved and insert them
+ foreach ($songs as $data) {
+ if (!$this->insert_remote_song($data['song'])) {
+ debug_event('REMOTE_INSERT','Remote Insert failed, see previous log messages -' . $data['song']['self']['id'],'1');
+ Error::add('general', T_('Unable to Insert Song - %s'),$data['song']['title']);
+ Error::display('general');
+ flush();
+ }
+ } // end foreach
+ } // end while
+
+ echo "<p>" . T_('Completed updating remote catalog(s)') . ".</p><hr />\n";
+ flush();
+
+ // Update the last update value
+ $this->update_last_update();
+
+ return true;
+
+ } // get_remote_catalog
+
+ /**
+ * update_remote_catalog
+ * actually updates from the remote data, takes an array of songs that are base64 encoded and parses them
+ */
+ public function update_remote_catalog($data,$root_path) {
+
+ // Going to leave this be for now
+ //FIXME: Implement
+
+ return true;
+
+ } // update_remote_catalog
+
+ /**
+ * clean_catalog
+ * Cleans the catalog of files that no longer exist.
+ */
+ public function clean_catalog() {
+
+ // We don't want to run out of time
+ set_time_limit(0);
+
+ debug_event('clean', 'Starting on ' . $this->name, 5, 'ampache-catalog');
+
+ require_once Config::get('prefix') . '/templates/show_clean_catalog.inc.php';
+ ob_flush();
+ flush();
+
+ // Do a quick check to make sure that the root of the catalog is
+ // readable. This will minimize the loss of catalog data if
+ // mount points fail
+ if ($this->catalog_type == 'local' && !is_readable($this->path)) {
+ debug_event('catalog', 'Catalog path:' . $this->path . ' unreadable, clean failed', 1);
+ Error::add('general', T_('Catalog Root unreadable, stopping clean'));
+ Error::display('general');
+ return false;
+ }
+
+
+ $dead_total = 0;
+ $stats = self::get_stats($this->id);
+ foreach(array('video', 'song') as $media_type) {
+ $total = $stats[$media_type . 's']; // UGLY
+ if ($total == 0) {
+ continue;
+ }
+ $chunks = floor($total / 10000);
+ $dead = array();
+ foreach(range(0, $chunks) as $chunk) {
+ $dead = array_merge($dead, $this->_clean_chunk($media_type, $chunk, 10000));
+ }
+
+ $dead_count = count($dead);
+ // The AlmightyOatmeal sanity check
+ // Never remove everything; it might be a dead mount
+ if ($dead_count >= $total) {
+ debug_event('catalog', 'All files would be removed. Doing nothing.', 1);
+ Error::add('general', T_('All files would be removed. Doing nothing'));
+ continue;
+ }
+ if ($dead_count) {
+ $dead_total += $dead_count;
+ $sql = "DELETE FROM `$media_type` WHERE `id` IN " .
+ '(' . implode(',',$dead) . ')';
+ $db_results = Dba::write($sql);
+ }
+ debug_event('clean', "$media_type finished, $dead_count removed from " .
+ $this->name, 5, 'ampache-catalog');
+ }
+
+ // Remove any orphaned artists/albums/etc.
+ self::gc();
+
+ UI::show_box_top();
+ echo "<strong>";
+ printf (T_ngettext('Catalog Clean Done. %d file removed.', 'Catalog Clean Done. %d files removed.', $dead_total), $dead_total);
+ echo "</strong><br />\n";
+ UI::show_box_bottom();
+ ob_flush();
+ flush();
+
+ $this->update_last_clean();
+ } // clean_catalog
+
+
+ /**
+ * _clean_chunk
+ * This is the clean function, its broken into
+ * said chunks to try to save a little memory
+ */
+ private function _clean_chunk($media_type, $chunk, $chunk_size) {
+ debug_event('clean', "Starting chunk $chunk", 5, 'ampache-catalog');
+ $dead = array();
+ $count = $chunk * $chunk_size;
+
+ $sql = "SELECT `id`, `file` FROM `$media_type` " .
+ "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size";
+ $db_results = Dba::read($sql);
+
+ while ($results = Dba::fetch_assoc($db_results)) {
+ debug_event('clean', 'Starting work on ' . $results['file'] . '(' . $results['id'] . ')', 5, 'ampache-catalog');
+ $count++;
+ if (UI::check_ticker()) {
+ $file = str_replace(array('(',')', '\''), '', $results['file']);
+ UI::update_text('clean_count_' . $this->id, $count);
+ UI::update_text('clean_dir_' . $this->id, scrub_out($file));
+ }
+ if($this->catalog_type == 'local') {
+ $file_info = filesize($results['file']);
+ if (!file_exists($results['file']) || $file_info < 1) {
+ debug_event('clean', 'File not found or empty: ' . $results['file'], 5, 'ampache-catalog');
+ Error::add('general', sprintf(T_('Error File Not Found or 0 Bytes: %s'), $results['file']));
+
+
+ // Store it in an array we'll delete it later...
+ $dead[] = $results['id'];
+
+ } //if error
+ else if (!is_readable($results['file'])) {
+ debug_event('clean', $results['file'] . ' is not readable, but does exist', 1, 'ampache-catalog');
+ }
+ } // if localtype
+ else {
+ //do remote url check
+ $file_info = $this->check_remote_song($results['file']);
+
+ if ($file_info == false) {
+ /* Add Error */
+ Error::add('general', sprintf(T_('Error Remote File Not Found or 0 Bytes: %s'), $results['file']));
+
+
+ // Store it in an array we'll delete it later...
+ $dead[] = $results['id'];
+
+ } //if error
+ } // remote catalog
+
+ } //while gettings songs
+ return $dead;
+
+ } //_clean_chunk
+
+ /**
+ * verify_catalog
+ * This function compares the DB's information with the ID3 tags
+ */
+ public function verify_catalog() {
+
+ debug_event('verify', 'Starting on ' . $this->name, 5, 'ampache-catalog');
+ set_time_limit(0);
+
+ $stats = self::get_stats($this->id);
+ $number = $stats['videos'] + $stats['songs'];
+ $total_updated = 0;
+
+ require_once Config::get('prefix') . '/templates/show_verify_catalog.inc.php';
+
+ foreach(array('video', 'song') as $media_type) {
+ $total = $stats[$media_type . 's']; // UGLY
+ if ($total == 0) {
+ continue;
+ }
+ $chunks = floor($total / 10000);
+ foreach(range(0, $chunks) as $chunk) {
+ // Try to be nice about memory usage
+ if ($chunk > 0) {
+ $media_type::clear_cache();
+ }
+ $total_updated += $this->_verify_chunk($media_type, $chunk, 10000);
+ }
+ }
+
+ debug_event('verify', "Finished, $total_updated updated in " . $this->name, 5, 'ampache-catalog');
+
+ self::gc();
+ $this->update_last_update();
+
+ UI::show_box_top();
+ echo '<strong>';
+ printf(T_('Catalog Verify Done. %d of %d files updated.'), $total_updated, $number);
+ echo "</strong><br />\n";
+ UI::show_box_bottom();
+ ob_flush();
+ flush();
+
+ return true;
+
+ } // verify_catalog
+
+ /**
+ * _verify_chunk
+ * This verifies a chunk of the catalog, done to save
+ * memory
+ */
+ private function _verify_chunk($media_type, $chunk, $chunk_size) {
+ debug_event('verify', "Starting chunk $chunk", 5, 'ampache-catalog');
+ $count = $chunk * $chunk_size;
+ $changed = 0;
+
+ $sql = "SELECT `id`, `file` FROM `$media_type` " .
+ "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size";
+ $db_results = Dba::read($sql);
+
+ if (Config::get('memory_cache')) {
+ while ($row = Dba::fetch_assoc($db_results, false)) {
+ $media_ids[] = $row['id'];
+ }
+ $media_type::build_cache($media_ids);
+ Dba::seek($db_results, 0);
+ }
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $count++;
+ if (UI::check_ticker()) {
+ $file = str_replace(array('(',')','\''), '', $row['file']);
+ UI::update_text('verify_count_' . $this->id, $count);
+ UI::update_text('verify_dir_' . $this->id, scrub_out($file));
+ }
+
+ if (!is_readable($row['file'])) {
+ Error::add('general', sprintf(T_('%s does not exist or is not readable'), $row['file']));
+ debug_event('read', $row['file'] . ' does not exist or is not readable', 5,'ampache-catalog');
+ continue;
+ }
+
+ $media = new $media_type($row['id']);
+
+ if (Flag::has_flag($media->id, $type)) {
+ debug_event('verify', "$media->file is flagged, skipping", 5, 'ampache-catalog');
+ continue;
+ }
+
+ $info = self::update_media_from_tags($media, $this->sort_pattern,$this->rename_pattern);
+ if ($info['change']) {
+ $changed++;
+ }
+ unset($info);
+ }
+
+ UI::update_text('verify_count_' . $this->id, $count);
+ return $changed;
+
+ } // _verfiy_chunk
+
+ /**
+ * gc
+ *
+ * This is a wrapper function for all of the different cleaning
+ * functions, it runs them in an order that resembles correct
+ */
+ public static function gc() {
+
+ debug_event('catalog', 'Database cleanup started', 5, 'ampache-catalog');
+ Song::gc();
+ Album::gc();
+ Artist::gc();
+ Art::gc();
+ Flag::gc();
+ Stats::gc();
+ Rating::gc();
+ Playlist::gc();
+ Tmp_Playlist::gc();
+ Shoutbox::gc();
+ Tag::gc();
+ debug_event('catalog', 'Database cleanup ended', 5, 'ampache-catalog');
+
+ }
+
+ /**
+ * trim_prefix
+ * Splits the prefix from the string
+ */
+ public static function trim_prefix($string) {
+ $prefix_pattern = '/^(' . implode('\\s|',explode('|',Config::get('catalog_prefix_pattern'))) . '\\s)(.*)/i';
+ preg_match($prefix_pattern, $string, $matches);
+
+ if (count($matches)) {
+ $string = trim($matches[2]);
+ $prefix = trim($matches[1]);
+ }
+ else {
+ $prefix = null;
+ }
+
+ return array('string' => $string, 'prefix' => $prefix);
+ } // trim_prefix
+
+ /**
+ * check_artist
+ * $artist checks if there then return id else insert and return id
+ * If readonly is passed then don't create, return false on not found
+ */
+ public static function check_artist($artist,$mbid='',$readonly='') {
+
+ /* Clean up the artist */
+ $artist = trim($artist);
+ $artist = Dba::escape($artist);
+
+ /* Ohh no the artist has lost it's mojo! */
+ if (!$artist) {
+ $artist = T_('Unknown (Orphaned)');
+ }
+
+ // Remove the prefix so we can sort it correctly
+ $trimmed = Catalog::trim_prefix($artist);
+ $artist = $trimmed['string'];
+ $prefix = $trimmed['prefix'];
+
+ // Check to see if we've seen this artist before
+ if (isset(self::$artists[$artist][$mbid])) {
+ return self::$artists[$artist][$mbid];
+ } // if we've seen this artist before
+
+ $exists = false;
+
+ $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'";
+ $db_results = Dba::read($sql);
+
+ // Check for results
+ if ($r = Dba::fetch_assoc($db_results)) {
+ $artist_id = $r['id'];
+ $exists = true;
+ }
+
+ else { // No exact match based on MBID
+ $sql = "SELECT `id`, `mbid` FROM `artist` WHERE `name` LIKE '$artist'";
+ $db_results = Dba::read($sql);
+
+
+ /* If we have results */
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $key = is_null($r['mbid']) ? 'null' : $r['mbid'];
+ $id_array[$key] = $r['id'];
+ } // while
+
+ /* Choose one */
+ if (isset($id_array)) {
+ if ($mbid == '') { // Prefer null entry, otherwise pick the first
+ if (isset($id_array['null'])) {
+ $key = 'null';
+ }
+ else {
+ $keys = array_keys($id_array);
+ $key = array_shift($keys);
+ }
+ $artist_id = $id_array[$key];
+ $exists = true;
+ }
+ elseif (isset($id_array['null'])) {
+ $artist_id = $id_array['null'];
+ $exists = true;
+ if (!$readonly) {
+ $sql = "UPDATE `artist` SET `mbid`='$mbid' WHERE `id`='$artist_id'";
+ $db_results = Dba::write($sql);
+ if (!$db_results) {
+ Error::add('general', sprintf(T_('Updating Artist: %s'), $artist));
+ }
+ }
+ }
+ unset($id_array);
+ }
+ } // fuzzy matching
+
+ /* If not found create */
+ if (!$readonly && !$exists) {
+
+ $prefix_txt = $prefix ? "'$prefix'" : 'NULL';
+
+ $mbid = $mbid == '' ? 'NULL' : "'$mbid'";
+
+ $sql = "INSERT INTO `artist` (`name`, `prefix`, `mbid`) " .
+ "VALUES ('$artist',$prefix_txt,$mbid)";
+ $db_results = Dba::write($sql);
+ $artist_id = Dba::insert_id();
+
+ if (!$db_results) {
+ Error::add('general', sprintf(T_('Inserting Artist: %s'), $artist));
+ }
+
+ } // not found
+ // If readonly, and not found return false
+ elseif (!$exists) {
+ return false;
+ }
+
+ self::$artists[$artist][$mbid] = $artist_id;
+
+ return $artist_id;
+
+ } // check_artist
+
+ /**
+ * check_album
+ * Searches for album; if found returns id else inserts and returns id
+ */
+ public static function check_album($album, $album_year = 0,
+ $album_disk = 0, $mbid = '', $readonly = false) {
+
+ /* Clean up the values */
+ $album = trim($album);
+ $album = Dba::escape($album);
+ // Not even sure if these can be negative, but better safe than
+ // llama.
+ $album_year = abs(intval($album_year));
+ $album_disk = abs(intval($album_disk));
+
+ /* Ohh no the album has lost its mojo */
+ if (!$album) {
+ $album = T_('Unknown (Orphaned)');
+ unset($album_year, $album_disk);
+ }
+
+ // Remove the prefix so we can sort it correctly
+ $trimmed = Catalog::trim_prefix($album);
+ $album = $trimmed['string'];
+ $prefix = $trimmed['prefix'];
+
+ // Check to see if we've seen this album before
+ if (isset(self::$albums[$album][$album_year][$album_disk][$mbid])) {
+ return self::$albums[$album][$album_year][$album_disk][$mbid];
+ }
+
+ /* Set up the Query */
+ $sql = "SELECT `id` FROM `album` WHERE `name` = '$album'" .
+ " AND `disk`='$album_disk' AND `year`='$album_year'" .
+ " AND `mbid`" . ($mbid ? "='$mbid'" : ' IS NULL') .
+ " AND `prefix`" . ($prefix ? "='$prefix'" : ' IS NULL');
+
+ $db_results = Dba::read($sql);
+
+ /* If it's found */
+ if ($r = Dba::fetch_assoc($db_results)) {
+ $album_id = $r['id'];
+
+ // If we don't have art put it in the 'needs me some
+ // art' array
+ $art = new Art($r['id'], 'album');
+ $art->get_db();
+ if (!$art->raw) {
+ $key = $r['id'];
+ self::$_art_albums[$key] = $key;
+ }
+
+ } //if found
+ elseif (!$readonly) { // If not found, create
+
+ $prefix = $prefix ? "'$prefix'" : 'NULL';
+ $mbid = $mbid ? "'$mbid'" : 'NULL';
+
+ $sql = "INSERT INTO `album` (`name`, `prefix`,`year`,`disk`,`mbid`) " .
+ "VALUES ('$album',$prefix,'$album_year','$album_disk',$mbid)";
+ $db_results = Dba::write($sql);
+ $album_id = Dba::insert_id();
+
+ if (!$db_results) {
+ debug_event('album',"Error Unable to insert Album:$album",'2');
+ return false;
+ }
+
+ // Add it to the I needs me some album art array
+ self::$_art_albums[$album_id] = $album_id;
+
+ } //not found
+ else {
+ // readonly and not found
+ return false;
+ }
+
+ // Save the cache
+ self::$albums[$album][$album_year][$album_disk][$mbid] = $album_id;
+
+ return $album_id;
+
+ } // check_album
+
+ /**
+ * check_tag
+ * This checks the tag we've been passed (name)
+ * and sees if it exists, and if so if it's mapped
+ * to this object, this is only done for songs for now
+ */
+ public static function check_tag($value,$object_id,$object_type='song') {
+
+ $map_id = Tag::add($object_type,$object_id,$value,'0');
+
+ return $map_id;
+
+ } // check_tag
+
+ /**
+ * check_title
+ * this checks to make sure something is
+ * set on the title, if it isn't it looks at the
+ * filename and trys to set the title based on that
+ */
+ public static function check_title($title,$file=0) {
+
+ if (strlen(trim($title)) < 1) {
+ $title = Dba::escape($file);
+ }
+
+ return $title;
+
+ } // check_title
+
+ /**
+ * insert_local_song
+ * Insert a song that isn't already in the database this
+ * function is in here so we don't have to create a song object
+ */
+ public function insert_local_song($file,$file_info) {
+
+ /* Create the vainfo object and get info */
+ $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern);
+ $vainfo->get_info();
+
+ $key = vainfo::get_tag_type($vainfo->tags);
+
+ /* Clean Up the tags */
+ $results = vainfo::clean_tag_info($vainfo->tags,$key,$file);
+
+ /* Set the vars here... so we don't have to do the '" . $blah['asd'] . "' */
+ $title = Dba::escape($results['title']);
+ $artist = $results['artist'];
+ $album = $results['album'];
+ $bitrate = $results['bitrate'];
+ $rate = $results['rate'];
+ $mode = $results['mode'];
+ $size = $results['size'];
+ $song_time = $results['time'];
+ $track = $results['track'];
+ $track_mbid = $results['mb_trackid'];
+ $album_mbid = $results['mb_albumid'];
+ $artist_mbid= $results['mb_artistid'];
+ $disk = $results['disk'];
+ $year = $results['year'];
+ $comment = $results['comment'];
+ $tags = $results['genre']; // multiple genre support makes this an array
+ $current_time = time();
+ $lyrics = ' ';
+
+ /*
+ * We have the artist/genre/album name need to check it in the tables
+ * If found then add & return id, else return id
+ */
+ $artist_id = self::check_artist($artist,$artist_mbid);
+ $album_id = self::check_album($album,$year,$disk,$album_mbid);
+ $title = self::check_title($title,$file);
+ $add_file = Dba::escape($file);
+
+ $sql = "INSERT INTO `song` (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,addition_time,year,mbid)" .
+ " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$track_mbid')";
+ $db_results = Dba::write($sql);
+
+ if (!$db_results) {
+ debug_event('insert',"Unable to insert $file -- $sql" . Dba::error(),'5','ampache-catalog');
+ Error::add('catalog_add', sprintf(T_('SQL Error Adding %s'), $file));
+ }
+
+ $song_id = Dba::insert_id();
+
+ // multiple genre support
+ foreach ($tags as $tag) {
+ $tag = trim($tag);
+ self::check_tag($tag,$song_id);
+ self::check_tag($tag,$album_id,'album');
+ self::check_tag($tag,$artist_id,'artist');
+ }
+
+
+ /* Add the EXT information */
+ $sql = "INSERT INTO `song_data` (`song_id`,`comment`,`lyrics`) " .
+ " VALUES ('$song_id','$comment','$lyrics')";
+ $db_results = Dba::write($sql);
+
+ if (!$db_results) {
+ debug_event('insert',"Unable to insert EXT Info for $file -- $sql",'5','ampache-catalog');
+ }
+
+ } // insert_local_song
+
+ /**
+ * insert_remote_song
+ * takes the information gotten from XML-RPC and
+ * inserts it into the local database. The filename
+ * ends up being the url.
+ */
+ public function insert_remote_song($song) {
+
+ /* Limitations:
+ * Missing Following Metadata
+ * Disk,Rate
+ */
+
+ // Strip the SSID off of the url, we will need to regenerate this every time
+ $url = preg_replace("/ssid=.*&/","",$song['url']);
+ $title = Dba::escape($song['title']);
+ $album = self::check_album($song['album'],$song['year'],null,$song['album_mbid']);
+ $artist = self::check_artist($song['artist'],$song['artist_mbid']);
+ $bitrate = Dba::escape($song['bitrate']);
+ $size = Dba::escape($song['size']);
+ $song_time = Dba::escape($song['time']);
+ $track = Dba::escape($song['track']);
+ $year = Dba::escape($song['year']);
+ $title = Dba::escape($song['title']);
+ $mbid = Dba::escape($song['mbid']);
+ $mode = Dba::escape($song['mode']);
+ $current_time = time();
+ $catalog_id = Dba::escape($this->id);
+
+ $sql = "INSERT INTO `song` (`file`,`catalog`,`album`,`artist`,`title`,`bitrate`,`rate`,`mode`,`size`,`time`,`track`,`addition_time`,`year`,`mbid`)" .
+ " VALUES ('$url','$catalog_id','$album','$artist','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$mbid')";
+ $db_results = Dba::write($sql);
+
+ if (!$db_results) {
+ debug_event('insert',"Unable to Add Remote $url -- $sql",'5','ampache-catalog');
+ return false;
+ }
+
+ // Weird to do this here, but we have the information - see if the album has art, if it doesn't then use the remote
+ // art url
+ $art = new Art($album, 'album');
+ // If it doesn't have art...
+ if (!$art->get()) {
+ // Get the mime out
+ $get_vars = parse_url($song['art']);
+ $extension = substr($get_vars['query'],strlen($get_vars['query'])-3,3);
+ // Pull the image
+ $raw = Art::get_from_source(
+ array('url' => $song['art']), 'album');
+ $inserted = $art->insert($raw,'image/' . $extension);
+ }
+
+ return true;
+
+ } // insert_remote_song
+
+ /**
+ * insert_local_video
+ * This inserts a video file into the video file table the tag
+ * information we can get is super sketchy so it's kind of a crap shoot
+ * here
+ */
+ public function insert_local_video($file,$filesize) {
+
+ /* Create the vainfo object and get info */
+ $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern);
+ $vainfo->get_info();
+
+ $tag_name = vainfo::get_tag_type($vainfo->tags);
+ $results = vainfo::clean_tag_info($vainfo->tags,$tag_name,$file);
+
+
+ $file = Dba::escape($file);
+ $catalog_id = Dba::escape($this->id);
+ $title = Dba::escape($results['title']);
+ $vcodec = $results['video_codec'];
+ $acodec = $results['audio_codec'];
+ $rezx = intval($results['resolution_x']);
+ $rezy = intval($results['resolution_y']);
+ $filesize = Dba::escape($filesize);
+ $time = Dba::escape($results['time']);
+ $mime = Dba::escape($results['mime']);
+ // UNUSED CURRENTLY
+ $comment = Dba::escape($results['comment']);
+ $year = Dba::escape($results['year']);
+ $disk = Dba::escape($results['disk']);
+
+ $sql = "INSERT INTO `video` (`file`,`catalog`,`title`,`video_codec`,`audio_codec`,`resolution_x`,`resolution_y`,`size`,`time`,`mime`) " .
+ " VALUES ('$file','$catalog_id','$title','$vcodec','$acodec','$rezx','$rezy','$filesize','$time','$mime')";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // insert_local_video
+
+ /**
+ * check_remote_song
+ * checks to see if a remote song exists in the database or not
+ * if it find a song it returns the UID
+ */
+ public function check_remote_song($url) {
+
+ $url = Dba::escape($url);
+
+ $sql = "SELECT `id` FROM `song` WHERE `file`='$url'";
+ $db_results = Dba::read($sql);
+
+ if ($results = Dba::fetch_assoc($db_results)) {
+ return $results['id'];
+ }
+
+ return false;
+
+ } // check_remote_song
+
+ /**
+ * check_local_mp3
+ * Checks the song to see if it's there already returns true if found, false if not
+ */
+ public function check_local_mp3($full_file, $gather_type='') {
+
+ $file_date = filemtime($full_file);
+ if ($file_date < $this->last_add) {
+ debug_event('Check','Skipping ' . $full_file . ' File modify time before last add run','3');
+ return true;
+ }
+
+ $full_file = Dba::escape($full_file);
- $sql = "SELECT `id` FROM `song` WHERE `file` = '$full_file'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `song` WHERE `file` = '$full_file'";
+ $db_results = Dba::read($sql);
- //If it's found then return true
- if (Dba::fetch_row($db_results)) {
- return true;
- }
+ //If it's found then return true
+ if (Dba::fetch_row($db_results)) {
+ return true;
+ }
- return false;
+ return false;
- } //check_local_mp3
+ } //check_local_mp3
- /**
- * import_m3u
- * this takes m3u filename and then attempts to create a Public Playlist based on the filenames
- * listed in the m3u
- */
- public function import_m3u($filename) {
+ /**
+ * import_m3u
+ * this takes m3u filename and then attempts to create a Public Playlist based on the filenames
+ * listed in the m3u
+ */
+ public function import_m3u($filename) {
- $m3u_handle = fopen($filename,'r');
+ $m3u_handle = fopen($filename,'r');
- $data = fread($m3u_handle,filesize($filename));
+ $data = fread($m3u_handle,filesize($filename));
- $results = explode("\n",$data);
+ $results = explode("\n",$data);
- $pattern = '/\.(' . Config::get('catalog_file_pattern') . ')$/i';
+ $pattern = '/\.(' . Config::get('catalog_file_pattern') . ')$/i';
- // Foreach what we're able to pull out from the file
- foreach ($results as $value) {
+ // Foreach what we're able to pull out from the file
+ foreach ($results as $value) {
- // Remove extra whitespace
- $value = trim($value);
- if (preg_match($pattern,$value)) {
+ // Remove extra whitespace
+ $value = trim($value);
+ if (preg_match($pattern,$value)) {
- /* Translate from \ to / so basename works */
- $value = str_replace("\\","/",$value);
- $file = basename($value);
+ /* Translate from \ to / so basename works */
+ $value = str_replace("\\","/",$value);
+ $file = basename($value);
- /* Search for this filename, cause it's a audio file */
- $sql = "SELECT `id` FROM `song` WHERE `file` LIKE '%" . Dba::escape($file) . "'";
- $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ /* Search for this filename, cause it's a audio file */
+ $sql = "SELECT `id` FROM `song` WHERE `file` LIKE '%" . Dba::escape($file) . "'";
+ $db_results = Dba::read($sql);
+ $results = Dba::fetch_assoc($db_results);
- if (isset($results['id'])) { $songs[] = $results['id']; }
+ if (isset($results['id'])) { $songs[] = $results['id']; }
- } // if it's a file
- // Check to see if it's a url from this ampache instance
- elseif (substr($value,0,strlen(Config::get('web_path'))) == Config::get('web_path')) {
- $song_id = intval(Song::parse_song_url($value));
+ } // if it's a file
+ // Check to see if it's a url from this ampache instance
+ elseif (substr($value,0,strlen(Config::get('web_path'))) == Config::get('web_path')) {
+ $song_id = intval(Song::parse_song_url($value));
- $sql = "SELECT COUNT(*) FROM `song` WHERE `id`='$song_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT COUNT(*) FROM `song` WHERE `id`='$song_id'";
+ $db_results = Dba::read($sql);
- if (Dba::num_rows($db_results)) {
- $songs[] = $song_id;
- }
+ if (Dba::num_rows($db_results)) {
+ $songs[] = $song_id;
+ }
- } // end if it's an http url
+ } // end if it's an http url
- } // end foreach line
+ } // end foreach line
- debug_event('m3u_parse', "Parsed $filename, found " . count($songs) . " songs", 5);
-
- if (count($songs)) {
- $name = "M3U - " . basename($filename,'.m3u');
- $playlist_id = Playlist::create($name,'public');
-
- if (!$playlist_id) {
- return array(
- 'success' => false,
- 'error' => 'Failed to create playlist.',
- );
- }
-
- /* Recreate the Playlist */
- $playlist = new Playlist($playlist_id);
- $playlist->add_songs($songs, true);
-
- return array(
- 'success' => true,
- 'id' => $playlist_id,
- 'count' => count($songs)
- );
- }
-
- return array(
- 'success' => false,
- 'error' => 'No valid songs found in M3U.'
- );
-
- } // import_m3u
-
- /**
- * delete
- * Deletes the catalog and everything associated with it
- * it takes the catalog id
- */
- public static function delete($catalog_id) {
-
- $catalog_id = Dba::escape($catalog_id);
-
- // First remove the songs in this catalog
- $sql = "DELETE FROM `song` WHERE `catalog` = '$catalog_id'";
- $db_results = Dba::write($sql);
-
- // Only if the previous one works do we go on
- if (!$db_results) { return false; }
-
- $sql = "DELETE FROM `video` WHERE `catalog` = '$catalog_id'";
- $db_results = Dba::write($sql);
-
- if (!$db_results) { return false; }
-
- // Next Remove the Catalog Entry it's self
- $sql = "DELETE FROM `catalog` WHERE `id` = '$catalog_id'";
- $db_results = Dba::write($sql);
-
- // Run the cleaners...
- self::gc();
-
- } // delete
-
- /**
- * exports the catalog
- * it exports all songs in the database to the given export type.
- */
- public function export($type) {
-
- // Select all songs in catalog
- if($this->id) {
- $sql = 'SELECT `id` FROM `song` ' .
- "WHERE `catalog`='$this->id' " .
- 'ORDER BY `album`, `track`';
- }
- else {
- $sql = 'SELECT `id` FROM `song` ORDER BY `album`, `track`';
- }
- $db_results = Dba::read($sql);
-
- switch ($type) {
- case 'itunes':
- echo xml_get_header('itunes');
- while ($results = Dba::fetch_assoc($db_results)) {
- $song = new Song($results['id']);
- $song->format();
-
- $xml = array();
- $xml['key']= $results['id'];
- $xml['dict']['Track ID']= intval($results['id']);
- $xml['dict']['Name'] = $song->title;
- $xml['dict']['Artist'] = $song->f_artist_full;
- $xml['dict']['Album'] = $song->f_album_full;
- $xml['dict']['Total Time'] = intval($song->time) * 1000; // iTunes uses milliseconds
- $xml['dict']['Track Number'] = intval($song->track);
- $xml['dict']['Year'] = intval($song->year);
- $xml['dict']['Date Added'] = date("Y-m-d\TH:i:s\Z",$song->addition_time);
- $xml['dict']['Bit Rate'] = intval($song->bitrate/1000);
- $xml['dict']['Sample Rate'] = intval($song->rate);
- $xml['dict']['Play Count'] = intval($song->played);
- $xml['dict']['Track Type'] = "URL";
- $xml['dict']['Location'] = Song::play_url($song->id);
- echo xml_from_array($xml, 1, 'itunes');
- // flush output buffer
- } // while result
- echo xml_get_footer('itunes');
-
- break;
- case 'csv':
- echo "ID,Title,Artist,Album,Length,Track,Year,Date Added,Bitrate,Played,File\n";
- while ($results = Dba::fetch_assoc($db_results)) {
- $song = new Song($results['id']);
- $song->format();
- echo '"' . $song->id . '","' .
- $song->title . '","' .
- $song->f_artist_full . '","' .
- $song->f_album_full .'","' .
- $song->f_time . '","' .
- $song->f_track . '","' .
- $song->year .'","' .
- date("Y-m-d\TH:i:s\Z", $song->addition_time) . '","' .
- $song->f_bitrate .'","' .
- $song->played . '","' .
- $song->file . "\n";
- }
- break;
- } // end switch
-
- } // export
+ debug_event('m3u_parse', "Parsed $filename, found " . count($songs) . " songs", 5);
+
+ if (count($songs)) {
+ $name = "M3U - " . basename($filename,'.m3u');
+ $playlist_id = Playlist::create($name,'public');
+
+ if (!$playlist_id) {
+ return array(
+ 'success' => false,
+ 'error' => 'Failed to create playlist.',
+ );
+ }
+
+ /* Recreate the Playlist */
+ $playlist = new Playlist($playlist_id);
+ $playlist->add_songs($songs, true);
+
+ return array(
+ 'success' => true,
+ 'id' => $playlist_id,
+ 'count' => count($songs)
+ );
+ }
+
+ return array(
+ 'success' => false,
+ 'error' => 'No valid songs found in M3U.'
+ );
+
+ } // import_m3u
+
+ /**
+ * delete
+ * Deletes the catalog and everything associated with it
+ * it takes the catalog id
+ */
+ public static function delete($catalog_id) {
+
+ $catalog_id = Dba::escape($catalog_id);
+
+ // First remove the songs in this catalog
+ $sql = "DELETE FROM `song` WHERE `catalog` = '$catalog_id'";
+ $db_results = Dba::write($sql);
+
+ // Only if the previous one works do we go on
+ if (!$db_results) { return false; }
+
+ $sql = "DELETE FROM `video` WHERE `catalog` = '$catalog_id'";
+ $db_results = Dba::write($sql);
+
+ if (!$db_results) { return false; }
+
+ // Next Remove the Catalog Entry it's self
+ $sql = "DELETE FROM `catalog` WHERE `id` = '$catalog_id'";
+ $db_results = Dba::write($sql);
+
+ // Run the cleaners...
+ self::gc();
+
+ } // delete
+
+ /**
+ * exports the catalog
+ * it exports all songs in the database to the given export type.
+ */
+ public function export($type) {
+
+ // Select all songs in catalog
+ if($this->id) {
+ $sql = 'SELECT `id` FROM `song` ' .
+ "WHERE `catalog`='$this->id' " .
+ 'ORDER BY `album`, `track`';
+ }
+ else {
+ $sql = 'SELECT `id` FROM `song` ORDER BY `album`, `track`';
+ }
+ $db_results = Dba::read($sql);
+
+ switch ($type) {
+ case 'itunes':
+ echo xml_get_header('itunes');
+ while ($results = Dba::fetch_assoc($db_results)) {
+ $song = new Song($results['id']);
+ $song->format();
+
+ $xml = array();
+ $xml['key']= $results['id'];
+ $xml['dict']['Track ID']= intval($results['id']);
+ $xml['dict']['Name'] = $song->title;
+ $xml['dict']['Artist'] = $song->f_artist_full;
+ $xml['dict']['Album'] = $song->f_album_full;
+ $xml['dict']['Total Time'] = intval($song->time) * 1000; // iTunes uses milliseconds
+ $xml['dict']['Track Number'] = intval($song->track);
+ $xml['dict']['Year'] = intval($song->year);
+ $xml['dict']['Date Added'] = date("Y-m-d\TH:i:s\Z",$song->addition_time);
+ $xml['dict']['Bit Rate'] = intval($song->bitrate/1000);
+ $xml['dict']['Sample Rate'] = intval($song->rate);
+ $xml['dict']['Play Count'] = intval($song->played);
+ $xml['dict']['Track Type'] = "URL";
+ $xml['dict']['Location'] = Song::play_url($song->id);
+ echo xml_from_array($xml, 1, 'itunes');
+ // flush output buffer
+ } // while result
+ echo xml_get_footer('itunes');
+
+ break;
+ case 'csv':
+ echo "ID,Title,Artist,Album,Length,Track,Year,Date Added,Bitrate,Played,File\n";
+ while ($results = Dba::fetch_assoc($db_results)) {
+ $song = new Song($results['id']);
+ $song->format();
+ echo '"' . $song->id . '","' .
+ $song->title . '","' .
+ $song->f_artist_full . '","' .
+ $song->f_album_full .'","' .
+ $song->f_time . '","' .
+ $song->f_track . '","' .
+ $song->year .'","' .
+ date("Y-m-d\TH:i:s\Z", $song->addition_time) . '","' .
+ $song->f_bitrate .'","' .
+ $song->played . '","' .
+ $song->file . "\n";
+ }
+ break;
+ } // end switch
+
+ } // export
} // end of catalog class
diff --git a/lib/class/config.class.php b/lib/class/config.class.php
index 5b325ff4..84129760 100644
--- a/lib/class/config.class.php
+++ b/lib/class/config.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -35,95 +35,95 @@
*/
class Config {
- /**
- * These are the settings for this specific class
- *
- * @var array
- */
- private $_local = array();
-
- /**
- * These are the global settings they go where it goes
- *
- * @var array
- */
- private static $_global = array();
-
- /**
- * constructor
- * This is what is called when the class is loaded
- */
- public function __construct() {
-
- // Rien a faire
-
- } // constructor
-
- /**
- * get
- * This checks to see if this is an instance or procedure
- * call, procedure == global, instance == local
- *
- * @param string $name
- * @return mixed array or null
- */
- public static function get($name) {
-
- if (isset(self::$_global[$name])) { return self::$_global[$name]; }
- else { return null; }
-
- } // get
-
- /**
- * get_all
- * This returns all of the current config variables as an array
- *
- * @return array
- */
- public static function get_all() {
-
- return self::$_global;
-
- } // get_all
-
- /**
- * set
- *
- * This sets config values.
- *
- * @param string $name Key name
- * @param string $value Value name
- * @param boolean $clobber Clobber flag true or false
- * @return void
- */
- public static function set($name, $value, $clobber = false) {
-
- if (isset(self::$_global[$name]) && !$clobber) {
- debug_event('Config', "Tried to overwrite existing key $name without setting clobber", 5);
- Error::add('Config Global', sprintf(T_('Trying to clobber \'%s\' without setting clobber'), $name));
- return false;
- }
-
- self::$_global[$name] = $value;
-
- } // set
-
- /**
- * set_by_array
- *
- * This is the same as the set function except it takes an array as
- * input.
- *
- * @param array $array Array
- * @param boolean $clobber Clobber flag true or false
- */
- public static function set_by_array($array, $clobber = false) {
-
- foreach ($array as $name => $value) {
- self::set($name,$value,$clobber);
- }
-
- } // set_by_array
+ /**
+ * These are the settings for this specific class
+ *
+ * @var array
+ */
+ private $_local = array();
+
+ /**
+ * These are the global settings they go where it goes
+ *
+ * @var array
+ */
+ private static $_global = array();
+
+ /**
+ * constructor
+ * This is what is called when the class is loaded
+ */
+ public function __construct() {
+
+ // Rien a faire
+
+ } // constructor
+
+ /**
+ * get
+ * This checks to see if this is an instance or procedure
+ * call, procedure == global, instance == local
+ *
+ * @param string $name
+ * @return mixed array or null
+ */
+ public static function get($name) {
+
+ if (isset(self::$_global[$name])) { return self::$_global[$name]; }
+ else { return null; }
+
+ } // get
+
+ /**
+ * get_all
+ * This returns all of the current config variables as an array
+ *
+ * @return array
+ */
+ public static function get_all() {
+
+ return self::$_global;
+
+ } // get_all
+
+ /**
+ * set
+ *
+ * This sets config values.
+ *
+ * @param string $name Key name
+ * @param string $value Value name
+ * @param boolean $clobber Clobber flag true or false
+ * @return void
+ */
+ public static function set($name, $value, $clobber = false) {
+
+ if (isset(self::$_global[$name]) && !$clobber) {
+ debug_event('Config', "Tried to overwrite existing key $name without setting clobber", 5);
+ Error::add('Config Global', sprintf(T_('Trying to clobber \'%s\' without setting clobber'), $name));
+ return false;
+ }
+
+ self::$_global[$name] = $value;
+
+ } // set
+
+ /**
+ * set_by_array
+ *
+ * This is the same as the set function except it takes an array as
+ * input.
+ *
+ * @param array $array Array
+ * @param boolean $clobber Clobber flag true or false
+ */
+ public static function set_by_array($array, $clobber = false) {
+
+ foreach ($array as $name => $value) {
+ self::set($name,$value,$clobber);
+ }
+
+ } // set_by_array
} // end Config class
?>
diff --git a/lib/class/core.class.php b/lib/class/core.class.php
index b6033975..55e594d5 100644
--- a/lib/class/core.class.php
+++ b/lib/class/core.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,140 +29,140 @@
*/
class Core {
- /**
- * constructor
- * This doesn't do anything
- */
- private function __construct() {
-
- return false;
-
- } // construction
-
- /**
- * autoload
- * This function automatically loads any missing classes as they are
- * needed so that we don't use a million include statements which load
- * more than we need.
- */
- public static function autoload($class) {
- // Lowercase the class
- $class = strtolower($class);
-
- $file = Config::get('prefix') . "/lib/class/$class.class.php";
-
- // See if it exists
- if (is_readable($file)) {
- require $file;
- if (is_callable($class . '::_auto_init')) {
- $class::_auto_init();
- }
- }
- // Else log this as a fatal error
- else {
- debug_event('autoload', "'$class' not found!", 1);
- }
- } // autoload
-
- /**
- * form_register
- * This registers a form with a SID, inserts it into the session
- * variables and then returns a string for use in the HTML form
- */
- public static function form_register($name, $type = 'post') {
-
- // Make ourselves a nice little sid
- $sid = md5(uniqid(rand(), true));
- $window = Config::get('session_length');
- $expire = time() + $window;
-
- // Register it
- $_SESSION['forms'][$sid] = array('name' => $name, 'expire' => $expire);
- debug_event('Core', "Registered $type form $name with SID $sid and expiration $expire ($window seconds from now)", 5);
-
- switch ($type) {
- default:
- case 'post':
- $string = '<input type="hidden" name="form_validation" value="' . $sid . '" />';
- break;
- case 'get':
- $string = $sid;
- break;
- } // end switch on type
-
- return $string;
-
- } // form_register
-
- /**
- * form_verify
- *
- * This takes a form name and then compares it with the posted sid, if
- * they don't match then it returns false and doesn't let the person
- * continue
- */
- public static function form_verify($name, $type = 'post') {
- switch ($type) {
- case 'post':
- $sid = $_POST['form_validation'];
- break;
- case 'get':
- $sid = $_GET['form_validation'];
- break;
- case 'cookie':
- $sid = $_COOKIE['form_validation'];
- break;
- case 'request':
- $sid = $_REQUEST['form_validation'];
- break;
- }
-
- if (!isset($_SESSION['forms'][$sid])) {
- debug_event('Core', "Form $sid not found in session, rejecting request", 2);
- return false;
- }
-
- $form = $_SESSION['forms'][$sid];
- unset($_SESSION['forms'][$sid]);
-
- if ($form['name'] == $name) {
- debug_event('Core', "Verified SID $sid for $type form $name", 5);
- if ($form['expire'] < time()) {
- debug_event('Core', "Form $sid is expired, rejecting request", 2);
- return false;
- }
-
- return true;
- }
-
- // OMG HAX0RZ
- debug_event('Core', "$type form $sid failed consistency check, rejecting request", 2);
- return false;
-
- } // form_verify
-
- /**
- * image_dimensions
- * This returns the dimensions of the passed song of the passed type
- * returns an empty array if PHP-GD is not currently installed, returns
- * false on error
- */
- public static function image_dimensions($image_data) {
-
- if (!function_exists('ImageCreateFromString')) { return false; }
-
- $image = ImageCreateFromString($image_data);
-
- if (!$image) { return false; }
-
- $width = imagesx($image);
- $height = imagesy($image);
-
- if (!$width || !$height) { return false; }
-
- return array('width'=>$width,'height'=>$height);
-
- } // image_dimensions
+ /**
+ * constructor
+ * This doesn't do anything
+ */
+ private function __construct() {
+
+ return false;
+
+ } // construction
+
+ /**
+ * autoload
+ * This function automatically loads any missing classes as they are
+ * needed so that we don't use a million include statements which load
+ * more than we need.
+ */
+ public static function autoload($class) {
+ // Lowercase the class
+ $class = strtolower($class);
+
+ $file = Config::get('prefix') . "/lib/class/$class.class.php";
+
+ // See if it exists
+ if (is_readable($file)) {
+ require $file;
+ if (is_callable($class . '::_auto_init')) {
+ $class::_auto_init();
+ }
+ }
+ // Else log this as a fatal error
+ else {
+ debug_event('autoload', "'$class' not found!", 1);
+ }
+ } // autoload
+
+ /**
+ * form_register
+ * This registers a form with a SID, inserts it into the session
+ * variables and then returns a string for use in the HTML form
+ */
+ public static function form_register($name, $type = 'post') {
+
+ // Make ourselves a nice little sid
+ $sid = md5(uniqid(rand(), true));
+ $window = Config::get('session_length');
+ $expire = time() + $window;
+
+ // Register it
+ $_SESSION['forms'][$sid] = array('name' => $name, 'expire' => $expire);
+ debug_event('Core', "Registered $type form $name with SID $sid and expiration $expire ($window seconds from now)", 5);
+
+ switch ($type) {
+ default:
+ case 'post':
+ $string = '<input type="hidden" name="form_validation" value="' . $sid . '" />';
+ break;
+ case 'get':
+ $string = $sid;
+ break;
+ } // end switch on type
+
+ return $string;
+
+ } // form_register
+
+ /**
+ * form_verify
+ *
+ * This takes a form name and then compares it with the posted sid, if
+ * they don't match then it returns false and doesn't let the person
+ * continue
+ */
+ public static function form_verify($name, $type = 'post') {
+ switch ($type) {
+ case 'post':
+ $sid = $_POST['form_validation'];
+ break;
+ case 'get':
+ $sid = $_GET['form_validation'];
+ break;
+ case 'cookie':
+ $sid = $_COOKIE['form_validation'];
+ break;
+ case 'request':
+ $sid = $_REQUEST['form_validation'];
+ break;
+ }
+
+ if (!isset($_SESSION['forms'][$sid])) {
+ debug_event('Core', "Form $sid not found in session, rejecting request", 2);
+ return false;
+ }
+
+ $form = $_SESSION['forms'][$sid];
+ unset($_SESSION['forms'][$sid]);
+
+ if ($form['name'] == $name) {
+ debug_event('Core', "Verified SID $sid for $type form $name", 5);
+ if ($form['expire'] < time()) {
+ debug_event('Core', "Form $sid is expired, rejecting request", 2);
+ return false;
+ }
+
+ return true;
+ }
+
+ // OMG HAX0RZ
+ debug_event('Core', "$type form $sid failed consistency check, rejecting request", 2);
+ return false;
+
+ } // form_verify
+
+ /**
+ * image_dimensions
+ * This returns the dimensions of the passed song of the passed type
+ * returns an empty array if PHP-GD is not currently installed, returns
+ * false on error
+ */
+ public static function image_dimensions($image_data) {
+
+ if (!function_exists('ImageCreateFromString')) { return false; }
+
+ $image = ImageCreateFromString($image_data);
+
+ if (!$image) { return false; }
+
+ $width = imagesx($image);
+ $height = imagesy($image);
+
+ if (!$width || !$height) { return false; }
+
+ return array('width'=>$width,'height'=>$height);
+
+ } // image_dimensions
} // Core
?>
diff --git a/lib/class/database_object.abstract.php b/lib/class/database_object.abstract.php
index 535a83d1..dc9872cb 100644
--- a/lib/class/database_object.abstract.php
+++ b/lib/class/database_object.abstract.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,113 +30,113 @@
*/
abstract class database_object {
- private static $object_cache = array();
+ private static $object_cache = array();
- // Statistics for debugging
- public static $cache_hit = 0;
- private static $_enabled = false;
+ // Statistics for debugging
+ public static $cache_hit = 0;
+ private static $_enabled = false;
- /**
- * get_info
- * retrieves the info from the database and puts it in the cache
- */
- public function get_info($id,$table_name='') {
+ /**
+ * get_info
+ * retrieves the info from the database and puts it in the cache
+ */
+ public function get_info($id,$table_name='') {
- $table_name = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));
+ $table_name = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));
- // Make sure we've got a real id
- if (!is_numeric($id)) { return array(); }
+ // Make sure we've got a real id
+ if (!is_numeric($id)) { return array(); }
- if (self::is_cached($table_name,$id)) {
- return self::get_from_cache($table_name,$id);
- }
+ if (self::is_cached($table_name,$id)) {
+ return self::get_from_cache($table_name,$id);
+ }
- $sql = "SELECT * FROM `$table_name` WHERE `id`='$id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `$table_name` WHERE `id`='$id'";
+ $db_results = Dba::read($sql);
- if (!$db_results) { return array(); }
+ if (!$db_results) { return array(); }
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- self::add_to_cache($table_name,$id,$row);
+ self::add_to_cache($table_name,$id,$row);
- return $row;
+ return $row;
- } // get_info
+ } // get_info
- /**
- * clear_cache
- */
- public static function clear_cache() {
- self::$object_cache = array();
- }
+ /**
+ * clear_cache
+ */
+ public static function clear_cache() {
+ self::$object_cache = array();
+ }
- /**
- * is_cached
- * this checks the cache to see if the specified object is there
- */
- public static function is_cached($index,$id) {
+ /**
+ * is_cached
+ * this checks the cache to see if the specified object is there
+ */
+ public static function is_cached($index,$id) {
- // Make sure we've got some parents here before we dive below
- if (!isset(self::$object_cache[$index])) { return false; }
+ // Make sure we've got some parents here before we dive below
+ if (!isset(self::$object_cache[$index])) { return false; }
- return isset(self::$object_cache[$index][$id]);
+ return isset(self::$object_cache[$index][$id]);
- } // is_cached
+ } // is_cached
- /**
- * get_from_cache
- * This attempts to retrive the specified object from the cache we've got here
- */
- public static function get_from_cache($index,$id) {
+ /**
+ * get_from_cache
+ * This attempts to retrive the specified object from the cache we've got here
+ */
+ public static function get_from_cache($index,$id) {
- // Check if the object is set
- if (isset(self::$object_cache[$index])
- && isset(self::$object_cache[$index][$id])
- ) {
+ // Check if the object is set
+ if (isset(self::$object_cache[$index])
+ && isset(self::$object_cache[$index][$id])
+ ) {
- self::$cache_hit++;
- return self::$object_cache[$index][$id];
- }
+ self::$cache_hit++;
+ return self::$object_cache[$index][$id];
+ }
- return false;
+ return false;
- } // get_from_cache
+ } // get_from_cache
- /**
- * add_to_cache
- * This adds the specified object to the specified index in the cache
- */
- public static function add_to_cache($index,$id,$data) {
+ /**
+ * add_to_cache
+ * This adds the specified object to the specified index in the cache
+ */
+ public static function add_to_cache($index,$id,$data) {
- if (!self::$_enabled) { return false; }
+ if (!self::$_enabled) { return false; }
- $value = is_null($data) ? false : $data;
- self::$object_cache[$index][$id] = $value;
+ $value = is_null($data) ? false : $data;
+ self::$object_cache[$index][$id] = $value;
- } // add_to_cache
+ } // add_to_cache
- /**
- * remove_from_cache
- * This function clears something from the cache, there are a few places we need to do this
- * in order to have things display correctly
- */
- public static function remove_from_cache($index,$id) {
+ /**
+ * remove_from_cache
+ * This function clears something from the cache, there are a few places we need to do this
+ * in order to have things display correctly
+ */
+ public static function remove_from_cache($index,$id) {
- if (isset(self::$object_cache[$index]) && isset(self::$object_cache[$index][$id])) {
- unset(self::$object_cache[$index][$id]);
- }
+ if (isset(self::$object_cache[$index]) && isset(self::$object_cache[$index][$id])) {
+ unset(self::$object_cache[$index][$id]);
+ }
- } // remove_from_cache
+ } // remove_from_cache
- /**
- * _auto_init
- * Load in the cache settings once so we can avoid function calls
- */
- public static function _auto_init() {
+ /**
+ * _auto_init
+ * Load in the cache settings once so we can avoid function calls
+ */
+ public static function _auto_init() {
- self::$_enabled = Config::get('memory_cache');
+ self::$_enabled = Config::get('memory_cache');
- } // _auto_init
+ } // _auto_init
} // end database_object
diff --git a/lib/class/dba.class.php b/lib/class/dba.class.php
index ce5c38c4..6469b692 100644
--- a/lib/class/dba.class.php
+++ b/lib/class/dba.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -36,497 +36,497 @@ if (!defined('INIT_LOADED') || INIT_LOADED != '1') { exit; }
*/
class Dba {
- public static $stats = array('query'=>0);
-
- private static $_sql;
- private static $config;
-
- /**
- * constructor
- * This does nothing with the DBA class
- */
- private function __construct() {
-
- // Rien a faire
-
- } // construct
-
- /**
- * query
- * This is the meat of the class this does a query, it emulates
- * The mysql_query function
- */
- public static function query($sql) {
-
- // Run the query
- $resource = mysql_query($sql,self::dbh());
- debug_event('Query',$sql,'6');
-
- // Save the query, to make debug easier
- self::$_sql = $sql;
- self::$stats['query']++;
+ public static $stats = array('query'=>0);
+
+ private static $_sql;
+ private static $config;
+
+ /**
+ * constructor
+ * This does nothing with the DBA class
+ */
+ private function __construct() {
+
+ // Rien a faire
+
+ } // construct
+
+ /**
+ * query
+ * This is the meat of the class this does a query, it emulates
+ * The mysql_query function
+ */
+ public static function query($sql) {
+
+ // Run the query
+ $resource = mysql_query($sql,self::dbh());
+ debug_event('Query',$sql,'6');
+
+ // Save the query, to make debug easier
+ self::$_sql = $sql;
+ self::$stats['query']++;
- // Do a little error checking here and try to recover from some forms of failure
- if (!$resource) {
- switch (mysql_errno(self::dbh())) {
- case '2006':
- case '2013':
- case '2055':
- debug_event('DBH','Lost connection to database server, trying to re-connect and hope nobody noticed','1');
- self::disconnect();
- // Try again
- $resource = mysql_query($sql,self::dbh());
- break;
- default:
- debug_event('DBH',mysql_error(self::dbh()) . ' ['. mysql_errno(self::dbh()) . ']','1');
- break;
- } // end switch on error #
- } // if failed query
-
- return $resource;
-
- } // query
-
- /**
- * read
- * This is a wrapper for query, it's so that in the future if we ever wanted
- * to split reads and writes we could
- */
- public static function read($sql) {
-
- return self::query($sql);
-
- } // read
-
- /**
- * write
- * This is a wrapper for a write query, it is so that we can split out reads and
- * writes if we want to
- */
- public static function write($sql) {
-
- return self::query($sql);
-
- } // write
-
- /**
- * escape
- * This runs a escape on a variable so that it can be safely inserted
- * into the sql
- */
- public static function escape($var) {
-
- $string = mysql_real_escape_string($var,self::dbh());
-
- return $string;
-
- } // escape
-
- /**
- * fetch_assoc
- * This emulates the mysql_fetch_assoc and takes a resource result
- * we force it to always return an array, albeit an empty one
- * The optional finish parameter affects whether we automatically clean
- * up the result set after the last row is read.
- */
- public static function fetch_assoc($resource, $finish = true) {
-
- $result = mysql_fetch_assoc($resource);
-
- if (!$result) {
- if ($finish) {
- self::finish($resource);
- }
- return array();
- }
-
- return $result;
-
- } // fetch_assoc
-
- /**
- * fetch_row
- * This emulates the mysql_fetch_row and takes a resource result
- * we force it to always return an array, albeit an empty one
- * The optional finish parameter affects whether we automatically clean
- * up the result set after the last row is read.
- */
- public static function fetch_row($resource, $finish = true) {
-
- $result = mysql_fetch_row($resource);
-
- if (!$result) {
- if ($finish) {
- self::finish($resource);
- }
- return array();
- }
-
- return $result;
-
- } // fetch_row
-
- /**
- * num_rows
- * This emulates the mysql_num_rows function which is really
- * just a count of rows returned by our select statement, this
- * doesn't work for updates or inserts
- */
- public static function num_rows($resource) {
- if ($resource) {
- $result = mysql_num_rows($resource);
- if ($result) {
- return $result;
- }
- }
-
- return 0;
- } // num_rows
-
- /**
- * seek
- * This resets the row pointer to the specified position
- */
- public static function seek($resource, $row) {
- return mysql_data_seek($resource, $row);
- }
-
- /**
- * finish
- * This closes a result handle and clears the memory associated with it
- */
- public static function finish($resource) {
-
- // Clear the result memory
- mysql_free_result($resource);
-
- } // finish
-
- /**
- * affected_rows
- * This emulates the mysql_affected_rows function
- */
- public static function affected_rows($resource) {
-
- $result = mysql_affected_rows($resource);
-
- if (!$result) {
- return '0';
- }
-
- return $result;
-
- } // affected_rows
-
- /**
- * _connect
- * This connects to the database, used by the DBH function
- */
- private static function _connect() {
-
- $username = Config::get('database_username');
- $hostname = Config::get('database_hostname');
- $password = Config::get('database_password');
-
- $dbh = mysql_connect($hostname, $username, $password);
- if (!$dbh) {
- debug_event('Database', 'Unable to connect to database: ' . mysql_error(), 1);
- return null;
- }
-
- return $dbh;
- } // _connect
-
- private static function _setup_dbh($dbh, $database) {
- $data = self::translate_to_mysqlcharset(Config::get('site_charset'));
-
- if (function_exists('mysql_set_charset')) {
- if (!$charset = mysql_set_charset($data['charset'], $dbh)) {
- debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ', this may cause issues...', 1);
- }
- }
- else {
- $sql = "SET NAMES " . mysql_real_escape_string($data['charset']);
- $charset = mysql_query($sql,$dbh);
- if ($error = mysql_error($dbh)) {
- debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ' using SET NAMES, this may cause issues: ' . $error, 1);
- }
-
- }
-
- $select_db = mysql_select_db($database, $dbh);
- if (!$select_db) {
- debug_event('Database', 'Unable to select database ' . $database . ': ' . mysql_error(), 1);
- }
-
- if (Config::get('sql_profiling')) {
- mysql_query('set profiling=1', $dbh);
- mysql_query('set profiling_history_size=50', $dbh);
- mysql_query('set query_cache_type=0', $dbh);
- }
- } // _select_db
-
- /**
- * check_database
- *
- * Make sure that we can connect to the database
- */
- public static function check_database() {
-
- $dbh = self::_connect();
-
- if (!is_resource($dbh)) {
- return false;
- }
-
- mysql_close($dbh);
- return true;
-
- } // check_database
-
- public static function check_database_exists() {
- $dbh = self::_connect();
- $select = mysql_select_db(Config::get('database_name'), $dbh);
- mysql_close($dbh);
- return $select;
- }
-
- /**
- * check_database_inserted
- * checks to make sure that you have inserted the database
- * and that the user you are using has access to it
- */
- public static function check_database_inserted() {
-
- $sql = "DESCRIBE session";
- $db_results = Dba::read($sql);
-
- if (!$db_results) {
- return false;
- }
-
- // Make sure the whole table is there
- if (Dba::num_rows($db_results) != '7') {
- return false;
- }
-
- return true;
-
- } // check_database_inserted
-
- public static function get_client_info() {
- return mysql_get_client_info();
- }
-
- /**
- * show_profile
- * This function is used for debug, helps with profiling
- */
- public static function show_profile() {
-
- if (Config::get('sql_profiling')) {
- print '<br/>Profiling data: <br/>';
- $res = Dba::read('show profiles');
- print '<table>';
- while ($r = Dba::fetch_row($res)) {
- print '<tr><td>' . implode('</td><td>', $r) . '</td></tr>';
- }
- print '</table>';
- }
- } // show_profile
-
- /**
- * dbh
- * This is called by the class to return the database handle
- * for the specified database, if none is found it connects
- */
- public static function dbh($database='') {
-
- if (!$database) {
- $database = Config::get('database_name');
- }
-
- // Assign the Handle name that we are going to store
- $handle = 'dbh_' . $database;
-
- if (!is_resource(Config::get($handle))) {
- $dbh = self::_connect();
- self::_setup_dbh($dbh, $database);
- Config::set($handle, $dbh, true);
- return $dbh;
- }
- else {
- return Config::get($handle);
- }
-
-
- } // dbh
-
- /**
- * disconnect
- * This nukes the dbh connection based, this isn't used very often...
- */
- public static function disconnect($database='') {
-
- if (!$database) {
- $database = Config::get('database_name');
- }
-
- $handle = 'dbh_' . $database;
-
- // Try to close it correctly
- mysql_close(Config::get($handle));
-
- // Nuke it
- Config::set($handle, false, true);
-
- return true;
-
- } // disconnect
-
- /**
- * insert_id
- * This emulates the mysql_insert_id function, it takes
- * an optional database target
- */
- public static function insert_id() {
-
- $id = mysql_insert_id(self::dbh());
- return $id;
-
- } // insert_id
-
- /**
- * error
- * this returns the error of the db
- */
- public static function error() {
-
- return mysql_error();
-
- } // error
-
- /**
- * translate_to_mysqlcharset
- * This translates the specified charset to a mysqlcharset, stupid ass mysql
- * demands that it's charset list is different!
- */
- public static function translate_to_mysqlcharset($charset) {
-
- // MySQL translte real charset names into fancy smancy MySQL land names
- switch (strtoupper($charset)) {
- case 'CP1250':
- case 'WINDOWS-1250':
- $target_charset = 'cp1250';
- $target_collation = 'cp1250_general_ci';
- break;
- case 'ISO-8859':
- case 'ISO-8859-2':
- $target_charset = 'latin2';
- $target_collation = 'latin2_general_ci';
- break;
- case 'ISO-8859-1':
- case 'CP1252':
- case 'WINDOWS-1252':
- $target_charset = 'latin1';
- $target_collation = 'latin1_general_ci';
- break;
- case 'EUC-KR':
- $target_charset = 'euckr';
- $target_collation = 'euckr_korean_ci';
- break;
- case 'CP932':
- $target_charset = 'sjis';
- $target_collation = 'sjis_japanese_ci';
- break;
- case 'KOI8-U':
- $target_charset = 'koi8u';
- $target_collation = 'koi8u_general_ci';
- break;
- case 'KOI8-R':
- $target_charset = 'koi8r';
- $target_collation = 'koi8r_general_ci';
- break;
- default;
- case 'UTF-8':
- $target_charset = 'utf8';
- $target_collation = 'utf8_unicode_ci';
- break;
- } // end mysql charset translation
-
- return array('charset'=>$target_charset,'collation'=>$target_collation);
-
- } // translate_to_mysqlcharset
-
- /**
- * reset_db_charset
- * This cruises through the database and trys to set the charset to the current
- * site charset, this is an admin function that can be run by an administrator
- * this can mess up data if you switch between charsets that are not overlapping
- * a catalog verify must be re-run to correct them
- */
- public static function reset_db_charset() {
-
- $translated_charset = self::translate_to_mysqlcharset(Config::get('site_charset'));
- $target_charset = $translated_charset['charset'];
- $target_collation = $translated_charset['collation'];
-
- // Alter the charset for the entire database
- $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
- $db_results = Dba::write($sql);
-
- $sql = "SHOW TABLES";
- $db_results = Dba::read($sql);
-
- // Go through the tables!
- while ($row = Dba::fetch_row($db_results)) {
- $sql = "DESCRIBE `" . $row['0'] . "`";
- $describe_results = Dba::read($sql);
-
- // Change the tables default charset and colliation
- $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
- $alter_table = Dba::write($sql);
-
- // Itterate through the columns of the table
- while ($table = Dba::fetch_assoc($describe_results)) {
- if (
- (strpos($table['Type'], 'varchar') !== false) ||
- (strpos($table['Type'], 'enum') !== false) ||
- (strpos($table['Table'],'text') !== false)) {
- $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset;
- $charset_results = Dba::write($sql);
- if (!$charset_results) {
- debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3');
- } // if it fails
- } // if its a varchar
- } // end columns
-
- } // end tables
-
-
- } // reset_db_charset
-
- /**
- * optimize_tables
- *
- * This runs an optimize on the tables and updates the stats to improve
- * join speed.
- * This can be slow, but is a good idea to do from time to time. We do
- * it in case the dba isn't doing it... which we're going to assume they
- * aren't.
- */
- public static function optimize_tables() {
- $sql = "SHOW TABLES";
- $db_results = Dba::read($sql);
-
- while($row = Dba::fetch_row($db_results)) {
- $sql = "OPTIMIZE TABLE `" . $row[0] . "`";
- $db_results_inner = Dba::write($sql);
-
- $sql = "ANALYZE TABLE `" . $row[0] . "`";
- $db_results_inner = Dba::write($sql);
- }
- }
+ // Do a little error checking here and try to recover from some forms of failure
+ if (!$resource) {
+ switch (mysql_errno(self::dbh())) {
+ case '2006':
+ case '2013':
+ case '2055':
+ debug_event('DBH','Lost connection to database server, trying to re-connect and hope nobody noticed','1');
+ self::disconnect();
+ // Try again
+ $resource = mysql_query($sql,self::dbh());
+ break;
+ default:
+ debug_event('DBH',mysql_error(self::dbh()) . ' ['. mysql_errno(self::dbh()) . ']','1');
+ break;
+ } // end switch on error #
+ } // if failed query
+
+ return $resource;
+
+ } // query
+
+ /**
+ * read
+ * This is a wrapper for query, it's so that in the future if we ever wanted
+ * to split reads and writes we could
+ */
+ public static function read($sql) {
+
+ return self::query($sql);
+
+ } // read
+
+ /**
+ * write
+ * This is a wrapper for a write query, it is so that we can split out reads and
+ * writes if we want to
+ */
+ public static function write($sql) {
+
+ return self::query($sql);
+
+ } // write
+
+ /**
+ * escape
+ * This runs a escape on a variable so that it can be safely inserted
+ * into the sql
+ */
+ public static function escape($var) {
+
+ $string = mysql_real_escape_string($var,self::dbh());
+
+ return $string;
+
+ } // escape
+
+ /**
+ * fetch_assoc
+ * This emulates the mysql_fetch_assoc and takes a resource result
+ * we force it to always return an array, albeit an empty one
+ * The optional finish parameter affects whether we automatically clean
+ * up the result set after the last row is read.
+ */
+ public static function fetch_assoc($resource, $finish = true) {
+
+ $result = mysql_fetch_assoc($resource);
+
+ if (!$result) {
+ if ($finish) {
+ self::finish($resource);
+ }
+ return array();
+ }
+
+ return $result;
+
+ } // fetch_assoc
+
+ /**
+ * fetch_row
+ * This emulates the mysql_fetch_row and takes a resource result
+ * we force it to always return an array, albeit an empty one
+ * The optional finish parameter affects whether we automatically clean
+ * up the result set after the last row is read.
+ */
+ public static function fetch_row($resource, $finish = true) {
+
+ $result = mysql_fetch_row($resource);
+
+ if (!$result) {
+ if ($finish) {
+ self::finish($resource);
+ }
+ return array();
+ }
+
+ return $result;
+
+ } // fetch_row
+
+ /**
+ * num_rows
+ * This emulates the mysql_num_rows function which is really
+ * just a count of rows returned by our select statement, this
+ * doesn't work for updates or inserts
+ */
+ public static function num_rows($resource) {
+ if ($resource) {
+ $result = mysql_num_rows($resource);
+ if ($result) {
+ return $result;
+ }
+ }
+
+ return 0;
+ } // num_rows
+
+ /**
+ * seek
+ * This resets the row pointer to the specified position
+ */
+ public static function seek($resource, $row) {
+ return mysql_data_seek($resource, $row);
+ }
+
+ /**
+ * finish
+ * This closes a result handle and clears the memory associated with it
+ */
+ public static function finish($resource) {
+
+ // Clear the result memory
+ mysql_free_result($resource);
+
+ } // finish
+
+ /**
+ * affected_rows
+ * This emulates the mysql_affected_rows function
+ */
+ public static function affected_rows($resource) {
+
+ $result = mysql_affected_rows($resource);
+
+ if (!$result) {
+ return '0';
+ }
+
+ return $result;
+
+ } // affected_rows
+
+ /**
+ * _connect
+ * This connects to the database, used by the DBH function
+ */
+ private static function _connect() {
+
+ $username = Config::get('database_username');
+ $hostname = Config::get('database_hostname');
+ $password = Config::get('database_password');
+
+ $dbh = mysql_connect($hostname, $username, $password);
+ if (!$dbh) {
+ debug_event('Database', 'Unable to connect to database: ' . mysql_error(), 1);
+ return null;
+ }
+
+ return $dbh;
+ } // _connect
+
+ private static function _setup_dbh($dbh, $database) {
+ $data = self::translate_to_mysqlcharset(Config::get('site_charset'));
+
+ if (function_exists('mysql_set_charset')) {
+ if (!$charset = mysql_set_charset($data['charset'], $dbh)) {
+ debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ', this may cause issues...', 1);
+ }
+ }
+ else {
+ $sql = "SET NAMES " . mysql_real_escape_string($data['charset']);
+ $charset = mysql_query($sql,$dbh);
+ if ($error = mysql_error($dbh)) {
+ debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ' using SET NAMES, this may cause issues: ' . $error, 1);
+ }
+
+ }
+
+ $select_db = mysql_select_db($database, $dbh);
+ if (!$select_db) {
+ debug_event('Database', 'Unable to select database ' . $database . ': ' . mysql_error(), 1);
+ }
+
+ if (Config::get('sql_profiling')) {
+ mysql_query('set profiling=1', $dbh);
+ mysql_query('set profiling_history_size=50', $dbh);
+ mysql_query('set query_cache_type=0', $dbh);
+ }
+ } // _select_db
+
+ /**
+ * check_database
+ *
+ * Make sure that we can connect to the database
+ */
+ public static function check_database() {
+
+ $dbh = self::_connect();
+
+ if (!is_resource($dbh)) {
+ return false;
+ }
+
+ mysql_close($dbh);
+ return true;
+
+ } // check_database
+
+ public static function check_database_exists() {
+ $dbh = self::_connect();
+ $select = mysql_select_db(Config::get('database_name'), $dbh);
+ mysql_close($dbh);
+ return $select;
+ }
+
+ /**
+ * check_database_inserted
+ * checks to make sure that you have inserted the database
+ * and that the user you are using has access to it
+ */
+ public static function check_database_inserted() {
+
+ $sql = "DESCRIBE session";
+ $db_results = Dba::read($sql);
+
+ if (!$db_results) {
+ return false;
+ }
+
+ // Make sure the whole table is there
+ if (Dba::num_rows($db_results) != '7') {
+ return false;
+ }
+
+ return true;
+
+ } // check_database_inserted
+
+ public static function get_client_info() {
+ return mysql_get_client_info();
+ }
+
+ /**
+ * show_profile
+ * This function is used for debug, helps with profiling
+ */
+ public static function show_profile() {
+
+ if (Config::get('sql_profiling')) {
+ print '<br/>Profiling data: <br/>';
+ $res = Dba::read('show profiles');
+ print '<table>';
+ while ($r = Dba::fetch_row($res)) {
+ print '<tr><td>' . implode('</td><td>', $r) . '</td></tr>';
+ }
+ print '</table>';
+ }
+ } // show_profile
+
+ /**
+ * dbh
+ * This is called by the class to return the database handle
+ * for the specified database, if none is found it connects
+ */
+ public static function dbh($database='') {
+
+ if (!$database) {
+ $database = Config::get('database_name');
+ }
+
+ // Assign the Handle name that we are going to store
+ $handle = 'dbh_' . $database;
+
+ if (!is_resource(Config::get($handle))) {
+ $dbh = self::_connect();
+ self::_setup_dbh($dbh, $database);
+ Config::set($handle, $dbh, true);
+ return $dbh;
+ }
+ else {
+ return Config::get($handle);
+ }
+
+
+ } // dbh
+
+ /**
+ * disconnect
+ * This nukes the dbh connection based, this isn't used very often...
+ */
+ public static function disconnect($database='') {
+
+ if (!$database) {
+ $database = Config::get('database_name');
+ }
+
+ $handle = 'dbh_' . $database;
+
+ // Try to close it correctly
+ mysql_close(Config::get($handle));
+
+ // Nuke it
+ Config::set($handle, false, true);
+
+ return true;
+
+ } // disconnect
+
+ /**
+ * insert_id
+ * This emulates the mysql_insert_id function, it takes
+ * an optional database target
+ */
+ public static function insert_id() {
+
+ $id = mysql_insert_id(self::dbh());
+ return $id;
+
+ } // insert_id
+
+ /**
+ * error
+ * this returns the error of the db
+ */
+ public static function error() {
+
+ return mysql_error();
+
+ } // error
+
+ /**
+ * translate_to_mysqlcharset
+ * This translates the specified charset to a mysqlcharset, stupid ass mysql
+ * demands that it's charset list is different!
+ */
+ public static function translate_to_mysqlcharset($charset) {
+
+ // MySQL translte real charset names into fancy smancy MySQL land names
+ switch (strtoupper($charset)) {
+ case 'CP1250':
+ case 'WINDOWS-1250':
+ $target_charset = 'cp1250';
+ $target_collation = 'cp1250_general_ci';
+ break;
+ case 'ISO-8859':
+ case 'ISO-8859-2':
+ $target_charset = 'latin2';
+ $target_collation = 'latin2_general_ci';
+ break;
+ case 'ISO-8859-1':
+ case 'CP1252':
+ case 'WINDOWS-1252':
+ $target_charset = 'latin1';
+ $target_collation = 'latin1_general_ci';
+ break;
+ case 'EUC-KR':
+ $target_charset = 'euckr';
+ $target_collation = 'euckr_korean_ci';
+ break;
+ case 'CP932':
+ $target_charset = 'sjis';
+ $target_collation = 'sjis_japanese_ci';
+ break;
+ case 'KOI8-U':
+ $target_charset = 'koi8u';
+ $target_collation = 'koi8u_general_ci';
+ break;
+ case 'KOI8-R':
+ $target_charset = 'koi8r';
+ $target_collation = 'koi8r_general_ci';
+ break;
+ default;
+ case 'UTF-8':
+ $target_charset = 'utf8';
+ $target_collation = 'utf8_unicode_ci';
+ break;
+ } // end mysql charset translation
+
+ return array('charset'=>$target_charset,'collation'=>$target_collation);
+
+ } // translate_to_mysqlcharset
+
+ /**
+ * reset_db_charset
+ * This cruises through the database and trys to set the charset to the current
+ * site charset, this is an admin function that can be run by an administrator
+ * this can mess up data if you switch between charsets that are not overlapping
+ * a catalog verify must be re-run to correct them
+ */
+ public static function reset_db_charset() {
+
+ $translated_charset = self::translate_to_mysqlcharset(Config::get('site_charset'));
+ $target_charset = $translated_charset['charset'];
+ $target_collation = $translated_charset['collation'];
+
+ // Alter the charset for the entire database
+ $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
+ $db_results = Dba::write($sql);
+
+ $sql = "SHOW TABLES";
+ $db_results = Dba::read($sql);
+
+ // Go through the tables!
+ while ($row = Dba::fetch_row($db_results)) {
+ $sql = "DESCRIBE `" . $row['0'] . "`";
+ $describe_results = Dba::read($sql);
+
+ // Change the tables default charset and colliation
+ $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
+ $alter_table = Dba::write($sql);
+
+ // Itterate through the columns of the table
+ while ($table = Dba::fetch_assoc($describe_results)) {
+ if (
+ (strpos($table['Type'], 'varchar') !== false) ||
+ (strpos($table['Type'], 'enum') !== false) ||
+ (strpos($table['Table'],'text') !== false)) {
+ $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset;
+ $charset_results = Dba::write($sql);
+ if (!$charset_results) {
+ debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3');
+ } // if it fails
+ } // if its a varchar
+ } // end columns
+
+ } // end tables
+
+
+ } // reset_db_charset
+
+ /**
+ * optimize_tables
+ *
+ * This runs an optimize on the tables and updates the stats to improve
+ * join speed.
+ * This can be slow, but is a good idea to do from time to time. We do
+ * it in case the dba isn't doing it... which we're going to assume they
+ * aren't.
+ */
+ public static function optimize_tables() {
+ $sql = "SHOW TABLES";
+ $db_results = Dba::read($sql);
+
+ while($row = Dba::fetch_row($db_results)) {
+ $sql = "OPTIMIZE TABLE `" . $row[0] . "`";
+ $db_results_inner = Dba::write($sql);
+
+ $sql = "ANALYZE TABLE `" . $row[0] . "`";
+ $db_results_inner = Dba::write($sql);
+ }
+ }
} // dba class
diff --git a/lib/class/democratic.class.php b/lib/class/democratic.class.php
index 0e4fadbb..31913a07 100644
--- a/lib/class/democratic.class.php
+++ b/lib/class/democratic.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,610 +29,610 @@
*/
class Democratic extends Tmp_Playlist {
- public $name;
- public $cooldown;
- public $level;
- public $user;
- public $primary;
- public $base_playlist;
+ public $name;
+ public $cooldown;
+ public $level;
+ public $user;
+ public $primary;
+ public $base_playlist;
- // Build local, buy local
- public $tmp_playlist;
- public $object_ids = array();
- public $vote_ids = array();
- public $user_votes = array();
+ // Build local, buy local
+ public $tmp_playlist;
+ public $object_ids = array();
+ public $vote_ids = array();
+ public $user_votes = array();
- /**
- * constructor
- * We need a constructor for this class. It does it's own thing now
- */
- public function __construct($id='') {
+ /**
+ * constructor
+ * We need a constructor for this class. It does it's own thing now
+ */
+ public function __construct($id='') {
- if (!$id) { return false; }
+ if (!$id) { return false; }
- $info = $this->get_info($id);
+ $info = $this->get_info($id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
- } // constructor
+ } // constructor
- /**
- * build_vote_cache
- * This builds a vote cache of the objects we've got in the playlist
- */
- public static function build_vote_cache($ids) {
+ /**
+ * build_vote_cache
+ * This builds a vote cache of the objects we've got in the playlist
+ */
+ public static function build_vote_cache($ids) {
- if (!is_array($ids) || !count($ids)) { return false; }
+ if (!is_array($ids) || !count($ids)) { return false; }
- $idlist = '(' . implode(',', $ids) . ')';
+ $idlist = '(' . implode(',', $ids) . ')';
- $sql = 'SELECT `object_id`, COUNT(`user`) AS `count` ' .
- 'FROM `user_vote` ' .
- "WHERE `object_id` IN $idlist GROUP BY `object_id`";
+ $sql = 'SELECT `object_id`, COUNT(`user`) AS `count` ' .
+ 'FROM `user_vote` ' .
+ "WHERE `object_id` IN $idlist GROUP BY `object_id`";
- $db_results = Dba::read($sql);
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('democratic_vote', $row['object_id'], $row['count']);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('democratic_vote', $row['object_id'], $row['count']);
+ }
- return true;
+ return true;
- } // build_vote_cache
+ } // build_vote_cache
- /**
- * is_enabled
- * This function just returns true / false if the current democratic
- * playlist is currently enabled / configured
- */
- public function is_enabled() {
+ /**
+ * is_enabled
+ * This function just returns true / false if the current democratic
+ * playlist is currently enabled / configured
+ */
+ public function is_enabled() {
- if ($this->tmp_playlist) { return true; }
+ if ($this->tmp_playlist) { return true; }
- return false;
+ return false;
- } // is_enabled
+ } // is_enabled
- /**
- * set_parent
- * This returns the Tmp_Playlist for this democratic play instance
- */
- public function set_parent() {
+ /**
+ * set_parent
+ * This returns the Tmp_Playlist for this democratic play instance
+ */
+ public function set_parent() {
- $demo_id = Dba::escape($this->id);
+ $demo_id = Dba::escape($this->id);
- $sql = "SELECT * FROM `tmp_playlist` WHERE `session`='$demo_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `tmp_playlist` WHERE `session`='$demo_id'";
+ $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- $this->tmp_playlist = $row['id'];
+ $this->tmp_playlist = $row['id'];
- } // set_parent
+ } // set_parent
- /**
- * set_user_preferences
- * This sets up a (or all) user(s) to use democratic play. This sets
- * their play method and playlist method (clear on send) If no user is
- * passed it does it for everyone and also locks down the ability to
- * change to admins only
- */
- public static function set_user_preferences($user = null) {
+ /**
+ * set_user_preferences
+ * This sets up a (or all) user(s) to use democratic play. This sets
+ * their play method and playlist method (clear on send) If no user is
+ * passed it does it for everyone and also locks down the ability to
+ * change to admins only
+ */
+ public static function set_user_preferences($user = null) {
- //FIXME: Code in single user stuff
+ //FIXME: Code in single user stuff
- $preference_id = Preference::id_from_name('play_type');
- Preference::update_level($preference_id,'75');
- Preference::update_all($preference_id,'democratic');
+ $preference_id = Preference::id_from_name('play_type');
+ Preference::update_level($preference_id,'75');
+ Preference::update_all($preference_id,'democratic');
- $allow_demo = Preference::id_from_name('allow_democratic_playback');
- Preference::update_all($allow_demo,'1');
-
- $play_method = Preference::id_from_name('playlist_method');
- Preference::update_all($play_method,'clear');
-
- return true;
+ $allow_demo = Preference::id_from_name('allow_democratic_playback');
+ Preference::update_all($allow_demo,'1');
+
+ $play_method = Preference::id_from_name('playlist_method');
+ Preference::update_all($play_method,'clear');
+
+ return true;
- } // set_user_preferences
+ } // set_user_preferences
- /**
- * format
- * This makes the variables all purrty so that they can be displayed
- */
- public function format() {
+ /**
+ * format
+ * This makes the variables all purrty so that they can be displayed
+ */
+ public function format() {
- $this->f_cooldown = $this->cooldown . ' ' . T_('minutes');
- $this->f_primary = $this->primary ? T_('Primary') : '';
+ $this->f_cooldown = $this->cooldown . ' ' . T_('minutes');
+ $this->f_primary = $this->primary ? T_('Primary') : '';
- switch ($this->level) {
- case '5':
- $this->f_level = T_('Guest');
- break;
- case '25':
- $this->f_level = T_('User');
- break;
- case '50':
- $this->f_level = T_('Content Manager');
- break;
- case '75':
- $this->f_level = T_('Catalog Manager');
- break;
- case '100':
- $this->f_level = T_('Admin');
- break;
- }
+ switch ($this->level) {
+ case '5':
+ $this->f_level = T_('Guest');
+ break;
+ case '25':
+ $this->f_level = T_('User');
+ break;
+ case '50':
+ $this->f_level = T_('Content Manager');
+ break;
+ case '75':
+ $this->f_level = T_('Catalog Manager');
+ break;
+ case '100':
+ $this->f_level = T_('Admin');
+ break;
+ }
- } // format
+ } // format
- /**
- * get_playlists
- * This returns all of the current valid 'Democratic' Playlists
- * that have been created.
- */
- public static function get_playlists() {
+ /**
+ * get_playlists
+ * This returns all of the current valid 'Democratic' Playlists
+ * that have been created.
+ */
+ public static function get_playlists() {
- $sql = "SELECT `id` FROM `democratic` ORDER BY `name`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `democratic` ORDER BY `name`";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_playlists
+ } // get_playlists
- /**
- * get_current_playlist
- * This returns the curren users current playlist, or if specified
- * this current playlist of the user
- */
- public static function get_current_playlist() {
-
- $democratic_id = Config::get('democratic_id');
-
- if (!$democratic_id) {
- $level = Dba::escape($GLOBALS['user']->access);
- $sql = "SELECT `id` FROM `democratic` WHERE `level` <= '$level' " .
- " ORDER BY `level` DESC,`primary` DESC";
- $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
- $democratic_id = $row['id'];
- }
-
- $object = new Democratic($democratic_id);
-
- return $object;
-
- } // get_current_playlist
-
- /**
- * get_items
- * This returns a sorted array of all object_ids in this Tmp_Playlist.
- * The array is multidimensional; the inner array needs to contain the
- * keys 'id', 'object_type' and 'object_id'.
- *
- * Sorting is highest to lowest vote count, then by oldest to newest
- * vote activity.
- */
- public function get_items($limit = null) {
-
- $sql = 'SELECT `tmp_playlist_data`.`object_type`, ' .
- '`tmp_playlist_data`.`object_id`, ' .
- '`tmp_playlist_data`.`id` ' .
- 'FROM `tmp_playlist_data` INNER JOIN `user_vote` ' .
- 'ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` ' .
- "WHERE `tmp_playlist_data`.`tmp_playlist` = '" .
- Dba::escape($this->tmp_playlist) . "' " .
- 'GROUP BY 1, 2 ' .
- 'ORDER BY COUNT(*) DESC, MAX(`user_vote`.`date`) ';
-
- if ($limit) {
- $sql .= 'LIMIT ' . intval($limit);
- }
-
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($results[] = Dba::fetch_assoc($db_results)) {
- // Nada
- }
-
- return $results;
-
- } // get_items
-
- /**
- * play_url
- * This returns the special play URL for democratic play, only open to ADMINs
- */
- public function play_url() {
-
- $link = Stream::get_base_url() . 'uid=' . scrub_out($GLOBALS['user']->id) . '&demo_id=' . scrub_out($this->id);
-
- return $link;
-
- } // play_url
-
- /**
- * get_next_object
- * This returns the next object in the tmp_playlist.
- * Most of the time this will just be the top entry, but if there is a
- * base_playlist and no items in the playlist then it returns a random
- * entry from the base_playlist
- */
- public function get_next_object($offset = 0) {
-
- // FIXME: Shouldn't this return object_type?
-
- $offset = intval($offset);
-
- $items = $this->get_items($offset + 1);
-
- if (count($items) > $offset) {
- return $items[$offset]['object_id'];
- }
-
-
- // If nothing was found and this is a voting playlist then get
- // from base_playlist
- if ($this->base_playlist) {
- $base_playlist = new Playlist($this->base_playlist);
- $data = $base_playlist->get_random_items(1);
- return $data[0]['object_id'];
- }
- else {
- $sql = "SELECT `id` FROM `song` WHERE `enabled`='1' ORDER BY RAND() LIMIT 1";
- $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
- return $results['id'];
- }
-
- return null;
-
- } // get_next_object
-
- /**
- * get_uid_from_object_id
- * This takes an object_id and an object type and returns the ID for the row
- */
- public function get_uid_from_object_id($object_id, $object_type = 'song') {
-
- $object_id = Dba::escape($object_id);
- $object_type = Dba::escape($object_type);
- $tmp_id = Dba::escape($this->tmp_playlist);
-
- $sql = 'SELECT `id` FROM `tmp_playlist_data` ' .
- "WHERE `object_type`='$object_type' AND " .
- "`tmp_playlist`='$tmp_id' AND `object_id`='$object_id'";
- $db_results = Dba::read($sql);
-
- $row = Dba::fetch_assoc($db_results);
-
- return $row['id'];
-
- } // get_uid_from_object_id
-
- /**
- * get_cool_songs
- * This returns all of the song_ids for songs that have happened within
- * the last 'cooldown' for this user.
- */
- public function get_cool_songs() {
-
- // Convert cooldown time to a timestamp in the past
- $cool_time = time() - ($this->cooldown * 60);
-
- $song_ids = Stats::get_object_history($GLOBALS['user']->id, $cool_time);
-
- return $song_ids;
-
- } // get_cool_songs
-
- /**
- * vote
- * This function is called by users to vote on a system wide playlist
- * This adds the specified objects to the tmp_playlist and adds a 'vote'
- * by this user, naturally it checks to make sure that the user hasn't
- * already voted on any of these objects
- */
- public function add_vote($items) {
-
- /* Itterate through the objects if no vote, add to playlist and vote */
- foreach ($items as $element) {
- $type = array_shift($element);
- $object_id = array_shift($element);
- if (!$this->has_vote($object_id, $type)) {
- $this->_add_vote($object_id, $type);
- }
- } // end foreach
-
- } // vote
-
- /**
- * has_vote
- * This checks to see if the current user has already voted on this object
- */
- public function has_vote($object_id, $type = 'song') {
-
- $tmp_id = Dba::escape($this->tmp_playlist);
- $object_id = Dba::escape($object_id);
- $type = Dba::escape($type);
- $user_id = Dba::escape($GLOBALS['user']->id);
-
- /* Query vote table */
- $sql = 'SELECT `tmp_playlist_data`.`object_id` ' .
- 'FROM `user_vote` INNER JOIN `tmp_playlist_data` ' .
- 'ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` ' .
- "WHERE `user_vote`.`user`='$user_id' " .
- "AND `tmp_playlist_data`.`object_type`='$type' " .
- "AND `tmp_playlist_data`.`object_id`='$object_id' " .
- "AND `tmp_playlist_data`.`tmp_playlist`='$tmp_id'";
- $db_results = Dba::read($sql);
-
- /* If we find row, they've voted!! */
- if (Dba::num_rows($db_results)) {
- return true;
- }
-
- return false;
-
- } // has_vote
-
- /**
- * _add_vote
- * This takes a object id and user and actually inserts the row
- */
- private function _add_vote($object_id, $object_type = 'song') {
-
- $object_id = Dba::escape($object_id);
- $tmp_playlist = Dba::escape($this->tmp_playlist);
- $object_type = Dba::escape($object_type);
- $media = new $object_type($object_id);
- $track = isset($media->track) ? "'" . intval($media->track) . "'" : "NULL";
+ /**
+ * get_current_playlist
+ * This returns the curren users current playlist, or if specified
+ * this current playlist of the user
+ */
+ public static function get_current_playlist() {
+
+ $democratic_id = Config::get('democratic_id');
+
+ if (!$democratic_id) {
+ $level = Dba::escape($GLOBALS['user']->access);
+ $sql = "SELECT `id` FROM `democratic` WHERE `level` <= '$level' " .
+ " ORDER BY `level` DESC,`primary` DESC";
+ $db_results = Dba::read($sql);
+ $row = Dba::fetch_assoc($db_results);
+ $democratic_id = $row['id'];
+ }
+
+ $object = new Democratic($democratic_id);
+
+ return $object;
+
+ } // get_current_playlist
+
+ /**
+ * get_items
+ * This returns a sorted array of all object_ids in this Tmp_Playlist.
+ * The array is multidimensional; the inner array needs to contain the
+ * keys 'id', 'object_type' and 'object_id'.
+ *
+ * Sorting is highest to lowest vote count, then by oldest to newest
+ * vote activity.
+ */
+ public function get_items($limit = null) {
+
+ $sql = 'SELECT `tmp_playlist_data`.`object_type`, ' .
+ '`tmp_playlist_data`.`object_id`, ' .
+ '`tmp_playlist_data`.`id` ' .
+ 'FROM `tmp_playlist_data` INNER JOIN `user_vote` ' .
+ 'ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` ' .
+ "WHERE `tmp_playlist_data`.`tmp_playlist` = '" .
+ Dba::escape($this->tmp_playlist) . "' " .
+ 'GROUP BY 1, 2 ' .
+ 'ORDER BY COUNT(*) DESC, MAX(`user_vote`.`date`) ';
+
+ if ($limit) {
+ $sql .= 'LIMIT ' . intval($limit);
+ }
+
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($results[] = Dba::fetch_assoc($db_results)) {
+ // Nada
+ }
+
+ return $results;
+
+ } // get_items
+
+ /**
+ * play_url
+ * This returns the special play URL for democratic play, only open to ADMINs
+ */
+ public function play_url() {
+
+ $link = Stream::get_base_url() . 'uid=' . scrub_out($GLOBALS['user']->id) . '&demo_id=' . scrub_out($this->id);
+
+ return $link;
+
+ } // play_url
+
+ /**
+ * get_next_object
+ * This returns the next object in the tmp_playlist.
+ * Most of the time this will just be the top entry, but if there is a
+ * base_playlist and no items in the playlist then it returns a random
+ * entry from the base_playlist
+ */
+ public function get_next_object($offset = 0) {
+
+ // FIXME: Shouldn't this return object_type?
+
+ $offset = intval($offset);
+
+ $items = $this->get_items($offset + 1);
+
+ if (count($items) > $offset) {
+ return $items[$offset]['object_id'];
+ }
+
+
+ // If nothing was found and this is a voting playlist then get
+ // from base_playlist
+ if ($this->base_playlist) {
+ $base_playlist = new Playlist($this->base_playlist);
+ $data = $base_playlist->get_random_items(1);
+ return $data[0]['object_id'];
+ }
+ else {
+ $sql = "SELECT `id` FROM `song` WHERE `enabled`='1' ORDER BY RAND() LIMIT 1";
+ $db_results = Dba::read($sql);
+ $results = Dba::fetch_assoc($db_results);
+ return $results['id'];
+ }
+
+ return null;
+
+ } // get_next_object
+
+ /**
+ * get_uid_from_object_id
+ * This takes an object_id and an object type and returns the ID for the row
+ */
+ public function get_uid_from_object_id($object_id, $object_type = 'song') {
+
+ $object_id = Dba::escape($object_id);
+ $object_type = Dba::escape($object_type);
+ $tmp_id = Dba::escape($this->tmp_playlist);
+
+ $sql = 'SELECT `id` FROM `tmp_playlist_data` ' .
+ "WHERE `object_type`='$object_type' AND " .
+ "`tmp_playlist`='$tmp_id' AND `object_id`='$object_id'";
+ $db_results = Dba::read($sql);
+
+ $row = Dba::fetch_assoc($db_results);
+
+ return $row['id'];
+
+ } // get_uid_from_object_id
+
+ /**
+ * get_cool_songs
+ * This returns all of the song_ids for songs that have happened within
+ * the last 'cooldown' for this user.
+ */
+ public function get_cool_songs() {
+
+ // Convert cooldown time to a timestamp in the past
+ $cool_time = time() - ($this->cooldown * 60);
+
+ $song_ids = Stats::get_object_history($GLOBALS['user']->id, $cool_time);
+
+ return $song_ids;
+
+ } // get_cool_songs
+
+ /**
+ * vote
+ * This function is called by users to vote on a system wide playlist
+ * This adds the specified objects to the tmp_playlist and adds a 'vote'
+ * by this user, naturally it checks to make sure that the user hasn't
+ * already voted on any of these objects
+ */
+ public function add_vote($items) {
+
+ /* Itterate through the objects if no vote, add to playlist and vote */
+ foreach ($items as $element) {
+ $type = array_shift($element);
+ $object_id = array_shift($element);
+ if (!$this->has_vote($object_id, $type)) {
+ $this->_add_vote($object_id, $type);
+ }
+ } // end foreach
+
+ } // vote
+
+ /**
+ * has_vote
+ * This checks to see if the current user has already voted on this object
+ */
+ public function has_vote($object_id, $type = 'song') {
+
+ $tmp_id = Dba::escape($this->tmp_playlist);
+ $object_id = Dba::escape($object_id);
+ $type = Dba::escape($type);
+ $user_id = Dba::escape($GLOBALS['user']->id);
+
+ /* Query vote table */
+ $sql = 'SELECT `tmp_playlist_data`.`object_id` ' .
+ 'FROM `user_vote` INNER JOIN `tmp_playlist_data` ' .
+ 'ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` ' .
+ "WHERE `user_vote`.`user`='$user_id' " .
+ "AND `tmp_playlist_data`.`object_type`='$type' " .
+ "AND `tmp_playlist_data`.`object_id`='$object_id' " .
+ "AND `tmp_playlist_data`.`tmp_playlist`='$tmp_id'";
+ $db_results = Dba::read($sql);
+
+ /* If we find row, they've voted!! */
+ if (Dba::num_rows($db_results)) {
+ return true;
+ }
+
+ return false;
+
+ } // has_vote
+
+ /**
+ * _add_vote
+ * This takes a object id and user and actually inserts the row
+ */
+ private function _add_vote($object_id, $object_type = 'song') {
+
+ $object_id = Dba::escape($object_id);
+ $tmp_playlist = Dba::escape($this->tmp_playlist);
+ $object_type = Dba::escape($object_type);
+ $media = new $object_type($object_id);
+ $track = isset($media->track) ? "'" . intval($media->track) . "'" : "NULL";
- /* If it's on the playlist just vote */
- $sql = "SELECT `id` FROM `tmp_playlist_data` " .
- "WHERE `tmp_playlist_data`.`object_id`='$object_id' AND `tmp_playlist_data`.`tmp_playlist`='$tmp_playlist'";
- $db_results = Dba::write($sql);
+ /* If it's on the playlist just vote */
+ $sql = "SELECT `id` FROM `tmp_playlist_data` " .
+ "WHERE `tmp_playlist_data`.`object_id`='$object_id' AND `tmp_playlist_data`.`tmp_playlist`='$tmp_playlist'";
+ $db_results = Dba::write($sql);
- /* If it's not there, add it and pull ID */
- if (!$results = Dba::fetch_assoc($db_results)) {
- $sql = "INSERT INTO `tmp_playlist_data` (`tmp_playlist`,`object_id`,`object_type`,`track`) " .
- "VALUES ('$tmp_playlist','$object_id','$object_type',$track)";
- $db_results = Dba::write($sql);
- $results['id'] = Dba::insert_id();
- }
+ /* If it's not there, add it and pull ID */
+ if (!$results = Dba::fetch_assoc($db_results)) {
+ $sql = "INSERT INTO `tmp_playlist_data` (`tmp_playlist`,`object_id`,`object_type`,`track`) " .
+ "VALUES ('$tmp_playlist','$object_id','$object_type',$track)";
+ $db_results = Dba::write($sql);
+ $results['id'] = Dba::insert_id();
+ }
- /* Vote! */
- $time = time();
- $sql = "INSERT INTO user_vote (`user`,`object_id`,`date`) " .
- "VALUES ('" . Dba::escape($GLOBALS['user']->id) . "','" . $results['id'] . "','$time')";
- $db_results = Dba::write($sql);
+ /* Vote! */
+ $time = time();
+ $sql = "INSERT INTO user_vote (`user`,`object_id`,`date`) " .
+ "VALUES ('" . Dba::escape($GLOBALS['user']->id) . "','" . $results['id'] . "','$time')";
+ $db_results = Dba::write($sql);
- return true;
-
- } // add_vote
-
- /**
- * remove_vote
- * This is called to remove a vote by a user for an object, it uses the object_id
- * As that's what we'll have most the time, no need to check if they've got an existing
- * vote for this, just remove anything that is there
- */
- public function remove_vote($row_id) {
-
- $object_id = Dba::escape($row_id);
- $user_id = Dba::escape($GLOBALS['user']->id);
-
- $sql = "DELETE FROM `user_vote` WHERE `object_id`='$object_id' AND `user`='$user_id'";
- $db_results = Dba::write($sql);
-
- /* Clean up anything that has no votes */
- self::prune_tracks();
-
- return true;
-
- } // remove_vote
-
- /**
- * delete_votes
- * This removes the votes for the specified object on the current playlist
- */
- public function delete_votes($row_id) {
-
- $row_id = Dba::escape($row_id);
-
- $sql = "DELETE FROM `user_vote` WHERE `object_id`='$row_id'";
- $db_results = Dba::write($sql);
-
- $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$row_id'";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // delete_votes
-
- /**
- * delete_from_oid
- * This takes an OID and type and removes the object from the democratic playlist
- */
- public function delete_from_oid($oid,$object_type) {
-
- $row_id = $this->get_uid_from_object_id($oid,$object_type);
- if ($row_id) {
- debug_event('Democratic','Removing Votes for ' . $oid . ' of type ' . $object_type,'5');
- $this->delete_votes($row_id);
- }
- else { debug_event('Democratic','Unable to find Votes for ' . $oid . ' of type ' . $object_type,'3'); }
+ return true;
+
+ } // add_vote
+
+ /**
+ * remove_vote
+ * This is called to remove a vote by a user for an object, it uses the object_id
+ * As that's what we'll have most the time, no need to check if they've got an existing
+ * vote for this, just remove anything that is there
+ */
+ public function remove_vote($row_id) {
+
+ $object_id = Dba::escape($row_id);
+ $user_id = Dba::escape($GLOBALS['user']->id);
+
+ $sql = "DELETE FROM `user_vote` WHERE `object_id`='$object_id' AND `user`='$user_id'";
+ $db_results = Dba::write($sql);
+
+ /* Clean up anything that has no votes */
+ self::prune_tracks();
+
+ return true;
+
+ } // remove_vote
+
+ /**
+ * delete_votes
+ * This removes the votes for the specified object on the current playlist
+ */
+ public function delete_votes($row_id) {
+
+ $row_id = Dba::escape($row_id);
+
+ $sql = "DELETE FROM `user_vote` WHERE `object_id`='$row_id'";
+ $db_results = Dba::write($sql);
+
+ $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$row_id'";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // delete_votes
+
+ /**
+ * delete_from_oid
+ * This takes an OID and type and removes the object from the democratic playlist
+ */
+ public function delete_from_oid($oid,$object_type) {
+
+ $row_id = $this->get_uid_from_object_id($oid,$object_type);
+ if ($row_id) {
+ debug_event('Democratic','Removing Votes for ' . $oid . ' of type ' . $object_type,'5');
+ $this->delete_votes($row_id);
+ }
+ else { debug_event('Democratic','Unable to find Votes for ' . $oid . ' of type ' . $object_type,'3'); }
- return true;
+ return true;
- } // delete_from_oid
+ } // delete_from_oid
- /**
- * delete
- * This deletes a democratic playlist
- */
- public static function delete($democratic_id) {
+ /**
+ * delete
+ * This deletes a democratic playlist
+ */
+ public static function delete($democratic_id) {
- $democratic_id = Dba::escape($democratic_id);
+ $democratic_id = Dba::escape($democratic_id);
- $sql = "DELETE FROM `democratic` WHERE `id`='$democratic_id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `democratic` WHERE `id`='$democratic_id'";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$democratic_id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$democratic_id'";
+ $db_results = Dba::write($sql);
- self::prune_tracks();
+ self::prune_tracks();
- return true;
+ return true;
- } // delete
+ } // delete
- /**
- * update
- * This updates an existing democratic playlist item. It takes a key'd array just like the create
- */
- public function update($data) {
+ /**
+ * update
+ * This updates an existing democratic playlist item. It takes a key'd array just like the create
+ */
+ public function update($data) {
- $name = Dba::escape($data['name']);
- $base = Dba::escape($data['democratic']);
- $cool = Dba::escape($data['cooldown']);
- $id = Dba::escape($this->id);
+ $name = Dba::escape($data['name']);
+ $base = Dba::escape($data['democratic']);
+ $cool = Dba::escape($data['cooldown']);
+ $id = Dba::escape($this->id);
- $sql = "UPDATE `democratic` SET `name`='$name', `base_playlist`='$base',`cooldown`='$cool' WHERE `id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `democratic` SET `name`='$name', `base_playlist`='$base',`cooldown`='$cool' WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // update
+ } // update
- /**
- * create
- * This is the democratic play create function it inserts this into the democratic table
- */
- public static function create($data) {
+ /**
+ * create
+ * This is the democratic play create function it inserts this into the democratic table
+ */
+ public static function create($data) {
- // Clean up the input
- $name = Dba::escape($data['name']);
- $base = Dba::escape($data['democratic']);
- $cool = Dba::escape($data['cooldown']);
- $level = Dba::escape($data['level']);
- $default = Dba::escape($data['make_default']);
- $user = Dba::escape($GLOBALS['user']->id);
+ // Clean up the input
+ $name = Dba::escape($data['name']);
+ $base = Dba::escape($data['democratic']);
+ $cool = Dba::escape($data['cooldown']);
+ $level = Dba::escape($data['level']);
+ $default = Dba::escape($data['make_default']);
+ $user = Dba::escape($GLOBALS['user']->id);
- $sql = "INSERT INTO `democratic` (`name`,`base_playlist`,`cooldown`,`level`,`user`,`primary`) " .
- "VALUES ('$name','$base','$cool','$level','$user','$default')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `democratic` (`name`,`base_playlist`,`cooldown`,`level`,`user`,`primary`) " .
+ "VALUES ('$name','$base','$cool','$level','$user','$default')";
+ $db_results = Dba::write($sql);
- if ($db_results) {
- $insert_id = Dba::insert_id();
- parent::create(array(
- 'session_id' => $insert_id,
- 'type' => 'vote',
- 'object_type' => 'song'
- ));
- }
+ if ($db_results) {
+ $insert_id = Dba::insert_id();
+ parent::create(array(
+ 'session_id' => $insert_id,
+ 'type' => 'vote',
+ 'object_type' => 'song'
+ ));
+ }
- return $db_results;
+ return $db_results;
- } // create
+ } // create
- /**
- * prune_tracks
- * This replaces the normal prune tracks and correctly removes the votes
- * as well
- */
- public static function prune_tracks() {
+ /**
+ * prune_tracks
+ * This replaces the normal prune tracks and correctly removes the votes
+ * as well
+ */
+ public static function prune_tracks() {
- // This deletes data without votes, if it's a voting democratic playlist
- $sql = "DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` " .
- "LEFT JOIN `user_vote` ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` " .
- "LEFT JOIN `tmp_playlist` ON `tmp_playlist`.`id`=`tmp_playlist_data`.`tmp_playlist` " .
- "WHERE `user_vote`.`object_id` IS NULL AND `tmp_playlist`.`type` = 'vote'";
- $db_results = Dba::write($sql);
+ // This deletes data without votes, if it's a voting democratic playlist
+ $sql = "DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` " .
+ "LEFT JOIN `user_vote` ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` " .
+ "LEFT JOIN `tmp_playlist` ON `tmp_playlist`.`id`=`tmp_playlist_data`.`tmp_playlist` " .
+ "WHERE `user_vote`.`object_id` IS NULL AND `tmp_playlist`.`type` = 'vote'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // prune_tracks
+ } // prune_tracks
- /**
- * clear
- * This is really just a wrapper function, it clears the entire playlist
- * including all votes etc.
- */
- public function clear() {
+ /**
+ * clear
+ * This is really just a wrapper function, it clears the entire playlist
+ * including all votes etc.
+ */
+ public function clear() {
- $tmp_id = Dba::escape($this->tmp_playlist);
+ $tmp_id = Dba::escape($this->tmp_playlist);
- /* Clear all votes then prune */
- $sql = "DELETE FROM `user_vote` USING `user_vote` " .
- "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` " .
- "WHERE `tmp_playlist_data`.`tmp_playlist`='$tmp_id'";
- $db_results = Dba::write($sql);
+ /* Clear all votes then prune */
+ $sql = "DELETE FROM `user_vote` USING `user_vote` " .
+ "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` " .
+ "WHERE `tmp_playlist_data`.`tmp_playlist`='$tmp_id'";
+ $db_results = Dba::write($sql);
- // Prune!
- self::prune_tracks();
+ // Prune!
+ self::prune_tracks();
- // Clean the votes
- self::clear_votes();
+ // Clean the votes
+ self::clear_votes();
- return true;
+ return true;
- } // clear_playlist
+ } // clear_playlist
- /**
- * clean_votes
- * This removes in left over garbage in the votes table
- */
- public function clear_votes() {
+ /**
+ * clean_votes
+ * This removes in left over garbage in the votes table
+ */
+ public function clear_votes() {
- $sql = "DELETE FROM `user_vote` USING `user_vote` " .
- "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id`=`tmp_playlist_data`.`id` " .
- "WHERE `tmp_playlist_data`.`id` IS NULL";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `user_vote` USING `user_vote` " .
+ "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id`=`tmp_playlist_data`.`id` " .
+ "WHERE `tmp_playlist_data`.`id` IS NULL";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // clear_votes
+ } // clear_votes
- /**
- * get_vote
- * This returns the current count for a specific song
- */
- public function get_vote($id) {
+ /**
+ * get_vote
+ * This returns the current count for a specific song
+ */
+ public function get_vote($id) {
- if (parent::is_cached('democratic_vote', $id)) {
- return parent::get_from_cache('democratic_vote', $id);
- }
-
- $sql = 'SELECT COUNT(`user`) AS `count` FROM `user_vote` ' .
- "WHERE `object_id`='" . Dba::escape($id) . "'";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
- parent::add_to_cache('democratic_vote', $id, $results['count']);
- return $results['count'];
-
- } // get_vote
+ if (parent::is_cached('democratic_vote', $id)) {
+ return parent::get_from_cache('democratic_vote', $id);
+ }
+
+ $sql = 'SELECT COUNT(`user`) AS `count` FROM `user_vote` ' .
+ "WHERE `object_id`='" . Dba::escape($id) . "'";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+ parent::add_to_cache('democratic_vote', $id, $results['count']);
+ return $results['count'];
+
+ } // get_vote
- /**
- * get_voters
- * This returns the users that voted for the specified object
- * This is an array of user ids
- */
- public function get_voters($object_id) {
+ /**
+ * get_voters
+ * This returns the users that voted for the specified object
+ * This is an array of user ids
+ */
+ public function get_voters($object_id) {
- return parent::get_from_cache('democratic_voters',$object_id);
+ return parent::get_from_cache('democratic_voters',$object_id);
- } // get_voters
+ } // get_voters
} // Democratic class
diff --git a/lib/class/error.class.php b/lib/class/error.class.php
index 3cc52e74..6d2189af 100644
--- a/lib/class/error.class.php
+++ b/lib/class/error.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,111 +29,111 @@
*/
class Error {
- private static $state = false; // set to one when an error occurs
- private static $errors = array(); // Errors array key'd array with errors that have occured
+ private static $state = false; // set to one when an error occurs
+ private static $errors = array(); // Errors array key'd array with errors that have occured
- /**
- * __constructor
- * This does nothing... amazing isn't it!
- */
- private function __construct() {
+ /**
+ * __constructor
+ * This does nothing... amazing isn't it!
+ */
+ private function __construct() {
- // Rien a faire
+ // Rien a faire
- } // __construct
+ } // __construct
- /**
- * __destruct
- * This saves all of the errors that are left into the session
- */
- public function __destruct() {
+ /**
+ * __destruct
+ * This saves all of the errors that are left into the session
+ */
+ public function __destruct() {
- foreach (self::$errors as $key=>$error) {
- $_SESSION['errors'][$key] = $error;
- }
+ foreach (self::$errors as $key=>$error) {
+ $_SESSION['errors'][$key] = $error;
+ }
- } // __destruct
+ } // __destruct
- /**
- * add
- * This is a public static function it adds a new error message to the array
- * It can optionally clobber rather then adding to the error message
- */
- public static function add($name,$message,$clobber=0) {
+ /**
+ * add
+ * This is a public static function it adds a new error message to the array
+ * It can optionally clobber rather then adding to the error message
+ */
+ public static function add($name,$message,$clobber=0) {
- // Make sure its set first
- if (!isset(Error::$errors[$name])) {
- Error::$errors[$name] = $message;
- Error::$state = 1;
- $_SESSION['errors'][$name] = $message;
- }
- // They want us to clobber it
- elseif ($clobber) {
- Error::$state = 1;
- Error::$errors[$name] = $message;
- $_SESSION['errors'][$name] = $message;
- }
- // They want us to append the error, add a BR\n and then the message
- else {
- Error::$state = 1;
- Error::$errors[$name] .= "<br />\n" . $message;
- $_SESSION['errors'][$name] .= "<br />\n" . $message;
- }
+ // Make sure its set first
+ if (!isset(Error::$errors[$name])) {
+ Error::$errors[$name] = $message;
+ Error::$state = 1;
+ $_SESSION['errors'][$name] = $message;
+ }
+ // They want us to clobber it
+ elseif ($clobber) {
+ Error::$state = 1;
+ Error::$errors[$name] = $message;
+ $_SESSION['errors'][$name] = $message;
+ }
+ // They want us to append the error, add a BR\n and then the message
+ else {
+ Error::$state = 1;
+ Error::$errors[$name] .= "<br />\n" . $message;
+ $_SESSION['errors'][$name] .= "<br />\n" . $message;
+ }
- } // add
+ } // add
- /**
- * occurred
- * This returns true / false if an error has occured anywhere
- */
- public static function occurred() {
+ /**
+ * occurred
+ * This returns true / false if an error has occured anywhere
+ */
+ public static function occurred() {
- if (self::$state == '1') { return true; }
+ if (self::$state == '1') { return true; }
- return false;
+ return false;
- } // occurred
+ } // occurred
- /**
- * get
- * This returns an error by name
- */
- public static function get($name) {
+ /**
+ * get
+ * This returns an error by name
+ */
+ public static function get($name) {
- if (!isset(Error::$errors[$name])) { return ''; }
+ if (!isset(Error::$errors[$name])) { return ''; }
- return Error::$errors[$name];
+ return Error::$errors[$name];
- } // get
+ } // get
- /**
- * display
- * This prints the error out with a standard Error class span
- * Ben Goska: Renamed from print to display, print is reserved
- */
- public static function display($name) {
+ /**
+ * display
+ * This prints the error out with a standard Error class span
+ * Ben Goska: Renamed from print to display, print is reserved
+ */
+ public static function display($name) {
- // Be smart about this, if no error don't print
- if (!isset(Error::$errors[$name])) { return ''; }
+ // Be smart about this, if no error don't print
+ if (!isset(Error::$errors[$name])) { return ''; }
- echo '<span class="error">' . Error::$errors[$name] . '</span>';
+ echo '<span class="error">' . Error::$errors[$name] . '</span>';
- } // display
+ } // display
- /**
- * auto_init
- * This loads the errors from the session back into Ampache
- */
- public static function auto_init() {
+ /**
+ * auto_init
+ * This loads the errors from the session back into Ampache
+ */
+ public static function auto_init() {
- if (!is_array($_SESSION['errors'])) { return false; }
+ if (!is_array($_SESSION['errors'])) { return false; }
- // Re-insert them
- foreach ($_SESSION['errors'] as $key=>$error) {
- self::add($key,$error);
- }
+ // Re-insert them
+ foreach ($_SESSION['errors'] as $key=>$error) {
+ self::add($key,$error);
+ }
- } // auto_init
+ } // auto_init
} // Error
diff --git a/lib/class/flag.class.php b/lib/class/flag.class.php
index ed1fef06..d7fdc811 100644
--- a/lib/class/flag.class.php
+++ b/lib/class/flag.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,396 +29,396 @@
*/
class Flag extends database_object {
- public $id;
- public $user;
- public $object_id;
- public $object_type;
- public $comment;
- public $flag;
- public $date;
- public $approved=0;
+ public $id;
+ public $user;
+ public $object_id;
+ public $object_type;
+ public $comment;
+ public $flag;
+ public $date;
+ public $approved=0;
- /* Generated Values */
- public $name; // Blank
- public $title; // Blank
+ /* Generated Values */
+ public $name; // Blank
+ public $title; // Blank
- /**
- * Constructor
- * This takes a flagged.id and then pulls in the information for said flag entry
- */
- public function __construct($flag_id) {
+ /**
+ * Constructor
+ * This takes a flagged.id and then pulls in the information for said flag entry
+ */
+ public function __construct($flag_id) {
- $info = $this->get_info($flag_id,'flagged');
+ $info = $this->get_info($flag_id,'flagged');
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
- return true;
+ return true;
- } // Constructor
+ } // Constructor
- /**
- * gc
- *
- * This cleans out unused flagged items
- */
- public static function gc() {
- Dba::write("DELETE FROM `flagged` USING `flagged` LEFT JOIN `song` ON `song`.`id` = `flagged`.`object_id` WHERE `song`.`id` IS NULL AND `object_type` = 'song'");
- }
+ /**
+ * gc
+ *
+ * This cleans out unused flagged items
+ */
+ public static function gc() {
+ Dba::write("DELETE FROM `flagged` USING `flagged` LEFT JOIN `song` ON `song`.`id` = `flagged`.`object_id` WHERE `song`.`id` IS NULL AND `object_type` = 'song'");
+ }
- /**
- * build_cache
- * This takes an array of ids and builds up a nice little cache
- * for us
- */
- public static function build_cache($ids) {
+ /**
+ * build_cache
+ * This takes an array of ids and builds up a nice little cache
+ * for us
+ */
+ public static function build_cache($ids) {
- if (!is_array($ids) OR !count($ids)) { return false; }
+ if (!is_array($ids) OR !count($ids)) { return false; }
- $idlist = '(' . implode(',',$ids) . ')';
+ $idlist = '(' . implode(',',$ids) . ')';
- $sql = "SELECT * FROM `flagged` WHERE `id` IN $idlist";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `flagged` WHERE `id` IN $idlist";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('flagged',$row['id'],$row);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('flagged',$row['id'],$row);
+ }
- } // build_cache
+ } // build_cache
- /**
- * build_map_cache
- * This takes an array of ids and builds a map cache to avoid some of the object_type calls
- * we would normally have to make
- */
- public static function build_map_cache($ids,$type) {
+ /**
+ * build_map_cache
+ * This takes an array of ids and builds a map cache to avoid some of the object_type calls
+ * we would normally have to make
+ */
+ public static function build_map_cache($ids,$type) {
- if (!is_array($ids) OR !count($ids)) { return false; }
+ if (!is_array($ids) OR !count($ids)) { return false; }
- $idlist = '(' . implode(',',$ids) . ')';
- $type = Dba::escape($type);
+ $idlist = '(' . implode(',',$ids) . ')';
+ $type = Dba::escape($type);
- $sql = "SELECT * FROM `flagged` " .
- "WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id` IN $idlist";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `flagged` " .
+ "WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id` IN $idlist";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[$row['object_id']] = $row;
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[$row['object_id']] = $row;
+ }
- // Itterate through the passed ids as we need to cache 'nulls'
- foreach ($ids as $id) {
- parent::add_to_cache('flagged_' . $type,$id,$results[$id]);
- }
+ // Itterate through the passed ids as we need to cache 'nulls'
+ foreach ($ids as $id) {
+ parent::add_to_cache('flagged_' . $type,$id,$results[$id]);
+ }
- return true;
+ return true;
- } // build_map_cache
+ } // build_map_cache
- /**
- * has_flag
- * Static function, tries to check the cache, but falls back on a query
- */
- public static function has_flag($id,$type) {
+ /**
+ * has_flag
+ * Static function, tries to check the cache, but falls back on a query
+ */
+ public static function has_flag($id,$type) {
- if (parent::is_cached('flagged_' . $type,$id)) {
- $data = parent::get_from_cache('flagged_' . $type,$id);
- return $data['date'];
- }
+ if (parent::is_cached('flagged_' . $type,$id)) {
+ $data = parent::get_from_cache('flagged_' . $type,$id);
+ return $data['date'];
+ }
- // Ok we have to query this
- $type = Dba::escape($type);
+ // Ok we have to query this
+ $type = Dba::escape($type);
- $sql = "SELECT * FROM `flagged` WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id`='$id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `flagged` WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id`='$id'";
+ $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
- parent::add_to_cache('flagged_' . $type,$row['object_id'],$row);
+ $row = Dba::fetch_assoc($db_results);
+ parent::add_to_cache('flagged_' . $type,$row['object_id'],$row);
- return $row['date'];
+ return $row['date'];
- } // has_flag
+ } // has_flag
- /**
- * get_recent
- * This returns the id's of the most recently flagged songs, it takes an int
- * as an argument which is the count of the object you want to return
- */
- public static function get_recent($count=0) {
+ /**
+ * get_recent
+ * This returns the id's of the most recently flagged songs, it takes an int
+ * as an argument which is the count of the object you want to return
+ */
+ public static function get_recent($count=0) {
- if ($count) { $limit = " LIMIT " . intval($count); }
+ if ($count) { $limit = " LIMIT " . intval($count); }
- $results = array();
+ $results = array();
- $sql = "SELECT id FROM flagged ORDER BY date " . $limit;
- $db_results = Dba::read($sql);
+ $sql = "SELECT id FROM flagged ORDER BY date " . $limit;
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['id'];
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['id'];
+ }
- return $results;
+ return $results;
- } // get_recent
+ } // get_recent
- /**
- * get_disabled
- * This returns all of the songs that have been disabled, this is
- * a form of being flagged
- */
- public static function get_disabled() {
+ /**
+ * get_disabled
+ * This returns all of the songs that have been disabled, this is
+ * a form of being flagged
+ */
+ public static function get_disabled() {
- $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_disabled
+ } // get_disabled
- /**
- * get_all
- * This returns an array of ids of flagged songs if no limit is passed
- * it gets everything
- */
- public static function get_all($count=0) {
+ /**
+ * get_all
+ * This returns an array of ids of flagged songs if no limit is passed
+ * it gets everything
+ */
+ public static function get_all($count=0) {
- if ($count) { $limit_clause = "LIMIT " . intval($count); }
+ if ($count) { $limit_clause = "LIMIT " . intval($count); }
- $sql = "SELECT `id` FROM `flagged` $limit_clause";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `flagged` $limit_clause";
+ $db_results = Dba::read($sql);
- /* Default it to an array */
- $results = array();
+ /* Default it to an array */
+ $results = array();
- /* While the query */
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ /* While the query */
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_all
+ } // get_all
- /**
- * get_approved
- * This returns an array of approved flagged songs
- */
- public static function get_approved() {
+ /**
+ * get_approved
+ * This returns an array of approved flagged songs
+ */
+ public static function get_approved() {
- $sql = "SELECT `id` FROM `flagged` WHERE `approved`='1'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `flagged` WHERE `approved`='1'";
+ $db_results = Dba::read($sql);
- /* Default the results array */
- $results = array();
+ /* Default the results array */
+ $results = array();
- /* While it */
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['id'];
- }
+ /* While it */
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['id'];
+ }
- return $results;
+ return $results;
- } // get_approved
+ } // get_approved
- /**
- * add
- * This adds a flag entry for an item, it takes an id, a type, the flag type
- * and a comment and then inserts the mofo
- */
- public static function add($id,$type,$flag,$comment) {
+ /**
+ * add
+ * This adds a flag entry for an item, it takes an id, a type, the flag type
+ * and a comment and then inserts the mofo
+ */
+ public static function add($id,$type,$flag,$comment) {
- $id = Dba::escape($id);
- $type = Dba::escape($type);
- $flag = self::validate_flag($flag);
- $user = Dba::escape($GLOBALS['user']->id);
- $comment = Dba::escape($comment);
- $time = time();
- $approved = '0';
+ $id = Dba::escape($id);
+ $type = Dba::escape($type);
+ $flag = self::validate_flag($flag);
+ $user = Dba::escape($GLOBALS['user']->id);
+ $comment = Dba::escape($comment);
+ $time = time();
+ $approved = '0';
- /* If they are an content manager or higher, it's auto approved */
- if (Access::check('interface','75')) { $approved = '1'; }
+ /* If they are an content manager or higher, it's auto approved */
+ if (Access::check('interface','75')) { $approved = '1'; }
- $sql = "INSERT INTO `flagged` (`object_id`,`object_type`,`flag`,`comment`,`date`,`approved`,`user`) VALUES " .
- " ('$id','$type','$flag','$comment','$time','$approved','$user')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `flagged` (`object_id`,`object_type`,`flag`,`comment`,`date`,`approved`,`user`) VALUES " .
+ " ('$id','$type','$flag','$comment','$time','$approved','$user')";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // add
+ } // add
- /**
- * delete
- * This deletes the flagged entry and rescans the file to revert to the origional
- * state, in a perfect world, I could just roll the changes back... not until 3.4
- * or.. haha 3.5!
- */
- public function delete() {
+ /**
+ * delete
+ * This deletes the flagged entry and rescans the file to revert to the origional
+ * state, in a perfect world, I could just roll the changes back... not until 3.4
+ * or.. haha 3.5!
+ */
+ public function delete() {
- // Re-scan the file
- $song = new Song($this->object_id);
- $info = Catalog::update_media_from_tags($song);
-
- // Delete the row
- $sql = "DELETE FROM `flagged` WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Reset the Last-Updated date so that it'll get re-scaned
- $song->update_utime($song->id,1);
-
- return true;
-
- } // delete
-
- /**
- * approve
- * This approves the current flag object ($this->id) by setting approved to
- * 1
- */
- public function approve() {
-
- $sql = "UPDATE `flagged` SET `approved`='1' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- $this->approved = 1;
-
- return true;
-
- } // approve
-
- /**
- * format
- * This function figures out what kind of object we've got and sets up all the
- * vars all nice and fuzzy like
- */
- public function format() {
-
- switch ($this->object_type) {
- case 'song':
- $song = new Song($this->object_id);
- $song->format();
- $this->f_name = $song->f_link;
- break;
- } // end switch on type
-
- $client = new User($this->user);
- $client->format();
- $this->f_user = $client->f_link;
-
- } // format
-
- /**
- * print_status
- * This prints out a userfriendly version of the current status for this flagged
- * object
- */
- public function print_status() {
-
- if ($this->approved) { echo T_('Approved'); }
- else { echo T_('Pending'); }
-
- } // print_status
-
- /**
- * print_flag
- * This prints out a userfriendly version of the current flag type
- */
- public function print_flag() {
-
- switch ($this->flag) {
- case 'delete':
- $name = T_('Delete');
- break;
- case 'retag':
- $name = T_('Re-Tag');
- break;
- case 'reencode':
- $name = T_('Re-encode');
- break;
- case 'other':
- $name = T_('Other');
- break;
- default:
- $name = T_('Unknown');
- break;
- } // end switch
-
- echo $name;
-
- } // print_flag
-
- /**
- * validate_flag
- * This takes a flag input and makes sure it's one of the reigstered
- * and valid 'flag' values
- */
- public static function validate_flag($flag) {
-
- switch ($flag) {
- case 'delete':
- case 'retag':
- case 'reencode':
- case 'other':
- return $flag;
- break;
- default:
- return 'other';
- break;
- } // end switch
-
- } // validate_flag
-
- /**
- * fill_tags
- * This is used by the write_tags script.
- */
- public static function fill_tags( $tagWriter, $song, $type = 'comment' ) {
-
- // Set all of the attributes for the tag to be written(All pulled from the song object)
- // Use a function since ID3v1, ID3v2, and vorbis/flac/ape are different
- switch ($type) {
- case 'comment':
- $tagWriter->comments['title'] = $song->title;
- $tagWriter->comments['date'] = $song->year;
- $tagWriter->comments['year'] = $song->year;
- $tagWriter->comments['comment'] = $song->comment;
- $tagWriter->comments['size'] = $song->size;
- $tagWriter->comments['time'] = $song->time;
- $tagWriter->comments['album'] = $song->get_album_name();
- $tagWriter->comments['artist'] = $song->get_artist_name();
- $tagWriter->comments['genre'] = $song->get_genre_name();
- $tagWriter->comments['track'] = $song->track;
- break;
- case 'id3v1':
- $tagWriter->title = $song->title;
- $tagWriter->year = $song->year;
- $tagWriter->comment = $song->comment;
- $tagWriter->artist = $song->get_artist_name();
- $tagWriter->album = $song->get_album_name();
- $tagWriter->genre = $song->get_genre_name();
- $tagWriter->track = $song->track;
- unset($tagWriter->genre_id);
- break;
- case 'id3v2':
- $tagWriter->title = $song->title;
- $tagWriter->year = $song->year;
- $tagWriter->comment = $song->comment;
- $tagWriter->artist = $song->get_artist_name();
- $tagWriter->album = $song->get_album_name();
- $tagWriter->genre = $song->get_genre_name();
- $tagWriter->track = $song->track;
- unset($tagWriter->genre_id);
- break;
- } // end switch on type
-
- } // fill_tags
+ // Re-scan the file
+ $song = new Song($this->object_id);
+ $info = Catalog::update_media_from_tags($song);
+
+ // Delete the row
+ $sql = "DELETE FROM `flagged` WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Reset the Last-Updated date so that it'll get re-scaned
+ $song->update_utime($song->id,1);
+
+ return true;
+
+ } // delete
+
+ /**
+ * approve
+ * This approves the current flag object ($this->id) by setting approved to
+ * 1
+ */
+ public function approve() {
+
+ $sql = "UPDATE `flagged` SET `approved`='1' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ $this->approved = 1;
+
+ return true;
+
+ } // approve
+
+ /**
+ * format
+ * This function figures out what kind of object we've got and sets up all the
+ * vars all nice and fuzzy like
+ */
+ public function format() {
+
+ switch ($this->object_type) {
+ case 'song':
+ $song = new Song($this->object_id);
+ $song->format();
+ $this->f_name = $song->f_link;
+ break;
+ } // end switch on type
+
+ $client = new User($this->user);
+ $client->format();
+ $this->f_user = $client->f_link;
+
+ } // format
+
+ /**
+ * print_status
+ * This prints out a userfriendly version of the current status for this flagged
+ * object
+ */
+ public function print_status() {
+
+ if ($this->approved) { echo T_('Approved'); }
+ else { echo T_('Pending'); }
+
+ } // print_status
+
+ /**
+ * print_flag
+ * This prints out a userfriendly version of the current flag type
+ */
+ public function print_flag() {
+
+ switch ($this->flag) {
+ case 'delete':
+ $name = T_('Delete');
+ break;
+ case 'retag':
+ $name = T_('Re-Tag');
+ break;
+ case 'reencode':
+ $name = T_('Re-encode');
+ break;
+ case 'other':
+ $name = T_('Other');
+ break;
+ default:
+ $name = T_('Unknown');
+ break;
+ } // end switch
+
+ echo $name;
+
+ } // print_flag
+
+ /**
+ * validate_flag
+ * This takes a flag input and makes sure it's one of the reigstered
+ * and valid 'flag' values
+ */
+ public static function validate_flag($flag) {
+
+ switch ($flag) {
+ case 'delete':
+ case 'retag':
+ case 'reencode':
+ case 'other':
+ return $flag;
+ break;
+ default:
+ return 'other';
+ break;
+ } // end switch
+
+ } // validate_flag
+
+ /**
+ * fill_tags
+ * This is used by the write_tags script.
+ */
+ public static function fill_tags( $tagWriter, $song, $type = 'comment' ) {
+
+ // Set all of the attributes for the tag to be written(All pulled from the song object)
+ // Use a function since ID3v1, ID3v2, and vorbis/flac/ape are different
+ switch ($type) {
+ case 'comment':
+ $tagWriter->comments['title'] = $song->title;
+ $tagWriter->comments['date'] = $song->year;
+ $tagWriter->comments['year'] = $song->year;
+ $tagWriter->comments['comment'] = $song->comment;
+ $tagWriter->comments['size'] = $song->size;
+ $tagWriter->comments['time'] = $song->time;
+ $tagWriter->comments['album'] = $song->get_album_name();
+ $tagWriter->comments['artist'] = $song->get_artist_name();
+ $tagWriter->comments['genre'] = $song->get_genre_name();
+ $tagWriter->comments['track'] = $song->track;
+ break;
+ case 'id3v1':
+ $tagWriter->title = $song->title;
+ $tagWriter->year = $song->year;
+ $tagWriter->comment = $song->comment;
+ $tagWriter->artist = $song->get_artist_name();
+ $tagWriter->album = $song->get_album_name();
+ $tagWriter->genre = $song->get_genre_name();
+ $tagWriter->track = $song->track;
+ unset($tagWriter->genre_id);
+ break;
+ case 'id3v2':
+ $tagWriter->title = $song->title;
+ $tagWriter->year = $song->year;
+ $tagWriter->comment = $song->comment;
+ $tagWriter->artist = $song->get_artist_name();
+ $tagWriter->album = $song->get_album_name();
+ $tagWriter->genre = $song->get_genre_name();
+ $tagWriter->track = $song->track;
+ unset($tagWriter->genre_id);
+ break;
+ } // end switch on type
+
+ } // fill_tags
} //end of flag class
diff --git a/lib/class/localplay.class.php b/lib/class/localplay.class.php
index 28c8bed9..187ae548 100644
--- a/lib/class/localplay.class.php
+++ b/lib/class/localplay.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,647 +22,647 @@
class Localplay {
- /* Base Variables */
- public $type;
-
- /* Built Variables */
- private $_template;
- private $_preferences = array();
- private $_player;
-
- /**
- * Constructor
- * This must be called with a localplay type, it then loads the config
- * file for the specified type and attempts to load in the function
- * map, the preferences and the template
- */
- public function __construct($type) {
-
- $this->type = $type;
-
- $this->_get_info();
-
- } // Localplay
-
- /**
- * _get_info
- * This functions takes the type and attempts to get all the
- * information needed to load it. Will log errors if there are
- * any failures, fatal errors will actually return something to the
- * gui
- */
- private function _get_info() {
-
- $this->_load_player();
-
- } // _get_info
-
- /**
- * player_loaded
- * This returns true / false if the player load
- * failed / worked
- */
- public function player_loaded() {
-
- if (is_object($this->_player)) {
- return true;
- }
- else {
- return false;
- }
-
- } // player_loaded
-
- /**
- * format
- * This makes the localplay/plugin information
- * human readable
- */
- public function format() {
-
- if (!is_object($this->_player)) { return false; }
-
- $this->f_name = ucfirst($this->type);
- $this->f_description = $this->_player->get_description();
- $this->f_version = $this->_player->get_version();
-
-
- } // format
-
- /**
- * _load_player
- * This function attempts to load the player class that localplay
- * Will interface with in order to make all this magical stuf work
- * all LocalPlay modules should be located in /modules/<name>/<name>.class.php
- */
- private function _load_player() {
-
- if (!$this->type) { return false; }
-
- $filename = Config::get('prefix') . '/modules/localplay/' . $this->type . '.controller.php';
- $include = require_once $filename;
-
- if (!$include) {
- /* Throw Error Here */
- debug_event('localplay','Unable to load ' . $this->type . ' controller','2');
- return false;
- } // include
- else {
- $class_name = "Ampache" . $this->type;
- $this->_player = new $class_name();
- if (!($this->_player instanceof localplay_controller)) {
- debug_event('Localplay',$this->type . ' not an instance of controller abstract, unable to load','1');
- unset($this->_player);
- return false;
- }
- }
-
- } // _load_player
-
- /**
- * format_name
- * This function takes the track name and checks to see if 'skip'
- * is supported in the current player, if so it returns a 'skip to'
- * link, otherwise it returns just the text
- */
- public function format_name($name,$id) {
-
- $name = scrub_out($name);
- $name = Ajax::text('?page=localplay&action=command&command=skip&id=' . $id,$name,'localplay_skip_' . $id);
- return $name;
-
- } // format_name
-
- /**
- * get_controllers
- * This returns the controllers that are currently loaded into this instance
- */
- public static function get_controllers() {
-
- /* First open the dir */
- $handle = opendir(Config::get('prefix') . '/modules/localplay');
-
- if (!is_resource($handle)) {
- debug_event('Localplay','Error: Unable to read localplay controller directory','1');
- return array();
- }
-
- $results = array();
-
- while ($file = readdir($handle)) {
-
- if (substr($file,-14,14) != 'controller.php') { continue; }
+ /* Base Variables */
+ public $type;
+
+ /* Built Variables */
+ private $_template;
+ private $_preferences = array();
+ private $_player;
+
+ /**
+ * Constructor
+ * This must be called with a localplay type, it then loads the config
+ * file for the specified type and attempts to load in the function
+ * map, the preferences and the template
+ */
+ public function __construct($type) {
+
+ $this->type = $type;
+
+ $this->_get_info();
+
+ } // Localplay
+
+ /**
+ * _get_info
+ * This functions takes the type and attempts to get all the
+ * information needed to load it. Will log errors if there are
+ * any failures, fatal errors will actually return something to the
+ * gui
+ */
+ private function _get_info() {
+
+ $this->_load_player();
+
+ } // _get_info
+
+ /**
+ * player_loaded
+ * This returns true / false if the player load
+ * failed / worked
+ */
+ public function player_loaded() {
+
+ if (is_object($this->_player)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ } // player_loaded
+
+ /**
+ * format
+ * This makes the localplay/plugin information
+ * human readable
+ */
+ public function format() {
+
+ if (!is_object($this->_player)) { return false; }
+
+ $this->f_name = ucfirst($this->type);
+ $this->f_description = $this->_player->get_description();
+ $this->f_version = $this->_player->get_version();
+
+
+ } // format
+
+ /**
+ * _load_player
+ * This function attempts to load the player class that localplay
+ * Will interface with in order to make all this magical stuf work
+ * all LocalPlay modules should be located in /modules/<name>/<name>.class.php
+ */
+ private function _load_player() {
+
+ if (!$this->type) { return false; }
+
+ $filename = Config::get('prefix') . '/modules/localplay/' . $this->type . '.controller.php';
+ $include = require_once $filename;
+
+ if (!$include) {
+ /* Throw Error Here */
+ debug_event('localplay','Unable to load ' . $this->type . ' controller','2');
+ return false;
+ } // include
+ else {
+ $class_name = "Ampache" . $this->type;
+ $this->_player = new $class_name();
+ if (!($this->_player instanceof localplay_controller)) {
+ debug_event('Localplay',$this->type . ' not an instance of controller abstract, unable to load','1');
+ unset($this->_player);
+ return false;
+ }
+ }
+
+ } // _load_player
+
+ /**
+ * format_name
+ * This function takes the track name and checks to see if 'skip'
+ * is supported in the current player, if so it returns a 'skip to'
+ * link, otherwise it returns just the text
+ */
+ public function format_name($name,$id) {
+
+ $name = scrub_out($name);
+ $name = Ajax::text('?page=localplay&action=command&command=skip&id=' . $id,$name,'localplay_skip_' . $id);
+ return $name;
+
+ } // format_name
+
+ /**
+ * get_controllers
+ * This returns the controllers that are currently loaded into this instance
+ */
+ public static function get_controllers() {
+
+ /* First open the dir */
+ $handle = opendir(Config::get('prefix') . '/modules/localplay');
+
+ if (!is_resource($handle)) {
+ debug_event('Localplay','Error: Unable to read localplay controller directory','1');
+ return array();
+ }
+
+ $results = array();
+
+ while ($file = readdir($handle)) {
+
+ if (substr($file,-14,14) != 'controller.php') { continue; }
- /* Make sure it isn't a dir */
- if (!is_dir($file)) {
- /* Get the basename and then everything before controller */
- $filename = basename($file,'.controller.php');
- $results[] = $filename;
- }
- } // end while
-
- return $results;
+ /* Make sure it isn't a dir */
+ if (!is_dir($file)) {
+ /* Get the basename and then everything before controller */
+ $filename = basename($file,'.controller.php');
+ $results[] = $filename;
+ }
+ } // end while
+
+ return $results;
- } // get_controllers
-
- /**
- * is_enabled
- * This returns true or false depending on if the specified controller
- * is currently enabled
- */
- public static function is_enabled($controller) {
+ } // get_controllers
+
+ /**
+ * is_enabled
+ * This returns true or false depending on if the specified controller
+ * is currently enabled
+ */
+ public static function is_enabled($controller) {
- // Load the controller and then check for its preferences
- $localplay = new Localplay($controller);
- // If we can't even load it no sense in going on
- if (!isset($localplay->_player)) { return false; }
+ // Load the controller and then check for its preferences
+ $localplay = new Localplay($controller);
+ // If we can't even load it no sense in going on
+ if (!isset($localplay->_player)) { return false; }
- return $localplay->_player->is_installed();
+ return $localplay->_player->is_installed();
- } // is_enabled
+ } // is_enabled
- /**
- * install
- * This runs the install for the localplay controller we've
- * currently got pimped out
- */
- public function install() {
+ /**
+ * install
+ * This runs the install for the localplay controller we've
+ * currently got pimped out
+ */
+ public function install() {
- // Run the player's installer
- $installed = $this->_player->install();
-
- return $installed;
-
- } // install
+ // Run the player's installer
+ $installed = $this->_player->install();
+
+ return $installed;
+
+ } // install
- /**
- * uninstall
- * This runs the uninstall for the localplay controller we've
- * currently pimped out
- */
- public function uninstall() {
+ /**
+ * uninstall
+ * This runs the uninstall for the localplay controller we've
+ * currently pimped out
+ */
+ public function uninstall() {
- // Run the players uninstaller
- $this->_player->uninstall();
+ // Run the players uninstaller
+ $this->_player->uninstall();
- // If its our current player, reset player to nothing
- if (Config::get('localplay_controller') == $this->type) {
- Preference::update('localplay_controller',$GLOBALS['user']->id,'');
- }
+ // If its our current player, reset player to nothing
+ if (Config::get('localplay_controller') == $this->type) {
+ Preference::update('localplay_controller',$GLOBALS['user']->id,'');
+ }
- return true;
+ return true;
- } // uninstall
+ } // uninstall
- /**
- * connect
- * This function attempts to connect to the localplay
- * player that we are using
- */
- public function connect() {
+ /**
+ * connect
+ * This function attempts to connect to the localplay
+ * player that we are using
+ */
+ public function connect() {
- if (!$this->_player->connect()) {
- debug_event('localplay','Error Unable to connect, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->connect()) {
+ debug_event('localplay','Error Unable to connect, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // connect
+ } // connect
- /**
- * play
- * This function passes NULL and calls the play function of the player
- * object
- */
- public function play() {
+ /**
+ * play
+ * This function passes NULL and calls the play function of the player
+ * object
+ */
+ public function play() {
- if (!$this->_player->play()) {
- debug_event('localplay','Error Unable to start playback, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->play()) {
+ debug_event('localplay','Error Unable to start playback, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // play
+ } // play
- /**
- * stop
- * This functions passes NULl and calls the stop function of the player
- * object, it should recieve a true/false boolean value
- */
- public function stop() {
+ /**
+ * stop
+ * This functions passes NULl and calls the stop function of the player
+ * object, it should recieve a true/false boolean value
+ */
+ public function stop() {
- if (!$this->_player->stop()) {
- debug_event('localplay','Error Unable to stop playback, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->stop()) {
+ debug_event('localplay','Error Unable to stop playback, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // stop
+ } // stop
- /**
- * add
- */
- public function add($object) {
+ /**
+ * add
+ */
+ public function add($object) {
- debug_event('localplay', 'Deprecated add method called: ' . json_encode($object), 5);
- return false;
+ debug_event('localplay', 'Deprecated add method called: ' . json_encode($object), 5);
+ return false;
- } // add
+ } // add
- /**
- * add_url
- * This directly adds an URL to the localplay module. Is more betterer.
- */
- public function add_url(Stream_URL $url) {
+ /**
+ * add_url
+ * This directly adds an URL to the localplay module. Is more betterer.
+ */
+ public function add_url(Stream_URL $url) {
- if (!$this->_player->add_url($url)) {
- debug_event('localplay', 'Unable to add url ' . $url . ', check ' . $this->type . ' controller', 1);
- return false;
- }
+ if (!$this->_player->add_url($url)) {
+ debug_event('localplay', 'Unable to add url ' . $url . ', check ' . $this->type . ' controller', 1);
+ return false;
+ }
- return true;
+ return true;
- } // add_url
+ } // add_url
- /**
- * repeat
- * This turns the repeat feature of a localplay method on or
- * off, takes a 0/1 value
- */
- public function repeat($state) {
+ /**
+ * repeat
+ * This turns the repeat feature of a localplay method on or
+ * off, takes a 0/1 value
+ */
+ public function repeat($state) {
- $data = $this->_player->repeat($state);
+ $data = $this->_player->repeat($state);
- if (!$data) {
- debug_event('localplay',"Error Unable to set Repeat to $state",'1');
- }
+ if (!$data) {
+ debug_event('localplay',"Error Unable to set Repeat to $state",'1');
+ }
- return $data;
+ return $data;
- } // repeat
+ } // repeat
- /**
- * random
- * This turns on the random feature of a localplay method
- * It takes a 0/1 value
- */
- public function random($state) {
+ /**
+ * random
+ * This turns on the random feature of a localplay method
+ * It takes a 0/1 value
+ */
+ public function random($state) {
- $data = $this->_player->random($state);
+ $data = $this->_player->random($state);
- if (!$data) {
- debug_event('localplay',"Error Unable to set Random to $state",'1');
- }
+ if (!$data) {
+ debug_event('localplay',"Error Unable to set Random to $state",'1');
+ }
- return $data;
+ return $data;
- } // random
+ } // random
- /**
- * status
- * This returns current information about the state of the player
- * There is an expected array format
- */
- public function status() {
+ /**
+ * status
+ * This returns current information about the state of the player
+ * There is an expected array format
+ */
+ public function status() {
- $data = $this->_player->status();
+ $data = $this->_player->status();
- if (!count($data)) {
- debug_event('localplay','Error Unable to get status, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!count($data)) {
+ debug_event('localplay','Error Unable to get status, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return $data;
+ return $data;
- } // status
+ } // status
- /**
- * get
- * This calls the get function of the player and then returns
- * the array of current songs for display or whatever
- * an empty array is passed on failure
- */
- public function get() {
+ /**
+ * get
+ * This calls the get function of the player and then returns
+ * the array of current songs for display or whatever
+ * an empty array is passed on failure
+ */
+ public function get() {
- $data = $this->_player->get();
+ $data = $this->_player->get();
- if (!count($data) OR !is_array($data)) {
- debug_event('localplay','Error Unable to get song info, check ' . $this->type . ' controller','1');
- return array();
- }
+ if (!count($data) OR !is_array($data)) {
+ debug_event('localplay','Error Unable to get song info, check ' . $this->type . ' controller','1');
+ return array();
+ }
- return $data;
+ return $data;
- } // get
+ } // get
- /**
- * volume_set
- * This isn't a required function, it sets the volume to a specified value
- * as passed in the variable it is a 0 - 100 scale the controller is
- * responsible for adjusting the scale if nessecary
- */
- public function volume_set($value) {
+ /**
+ * volume_set
+ * This isn't a required function, it sets the volume to a specified value
+ * as passed in the variable it is a 0 - 100 scale the controller is
+ * responsible for adjusting the scale if nessecary
+ */
+ public function volume_set($value) {
- /* Make sure it's int and 0 - 100 */
- $value = int($value);
+ /* Make sure it's int and 0 - 100 */
+ $value = int($value);
- /* Make sure that it's between 0 and 100 */
- if ($value > 100 OR $value < 0) { return false; }
+ /* Make sure that it's between 0 and 100 */
+ if ($value > 100 OR $value < 0) { return false; }
- if (!$this->_player->volume($value)) {
- debug_event('localplay','Error: Unable to set volume, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->volume($value)) {
+ debug_event('localplay','Error: Unable to set volume, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // volume_set
+ } // volume_set
- /**
- * volume_up
- * This function isn't required. It tells the daemon to increase the volume
- * by a pre-defined amount controlled by the controller
- */
- public function volume_up() {
+ /**
+ * volume_up
+ * This function isn't required. It tells the daemon to increase the volume
+ * by a pre-defined amount controlled by the controller
+ */
+ public function volume_up() {
- if (!$this->_player->volume_up()) {
- debug_event('localplay','Error: Unable to increase volume, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->volume_up()) {
+ debug_event('localplay','Error: Unable to increase volume, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // volume_up
+ } // volume_up
- /**
- * volume_down
- * This function isn't required. It tells the daemon to decrese the volume
- * by a pre-defined amount controlled by the controller.
- */
- public function volume_down() {
+ /**
+ * volume_down
+ * This function isn't required. It tells the daemon to decrese the volume
+ * by a pre-defined amount controlled by the controller.
+ */
+ public function volume_down() {
- if (!$this->_player->volume_down()) {
- debug_event('localplay','Error: Unable to decrese volume, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->volume_down()) {
+ debug_event('localplay','Error: Unable to decrese volume, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // volume_down
+ } // volume_down
- /**
- * volume_mute
- * This function isn't required, It tells the daemon to mute all output
- * It's up to the controller to decide what that actually entails
- */
- public function volume_mute() {
+ /**
+ * volume_mute
+ * This function isn't required, It tells the daemon to mute all output
+ * It's up to the controller to decide what that actually entails
+ */
+ public function volume_mute() {
- if (!$this->_player->volume(0)){
- debug_event('localplay','Error: Unable to mute volume, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->volume(0)){
+ debug_event('localplay','Error: Unable to mute volume, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // volume_mute
+ } // volume_mute
- /**
- * skip
- * This isn't a required function, it tells the daemon to skip to the specified song
- */
- public function skip($track_id) {
+ /**
+ * skip
+ * This isn't a required function, it tells the daemon to skip to the specified song
+ */
+ public function skip($track_id) {
- if (!$this->_player->skip($track_id)) {
- debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->skip($track_id)) {
+ debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // skip
+ } // skip
- /**
- * next
- * This isn't a required function, it tells the daemon to go to the next
- * song
- */
- public function next() {
+ /**
+ * next
+ * This isn't a required function, it tells the daemon to go to the next
+ * song
+ */
+ public function next() {
- if (!$this->_player->next()) {
- debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->next()) {
+ debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // next
+ } // next
- /**
- * prev
- * This isn't a required function, it tells the daemon to go the the previous
- * song
- */
- public function prev() {
+ /**
+ * prev
+ * This isn't a required function, it tells the daemon to go the the previous
+ * song
+ */
+ public function prev() {
- if (!$this->_player->prev()) {
- debug_event('localplay','Error: Unable to skip to previous song, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->prev()) {
+ debug_event('localplay','Error: Unable to skip to previous song, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // prev
+ } // prev
- /**
- * pause
- * This isn't a required function, it tells the daemon to pause the
- * song
- */
- public function pause() {
+ /**
+ * pause
+ * This isn't a required function, it tells the daemon to pause the
+ * song
+ */
+ public function pause() {
- if (!$this->_player->pause()) {
- debug_event('localplay','Error: Unable to pause song, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->pause()) {
+ debug_event('localplay','Error: Unable to pause song, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // pause
+ } // pause
- /**
- * get_instances
- * This returns the instances of the current type
- */
- public function get_instances() {
+ /**
+ * get_instances
+ * This returns the instances of the current type
+ */
+ public function get_instances() {
- $instances = $this->_player->get_instances();
+ $instances = $this->_player->get_instances();
- return $instances;
+ return $instances;
- } // get_instances
+ } // get_instances
- /**
- * current_instance
- * This returns the UID of the current Instance
- */
- public function current_instance() {
+ /**
+ * current_instance
+ * This returns the UID of the current Instance
+ */
+ public function current_instance() {
- $data = $this->_player->get_instance();
+ $data = $this->_player->get_instance();
- return $data['id'];
+ return $data['id'];
- } // current_instance
+ } // current_instance
- /**
- * get_instance
- * This returns the specified instance
- */
- public function get_instance($uid) {
+ /**
+ * get_instance
+ * This returns the specified instance
+ */
+ public function get_instance($uid) {
- $data = $this->_player->get_instance($uid);
+ $data = $this->_player->get_instance($uid);
- return $data;
+ return $data;
- } // get_instance
+ } // get_instance
- /**
- * update_instance
- * This updates the specified instance with a named array of data (_POST most likely)
- */
- public function update_instance($uid,$data) {
+ /**
+ * update_instance
+ * This updates the specified instance with a named array of data (_POST most likely)
+ */
+ public function update_instance($uid,$data) {
- $data = $this->_player->update_instance($uid,$data);
+ $data = $this->_player->update_instance($uid,$data);
- return $data;
+ return $data;
- } // update_instance
+ } // update_instance
- /**
- * add_instance
- * This adds a new instance for the current controller type
- */
- public function add_instance($data) {
+ /**
+ * add_instance
+ * This adds a new instance for the current controller type
+ */
+ public function add_instance($data) {
- $this->_player->add_instance($data);
+ $this->_player->add_instance($data);
- } // add_instance
+ } // add_instance
- /**
- * delete_instance
- * This removes an instance (it actually calls the players function)
- */
- public function delete_instance($instance_uid) {
+ /**
+ * delete_instance
+ * This removes an instance (it actually calls the players function)
+ */
+ public function delete_instance($instance_uid) {
- $this->_player->delete_instance($instance_uid);
+ $this->_player->delete_instance($instance_uid);
- } // delete_instance
+ } // delete_instance
- /**
- * set_active_instance
- * This sets the active instance of the localplay controller
- */
- public function set_active_instance($instance) {
+ /**
+ * set_active_instance
+ * This sets the active instance of the localplay controller
+ */
+ public function set_active_instance($instance) {
- $this->_player->set_active_instance($instance);
+ $this->_player->set_active_instance($instance);
- } // set_active_instance
+ } // set_active_instance
- /**
- * delete_track
- * This removes songs from the players playlist it takes a single ID as provided
- * by the get command
- */
- public function delete_track($object_id) {
+ /**
+ * delete_track
+ * This removes songs from the players playlist it takes a single ID as provided
+ * by the get command
+ */
+ public function delete_track($object_id) {
- if (!$this->_player->delete_track($object_id)) {
- debug_event('localplay','Error: Unable to remove songs, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->delete_track($object_id)) {
+ debug_event('localplay','Error: Unable to remove songs, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // delete
+ } // delete
- /**
- * delete_all
- * This removes every song from the players playlist as defined by the delete_all function
- * map
- */
- public function delete_all() {
+ /**
+ * delete_all
+ * This removes every song from the players playlist as defined by the delete_all function
+ * map
+ */
+ public function delete_all() {
- if (!$this->_player->clear_playlist()) {
- debug_event('localplay','Error: Unable to delete entire playlist, check ' . $this->type . ' controller','1');
- return false;
- }
+ if (!$this->_player->clear_playlist()) {
+ debug_event('localplay','Error: Unable to delete entire playlist, check ' . $this->type . ' controller','1');
+ return false;
+ }
- return true;
+ return true;
- } // delete_all
+ } // delete_all
- /**
- * get_instance_fields
- * This loads the fields from the localplay
- * player and returns them
- */
- public function get_instance_fields() {
+ /**
+ * get_instance_fields
+ * This loads the fields from the localplay
+ * player and returns them
+ */
+ public function get_instance_fields() {
- $fields = $this->_player->instance_fields();
+ $fields = $this->_player->instance_fields();
- return $fields;
+ return $fields;
- } // get_instance_fields
+ } // get_instance_fields
- /**
- * get_user_state
- * This function returns a user friendly version
- * of the current player state
- */
- public function get_user_state($state) {
+ /**
+ * get_user_state
+ * This function returns a user friendly version
+ * of the current player state
+ */
+ public function get_user_state($state) {
- switch ($state) {
- case 'play':
- return T_('Now Playing');
- break;
- case 'stop':
- return T_('Stopped');
- break;
- case 'pause':
- return T_('Paused');
- break;
- default:
- return T_('Unknown');
- break;
- } // switch on state
+ switch ($state) {
+ case 'play':
+ return T_('Now Playing');
+ break;
+ case 'stop':
+ return T_('Stopped');
+ break;
+ case 'pause':
+ return T_('Paused');
+ break;
+ default:
+ return T_('Unknown');
+ break;
+ } // switch on state
- } // get_user_state
+ } // get_user_state
- /**
- * get_user_playing
- * This attempts to return a nice user friendly
- * currently playing string
- */
- public function get_user_playing() {
+ /**
+ * get_user_playing
+ * This attempts to return a nice user friendly
+ * currently playing string
+ */
+ public function get_user_playing() {
- $status = $this->status();
+ $status = $this->status();
- /* Format the track name */
- $track_name = $status['track_artist'] . ' - ' . $status['track_album'] . ' - ' . $status['track_title'];
+ /* Format the track name */
+ $track_name = $status['track_artist'] . ' - ' . $status['track_album'] . ' - ' . $status['track_title'];
- /* This is a cheezball fix for when we were unable to find a
- * artist/album (or one wasn't provided)
- */
- $track_name = ltrim(ltrim($track_name,' - '),' - ');
+ /* This is a cheezball fix for when we were unable to find a
+ * artist/album (or one wasn't provided)
+ */
+ $track_name = ltrim(ltrim($track_name,' - '),' - ');
- $track_name = "[" . $status['track'] . "] - " . $track_name;
+ $track_name = "[" . $status['track'] . "] - " . $track_name;
- return $track_name;
+ return $track_name;
- } // get_user_playing
+ } // get_user_playing
} // end localplay class
diff --git a/lib/class/localplay_controller.abstract.php b/lib/class/localplay_controller.abstract.php
index 38e2bc7d..e1b79db9 100644
--- a/lib/class/localplay_controller.abstract.php
+++ b/lib/class/localplay_controller.abstract.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,83 +28,83 @@
*/
abstract class localplay_controller {
- // Required Functions
- abstract public function add_url(Stream_URL $url); // Takes an array of song_ids
- abstract public function delete_track($object_id); // Takes a single object_id and removes it from the playlist
- abstract public function play();
- abstract public function stop();
- abstract public function get();
- abstract public function connect();
- abstract public function status();
- abstract public function get_version(); // Returns the version of this plugin
- abstract public function get_description(); // Returns the description
- abstract public function is_installed(); // Returns an boolean t/f
- abstract public function install();
- abstract public function uninstall();
-
- // For display we need the following 'instance' functions
- abstract public function add_instance($data);
- abstract public function delete_instance($id);
- abstract public function update_instance($id,$post);
- abstract public function get_instances();
- abstract public function instance_fields();
- abstract public function set_active_instance($uid);
- abstract public function get_active_instance();
-
- /**
- * get_url
- * This returns the URL for the passed object
- */
- public function get_url($object) {
-
- // This might not be an object!
- if (!is_object($object)) {
- // Stupiidly we'll just blindly add it for now
- return $object;
- }
-
- $class = get_class($object);
-
- $url = call_user_func(array($class,'play_url'),$object->id);
-
- return $url;
-
- } // get_url
-
- /**
- * get_file
- * This returns the Filename for the passed object, not
- * always possible
- */
- public function get_file($object) {
-
-
- } // get_file
-
- /**
- * parse_url
- * This takes an Ampache URL and then returns the 'primary' part of it
- * So that it's easier for localplay modules to return valid song information
- */
- public function parse_url($url) {
-
- // Define possible 'primary' keys
- $primary_array = array('oid','demo_id','random');
- $data = array();
-
- $variables = parse_url($url,PHP_URL_QUERY);
- parse_str($variables,$data);
-
- foreach ($primary_array as $pkey) {
- if ($data[$pkey]) {
- $data['primary_key'] = $pkey;
- return $data;
- }
-
- } // end foreach
-
- return $data;
-
- } // parse_url
+ // Required Functions
+ abstract public function add_url(Stream_URL $url); // Takes an array of song_ids
+ abstract public function delete_track($object_id); // Takes a single object_id and removes it from the playlist
+ abstract public function play();
+ abstract public function stop();
+ abstract public function get();
+ abstract public function connect();
+ abstract public function status();
+ abstract public function get_version(); // Returns the version of this plugin
+ abstract public function get_description(); // Returns the description
+ abstract public function is_installed(); // Returns an boolean t/f
+ abstract public function install();
+ abstract public function uninstall();
+
+ // For display we need the following 'instance' functions
+ abstract public function add_instance($data);
+ abstract public function delete_instance($id);
+ abstract public function update_instance($id,$post);
+ abstract public function get_instances();
+ abstract public function instance_fields();
+ abstract public function set_active_instance($uid);
+ abstract public function get_active_instance();
+
+ /**
+ * get_url
+ * This returns the URL for the passed object
+ */
+ public function get_url($object) {
+
+ // This might not be an object!
+ if (!is_object($object)) {
+ // Stupiidly we'll just blindly add it for now
+ return $object;
+ }
+
+ $class = get_class($object);
+
+ $url = call_user_func(array($class,'play_url'),$object->id);
+
+ return $url;
+
+ } // get_url
+
+ /**
+ * get_file
+ * This returns the Filename for the passed object, not
+ * always possible
+ */
+ public function get_file($object) {
+
+
+ } // get_file
+
+ /**
+ * parse_url
+ * This takes an Ampache URL and then returns the 'primary' part of it
+ * So that it's easier for localplay modules to return valid song information
+ */
+ public function parse_url($url) {
+
+ // Define possible 'primary' keys
+ $primary_array = array('oid','demo_id','random');
+ $data = array();
+
+ $variables = parse_url($url,PHP_URL_QUERY);
+ parse_str($variables,$data);
+
+ foreach ($primary_array as $pkey) {
+ if ($data[$pkey]) {
+ $data['primary_key'] = $pkey;
+ return $data;
+ }
+
+ } // end foreach
+
+ return $data;
+
+ } // parse_url
} // end localplay_controller interface
diff --git a/lib/class/media.interface.php b/lib/class/media.interface.php
index 97e018d1..f1f794f8 100644
--- a/lib/class/media.interface.php
+++ b/lib/class/media.interface.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,44 +28,44 @@
*/
interface media {
- /**
- * format
- *
- * Creates the gussied-up member variables for output
- */
- public function format();
+ /**
+ * format
+ *
+ * Creates the gussied-up member variables for output
+ */
+ public function format();
- /**
- * get_stream_types
- *
- * Returns an array of strings; current types are 'native'
- * and 'transcode'
- */
- public function get_stream_types();
+ /**
+ * get_stream_types
+ *
+ * Returns an array of strings; current types are 'native'
+ * and 'transcode'
+ */
+ public function get_stream_types();
- /**
- * play_url
- *
- * Returns the url to stream the specified object
- *
- */
- public static function play_url($oid);
+ /**
+ * play_url
+ *
+ * Returns the url to stream the specified object
+ *
+ */
+ public static function play_url($oid);
- /**
- * get_transcode_settings
- *
- * Should only be called if 'transcode' was returned by get_stream_types
- * Returns a raw transcode command for this item; the optional target
- * parameter can be used to request a specific format instead of the
- * default from the configuration file.
- */
- public function get_transcode_settings($target = null);
+ /**
+ * get_transcode_settings
+ *
+ * Should only be called if 'transcode' was returned by get_stream_types
+ * Returns a raw transcode command for this item; the optional target
+ * parameter can be used to request a specific format instead of the
+ * default from the configuration file.
+ */
+ public function get_transcode_settings($target = null);
- /**
- * has_flag
- *
- */
- public function has_flag();
+ /**
+ * has_flag
+ *
+ */
+ public function has_flag();
} // end interface
?>
diff --git a/lib/class/memory_object.class.php b/lib/class/memory_object.class.php
index 3ee4f183..2a8fa133 100644
--- a/lib/class/memory_object.class.php
+++ b/lib/class/memory_object.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -25,31 +25,31 @@
class memory_object {
- private $_data = array();
- public $properties;
+ private $_data = array();
+ public $properties;
- public function __construct($data) {
+ public function __construct($data) {
- foreach ($data as $key => $value) {
- if (in_array($key, $this->properties)) {
- $this->_data[$key] = $value;
- }
- }
+ foreach ($data as $key => $value) {
+ if (in_array($key, $this->properties)) {
+ $this->_data[$key] = $value;
+ }
+ }
- }
+ }
- public function __set($name, $value) {
- if (!in_array($name, $this->properties)) {
- return false;
- }
- $this->_data[$name] = $value;
- }
+ public function __set($name, $value) {
+ if (!in_array($name, $this->properties)) {
+ return false;
+ }
+ $this->_data[$name] = $value;
+ }
- public function __get($name) {
- if (!in_array($name, $this->properties)) {
- return false;
- }
+ public function __get($name) {
+ if (!in_array($name, $this->properties)) {
+ return false;
+ }
- return isset($this->_data[$name]) ? $this->_data[$name] : null;
- }
+ return isset($this->_data[$name]) ? $this->_data[$name] : null;
+ }
}
diff --git a/lib/class/playlist.class.php b/lib/class/playlist.class.php
index 20035f2b..ae3ceb2e 100644
--- a/lib/class/playlist.class.php
+++ b/lib/class/playlist.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,437 +29,437 @@
*/
class Playlist extends playlist_object {
- /* Variables from the database */
- public $genre;
- public $date;
+ /* Variables from the database */
+ public $genre;
+ public $date;
- /* Generated Elements */
- public $items = array();
+ /* Generated Elements */
+ public $items = array();
- /**
- * Constructor
- * This takes a playlist_id as an optional argument and gathers the information
- * if not playlist_id is passed returns false (or if it isn't found
- */
- public function __construct($id) {
+ /**
+ * Constructor
+ * This takes a playlist_id as an optional argument and gathers the information
+ * if not playlist_id is passed returns false (or if it isn't found
+ */
+ public function __construct($id) {
- $info = $this->get_info($id);
+ $info = $this->get_info($id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
- } // Playlist
+ } // Playlist
- /**
- * gc
- *
- * Clean dead items out of playlists
- */
- public static function gc() {
- Dba::write("DELETE FROM `playlist_data` USING `playlist_data` LEFT JOIN `song` ON `song`.`id` = `playlist_data`.`object_id` WHERE `song`.`file` IS NULL AND `playlist_data`.`object_type`='song'");
- }
+ /**
+ * gc
+ *
+ * Clean dead items out of playlists
+ */
+ public static function gc() {
+ Dba::write("DELETE FROM `playlist_data` USING `playlist_data` LEFT JOIN `song` ON `song`.`id` = `playlist_data`.`object_id` WHERE `song`.`file` IS NULL AND `playlist_data`.`object_type`='song'");
+ }
- /**
- * build_cache
- * This is what builds the cache from the objects
- */
- public static function build_cache($ids) {
+ /**
+ * build_cache
+ * This is what builds the cache from the objects
+ */
+ public static function build_cache($ids) {
- if (!count($ids)) { return false; }
+ if (!count($ids)) { return false; }
- $idlist = '(' . implode(',',$ids) . ')';
+ $idlist = '(' . implode(',',$ids) . ')';
- $sql = "SELECT * FROM `playlist` WHERE `id` IN $idlist";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `playlist` WHERE `id` IN $idlist";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('playlist',$row['id'],$row);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('playlist',$row['id'],$row);
+ }
- } // build_cache
+ } // build_cache
- /**
- * get_playlists
- * Returns a list of playlists accessible by the current user.
- */
- public static function get_playlists() {
- $sql = "SELECT `id` from `playlist` WHERE `type`='public' OR " .
- "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`";
- $db_results = Dba::read($sql);
+ /**
+ * get_playlists
+ * Returns a list of playlists accessible by the current user.
+ */
+ public static function get_playlists() {
+ $sql = "SELECT `id` from `playlist` WHERE `type`='public' OR " .
+ "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
- } // get_playlists
+ return $results;
+ } // get_playlists
- /**
- * format
- * This takes the current playlist object and gussies it up a little
- * bit so it is presentable to the users
- */
- public function format() {
- parent::format();
- $this->f_link = '<a href="' . Config::get('web_path') . '/playlist.php?action=show_playlist&amp;playlist_id=' . $this->id . '">' . $this->f_name . '</a>';
+ /**
+ * format
+ * This takes the current playlist object and gussies it up a little
+ * bit so it is presentable to the users
+ */
+ public function format() {
+ parent::format();
+ $this->f_link = '<a href="' . Config::get('web_path') . '/playlist.php?action=show_playlist&amp;playlist_id=' . $this->id . '">' . $this->f_name . '</a>';
- } // format
+ } // format
- /**
- * get_track
- * Returns the single item on the playlist and all of it's information, restrict
- * it to this Playlist
- */
- public function get_track($track_id) {
+ /**
+ * get_track
+ * Returns the single item on the playlist and all of it's information, restrict
+ * it to this Playlist
+ */
+ public function get_track($track_id) {
- $track_id = Dba::escape($track_id);
- $playlist_id = Dba::escape($this->id);
+ $track_id = Dba::escape($track_id);
+ $playlist_id = Dba::escape($this->id);
- $sql = "SELECT * FROM `playlist_data` WHERE `id`='$track_id' AND `playlist`='$playlist_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `playlist_data` WHERE `id`='$track_id' AND `playlist`='$playlist_id'";
+ $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- return $row;
+ return $row;
- } // get_track
+ } // get_track
- /**
- * get_items
- * This returns an array of playlist songs that are in this playlist.
- * Because the same song can be on the same playlist twice they are
- * keyed by the uid from playlist_data
- */
- public function get_items() {
+ /**
+ * get_items
+ * This returns an array of playlist songs that are in this playlist.
+ * Because the same song can be on the same playlist twice they are
+ * keyed by the uid from playlist_data
+ */
+ public function get_items() {
- $results = array();
+ $results = array();
- $sql = "SELECT `id`,`object_id`,`object_type`,`track` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id`,`object_id`,`object_type`,`track` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = array(
- 'object_type' => $row['object_type'],
- 'object_id' => $row['object_id'],
- 'track' => $row['track'],
- 'track_id' => $row['id']
- );
- } // end while
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = array(
+ 'object_type' => $row['object_type'],
+ 'object_id' => $row['object_id'],
+ 'track' => $row['track'],
+ 'track_id' => $row['id']
+ );
+ } // end while
- return $results;
+ return $results;
- } // get_items
+ } // get_items
- /**
- * get_random_items
- * This is the same as before but we randomize the buggers!
- */
- public function get_random_items($limit='') {
+ /**
+ * get_random_items
+ * This is the same as before but we randomize the buggers!
+ */
+ public function get_random_items($limit='') {
- $results = array();
+ $results = array();
- $limit_sql = $limit ? 'LIMIT ' . intval($limit) : '';
+ $limit_sql = $limit ? 'LIMIT ' . intval($limit) : '';
- $sql = "SELECT `object_id`,`object_type` FROM `playlist_data` " .
- "WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY RAND() $limit_sql";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `object_id`,`object_type` FROM `playlist_data` " .
+ "WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY RAND() $limit_sql";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
+ while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = array(
- 'object_type' => $row['object_type'],
- 'object_id' => $row['object_id']
- );
- } // end while
+ $results[] = array(
+ 'object_type' => $row['object_type'],
+ 'object_id' => $row['object_id']
+ );
+ } // end while
- return $results;
+ return $results;
- } // get_random_items
+ } // get_random_items
- /**
- * get_songs
- * This is called by the batch script, because we can't pass in Dynamic objects they pulled once and then their
- * target song.id is pushed into the array
- */
- function get_songs() {
+ /**
+ * get_songs
+ * This is called by the batch script, because we can't pass in Dynamic objects they pulled once and then their
+ * target song.id is pushed into the array
+ */
+ function get_songs() {
- $results = array();
+ $results = array();
- $sql = "SELECT * FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- if ($r['dyn_song']) {
- $array = $this->get_dyn_songs($r['dyn_song']);
- $results = array_merge($array,$results);
- }
- else {
- $results[] = $r['object_id'];
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ if ($r['dyn_song']) {
+ $array = $this->get_dyn_songs($r['dyn_song']);
+ $results = array_merge($array,$results);
+ }
+ else {
+ $results[] = $r['object_id'];
+ }
- } // end while
+ } // end while
- return $results;
+ return $results;
- } // get_songs
+ } // get_songs
- /**
- * get_song_count
- * This simply returns a int of how many song elements exist in this playlist
- * For now let's consider a dyn_song a single entry
- */
- public function get_song_count() {
+ /**
+ * get_song_count
+ * This simply returns a int of how many song elements exist in this playlist
+ * For now let's consider a dyn_song a single entry
+ */
+ public function get_song_count() {
- $sql = "SELECT COUNT(`id`) FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT COUNT(`id`) FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_row($db_results);
+ $results = Dba::fetch_row($db_results);
- return $results['0'];
+ return $results['0'];
- } // get_song_count
+ } // get_song_count
- /**
- * get_users
- * This returns the specified users playlists as an array of
- * playlist ids
- */
- public static function get_users($user_id) {
+ /**
+ * get_users
+ * This returns the specified users playlists as an array of
+ * playlist ids
+ */
+ public static function get_users($user_id) {
- $user_id = Dba::escape($user_id);
- $results = array();
+ $user_id = Dba::escape($user_id);
+ $results = array();
- $sql = "SELECT `id` FROM `playlist` WHERE `user`='$user_id' ORDER BY `name`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `playlist` WHERE `user`='$user_id' ORDER BY `name`";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_users
+ } // get_users
- /**
- * update
- * This function takes a key'd array of data and runs updates
- */
- public function update($data) {
+ /**
+ * update
+ * This function takes a key'd array of data and runs updates
+ */
+ public function update($data) {
- if ($data['name'] != $this->name) {
- $this->update_name($data['name']);
- }
- if ($data['pl_type'] != $this->type) {
- $this->update_type($data['pl_type']);
- }
+ if ($data['name'] != $this->name) {
+ $this->update_name($data['name']);
+ }
+ if ($data['pl_type'] != $this->type) {
+ $this->update_type($data['pl_type']);
+ }
- } // update
+ } // update
- /**
- * update_type
- * This updates the playlist type, it calls the generic update_item function
- */
- private function update_type($new_type) {
-
- if ($this->_update_item('type',$new_type,'50')) {
- $this->type = $new_type;
- }
-
- } // update_type
-
- /**
- * update_name
- * This updates the playlist name, it calls the generic update_item function
- */
- private function update_name($new_name) {
-
- if ($this->_update_item('name',$new_name,'50')) {
- $this->name = $new_name;
- }
-
- } // update_name
+ /**
+ * update_type
+ * This updates the playlist type, it calls the generic update_item function
+ */
+ private function update_type($new_type) {
+
+ if ($this->_update_item('type',$new_type,'50')) {
+ $this->type = $new_type;
+ }
+
+ } // update_type
+
+ /**
+ * update_name
+ * This updates the playlist name, it calls the generic update_item function
+ */
+ private function update_name($new_name) {
+
+ if ($this->_update_item('name',$new_name,'50')) {
+ $this->name = $new_name;
+ }
+
+ } // update_name
- /**
- * _update_item
- * This is the generic update function, it does the escaping and error checking
- */
- private function _update_item($field,$value,$level) {
+ /**
+ * _update_item
+ * This is the generic update function, it does the escaping and error checking
+ */
+ private function _update_item($field,$value,$level) {
- if ($GLOBALS['user']->id != $this->user AND !Access::check('interface',$level)) {
- return false;
- }
+ if ($GLOBALS['user']->id != $this->user AND !Access::check('interface',$level)) {
+ return false;
+ }
- $value = Dba::escape($value);
+ $value = Dba::escape($value);
- $sql = "UPDATE `playlist` SET $field='$value' WHERE `id`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `playlist` SET $field='$value' WHERE `id`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::write($sql);
- return $db_results;
+ return $db_results;
- } // update_item
+ } // update_item
- /**
- * update_track_number
- * This takes a playlist_data.id and a track (int) and updates the track value
- */
- public function update_track_number($track_id,$track) {
-
- $playlist_id = Dba::escape($this->id);
- $track_id = Dba::escape($track_id);
- $track = Dba::escape($track);
-
- $sql = "UPDATE `playlist_data` SET `track`='$track' WHERE `id`='$track_id' AND `playlist`='$playlist_id'";
- $db_results = Dba::write($sql);
-
- } // update_track_number
-
- /**
- * add_songs
- * This takes an array of song_ids and then adds it to the playlist
- * if you want to add a dyn_song you need to use the one shot function
- * add_dyn_song
- */
- public function add_songs($song_ids=array(),$ordered=false) {
-
- /* We need to pull the current 'end' track and then use that to
- * append, rather then integrate take end track # and add it to
- * $song->track add one to make sure it really is 'next'
- */
- $sql = "SELECT `track` FROM `playlist_data` WHERE `playlist`='" . $this->id . "' ORDER BY `track` DESC LIMIT 1";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_assoc($db_results);
- $base_track = $data['track'];
- debug_event('add_songs', 'Track number: '.$base_track, '5');
-
- foreach ($song_ids as $song_id) {
- /* We need the songs track */
- $song = new Song($song_id);
-
- // Based on the ordered prop we use track + base or just $i++
- if (!$ordered) {
- $track = Dba::escape($song->track+$base_track);
- }
- else {
- $i++;
- $track = Dba::escape($base_track+$i);
- }
- $id = Dba::escape($song->id);
- $pl_id = Dba::escape($this->id);
-
- /* Don't insert dead songs */
- if ($id) {
- $sql = "INSERT INTO `playlist_data` (`playlist`,`object_id`,`object_type`,`track`) " .
- " VALUES ('$pl_id','$id','song','$track')";
- $db_results = Dba::write($sql);
- } // if valid id
+ /**
+ * update_track_number
+ * This takes a playlist_data.id and a track (int) and updates the track value
+ */
+ public function update_track_number($track_id,$track) {
+
+ $playlist_id = Dba::escape($this->id);
+ $track_id = Dba::escape($track_id);
+ $track = Dba::escape($track);
+
+ $sql = "UPDATE `playlist_data` SET `track`='$track' WHERE `id`='$track_id' AND `playlist`='$playlist_id'";
+ $db_results = Dba::write($sql);
+
+ } // update_track_number
+
+ /**
+ * add_songs
+ * This takes an array of song_ids and then adds it to the playlist
+ * if you want to add a dyn_song you need to use the one shot function
+ * add_dyn_song
+ */
+ public function add_songs($song_ids=array(),$ordered=false) {
+
+ /* We need to pull the current 'end' track and then use that to
+ * append, rather then integrate take end track # and add it to
+ * $song->track add one to make sure it really is 'next'
+ */
+ $sql = "SELECT `track` FROM `playlist_data` WHERE `playlist`='" . $this->id . "' ORDER BY `track` DESC LIMIT 1";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_assoc($db_results);
+ $base_track = $data['track'];
+ debug_event('add_songs', 'Track number: '.$base_track, '5');
+
+ foreach ($song_ids as $song_id) {
+ /* We need the songs track */
+ $song = new Song($song_id);
+
+ // Based on the ordered prop we use track + base or just $i++
+ if (!$ordered) {
+ $track = Dba::escape($song->track+$base_track);
+ }
+ else {
+ $i++;
+ $track = Dba::escape($base_track+$i);
+ }
+ $id = Dba::escape($song->id);
+ $pl_id = Dba::escape($this->id);
+
+ /* Don't insert dead songs */
+ if ($id) {
+ $sql = "INSERT INTO `playlist_data` (`playlist`,`object_id`,`object_type`,`track`) " .
+ " VALUES ('$pl_id','$id','song','$track')";
+ $db_results = Dba::write($sql);
+ } // if valid id
- } // end foreach songs
+ } // end foreach songs
- } // add_songs
+ } // add_songs
- /**
- * create
- * This function creates an empty playlist, gives it a name and type
- * Assumes $GLOBALS['user']->id as the user
- */
- public static function create($name,$type) {
+ /**
+ * create
+ * This function creates an empty playlist, gives it a name and type
+ * Assumes $GLOBALS['user']->id as the user
+ */
+ public static function create($name,$type) {
- $name = Dba::escape($name);
- $type = Dba::escape($type);
- $user = Dba::escape($GLOBALS['user']->id);
- $date = time();
+ $name = Dba::escape($name);
+ $type = Dba::escape($type);
+ $user = Dba::escape($GLOBALS['user']->id);
+ $date = time();
- $sql = "INSERT INTO `playlist` (`name`,`user`,`type`,`date`) " .
- " VALUES ('$name','$user','$type','$date')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `playlist` (`name`,`user`,`type`,`date`) " .
+ " VALUES ('$name','$user','$type','$date')";
+ $db_results = Dba::write($sql);
- $insert_id = Dba::insert_id();
+ $insert_id = Dba::insert_id();
- return $insert_id;
+ return $insert_id;
- } // create
+ } // create
- /**
- * set_items
- * This calles the get_items function and sets it to $this->items which is an array in this object
- */
- function set_items() {
+ /**
+ * set_items
+ * This calles the get_items function and sets it to $this->items which is an array in this object
+ */
+ function set_items() {
- $this->items = $this->get_items();
+ $this->items = $this->get_items();
- } // set_items
+ } // set_items
- /**
- * normalize_tracks
- * this takes the crazy out of order tracks
- * and numbers them in a liner fashion, not allowing for
- * the same track # twice, this is an optional funcition
- */
- public function normalize_tracks() {
-
- /* First get all of the songs in order of their tracks */
- $sql = "SELECT `id` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track` ASC";
- $db_results = Dba::read($sql);
-
- $i = 1;
- $results = array();
+ /**
+ * normalize_tracks
+ * this takes the crazy out of order tracks
+ * and numbers them in a liner fashion, not allowing for
+ * the same track # twice, this is an optional funcition
+ */
+ public function normalize_tracks() {
+
+ /* First get all of the songs in order of their tracks */
+ $sql = "SELECT `id` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track` ASC";
+ $db_results = Dba::read($sql);
+
+ $i = 1;
+ $results = array();
- while ($r = Dba::fetch_assoc($db_results)) {
- $new_data = array();
- $new_data['id'] = $r['id'];
- $new_data['track'] = $i;
- $results[] = $new_data;
- $i++;
- } // end while results
-
- foreach($results as $data) {
- $sql = "UPDATE `playlist_data` SET `track`='" . $data['track'] . "' WHERE" .
- " `id`='" . $data['id'] . "'";
- $db_results = Dba::write($sql);
- } // foreach re-ordered results
-
- return true;
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $new_data = array();
+ $new_data['id'] = $r['id'];
+ $new_data['track'] = $i;
+ $results[] = $new_data;
+ $i++;
+ } // end while results
+
+ foreach($results as $data) {
+ $sql = "UPDATE `playlist_data` SET `track`='" . $data['track'] . "' WHERE" .
+ " `id`='" . $data['id'] . "'";
+ $db_results = Dba::write($sql);
+ } // foreach re-ordered results
+
+ return true;
- } // normalize_tracks
-
- /**
- * delete_track
- * this deletes a single track, you specify the playlist_data.id here
- */
- public function delete_track($id) {
+ } // normalize_tracks
+
+ /**
+ * delete_track
+ * this deletes a single track, you specify the playlist_data.id here
+ */
+ public function delete_track($id) {
- $this_id = Dba::escape($this->id);
- $id = Dba::escape($id);
+ $this_id = Dba::escape($this->id);
+ $id = Dba::escape($id);
- $sql = "DELETE FROM `playlist_data` WHERE `playlist_data`.`playlist`='$this_id' AND `playlist_data`.`id`='$id' LIMIT 1";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `playlist_data` WHERE `playlist_data`.`playlist`='$this_id' AND `playlist_data`.`id`='$id' LIMIT 1";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // delete_track
+ } // delete_track
- /**
- * delete
- * This deletes the current playlist and all associated data
- */
- public function delete() {
+ /**
+ * delete
+ * This deletes the current playlist and all associated data
+ */
+ public function delete() {
- $id = Dba::escape($this->id);
+ $id = Dba::escape($this->id);
- $sql = "DELETE FROM `playlist_data` WHERE `playlist` = '$id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `playlist_data` WHERE `playlist` = '$id'";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `playlist` WHERE `id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `playlist` WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `object_count` WHERE `object_type`='playlist' AND `object_id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `object_count` WHERE `object_type`='playlist' AND `object_id`='$id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // delete
+ } // delete
} // class Playlist
diff --git a/lib/class/playlist_object.abstract.php b/lib/class/playlist_object.abstract.php
index d232d6d7..5cf0bdb7 100644
--- a/lib/class/playlist_object.abstract.php
+++ b/lib/class/playlist_object.abstract.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -26,48 +26,48 @@
*/
abstract class playlist_object extends database_object {
- // Database variables
- public $id;
- public $name;
- public $user;
- public $type;
+ // Database variables
+ public $id;
+ public $name;
+ public $user;
+ public $type;
- /**
- * format
- * This takes the current playlist object and gussies it up a little
- * bit so it is presentable to the users
- */
- public function format() {
+ /**
+ * format
+ * This takes the current playlist object and gussies it up a little
+ * bit so it is presentable to the users
+ */
+ public function format() {
- $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title'));
- $this->f_type = ($this->type == 'private') ? UI::get_icon('lock', T_('Private')) : '';
+ $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title'));
+ $this->f_type = ($this->type == 'private') ? UI::get_icon('lock', T_('Private')) : '';
- $client = new User($this->user);
+ $client = new User($this->user);
- $this->f_user = $client->fullname;
+ $this->f_user = $client->fullname;
- } // format
+ } // format
- /**
- * has_access
- * This function returns true or false if the current user
- * has access to this playlist
- */
- public function has_access() {
+ /**
+ * has_access
+ * This function returns true or false if the current user
+ * has access to this playlist
+ */
+ public function has_access() {
- if (!Access::check('interface','25')) {
- return false;
- }
- if ($this->user == $GLOBALS['user']->id) {
- return true;
- }
- else {
- return Access::check('interface','100');
- }
+ if (!Access::check('interface','25')) {
+ return false;
+ }
+ if ($this->user == $GLOBALS['user']->id) {
+ return true;
+ }
+ else {
+ return Access::check('interface','100');
+ }
- return false;
+ return false;
- } // has_access
+ } // has_access
} // end playlist_object
diff --git a/lib/class/plugin.class.php b/lib/class/plugin.class.php
index 8878ba90..a2ca4891 100644
--- a/lib/class/plugin.class.php
+++ b/lib/class/plugin.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,273 +22,273 @@
class Plugin {
- /* Base Variables */
- public $name;
-
- /* constructed objects */
- public $_plugin;
-
- /**
- * Constructor
- * This constructor loads the Plugin config file which defines how to
- * install/uninstall the plugin from Ampache's database
- */
- public function __construct($name) {
-
- /* Load the plugin */
- if (!$this->_get_info($name)) {
- return false;
- }
-
- return true;
-
- } // Constructor
-
-
- /**
- * _get_info
- * This actually loads the config file for the plugin the name of the
- * class contained within the config file must be Plugin[NAME OF FILE]
- */
- public function _get_info($name) {
-
- /* Require the file we want */
- require_once Config::get('prefix') . '/modules/plugins/' . $name . '.plugin.php';
-
- $plugin_name = "Ampache$name";
-
- $this->_plugin = new $plugin_name();
-
- if (!$this->is_valid()) {
- return false;
- }
-
- return true;
-
- } // _get_info
-
- /**
- * get_plugins
- * This returns an array of plugin names
- */
- public static function get_plugins($type='') {
-
- $results = array();
-
- // Open up the plugin dir
- $handle = opendir(Config::get('prefix') . '/modules/plugins');
-
- if (!is_resource($handle)) {
- debug_event('Plugins','Unable to read plugins directory','1');
- }
-
- // Recurse the directory
- while ($file = readdir($handle)) {
- // Ignore non-plugin files
- if (substr($file,-10,10) != 'plugin.php') { continue; }
- if (is_dir($file)) { continue; }
- $plugin_name = basename($file,'.plugin.php');
- if ($type != '') {
- $plugin = new Plugin($plugin_name);
- if (! Plugin::is_installed($plugin->_plugin->name)) {
- debug_event('Plugins', 'Plugin ' . $plugin->_plugin->name . ' is not installed, skipping', 5);
- continue;
- }
- if (! $plugin->is_valid()) {
- debug_event('Plugins', 'Plugin ' . $plugin_name . ' is not valid, skipping', 5);
- continue;
- }
- if (! method_exists($plugin->_plugin, $type)) {
- debug_event('Plugins', 'Plugin ' . $plugin_name . ' does not support ' . $type . ', skipping', 5);
- continue;
- }
- }
- // It's a plugin record it
- $results[$plugin_name] = $plugin_name;
- } // end while
-
- // Little stupid but hey
- ksort($results);
-
- return $results;
-
- } // get_plugins
-
- /**
- * is_valid
- * This checks to make sure the plugin has the required functions and
- * settings. Ampache requires public variables name, description, and
- * version (as an int), and methods install, uninstall, and load. We
- * also check that Ampache's database version falls within the min/max
- * version specified by the plugin.
- */
- function is_valid() {
-
- /* Check the plugin to make sure it's got the needed vars */
- if (!strlen($this->_plugin->name)) {
- return false;
- }
- if (!strlen($this->_plugin->description)) {
- return false;
- }
- if (!strlen($this->_plugin->version)) {
- return false;
- }
-
- /* Make sure we've got the required methods */
- if (!method_exists($this->_plugin,'install')) {
- return false;
- }
-
- if (!method_exists($this->_plugin,'uninstall')) {
- return false;
- }
-
- if (!method_exists($this->_plugin,'load')) {
- return false;
- }
-
- /* Make sure it's within the version confines */
- $db_version = $this->get_ampache_db_version();
-
- if ($db_version < $this->_plugin->min_ampache) {
- return false;
- }
-
- if ($db_version > $this->_plugin->max_ampache) {
- return false;
- }
-
- // We've passed all of the tests
- return true;
-
- } // is_valid
-
- /**
- * is_installed
- * This checks to see if the specified plugin is currently installed in
- * the database, it doesn't check the files for integrity
- */
- public static function is_installed($plugin_name) {
-
- /* All we do is check the version */
- return self::get_plugin_version($plugin_name);
-
- } // is_installed
-
- /**
- * install
- * This runs the install function of the plugin and inserts a row into
- * the update_info table to indicate that it's installed.
- */
- public function install() {
- if ($this->_plugin->install() &&
- $this->set_plugin_version($this->_plugin->version)) {
- return true;
- }
-
- return false;
- } // install
-
- /**
- * uninstall
- * This runs the uninstall function of the plugin and removes the row
- * from the update_info table to indicate that it isn't installed.
- */
- public function uninstall() {
-
- $this->_plugin->uninstall();
-
- $this->remove_plugin_version();
-
- } // uninstall
-
- /**
- * upgrade
- * This runs the upgrade function of the plugin (if it exists) and
- * updates the database to indicate our new version.
- */
- public function upgrade() {
- if (method_exists($this->_plugin, 'upgrade')) {
- if($this->_plugin->upgrade()) {
- $this->set_plugin_version($this->_plugin->version);
- }
- }
- } // upgrade
-
- /**
- * load
- * This calls the plugin's load function
- */
- public function load() {
- $GLOBALS['user']->set_preferences();
- return $this->_plugin->load();
- }
-
- /**
- * get_plugin_version
- * This returns the version of the specified plugin
- */
- public static function get_plugin_version($plugin_name) {
+ /* Base Variables */
+ public $name;
+
+ /* constructed objects */
+ public $_plugin;
+
+ /**
+ * Constructor
+ * This constructor loads the Plugin config file which defines how to
+ * install/uninstall the plugin from Ampache's database
+ */
+ public function __construct($name) {
+
+ /* Load the plugin */
+ if (!$this->_get_info($name)) {
+ return false;
+ }
+
+ return true;
+
+ } // Constructor
+
+
+ /**
+ * _get_info
+ * This actually loads the config file for the plugin the name of the
+ * class contained within the config file must be Plugin[NAME OF FILE]
+ */
+ public function _get_info($name) {
+
+ /* Require the file we want */
+ require_once Config::get('prefix') . '/modules/plugins/' . $name . '.plugin.php';
+
+ $plugin_name = "Ampache$name";
+
+ $this->_plugin = new $plugin_name();
+
+ if (!$this->is_valid()) {
+ return false;
+ }
+
+ return true;
+
+ } // _get_info
+
+ /**
+ * get_plugins
+ * This returns an array of plugin names
+ */
+ public static function get_plugins($type='') {
+
+ $results = array();
+
+ // Open up the plugin dir
+ $handle = opendir(Config::get('prefix') . '/modules/plugins');
+
+ if (!is_resource($handle)) {
+ debug_event('Plugins','Unable to read plugins directory','1');
+ }
+
+ // Recurse the directory
+ while ($file = readdir($handle)) {
+ // Ignore non-plugin files
+ if (substr($file,-10,10) != 'plugin.php') { continue; }
+ if (is_dir($file)) { continue; }
+ $plugin_name = basename($file,'.plugin.php');
+ if ($type != '') {
+ $plugin = new Plugin($plugin_name);
+ if (! Plugin::is_installed($plugin->_plugin->name)) {
+ debug_event('Plugins', 'Plugin ' . $plugin->_plugin->name . ' is not installed, skipping', 5);
+ continue;
+ }
+ if (! $plugin->is_valid()) {
+ debug_event('Plugins', 'Plugin ' . $plugin_name . ' is not valid, skipping', 5);
+ continue;
+ }
+ if (! method_exists($plugin->_plugin, $type)) {
+ debug_event('Plugins', 'Plugin ' . $plugin_name . ' does not support ' . $type . ', skipping', 5);
+ continue;
+ }
+ }
+ // It's a plugin record it
+ $results[$plugin_name] = $plugin_name;
+ } // end while
+
+ // Little stupid but hey
+ ksort($results);
+
+ return $results;
+
+ } // get_plugins
+
+ /**
+ * is_valid
+ * This checks to make sure the plugin has the required functions and
+ * settings. Ampache requires public variables name, description, and
+ * version (as an int), and methods install, uninstall, and load. We
+ * also check that Ampache's database version falls within the min/max
+ * version specified by the plugin.
+ */
+ function is_valid() {
+
+ /* Check the plugin to make sure it's got the needed vars */
+ if (!strlen($this->_plugin->name)) {
+ return false;
+ }
+ if (!strlen($this->_plugin->description)) {
+ return false;
+ }
+ if (!strlen($this->_plugin->version)) {
+ return false;
+ }
+
+ /* Make sure we've got the required methods */
+ if (!method_exists($this->_plugin,'install')) {
+ return false;
+ }
+
+ if (!method_exists($this->_plugin,'uninstall')) {
+ return false;
+ }
+
+ if (!method_exists($this->_plugin,'load')) {
+ return false;
+ }
+
+ /* Make sure it's within the version confines */
+ $db_version = $this->get_ampache_db_version();
+
+ if ($db_version < $this->_plugin->min_ampache) {
+ return false;
+ }
+
+ if ($db_version > $this->_plugin->max_ampache) {
+ return false;
+ }
+
+ // We've passed all of the tests
+ return true;
+
+ } // is_valid
+
+ /**
+ * is_installed
+ * This checks to see if the specified plugin is currently installed in
+ * the database, it doesn't check the files for integrity
+ */
+ public static function is_installed($plugin_name) {
+
+ /* All we do is check the version */
+ return self::get_plugin_version($plugin_name);
+
+ } // is_installed
+
+ /**
+ * install
+ * This runs the install function of the plugin and inserts a row into
+ * the update_info table to indicate that it's installed.
+ */
+ public function install() {
+ if ($this->_plugin->install() &&
+ $this->set_plugin_version($this->_plugin->version)) {
+ return true;
+ }
+
+ return false;
+ } // install
+
+ /**
+ * uninstall
+ * This runs the uninstall function of the plugin and removes the row
+ * from the update_info table to indicate that it isn't installed.
+ */
+ public function uninstall() {
+
+ $this->_plugin->uninstall();
+
+ $this->remove_plugin_version();
+
+ } // uninstall
+
+ /**
+ * upgrade
+ * This runs the upgrade function of the plugin (if it exists) and
+ * updates the database to indicate our new version.
+ */
+ public function upgrade() {
+ if (method_exists($this->_plugin, 'upgrade')) {
+ if($this->_plugin->upgrade()) {
+ $this->set_plugin_version($this->_plugin->version);
+ }
+ }
+ } // upgrade
+
+ /**
+ * load
+ * This calls the plugin's load function
+ */
+ public function load() {
+ $GLOBALS['user']->set_preferences();
+ return $this->_plugin->load();
+ }
+
+ /**
+ * get_plugin_version
+ * This returns the version of the specified plugin
+ */
+ public static function get_plugin_version($plugin_name) {
- $name = Dba::escape('Plugin_' . $plugin_name);
+ $name = Dba::escape('Plugin_' . $plugin_name);
- $sql = "SELECT * FROM `update_info` WHERE `key`='$name'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `update_info` WHERE `key`='$name'";
+ $db_results = Dba::read($sql);
- if ($results = Dba::fetch_assoc($db_results)) {
- return $results['value'];
- }
+ if ($results = Dba::fetch_assoc($db_results)) {
+ return $results['value'];
+ }
- return false;
+ return false;
- } // get_plugin_version
+ } // get_plugin_version
- /**
- * get_ampache_db_version
- * This function returns the Ampache database version
- */
- function get_ampache_db_version() {
+ /**
+ * get_ampache_db_version
+ * This function returns the Ampache database version
+ */
+ function get_ampache_db_version() {
- $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- return $results['value'];
+ return $results['value'];
- } // get_ampache_db_version
+ } // get_ampache_db_version
- /**
- * set_plugin_version
- * This sets the plugin version in the update_info table
- */
- public function set_plugin_version($version) {
+ /**
+ * set_plugin_version
+ * This sets the plugin version in the update_info table
+ */
+ public function set_plugin_version($version) {
- $name = Dba::escape('Plugin_' . $this->_plugin->name);
- $version = Dba::escape($version);
+ $name = Dba::escape('Plugin_' . $this->_plugin->name);
+ $version = Dba::escape($version);
- $sql = "REPLACE INTO `update_info` SET `key`='$name', `value`='$version'";
- $db_results = Dba::read($sql);
+ $sql = "REPLACE INTO `update_info` SET `key`='$name', `value`='$version'";
+ $db_results = Dba::read($sql);
- return true;
+ return true;
- } // set_plugin_version
+ } // set_plugin_version
- /**
- * remove_plugin_version
- * This removes the version row from the db done on uninstall
- */
- public function remove_plugin_version() {
+ /**
+ * remove_plugin_version
+ * This removes the version row from the db done on uninstall
+ */
+ public function remove_plugin_version() {
- $name = Dba::escape('Plugin_' . $this->_plugin->name);
+ $name = Dba::escape('Plugin_' . $this->_plugin->name);
- $sql = "DELETE FROM `update_info` WHERE `key`='$name'";
- $db_results = Dba::read($sql);
+ $sql = "DELETE FROM `update_info` WHERE `key`='$name'";
+ $db_results = Dba::read($sql);
- return true;
+ return true;
- } // remove_plugin_version
+ } // remove_plugin_version
} //end plugin class
?>
diff --git a/lib/class/preference.class.php b/lib/class/preference.class.php
index e342e65a..2515b750 100644
--- a/lib/class/preference.class.php
+++ b/lib/class/preference.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -29,419 +29,419 @@
*/
class Preference {
- /**
- * __constructor
- * This does nothing... amazing isn't it!
- */
- private function __construct() {
-
- // Rien a faire
-
- } // __construct
-
- /**
- * update
- * This updates a single preference from the given name or id
- */
- public static function update($preference,$user_id,$value,$applytoall='') {
-
- // First prepare
- if (!is_numeric($preference)) {
- $id = self::id_from_name($preference);
- $name = $preference;
- }
- else {
- $name = self::name_from_id($preference);
- $id = $preference;
- }
- if ($applytoall AND Access::check('interface','100')) {
- $user_check = "";
- }
- else {
- $user_check = " AND `user`='$user_id'";
- }
-
- // Now do
- if (self::has_access($name)) {
- $value = Dba::escape($value);
- $user_id = Dba::escape($user_id);
- $sql = "UPDATE `user_preference` SET `value`='$value' " .
- "WHERE `preference`='$id'$user_check";
- $db_results = Dba::write($sql);
- Preference::clear_from_session();
- return true;
- }
- else {
- debug_event('denied',$GLOBALS['user']->username . ' attempted to update ' . $name . ' but does not have sufficient permissions','3');
- }
+ /**
+ * __constructor
+ * This does nothing... amazing isn't it!
+ */
+ private function __construct() {
+
+ // Rien a faire
+
+ } // __construct
+
+ /**
+ * update
+ * This updates a single preference from the given name or id
+ */
+ public static function update($preference,$user_id,$value,$applytoall='') {
+
+ // First prepare
+ if (!is_numeric($preference)) {
+ $id = self::id_from_name($preference);
+ $name = $preference;
+ }
+ else {
+ $name = self::name_from_id($preference);
+ $id = $preference;
+ }
+ if ($applytoall AND Access::check('interface','100')) {
+ $user_check = "";
+ }
+ else {
+ $user_check = " AND `user`='$user_id'";
+ }
+
+ // Now do
+ if (self::has_access($name)) {
+ $value = Dba::escape($value);
+ $user_id = Dba::escape($user_id);
+ $sql = "UPDATE `user_preference` SET `value`='$value' " .
+ "WHERE `preference`='$id'$user_check";
+ $db_results = Dba::write($sql);
+ Preference::clear_from_session();
+ return true;
+ }
+ else {
+ debug_event('denied',$GLOBALS['user']->username . ' attempted to update ' . $name . ' but does not have sufficient permissions','3');
+ }
- return false;
- } // update
-
- /**
- * update_level
- * This takes a preference ID and updates the level required to update it (performed by an admin)
- */
- public static function update_level($preference,$level) {
-
- // First prepare
- if (!is_numeric($preference)) {
- $preference_id = self::id_from_name($preference);
- }
- else {
- $preference_id = $preference;
- }
+ return false;
+ } // update
+
+ /**
+ * update_level
+ * This takes a preference ID and updates the level required to update it (performed by an admin)
+ */
+ public static function update_level($preference,$level) {
+
+ // First prepare
+ if (!is_numeric($preference)) {
+ $preference_id = self::id_from_name($preference);
+ }
+ else {
+ $preference_id = $preference;
+ }
- $preference_id = Dba::escape($preference_id);
- $level = Dba::escape($level);
+ $preference_id = Dba::escape($preference_id);
+ $level = Dba::escape($level);
- $sql = "UPDATE `preference` SET `level`='$level' WHERE `id`='$preference_id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `level`='$level' WHERE `id`='$preference_id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // update_level
+ } // update_level
- /**
- * update_all
- * This takes a preference id and a value and updates all users with the new info
- */
- public static function update_all($preference_id,$value) {
+ /**
+ * update_all
+ * This takes a preference id and a value and updates all users with the new info
+ */
+ public static function update_all($preference_id,$value) {
- $preference_id = Dba::escape($preference_id);
- $value = Dba::escape($value);
+ $preference_id = Dba::escape($preference_id);
+ $value = Dba::escape($value);
- $sql = "UPDATE `user_preference` SET `value`='$value' WHERE `preference`='$preference_id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `user_preference` SET `value`='$value' WHERE `preference`='$preference_id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // update_all
+ } // update_all
- /**
- * exists
- * This just checks to see if a preference currently exists
- */
- public static function exists($preference) {
+ /**
+ * exists
+ * This just checks to see if a preference currently exists
+ */
+ public static function exists($preference) {
- // We assume it's the name
- $name = Dba::escape($preference);
- $sql = "SELECT * FROM `preference` WHERE `name`='$name'";
- $db_results = Dba::read($sql);
+ // We assume it's the name
+ $name = Dba::escape($preference);
+ $sql = "SELECT * FROM `preference` WHERE `name`='$name'";
+ $db_results = Dba::read($sql);
- return Dba::num_rows($db_results);
+ return Dba::num_rows($db_results);
- } // exists
+ } // exists
- /**
- * has_access
- * This checks to see if the current user has access to modify this preference
- * as defined by the preference name
- */
- public static function has_access($preference) {
+ /**
+ * has_access
+ * This checks to see if the current user has access to modify this preference
+ * as defined by the preference name
+ */
+ public static function has_access($preference) {
- // Nothing for those demo thugs
- if (Config::get('demo_mode')) { return false; }
+ // Nothing for those demo thugs
+ if (Config::get('demo_mode')) { return false; }
- $preference = Dba::escape($preference);
+ $preference = Dba::escape($preference);
- $sql = "SELECT `level` FROM `preference` WHERE `name`='$preference'";
- $db_results = Dba::read($sql);
- $data = Dba::fetch_assoc($db_results);
+ $sql = "SELECT `level` FROM `preference` WHERE `name`='$preference'";
+ $db_results = Dba::read($sql);
+ $data = Dba::fetch_assoc($db_results);
- if (Access::check('interface',$data['level'])) {
- return true;
- }
+ if (Access::check('interface',$data['level'])) {
+ return true;
+ }
- return false;
+ return false;
- } // has_access
+ } // has_access
- /**
- * id_from_name
- * This takes a name and returns the id
- */
- public static function id_from_name($name) {
+ /**
+ * id_from_name
+ * This takes a name and returns the id
+ */
+ public static function id_from_name($name) {
- $name = Dba::escape($name);
+ $name = Dba::escape($name);
- $sql = "SELECT `id` FROM `preference` WHERE `name`='$name'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `preference` WHERE `name`='$name'";
+ $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- return $row['id'];
+ return $row['id'];
- } // id_from_name
+ } // id_from_name
- /**
- * name_from_id
- * This returns the name from an id, it's the exact opposite
- * of the function above it, amazing!
- */
- public static function name_from_id($id) {
+ /**
+ * name_from_id
+ * This returns the name from an id, it's the exact opposite
+ * of the function above it, amazing!
+ */
+ public static function name_from_id($id) {
- $id = Dba::escape($id);
+ $id = Dba::escape($id);
- $sql = "SELECT `name` FROM `preference` WHERE `id`='$id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `name` FROM `preference` WHERE `id`='$id'";
+ $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- return $row['name'];
+ return $row['name'];
- } // name_from_id
+ } // name_from_id
- /**
- * get_catagories
- * This returns an array of the names of the different possible sections
- * it ignores the 'internal' catagory
- */
- public static function get_catagories() {
+ /**
+ * get_catagories
+ * This returns an array of the names of the different possible sections
+ * it ignores the 'internal' catagory
+ */
+ public static function get_catagories() {
- $sql = "SELECT `preference`.`catagory` FROM `preference` GROUP BY `catagory` ORDER BY `catagory`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `preference`.`catagory` FROM `preference` GROUP BY `catagory` ORDER BY `catagory`";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- if ($row['catagory'] != 'internal') {
- $results[] = $row['catagory'];
- }
- } // end while
+ while ($row = Dba::fetch_assoc($db_results)) {
+ if ($row['catagory'] != 'internal') {
+ $results[] = $row['catagory'];
+ }
+ } // end while
- return $results;
+ return $results;
- } // get_catagories
+ } // get_catagories
- /**
- * get_all
- * This returns a nice flat array of all of the possible preferences for the specified user
- */
- public static function get_all($user_id) {
+ /**
+ * get_all
+ * This returns a nice flat array of all of the possible preferences for the specified user
+ */
+ public static function get_all($user_id) {
- $user_id = Dba::escape($user_id);
+ $user_id = Dba::escape($user_id);
- if ($user_id != '-1') {
- $user_limit = "AND `preference`.`catagory` != 'system'";
- }
+ if ($user_id != '-1') {
+ $user_limit = "AND `preference`.`catagory` != 'system'";
+ }
- $sql = "SELECT `preference`.`name`,`preference`.`description`,`user_preference`.`value` FROM `preference` " .
- " INNER JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` " .
- " WHERE `user_preference`.`user`='$user_id' AND `preference`.`catagory` != 'internal' $user_limit " .
- " ORDER BY `preference`.`description`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `preference`.`name`,`preference`.`description`,`user_preference`.`value` FROM `preference` " .
+ " INNER JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` " .
+ " WHERE `user_preference`.`user`='$user_id' AND `preference`.`catagory` != 'internal' $user_limit " .
+ " ORDER BY `preference`.`description`";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = array('name'=>$row['name'],'level'=>$row['level'],'description'=>$row['description'],'value'=>$row['value']);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = array('name'=>$row['name'],'level'=>$row['level'],'description'=>$row['description'],'value'=>$row['value']);
+ }
- return $results;
+ return $results;
- } // get_all
+ } // get_all
- /**
- * insert
- * This inserts a new preference into the preference table
- * it does NOT sync up the users, that should be done independtly
- */
- public static function insert($name,$description,$default,$level,$type,$catagory) {
+ /**
+ * insert
+ * This inserts a new preference into the preference table
+ * it does NOT sync up the users, that should be done independtly
+ */
+ public static function insert($name,$description,$default,$level,$type,$catagory) {
- // Clean em up
- $name = Dba::escape($name);
- $description = Dba::escape($description);
- $default = Dba::escape($default);
- $level = Dba::escape($level);
- $type = Dba::escape($type);
- $catagory = Dba::escape($catagory);
+ // Clean em up
+ $name = Dba::escape($name);
+ $description = Dba::escape($description);
+ $default = Dba::escape($default);
+ $level = Dba::escape($level);
+ $type = Dba::escape($type);
+ $catagory = Dba::escape($catagory);
- $sql = "INSERT INTO `preference` (`name`,`description`,`value`,`level`,`type`,`catagory`) " .
- "VALUES ('$name','$description','$default','$level','$type','$catagory')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `preference` (`name`,`description`,`value`,`level`,`type`,`catagory`) " .
+ "VALUES ('$name','$description','$default','$level','$type','$catagory')";
+ $db_results = Dba::write($sql);
- if (!$db_results) { return false; }
+ if (!$db_results) { return false; }
- return true;
+ return true;
- } // insert
+ } // insert
- /**
- * delete
- * This deletes the specified preference, a name or a ID can be passed
- */
- public static function delete($preference) {
+ /**
+ * delete
+ * This deletes the specified preference, a name or a ID can be passed
+ */
+ public static function delete($preference) {
- // First prepare
- if (!is_numeric($preference)) {
- $name = Dba::escape($preference);
- $sql = "DELETE FROM `preference` WHERE `name`='$name'";
- }
- else {
- $id = Dba::escape($preference);
- $sql = "DELETE FROM `preference` WHERE `id`='$id'";
- }
-
- $db_results = Dba::write($sql);
-
- self::rebuild_preferences();
-
- } // delete
-
- /**
- * rename
- * This renames a preference in the database
- */
- public static function rename($old, $new) {
- $old = Dba::escape($old);
- $new = Dba::escape($new);
-
- $sql = "UPDATE `preference` SET `name`='$new' WHERE `name`='$old'";
- $db_results = Dba::write($sql);
- }
-
- /**
- * rebuild_preferences
- * This removes any garbage and then adds back in anything missing preferences wise
- */
- public static function rebuild_preferences() {
-
- // First remove garbage
- $sql = "DELETE FROM `user_preference` USING `user_preference` LEFT JOIN `preference` ON `preference`.`id`=`user_preference`.`preference` " .
- "WHERE `preference`.`id` IS NULL";
- $db_results = Dba::write($sql);
-
- // Now add anything that we are missing back in, except System
- $sql = "SELECT * FROM `preference` WHERE `type`!='system'";
- //FIXME: Uhh WTF shouldn't there be something here??
-
- } // rebuild_preferences
-
- /**
- * fix_preferences
- * This takes the preferences, explodes what needs to
- * become an array and boolean everythings
- */
- public static function fix_preferences($results) {
- $arrays = array('auth_methods', 'getid3_tag_order',
- 'metadata_order', 'art_order', 'amazon_base_urls');
-
- foreach ($arrays as $item) {
- $results[$item] = trim($results[$item])
- ? explode(',', $results[$item])
- : array();
- }
-
- foreach ($results as $key=>$data) {
- if (!is_array($data)) {
- if (strcasecmp($data,"true") == "0") { $results[$key] = 1; }
- if (strcasecmp($data,"false") == "0") { $results[$key] = 0; }
- }
- }
-
- return $results;
-
- } // fix_preferences
-
- /**
- * load_from_session
- * This loads the preferences from the session rather then creating a connection to the database
- */
- public static function load_from_session($uid=-1) {
-
- if (is_array($_SESSION['userdata']['preferences']) AND $_SESSION['userdata']['uid'] == $uid) {
- Config::set_by_array($_SESSION['userdata']['preferences'], true);
- return true;
- }
-
- return false;
-
- } // load_from_session
-
- /**
- * clear_from_session
- * This clears the users preferences, this is done whenever modifications are made to the preferences
- * or the admin resets something
- */
- public static function clear_from_session() {
-
- unset($_SESSION['userdata']['preferences']);
-
- } // clear_from_session
-
- /**
- * is_boolean
- * This returns true / false if the preference in question is a boolean preference
- * This is currently only used by the debug view, could be used other places.. wouldn't be a half
- * bad idea
- */
- public static function is_boolean($key) {
-
- $boolean_array = array('session_cookiesecure','require_session',
- 'access_control','require_localnet_session',
- 'downsample_remote','track_user_ip',
- 'xml_rpc','allow_zip_download',
- 'file_zip_download','ratings',
- 'shoutbox','resize_images',
- 'show_album_art','allow_public_registration',
- 'captcha_public_reg','admin_notify_reg',
- 'use_rss','download','force_http_play','cookie_secure',
- 'allow_stream_playback','allow_democratic_playback',
- 'use_auth','allow_localplay_playback','debug','lock_songs',
- 'transcode_m4a','transcode_mp3','transcode_ogg','transcode_flac',
- 'shoutcast_active','httpq_active','show_lyrics');
-
- if (in_array($key,$boolean_array)) {
- return true;
- }
-
- return false;
-
- } // is_boolean
-
- /**
- * init
- * This grabs the preferences and then loads them into conf it should be run on page load
- * to initialize the needed variables
- */
- public static function init() {
-
- $user_id = $GLOBALS['user']->id ? Dba::escape($GLOBALS['user']->id) : '-1';
-
- // First go ahead and try to load it from the preferences
- if (self::load_from_session($user_id)) {
- return true;
- }
-
- /* Get Global Preferences */
- $sql = "SELECT `preference`.`name`,`user_preference`.`value`,`syspref`.`value` AS `system_value` FROM `preference` " .
- "LEFT JOIN `user_preference` `syspref` ON `syspref`.`preference`=`preference`.`id` AND `syspref`.`user`='-1' AND `preference`.`catagory`='system' " .
- "LEFT JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` AND `user_preference`.`user`='$user_id' AND `preference`.`catagory`!='system'";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $value = $row['system_value'] ? $row['system_value'] : $row['value'];
- $name = $row['name'];
- $results[$name] = $value;
- } // end while sys prefs
-
- /* Set the Theme mojo */
- if (strlen($results['theme_name']) > 0) {
- $results['theme_path'] = '/themes/' . $results['theme_name'];
- }
- // Default to the classic theme if we don't get anything from their
- // preferenecs because we're going to want at least something otherwise
- // the page is going to be really ugly
- else {
- $results['theme_path'] = '/themes/classic';
- }
-
- Config::set_by_array($results, true);
- $_SESSION['userdata']['preferences'] = $results;
- $_SESSION['userdata']['uid'] = $user_id;
-
- } // init
+ // First prepare
+ if (!is_numeric($preference)) {
+ $name = Dba::escape($preference);
+ $sql = "DELETE FROM `preference` WHERE `name`='$name'";
+ }
+ else {
+ $id = Dba::escape($preference);
+ $sql = "DELETE FROM `preference` WHERE `id`='$id'";
+ }
+
+ $db_results = Dba::write($sql);
+
+ self::rebuild_preferences();
+
+ } // delete
+
+ /**
+ * rename
+ * This renames a preference in the database
+ */
+ public static function rename($old, $new) {
+ $old = Dba::escape($old);
+ $new = Dba::escape($new);
+
+ $sql = "UPDATE `preference` SET `name`='$new' WHERE `name`='$old'";
+ $db_results = Dba::write($sql);
+ }
+
+ /**
+ * rebuild_preferences
+ * This removes any garbage and then adds back in anything missing preferences wise
+ */
+ public static function rebuild_preferences() {
+
+ // First remove garbage
+ $sql = "DELETE FROM `user_preference` USING `user_preference` LEFT JOIN `preference` ON `preference`.`id`=`user_preference`.`preference` " .
+ "WHERE `preference`.`id` IS NULL";
+ $db_results = Dba::write($sql);
+
+ // Now add anything that we are missing back in, except System
+ $sql = "SELECT * FROM `preference` WHERE `type`!='system'";
+ //FIXME: Uhh WTF shouldn't there be something here??
+
+ } // rebuild_preferences
+
+ /**
+ * fix_preferences
+ * This takes the preferences, explodes what needs to
+ * become an array and boolean everythings
+ */
+ public static function fix_preferences($results) {
+ $arrays = array('auth_methods', 'getid3_tag_order',
+ 'metadata_order', 'art_order', 'amazon_base_urls');
+
+ foreach ($arrays as $item) {
+ $results[$item] = trim($results[$item])
+ ? explode(',', $results[$item])
+ : array();
+ }
+
+ foreach ($results as $key=>$data) {
+ if (!is_array($data)) {
+ if (strcasecmp($data,"true") == "0") { $results[$key] = 1; }
+ if (strcasecmp($data,"false") == "0") { $results[$key] = 0; }
+ }
+ }
+
+ return $results;
+
+ } // fix_preferences
+
+ /**
+ * load_from_session
+ * This loads the preferences from the session rather then creating a connection to the database
+ */
+ public static function load_from_session($uid=-1) {
+
+ if (is_array($_SESSION['userdata']['preferences']) AND $_SESSION['userdata']['uid'] == $uid) {
+ Config::set_by_array($_SESSION['userdata']['preferences'], true);
+ return true;
+ }
+
+ return false;
+
+ } // load_from_session
+
+ /**
+ * clear_from_session
+ * This clears the users preferences, this is done whenever modifications are made to the preferences
+ * or the admin resets something
+ */
+ public static function clear_from_session() {
+
+ unset($_SESSION['userdata']['preferences']);
+
+ } // clear_from_session
+
+ /**
+ * is_boolean
+ * This returns true / false if the preference in question is a boolean preference
+ * This is currently only used by the debug view, could be used other places.. wouldn't be a half
+ * bad idea
+ */
+ public static function is_boolean($key) {
+
+ $boolean_array = array('session_cookiesecure','require_session',
+ 'access_control','require_localnet_session',
+ 'downsample_remote','track_user_ip',
+ 'xml_rpc','allow_zip_download',
+ 'file_zip_download','ratings',
+ 'shoutbox','resize_images',
+ 'show_album_art','allow_public_registration',
+ 'captcha_public_reg','admin_notify_reg',
+ 'use_rss','download','force_http_play','cookie_secure',
+ 'allow_stream_playback','allow_democratic_playback',
+ 'use_auth','allow_localplay_playback','debug','lock_songs',
+ 'transcode_m4a','transcode_mp3','transcode_ogg','transcode_flac',
+ 'shoutcast_active','httpq_active','show_lyrics');
+
+ if (in_array($key,$boolean_array)) {
+ return true;
+ }
+
+ return false;
+
+ } // is_boolean
+
+ /**
+ * init
+ * This grabs the preferences and then loads them into conf it should be run on page load
+ * to initialize the needed variables
+ */
+ public static function init() {
+
+ $user_id = $GLOBALS['user']->id ? Dba::escape($GLOBALS['user']->id) : '-1';
+
+ // First go ahead and try to load it from the preferences
+ if (self::load_from_session($user_id)) {
+ return true;
+ }
+
+ /* Get Global Preferences */
+ $sql = "SELECT `preference`.`name`,`user_preference`.`value`,`syspref`.`value` AS `system_value` FROM `preference` " .
+ "LEFT JOIN `user_preference` `syspref` ON `syspref`.`preference`=`preference`.`id` AND `syspref`.`user`='-1' AND `preference`.`catagory`='system' " .
+ "LEFT JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` AND `user_preference`.`user`='$user_id' AND `preference`.`catagory`!='system'";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $value = $row['system_value'] ? $row['system_value'] : $row['value'];
+ $name = $row['name'];
+ $results[$name] = $value;
+ } // end while sys prefs
+
+ /* Set the Theme mojo */
+ if (strlen($results['theme_name']) > 0) {
+ $results['theme_path'] = '/themes/' . $results['theme_name'];
+ }
+ // Default to the classic theme if we don't get anything from their
+ // preferenecs because we're going to want at least something otherwise
+ // the page is going to be really ugly
+ else {
+ $results['theme_path'] = '/themes/classic';
+ }
+
+ Config::set_by_array($results, true);
+ $_SESSION['userdata']['preferences'] = $results;
+ $_SESSION['userdata']['uid'] = $user_id;
+
+ } // init
} // end Preference class
diff --git a/lib/class/query.class.php b/lib/class/query.class.php
index ea451a45..84729b8f 100644
--- a/lib/class/query.class.php
+++ b/lib/class/query.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,1421 +30,1421 @@
*/
class Query {
- public $id;
- public $catalog;
-
- protected $_state = array();
- protected $_cache;
-
- private static $allowed_filters;
- private static $allowed_sorts;
-
- /**
- * constructor
- * This should be called
- */
- public function __construct($id = null) {
- $sid = Dba::escape(session_id());
-
- if (is_null($id)) {
- $this->reset();
- $data = Dba::escape(serialize($this->_state));
-
- $sql = "INSERT INTO `tmp_browse` (`sid`, `data`) " .
- "VALUES('$sid', '$data')";
- $db_results = Dba::write($sql);
- $this->id = Dba::insert_id();
-
- return true;
- }
-
- $this->id = $id;
-
- $sql = "SELECT `data` FROM `tmp_browse` " .
- "WHERE `id`='$id' AND `sid`='$sid'";
-
- $db_results = Dba::read($sql);
-
- if ($results = Dba::fetch_assoc($db_results)) {
- $this->_state = unserialize($results['data']);
- return true;
- }
-
- Error::add('browse', T_('Browse not found or expired, try reloading the page'));
- return false;
- }
-
- /**
- * _auto_init
- * Automatically called when the class is loaded.
- * Populate static arrays if necessary
- */
- public static function _auto_init() {
- if (is_array(self::$allowed_filters)) {
- return true;
- }
-
- self::$allowed_filters = array(
- 'album' => array(
- 'add_lt',
- 'add_gt',
- 'update_lt',
- 'update_gt',
- 'show_art',
- 'starts_with',
- 'exact_match',
- 'alpha_match',
- 'catalog'
- ),
- 'artist' => array(
- 'add_lt',
- 'add_gt',
- 'update_lt',
- 'update_gt',
- 'exact_match',
- 'alpha_match',
- 'starts_with',
- 'tag',
- 'catalog'
- ),
- 'song' => array(
- 'add_lt',
- 'add_gt',
- 'update_lt',
- 'update_gt',
- 'exact_match',
- 'alpha_match',
- 'starts_with',
- 'tag',
- 'catalog'
- ),
- 'live_stream' => array(
- 'alpha_match',
- 'starts_with'
- ),
- 'playlist' => array(
- 'alpha_match',
- 'starts_with'
- ),
- 'smartplaylist' => array(
- 'alpha_match',
- 'starts_with'
- ),
- 'tag' => array(
- 'tag',
- 'object_type',
- 'exact_match',
- 'alpha_match'
- ),
- 'video' => array(
- 'starts_with',
- 'exact_match',
- 'alpha_match'
- )
- );
-
- if (Access::check('interface','50')) {
- array_push(self::$allowed_filters['playlist'], 'playlist_type');
- }
-
- self::$allowed_sorts = array(
- 'playlist_song' => array(
- 'title',
- 'year',
- 'track',
- 'time',
- 'album',
- 'artist'
- ),
- 'song' => array(
- 'title',
- 'year',
- 'track',
- 'time',
- 'album',
- 'artist'
- ),
- 'artist' => array(
- 'name',
- 'album'
- ),
- 'tag' => array(
- 'tag'
- ),
- 'album' => array(
- 'name',
- 'year',
- 'artist'
- ),
- 'playlist' => array(
- 'name',
- 'user'
- ),
- 'smartplaylist' => array(
- 'name',
- 'user'
- ),
- 'shoutbox' => array(
- 'date',
- 'user',
- 'sticky'
- ),
- 'live_stream' => array(
- 'name',
- 'call_sign',
- 'frequency'
- ),
- 'video' => array(
- 'title',
- 'resolution',
- 'length',
- 'codec'
- ),
- 'user' => array(
- 'fullname',
- 'username',
- 'last_seen',
- 'create_date'
- )
- );
- }
-
- /**
- * gc
- * This cleans old data out of the table
- */
- public static function gc() {
- $sql = "DELETE FROM `tmp_browse` USING `tmp_browse` LEFT JOIN ".
- "`session` ON `session`.`id`=`tmp_browse`.`sid` " .
- "WHERE `session`.`id` IS NULL";
- $db_results = Dba::write($sql);
- }
-
- /**
- * set_filter
- * This saves the filter data we pass it.
- */
- public function set_filter($key, $value) {
-
- switch ($key) {
- case 'tag':
- if (is_array($value)) {
- $this->_state['filter'][$key] = $value;
- }
- elseif (is_numeric($value)) {
- $this->_state['filter'][$key] = array($value);
- }
- else {
- $this->_state['filter'][$key] = array();
- }
- break;
- case 'artist':
- case 'catalog':
- case 'album':
- $this->_state['filter'][$key] = $value;
- break;
- case 'min_count':
- case 'unplayed':
- case 'rated':
-
- break;
- case 'add_lt':
- case 'add_gt':
- case 'update_lt':
- case 'update_gt':
- $this->_state['filter'][$key] = intval($value);
- break;
- case 'exact_match':
- case 'alpha_match':
- case 'starts_with':
- if ($this->is_static_content()) { return false; }
- $this->_state['filter'][$key] = $value;
- break;
- case 'playlist_type':
- // Must be a content manager to turn this off
- if ($this->_state['filter'][$key] AND Access::check('interface','50')) { unset($this->_state['filter'][$key]); }
- else { $this->_state['filter'][$key] = '1'; }
- break;
- default:
- // Rien a faire
- return false;
- break;
- } // end switch
-
- // If we've set a filter we need to reset the totals
- $this->reset_total();
- $this->set_start(0);
-
- return true;
-
- } // set_filter
-
- /**
- * reset
- * Reset everything, this should only be called when we are starting
- * fresh
- */
- public function reset() {
-
- $this->reset_base();
- $this->reset_filters();
- $this->reset_total();
- $this->reset_join();
- $this->reset_select();
- $this->reset_having();
- $this->set_static_content(false);
- $this->set_is_simple(false);
- $this->set_start(0);
- $this->set_offset(Config::get('offset_limit') ? Config::get('offset_limit') : '25');
-
- } // reset
-
- /**
- * reset_base
- * this resets the base string
- */
- public function reset_base() {
-
- $this->_state['base'] = NULL;
-
- } // reset_base
-
- /**
- * reset_select
- * This resets the select fields that we've added so far
- */
- public function reset_select() {
-
- $this->_state['select'] = array();
-
- } // reset_select
-
- /**
- * reset_having
- * Null out the having clause
- */
- public function reset_having() {
-
- unset($this->_state['having']);
-
- } // reset_having
-
- /**
- * reset_join
- * clears the joins if there are any
- */
- public function reset_join() {
-
- unset($this->_state['join']);
-
- } // reset_join
-
- /**
- * reset_filter
- * This is a wrapper function that resets the filters
- */
- public function reset_filters() {
-
- $this->_state['filter'] = array();
-
- } // reset_filters
-
- /**
- * reset_total
- * This resets the total for the browse type
- */
- public function reset_total() {
-
- unset($this->_state['total']);
-
- } // reset_total
-
- /**
- * get_filter
- * returns the specified filter value
- */
- public function get_filter($key) {
-
- // Simple enough, but if we ever move this crap
- // If we ever move this crap what?
- return isset($this->_state['filter'][$key])
- ? $this->_state['filter'][$key]
- : false;
-
- } // get_filter
-
- /**
- * get_start
- * This returns the current value of the start
- */
- public function get_start() {
-
- return $this->_state['start'];
-
- } // get_start
-
- /**
- * get_offset
- * This returns the current offset
- */
- public function get_offset() {
- if ($this->is_static_content()) {
- return $this->get_total();
- }
-
- return $this->_state['offset'];
- } // get_offset
-
- /**
- * set_total
- * This sets the total number of objects
- */
- public function set_total($total) {
- $this->_state['total'] = $total;
- }
-
- /**
- * get_total
- * This returns the total number of objects for this current sort type.
- * If it's already cached used it. if they pass us an array then use
- * that.
- */
- public function get_total($objects = null) {
-
- // If they pass something then just return that
- if (is_array($objects) and !$this->is_simple()) {
- return count($objects);
- }
-
- // See if we can find it in the cache
- if (isset($this->_state['total'])) {
- return $this->_state['total'];
- }
-
- $db_results = Dba::read($this->get_sql(false));
- $num_rows = Dba::num_rows($db_results);
-
- $this->_state['total'] = $num_rows;
-
- return $num_rows;
-
- } // get_total
-
- /**
- * get_allowed_filters
- * This returns an array of the allowed filters based on the type of
- * object we are working with, this is used to display the 'filter'
- * sidebar stuff.
- */
- public static function get_allowed_filters($type) {
- return isset(self::$allowed_filters[$type])
- ? self::$allowed_filters[$type]
- : array();
- } // get_allowed_filters
-
- /**
- * set_type
- * This sets the type of object that we want to browse by
- * we do this here so we only have to maintain a single whitelist
- * and if I want to change the location I only have to do it here
- */
- public function set_type($type) {
-
- switch($type) {
- case 'user':
- case 'video':
- case 'playlist':
- case 'playlist_song':
- case 'smartplaylist':
- case 'song':
- case 'flagged':
- case 'catalog':
- case 'album':
- case 'artist':
- case 'tag':
- case 'playlist_localplay':
- case 'shoutbox':
- case 'live_stream':
- case 'democratic':
- // Set it
- $this->_state['type'] = $type;
- $this->set_base_sql(true);
- break;
- default:
- // Rien a faire
- break;
- } // end type whitelist
- } // set_type
-
- /**
- * get_type
- * This returns the type of the browse we currently are using
- */
- public function get_type() {
-
- return $this->_state['type'];
-
- } // get_type
-
- /**
- * set_sort
- * This sets the current sort(s)
- */
- public function set_sort($sort,$order='') {
-
- // If it's not in our list, smeg off!
- if (!in_array($sort, self::$allowed_sorts[$this->get_type()])) {
- return false;
- }
-
- if ($order) {
- $order = ($order == 'DESC') ? 'DESC' : 'ASC';
- $this->_state['sort'] = array();
- $this->_state['sort'][$sort] = $order;
- }
- elseif ($this->_state['sort'][$sort] == 'DESC') {
- // Reset it till I can figure out how to interface the hotness
- $this->_state['sort'] = array();
- $this->_state['sort'][$sort] = 'ASC';
- }
- else {
- // Reset it till I can figure out how to interface the hotness
- $this->_state['sort'] = array();
- $this->_state['sort'][$sort] = 'DESC';
- }
-
- $this->resort_objects();
-
- } // set_sort
-
- /**
- * set_offset
- * This sets the current offset of this query
- */
- public function set_offset($offset) {
-
- $this->_state['offset'] = abs($offset);
-
- } // set_offset
+ public $id;
+ public $catalog;
+
+ protected $_state = array();
+ protected $_cache;
+
+ private static $allowed_filters;
+ private static $allowed_sorts;
+
+ /**
+ * constructor
+ * This should be called
+ */
+ public function __construct($id = null) {
+ $sid = Dba::escape(session_id());
+
+ if (is_null($id)) {
+ $this->reset();
+ $data = Dba::escape(serialize($this->_state));
+
+ $sql = "INSERT INTO `tmp_browse` (`sid`, `data`) " .
+ "VALUES('$sid', '$data')";
+ $db_results = Dba::write($sql);
+ $this->id = Dba::insert_id();
+
+ return true;
+ }
+
+ $this->id = $id;
+
+ $sql = "SELECT `data` FROM `tmp_browse` " .
+ "WHERE `id`='$id' AND `sid`='$sid'";
+
+ $db_results = Dba::read($sql);
+
+ if ($results = Dba::fetch_assoc($db_results)) {
+ $this->_state = unserialize($results['data']);
+ return true;
+ }
+
+ Error::add('browse', T_('Browse not found or expired, try reloading the page'));
+ return false;
+ }
+
+ /**
+ * _auto_init
+ * Automatically called when the class is loaded.
+ * Populate static arrays if necessary
+ */
+ public static function _auto_init() {
+ if (is_array(self::$allowed_filters)) {
+ return true;
+ }
+
+ self::$allowed_filters = array(
+ 'album' => array(
+ 'add_lt',
+ 'add_gt',
+ 'update_lt',
+ 'update_gt',
+ 'show_art',
+ 'starts_with',
+ 'exact_match',
+ 'alpha_match',
+ 'catalog'
+ ),
+ 'artist' => array(
+ 'add_lt',
+ 'add_gt',
+ 'update_lt',
+ 'update_gt',
+ 'exact_match',
+ 'alpha_match',
+ 'starts_with',
+ 'tag',
+ 'catalog'
+ ),
+ 'song' => array(
+ 'add_lt',
+ 'add_gt',
+ 'update_lt',
+ 'update_gt',
+ 'exact_match',
+ 'alpha_match',
+ 'starts_with',
+ 'tag',
+ 'catalog'
+ ),
+ 'live_stream' => array(
+ 'alpha_match',
+ 'starts_with'
+ ),
+ 'playlist' => array(
+ 'alpha_match',
+ 'starts_with'
+ ),
+ 'smartplaylist' => array(
+ 'alpha_match',
+ 'starts_with'
+ ),
+ 'tag' => array(
+ 'tag',
+ 'object_type',
+ 'exact_match',
+ 'alpha_match'
+ ),
+ 'video' => array(
+ 'starts_with',
+ 'exact_match',
+ 'alpha_match'
+ )
+ );
+
+ if (Access::check('interface','50')) {
+ array_push(self::$allowed_filters['playlist'], 'playlist_type');
+ }
+
+ self::$allowed_sorts = array(
+ 'playlist_song' => array(
+ 'title',
+ 'year',
+ 'track',
+ 'time',
+ 'album',
+ 'artist'
+ ),
+ 'song' => array(
+ 'title',
+ 'year',
+ 'track',
+ 'time',
+ 'album',
+ 'artist'
+ ),
+ 'artist' => array(
+ 'name',
+ 'album'
+ ),
+ 'tag' => array(
+ 'tag'
+ ),
+ 'album' => array(
+ 'name',
+ 'year',
+ 'artist'
+ ),
+ 'playlist' => array(
+ 'name',
+ 'user'
+ ),
+ 'smartplaylist' => array(
+ 'name',
+ 'user'
+ ),
+ 'shoutbox' => array(
+ 'date',
+ 'user',
+ 'sticky'
+ ),
+ 'live_stream' => array(
+ 'name',
+ 'call_sign',
+ 'frequency'
+ ),
+ 'video' => array(
+ 'title',
+ 'resolution',
+ 'length',
+ 'codec'
+ ),
+ 'user' => array(
+ 'fullname',
+ 'username',
+ 'last_seen',
+ 'create_date'
+ )
+ );
+ }
+
+ /**
+ * gc
+ * This cleans old data out of the table
+ */
+ public static function gc() {
+ $sql = "DELETE FROM `tmp_browse` USING `tmp_browse` LEFT JOIN ".
+ "`session` ON `session`.`id`=`tmp_browse`.`sid` " .
+ "WHERE `session`.`id` IS NULL";
+ $db_results = Dba::write($sql);
+ }
+
+ /**
+ * set_filter
+ * This saves the filter data we pass it.
+ */
+ public function set_filter($key, $value) {
+
+ switch ($key) {
+ case 'tag':
+ if (is_array($value)) {
+ $this->_state['filter'][$key] = $value;
+ }
+ elseif (is_numeric($value)) {
+ $this->_state['filter'][$key] = array($value);
+ }
+ else {
+ $this->_state['filter'][$key] = array();
+ }
+ break;
+ case 'artist':
+ case 'catalog':
+ case 'album':
+ $this->_state['filter'][$key] = $value;
+ break;
+ case 'min_count':
+ case 'unplayed':
+ case 'rated':
+
+ break;
+ case 'add_lt':
+ case 'add_gt':
+ case 'update_lt':
+ case 'update_gt':
+ $this->_state['filter'][$key] = intval($value);
+ break;
+ case 'exact_match':
+ case 'alpha_match':
+ case 'starts_with':
+ if ($this->is_static_content()) { return false; }
+ $this->_state['filter'][$key] = $value;
+ break;
+ case 'playlist_type':
+ // Must be a content manager to turn this off
+ if ($this->_state['filter'][$key] AND Access::check('interface','50')) { unset($this->_state['filter'][$key]); }
+ else { $this->_state['filter'][$key] = '1'; }
+ break;
+ default:
+ // Rien a faire
+ return false;
+ break;
+ } // end switch
+
+ // If we've set a filter we need to reset the totals
+ $this->reset_total();
+ $this->set_start(0);
+
+ return true;
+
+ } // set_filter
+
+ /**
+ * reset
+ * Reset everything, this should only be called when we are starting
+ * fresh
+ */
+ public function reset() {
+
+ $this->reset_base();
+ $this->reset_filters();
+ $this->reset_total();
+ $this->reset_join();
+ $this->reset_select();
+ $this->reset_having();
+ $this->set_static_content(false);
+ $this->set_is_simple(false);
+ $this->set_start(0);
+ $this->set_offset(Config::get('offset_limit') ? Config::get('offset_limit') : '25');
+
+ } // reset
+
+ /**
+ * reset_base
+ * this resets the base string
+ */
+ public function reset_base() {
+
+ $this->_state['base'] = NULL;
+
+ } // reset_base
+
+ /**
+ * reset_select
+ * This resets the select fields that we've added so far
+ */
+ public function reset_select() {
+
+ $this->_state['select'] = array();
+
+ } // reset_select
+
+ /**
+ * reset_having
+ * Null out the having clause
+ */
+ public function reset_having() {
+
+ unset($this->_state['having']);
+
+ } // reset_having
+
+ /**
+ * reset_join
+ * clears the joins if there are any
+ */
+ public function reset_join() {
+
+ unset($this->_state['join']);
+
+ } // reset_join
+
+ /**
+ * reset_filter
+ * This is a wrapper function that resets the filters
+ */
+ public function reset_filters() {
+
+ $this->_state['filter'] = array();
+
+ } // reset_filters
+
+ /**
+ * reset_total
+ * This resets the total for the browse type
+ */
+ public function reset_total() {
+
+ unset($this->_state['total']);
+
+ } // reset_total
+
+ /**
+ * get_filter
+ * returns the specified filter value
+ */
+ public function get_filter($key) {
+
+ // Simple enough, but if we ever move this crap
+ // If we ever move this crap what?
+ return isset($this->_state['filter'][$key])
+ ? $this->_state['filter'][$key]
+ : false;
+
+ } // get_filter
+
+ /**
+ * get_start
+ * This returns the current value of the start
+ */
+ public function get_start() {
+
+ return $this->_state['start'];
+
+ } // get_start
+
+ /**
+ * get_offset
+ * This returns the current offset
+ */
+ public function get_offset() {
+ if ($this->is_static_content()) {
+ return $this->get_total();
+ }
+
+ return $this->_state['offset'];
+ } // get_offset
+
+ /**
+ * set_total
+ * This sets the total number of objects
+ */
+ public function set_total($total) {
+ $this->_state['total'] = $total;
+ }
+
+ /**
+ * get_total
+ * This returns the total number of objects for this current sort type.
+ * If it's already cached used it. if they pass us an array then use
+ * that.
+ */
+ public function get_total($objects = null) {
+
+ // If they pass something then just return that
+ if (is_array($objects) and !$this->is_simple()) {
+ return count($objects);
+ }
+
+ // See if we can find it in the cache
+ if (isset($this->_state['total'])) {
+ return $this->_state['total'];
+ }
+
+ $db_results = Dba::read($this->get_sql(false));
+ $num_rows = Dba::num_rows($db_results);
+
+ $this->_state['total'] = $num_rows;
+
+ return $num_rows;
+
+ } // get_total
+
+ /**
+ * get_allowed_filters
+ * This returns an array of the allowed filters based on the type of
+ * object we are working with, this is used to display the 'filter'
+ * sidebar stuff.
+ */
+ public static function get_allowed_filters($type) {
+ return isset(self::$allowed_filters[$type])
+ ? self::$allowed_filters[$type]
+ : array();
+ } // get_allowed_filters
+
+ /**
+ * set_type
+ * This sets the type of object that we want to browse by
+ * we do this here so we only have to maintain a single whitelist
+ * and if I want to change the location I only have to do it here
+ */
+ public function set_type($type) {
+
+ switch($type) {
+ case 'user':
+ case 'video':
+ case 'playlist':
+ case 'playlist_song':
+ case 'smartplaylist':
+ case 'song':
+ case 'flagged':
+ case 'catalog':
+ case 'album':
+ case 'artist':
+ case 'tag':
+ case 'playlist_localplay':
+ case 'shoutbox':
+ case 'live_stream':
+ case 'democratic':
+ // Set it
+ $this->_state['type'] = $type;
+ $this->set_base_sql(true);
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end type whitelist
+ } // set_type
+
+ /**
+ * get_type
+ * This returns the type of the browse we currently are using
+ */
+ public function get_type() {
+
+ return $this->_state['type'];
+
+ } // get_type
+
+ /**
+ * set_sort
+ * This sets the current sort(s)
+ */
+ public function set_sort($sort,$order='') {
+
+ // If it's not in our list, smeg off!
+ if (!in_array($sort, self::$allowed_sorts[$this->get_type()])) {
+ return false;
+ }
+
+ if ($order) {
+ $order = ($order == 'DESC') ? 'DESC' : 'ASC';
+ $this->_state['sort'] = array();
+ $this->_state['sort'][$sort] = $order;
+ }
+ elseif ($this->_state['sort'][$sort] == 'DESC') {
+ // Reset it till I can figure out how to interface the hotness
+ $this->_state['sort'] = array();
+ $this->_state['sort'][$sort] = 'ASC';
+ }
+ else {
+ // Reset it till I can figure out how to interface the hotness
+ $this->_state['sort'] = array();
+ $this->_state['sort'][$sort] = 'DESC';
+ }
+
+ $this->resort_objects();
+
+ } // set_sort
+
+ /**
+ * set_offset
+ * This sets the current offset of this query
+ */
+ public function set_offset($offset) {
+
+ $this->_state['offset'] = abs($offset);
+
+ } // set_offset
public function set_catalog( $catalog_number ) {
$this->catalog = $catalog_number;
- debug_event("Catalog", "set catalog id: " . $this->catalog, "5");
+ debug_event("Catalog", "set catalog id: " . $this->catalog, "5");
+ }
+
+ /**
+ * set_select
+ * This appends more information to the select part of the SQL
+ * statement, we're going to move to the %%SELECT%% style queries, as I
+ * think it's the only way to do this...
+ */
+ public function set_select($field) {
+
+ $this->_state['select'][] = $field;
+
+ } // set_select
+
+ /**
+ * set_join
+ * This sets the joins for the current browse object
+ */
+ public function set_join($type, $table, $source, $dest, $priority) {
+
+ $this->_state['join'][$priority][$table] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $source . '=' . $dest;
+
+ } // set_join
+
+ /**
+ * set_having
+ * This sets the "HAVING" part of the query, we can only have one..
+ * god this is ugly
+ */
+ public function set_having($condition) {
+
+ $this->_state['having'] = $condition;
+
+ } // set_having
+
+ /**
+ * set_start
+ * This sets the start point for our show functions
+ * We need to store this in the session so that it can be pulled
+ * back, if they hit the back button
+ */
+ public function set_start($start) {
+
+
+ $start = intval($start);
+
+ if (!$this->is_static_content()) {
+ $this->_state['start'] = $start;
+ }
+
+ } // set_start
+
+ /**
+ * set_is_simple
+ * This sets the current browse object to a 'simple' browse method
+ * which means use the base query provided and expand from there
+ */
+ public function set_is_simple($value) {
+
+ $value = make_bool($value);
+ $this->_state['simple'] = $value;
+
+ } // set_is_simple
+
+ /**
+ * set_static_content
+ * This sets true/false if the content of this browse
+ * should be static, if they are then content filtering/altering
+ * methods will be skipped
+ */
+ public function set_static_content($value) {
+
+ $value = make_bool($value);
+
+ // We want to start at 0 if it's static
+ if ($value) {
+ $this->set_start('0');
+ }
+
+ $this->_state['static'] = $value;
+
+ } // set_static_content
+
+ public function is_static_content() {
+ return $this->_state['static'];
+ }
+
+ /**
+ * is_simple
+ * This returns whether or not the current browse type is set to static.
+ */
+ public function is_simple() {
+
+ return $this->_state['simple'];
+
+ } // is_simple
+
+ /**
+ * get_saved
+ * This looks in the session for the saved stuff and returns what it
+ * finds.
+ */
+ public function get_saved() {
+
+ // See if we have it in the local cache first
+ if (is_array($this->_cache)) {
+ return $this->_cache;
}
- /**
- * set_select
- * This appends more information to the select part of the SQL
- * statement, we're going to move to the %%SELECT%% style queries, as I
- * think it's the only way to do this...
- */
- public function set_select($field) {
+ if (!$this->is_simple()) {
+ $sid = Dba::escape(session_id());
+ $id = Dba::escape($this->id);
+ $sql = "SELECT `object_data` FROM `tmp_browse` WHERE `sid`='$sid' AND `id`='$id'";
+ $db_results = Dba::read($sql);
- $this->_state['select'][] = $field;
+ $row = Dba::fetch_assoc($db_results);
+
+ $this->_cache = unserialize($row['object_data']);
+ return $this->_cache;
+ }
+ else {
+ $objects = $this->get_objects();
+ }
+
+ return $objects;
+
+ } // get_saved
+
+ /**
+ * get_objects
+ * This gets an array of the ids of the objects that we are
+ * currently browsing by it applies the sql and logic based
+ * filters
+ */
+ public function get_objects() {
+
+ // First we need to get the SQL statement we are going to run
+ // This has to run against any possible filters (dependent on type)
+ $sql = $this->get_sql(true);
+ $db_results = Dba::read($sql);
+
+ $results = array();
+ while ($data = Dba::fetch_assoc($db_results)) {
+ $results[] = $data;
+ }
+
+ $results = $this->post_process($results);
+ $filtered = array();
+ foreach ($results as $data) {
+ // Make sure that this object passes the logic filter
+ if ($this->logic_filter($data['id'])) {
+ $filtered[] = $data['id'];
+ }
+ } // end while
+
+ // Save what we've found and then return it
+ $this->save_objects($filtered);
+
+ return $filtered;
+
+ } // get_objects
+
+ /**
+ * set_base_sql
+ * This saves the base sql statement we are going to use.
+ */
+ private function set_base_sql($force = false) {
+
+ // Only allow it to be set once
+ if (strlen($this->_state['base']) && !$force) { return true; }
+
+ switch ($this->get_type()) {
+ case 'album':
+ $this->set_select("DISTINCT(`album`.`id`)");
+ $sql = "SELECT %%SELECT%% FROM `album` ";
+ break;
+ case 'artist':
+ $this->set_select("`artist`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `artist` ";
+ break;
+ case 'catalog':
+ $this->set_select("`artist`.`name`");
+ $sql = "SELECT %%SELECT%% FROM `artist` ";
+ break;
+ case 'user':
+ $this->set_select("`user`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `user` ";
+ break;
+ case 'live_stream':
+ $this->set_select("`live_stream`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `live_stream` ";
+ break;
+ case 'playlist':
+ $this->set_select("`playlist`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `playlist` ";
+ break;
+ case 'smartplaylist':
+ self::set_select('`search`.`id`');
+ $sql = "SELECT %%SELECT%% FROM `search` ";
+ break;
+ case 'flagged':
+ $this->set_select("`flagged`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `flagged` ";
+ break;
+ case 'shoutbox':
+ $this->set_select("`user_shout`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `user_shout` ";
+ break;
+ case 'video':
+ $this->set_select("`video`.`id`");
+ $sql = "SELECT %%SELECT%% FROM `video` ";
+ break;
+ case 'tag':
+ $this->set_select("DISTINCT(`tag`.`id`)");
+ $this->set_join('left', 'tag_map', '`tag_map`.`tag_id`', '`tag`.`id`', 1);
+ $sql = "SELECT %%SELECT%% FROM `tag` ";
+ break;
+ case 'playlist_song':
+ case 'song':
+ default:
+ $this->set_select("DISTINCT(`song`.`id`)");
+ $sql = "SELECT %%SELECT%% FROM `song` ";
+ break;
+ } // end base sql
+
+ $this->_state['base'] = $sql;
+
+ } // set_base_sql
+
+ /**
+ * get_select
+ * This returns the selects in a format that is friendly for a sql
+ * statement.
+ */
+ private function get_select() {
+
+ $select_string = implode($this->_state['select'], ", ");
+ return $select_string;
+
+ } // get_select
+
+ /**
+ * get_base_sql
+ * This returns the base sql statement all parsed up, this should be
+ * called after all set operations.
+ */
+ private function get_base_sql() {
+
+ $sql = str_replace("%%SELECT%%", $this->get_select(), $this->_state['base']);
+ return $sql;
+
+ } // get_base_sql
+
+ /**
+ * get_filter_sql
+ * This returns the filter part of the sql statement
+ */
+ private function get_filter_sql() {
+
+ if (!is_array($this->_state['filter'])) {
+ return '';
+ }
+
+ $sql = "WHERE 1=1 AND ";
+
+ foreach ($this->_state['filter']
+ as $key => $value) {
+
+ $sql .= $this->sql_filter($key, $value);
+ }
+
+ $sql = rtrim($sql,'AND ') . ' ';
+
+ return $sql;
+
+ } // get_filter_sql
+
+ /**
+ * get_sort_sql
+ * Returns the sort sql part
+ */
+ private function get_sort_sql() {
+
+ if (!is_array($this->_state['sort'])) {
+ return '';
+ }
+
+ $sql = 'ORDER BY ';
+
+ foreach ($this->_state['sort']
+ as $key => $value) {
+ $sql .= $this->sql_sort($key, $value);
+ }
- } // set_select
+ $sql = rtrim($sql,'ORDER BY ');
+ $sql = rtrim($sql,',');
- /**
- * set_join
- * This sets the joins for the current browse object
- */
- public function set_join($type, $table, $source, $dest, $priority) {
+ return $sql;
- $this->_state['join'][$priority][$table] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $source . '=' . $dest;
+ } // get_sort_sql
- } // set_join
+ /**
+ * get_limit_sql
+ * This returns the limit part of the sql statement
+ */
+ private function get_limit_sql() {
- /**
- * set_having
- * This sets the "HAVING" part of the query, we can only have one..
- * god this is ugly
- */
- public function set_having($condition) {
+ if (!$this->is_simple()) { return ''; }
- $this->_state['having'] = $condition;
+ $sql = ' LIMIT ' . intval($this->get_start()) . ',' . intval($this->get_offset());
- } // set_having
+ return $sql;
- /**
- * set_start
- * This sets the start point for our show functions
- * We need to store this in the session so that it can be pulled
- * back, if they hit the back button
- */
- public function set_start($start) {
+ } // get_limit_sql
+ /**
+ * get_join_sql
+ * This returns the joins that this browse may need to work correctly
+ */
+ private function get_join_sql() {
- $start = intval($start);
+ if (!is_array($this->_state['join'])) {
+ return '';
+ }
- if (!$this->is_static_content()) {
- $this->_state['start'] = $start;
- }
+ $sql = '';
- } // set_start
+ foreach ($this->_state['join'] as $joins) {
+ foreach ($joins as $join) {
+ $sql .= $join . ' ';
+ } // end foreach joins at this level
+ } // end foreach of this level of joins
- /**
- * set_is_simple
- * This sets the current browse object to a 'simple' browse method
- * which means use the base query provided and expand from there
- */
- public function set_is_simple($value) {
+ return $sql;
- $value = make_bool($value);
- $this->_state['simple'] = $value;
+ } // get_join_sql
- } // set_is_simple
+ /**
+ * get_having_sql
+ * this returns the having sql stuff, if we've got anything
+ */
+ public function get_having_sql() {
- /**
- * set_static_content
- * This sets true/false if the content of this browse
- * should be static, if they are then content filtering/altering
- * methods will be skipped
- */
- public function set_static_content($value) {
+ $sql = $this->_state['having'];
- $value = make_bool($value);
-
- // We want to start at 0 if it's static
- if ($value) {
- $this->set_start('0');
- }
-
- $this->_state['static'] = $value;
-
- } // set_static_content
-
- public function is_static_content() {
- return $this->_state['static'];
- }
-
- /**
- * is_simple
- * This returns whether or not the current browse type is set to static.
- */
- public function is_simple() {
-
- return $this->_state['simple'];
-
- } // is_simple
-
- /**
- * get_saved
- * This looks in the session for the saved stuff and returns what it
- * finds.
- */
- public function get_saved() {
-
- // See if we have it in the local cache first
- if (is_array($this->_cache)) {
- return $this->_cache;
- }
-
- if (!$this->is_simple()) {
- $sid = Dba::escape(session_id());
- $id = Dba::escape($this->id);
- $sql = "SELECT `object_data` FROM `tmp_browse` WHERE `sid`='$sid' AND `id`='$id'";
- $db_results = Dba::read($sql);
-
- $row = Dba::fetch_assoc($db_results);
-
- $this->_cache = unserialize($row['object_data']);
- return $this->_cache;
- }
- else {
- $objects = $this->get_objects();
- }
-
- return $objects;
-
- } // get_saved
-
- /**
- * get_objects
- * This gets an array of the ids of the objects that we are
- * currently browsing by it applies the sql and logic based
- * filters
- */
- public function get_objects() {
-
- // First we need to get the SQL statement we are going to run
- // This has to run against any possible filters (dependent on type)
- $sql = $this->get_sql(true);
- $db_results = Dba::read($sql);
-
- $results = array();
- while ($data = Dba::fetch_assoc($db_results)) {
- $results[] = $data;
- }
-
- $results = $this->post_process($results);
- $filtered = array();
- foreach ($results as $data) {
- // Make sure that this object passes the logic filter
- if ($this->logic_filter($data['id'])) {
- $filtered[] = $data['id'];
- }
- } // end while
-
- // Save what we've found and then return it
- $this->save_objects($filtered);
-
- return $filtered;
-
- } // get_objects
-
- /**
- * set_base_sql
- * This saves the base sql statement we are going to use.
- */
- private function set_base_sql($force = false) {
-
- // Only allow it to be set once
- if (strlen($this->_state['base']) && !$force) { return true; }
-
- switch ($this->get_type()) {
- case 'album':
- $this->set_select("DISTINCT(`album`.`id`)");
- $sql = "SELECT %%SELECT%% FROM `album` ";
- break;
- case 'artist':
- $this->set_select("`artist`.`id`");
- $sql = "SELECT %%SELECT%% FROM `artist` ";
- break;
- case 'catalog':
- $this->set_select("`artist`.`name`");
- $sql = "SELECT %%SELECT%% FROM `artist` ";
- break;
- case 'user':
- $this->set_select("`user`.`id`");
- $sql = "SELECT %%SELECT%% FROM `user` ";
- break;
- case 'live_stream':
- $this->set_select("`live_stream`.`id`");
- $sql = "SELECT %%SELECT%% FROM `live_stream` ";
- break;
- case 'playlist':
- $this->set_select("`playlist`.`id`");
- $sql = "SELECT %%SELECT%% FROM `playlist` ";
- break;
- case 'smartplaylist':
- self::set_select('`search`.`id`');
- $sql = "SELECT %%SELECT%% FROM `search` ";
- break;
- case 'flagged':
- $this->set_select("`flagged`.`id`");
- $sql = "SELECT %%SELECT%% FROM `flagged` ";
- break;
- case 'shoutbox':
- $this->set_select("`user_shout`.`id`");
- $sql = "SELECT %%SELECT%% FROM `user_shout` ";
- break;
- case 'video':
- $this->set_select("`video`.`id`");
- $sql = "SELECT %%SELECT%% FROM `video` ";
- break;
- case 'tag':
- $this->set_select("DISTINCT(`tag`.`id`)");
- $this->set_join('left', 'tag_map', '`tag_map`.`tag_id`', '`tag`.`id`', 1);
- $sql = "SELECT %%SELECT%% FROM `tag` ";
- break;
- case 'playlist_song':
- case 'song':
- default:
- $this->set_select("DISTINCT(`song`.`id`)");
- $sql = "SELECT %%SELECT%% FROM `song` ";
- break;
- } // end base sql
-
- $this->_state['base'] = $sql;
-
- } // set_base_sql
-
- /**
- * get_select
- * This returns the selects in a format that is friendly for a sql
- * statement.
- */
- private function get_select() {
-
- $select_string = implode($this->_state['select'], ", ");
- return $select_string;
-
- } // get_select
-
- /**
- * get_base_sql
- * This returns the base sql statement all parsed up, this should be
- * called after all set operations.
- */
- private function get_base_sql() {
-
- $sql = str_replace("%%SELECT%%", $this->get_select(), $this->_state['base']);
- return $sql;
-
- } // get_base_sql
-
- /**
- * get_filter_sql
- * This returns the filter part of the sql statement
- */
- private function get_filter_sql() {
-
- if (!is_array($this->_state['filter'])) {
- return '';
- }
-
- $sql = "WHERE 1=1 AND ";
-
- foreach ($this->_state['filter']
- as $key => $value) {
-
- $sql .= $this->sql_filter($key, $value);
- }
-
- $sql = rtrim($sql,'AND ') . ' ';
-
- return $sql;
-
- } // get_filter_sql
-
- /**
- * get_sort_sql
- * Returns the sort sql part
- */
- private function get_sort_sql() {
-
- if (!is_array($this->_state['sort'])) {
- return '';
- }
-
- $sql = 'ORDER BY ';
-
- foreach ($this->_state['sort']
- as $key => $value) {
- $sql .= $this->sql_sort($key, $value);
- }
-
- $sql = rtrim($sql,'ORDER BY ');
- $sql = rtrim($sql,',');
-
- return $sql;
-
- } // get_sort_sql
-
- /**
- * get_limit_sql
- * This returns the limit part of the sql statement
- */
- private function get_limit_sql() {
+ return $sql;
- if (!$this->is_simple()) { return ''; }
+ } // get_having_sql
- $sql = ' LIMIT ' . intval($this->get_start()) . ',' . intval($this->get_offset());
+ /**
+ * get_sql
+ * This returns the sql statement we are going to use this has to be run
+ * every time we get the objects because it depends on the filters and
+ * the type of object we are currently browsing.
+ */
+ public function get_sql($limit = true) {
- return $sql;
+ $sql = $this->get_base_sql();
- } // get_limit_sql
+ $filter_sql = $this->get_filter_sql();
+ $join_sql = $this->get_join_sql();
+ $having_sql = $this->get_having_sql();
+ $order_sql = $this->get_sort_sql();
+ $limit_sql = $limit ? $this->get_limit_sql() : '';
+ $final_sql = $sql . $join_sql . $filter_sql . $having_sql;
+
+ if( $this->get_type() == 'artist' ) {
+ $final_sql .= " GROUP BY `" . $this->get_type() . "`.`name` ";
+ }
+ $final_sql .= $order_sql . $limit_sql;
+ debug_event("Catalog", "catalog sql: " . $final_sql, "6");
+ return $final_sql;
- /**
- * get_join_sql
- * This returns the joins that this browse may need to work correctly
- */
- private function get_join_sql() {
+ } // get_sql
- if (!is_array($this->_state['join'])) {
- return '';
- }
+ /**
+ * post_process
+ * This does some additional work on the results that we've received
+ * before returning them.
+ */
+ private function post_process($data) {
- $sql = '';
+ $tags = $this->_state['filter']['tag'];
- foreach ($this->_state['join'] as $joins) {
- foreach ($joins as $join) {
- $sql .= $join . ' ';
- } // end foreach joins at this level
- } // end foreach of this level of joins
+ if (!is_array($tags) || sizeof($tags) < 2) {
+ return $data;
+ }
- return $sql;
+ $tag_count = sizeof($tags);
+ $count = array();
- } // get_join_sql
+ foreach($data as $row) {
+ $count[$row['id']]++;
+ }
- /**
- * get_having_sql
- * this returns the having sql stuff, if we've got anything
- */
- public function get_having_sql() {
-
- $sql = $this->_state['having'];
-
- return $sql;
-
- } // get_having_sql
-
- /**
- * get_sql
- * This returns the sql statement we are going to use this has to be run
- * every time we get the objects because it depends on the filters and
- * the type of object we are currently browsing.
- */
- public function get_sql($limit = true) {
-
- $sql = $this->get_base_sql();
-
- $filter_sql = $this->get_filter_sql();
- $join_sql = $this->get_join_sql();
- $having_sql = $this->get_having_sql();
- $order_sql = $this->get_sort_sql();
- $limit_sql = $limit ? $this->get_limit_sql() : '';
- $final_sql = $sql . $join_sql . $filter_sql . $having_sql;
-
- if( $this->get_type() == 'artist' ) {
- $final_sql .= " GROUP BY `" . $this->get_type() . "`.`name` ";
- }
- $final_sql .= $order_sql . $limit_sql;
- debug_event("Catalog", "catalog sql: " . $final_sql, "6");
- return $final_sql;
-
- } // get_sql
-
- /**
- * post_process
- * This does some additional work on the results that we've received
- * before returning them.
- */
- private function post_process($data) {
-
- $tags = $this->_state['filter']['tag'];
-
- if (!is_array($tags) || sizeof($tags) < 2) {
- return $data;
- }
-
- $tag_count = sizeof($tags);
- $count = array();
-
- foreach($data as $row) {
- $count[$row['id']]++;
- }
-
- $results = array();
-
- foreach($count as $key => $value) {
- if ($value >= $tag_count) {
- $results[] = array('id' => $key);
- }
- } // end foreach
-
- return $results;
-
- } // post_process
-
- /**
- * sql_filter
- * This takes a filter name and value and if it is possible
- * to filter by this name on this type returns the appropriate sql
- * if not returns nothing
- */
- private function sql_filter($filter, $value) {
-
- $filter_sql = '';
-
- switch ($this->get_type()) {
-
- case 'song':
- switch($filter) {
- case 'tag':
- $this->set_join('left', '`tag_map`', '`tag_map`.`object_id`', '`song`.`id`', 100);
- $filter_sql = " `tag_map`.`object_type`='song' AND (";
-
- foreach ($value as $tag_id) {
- $filter_sql .= " `tag_map`.`tag_id`='" . Dba::escape($tag_id) . "' AND";
- }
- $filter_sql = rtrim($filter_sql,'AND') . ') AND ';
- break;
- case 'exact_match':
- $filter_sql = " `song`.`title` = '" . Dba::escape($value) . "' AND ";
- break;
- case 'alpha_match':
- $filter_sql = " `song`.`title` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $filter_sql = " `song`.`title` LIKE '" . Dba::escape($value) . "%' AND ";
- if( $this->catalog != 0 ) {
- $filter_sql .= " `song`.`catalog` = '" . $this->catalog . "' AND ";
- }
- break;
- case 'unplayed':
- $filter_sql = " `song`.`played`='0' AND ";
- break;
- case 'album':
- $filter_sql = " `song`.`album` = '". Dba::escape($value) . "' AND ";
- break;
- case 'artist':
- $filter_sql = " `song`.`artist` = '". Dba::escape($value) . "' AND ";
- break;
- case 'add_gt':
- $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND ";
- break;
- case 'add_lt':
- $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND ";
- break;
- case 'update_gt':
- $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND ";
- break;
- case 'update_lt':
- $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND ";
- break;
- case 'catalog':
- if($value != 0) {
- $filter_sql = " `song`.`catalog` = '$value' AND ";
- }
- break;
- default:
- // Rien a faire
- break;
- } // end list of sqlable filters
- break;
- case 'album':
- switch($filter) {
- case 'exact_match':
- $filter_sql = " `album`.`name` = '" . Dba::escape($value) . "' AND ";
- break;
- case 'alpha_match':
- $filter_sql = " `album`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $this->set_join('left', '`song`', '`album`.`id`', '`song`.`album`', 100);
- $filter_sql = " `album`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
- if( $this->catalog != 0 ) {
- $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND ";
- }
- break;
- case 'artist':
- $filter_sql = " `artist`.`id` = '". Dba::escape($value) . "' AND ";
- break;
- case 'add_lt':
- $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
- $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND ";
- break;
- case 'add_gt':
- $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
- $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND ";
- break;
- case 'catalog':
- if($value != 0) {
- $this->set_join('left','`song`','`album`.`id`','`song`.`album`', 100);
- $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100);
+ $results = array();
+
+ foreach($count as $key => $value) {
+ if ($value >= $tag_count) {
+ $results[] = array('id' => $key);
+ }
+ } // end foreach
+
+ return $results;
+
+ } // post_process
+
+ /**
+ * sql_filter
+ * This takes a filter name and value and if it is possible
+ * to filter by this name on this type returns the appropriate sql
+ * if not returns nothing
+ */
+ private function sql_filter($filter, $value) {
+
+ $filter_sql = '';
+
+ switch ($this->get_type()) {
+
+ case 'song':
+ switch($filter) {
+ case 'tag':
+ $this->set_join('left', '`tag_map`', '`tag_map`.`object_id`', '`song`.`id`', 100);
+ $filter_sql = " `tag_map`.`object_type`='song' AND (";
+
+ foreach ($value as $tag_id) {
+ $filter_sql .= " `tag_map`.`tag_id`='" . Dba::escape($tag_id) . "' AND";
+ }
+ $filter_sql = rtrim($filter_sql,'AND') . ') AND ';
+ break;
+ case 'exact_match':
+ $filter_sql = " `song`.`title` = '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'alpha_match':
+ $filter_sql = " `song`.`title` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $filter_sql = " `song`.`title` LIKE '" . Dba::escape($value) . "%' AND ";
+ if( $this->catalog != 0 ) {
+ $filter_sql .= " `song`.`catalog` = '" . $this->catalog . "' AND ";
+ }
+ break;
+ case 'unplayed':
+ $filter_sql = " `song`.`played`='0' AND ";
+ break;
+ case 'album':
+ $filter_sql = " `song`.`album` = '". Dba::escape($value) . "' AND ";
+ break;
+ case 'artist':
+ $filter_sql = " `song`.`artist` = '". Dba::escape($value) . "' AND ";
+ break;
+ case 'add_gt':
+ $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'add_lt':
+ $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'update_gt':
+ $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'update_lt':
+ $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'catalog':
+ if($value != 0) {
+ $filter_sql = " `song`.`catalog` = '$value' AND ";
+ }
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end list of sqlable filters
+ break;
+ case 'album':
+ switch($filter) {
+ case 'exact_match':
+ $filter_sql = " `album`.`name` = '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'alpha_match':
+ $filter_sql = " `album`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $this->set_join('left', '`song`', '`album`.`id`', '`song`.`album`', 100);
+ $filter_sql = " `album`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
+ if( $this->catalog != 0 ) {
+ $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND ";
+ }
+ break;
+ case 'artist':
+ $filter_sql = " `artist`.`id` = '". Dba::escape($value) . "' AND ";
+ break;
+ case 'add_lt':
+ $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
+ $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'add_gt':
+ $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
+ $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'catalog':
+ if($value != 0) {
+ $this->set_join('left','`song`','`album`.`id`','`song`.`album`', 100);
+ $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100);
$filter_sql = " (`song`.`catalog` = '$value') AND ";
}
- break;
- case 'update_lt':
- $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
- $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND ";
- break;
- case 'update_gt':
- $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
- $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND ";
- break;
- default:
- // Rien a faire
- break;
- }
- break;
- case 'artist':
- switch($filter) {
- case 'catalog':
- if($value != 0) {
- $this->set_join('left','`song`','`artist`.`id`','`song`.`artist`', 100);
- $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100);
- $filter_sql = " (`catalog`.`id` = '$value') AND ";
- }
- break;
- case 'exact_match':
- $filter_sql = " `artist`.`name` = '" . Dba::escape($value) . "' AND ";
- break;
- case 'alpha_match':
- $filter_sql = " `artist`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $this->set_join('left', '`song`', '`artist`.`id`', '`song`.`artist`', 100);
- $filter_sql = " `artist`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
- if( $this->catalog != 0 ) {
- $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND ";
- }
- break;
- case 'add_lt':
- $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
- $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND ";
- break;
- case 'add_gt':
- $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
- $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND ";
- break;
- case 'update_lt':
- $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
- $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND ";
- break;
- case 'update_gt':
- $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
- $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND ";
- break;
- default:
- // Rien a faire
- break;
- } // end filter
- break;
- case 'live_stream':
- switch ($filter) {
- case 'alpha_match':
- $filter_sql = " `live_stream`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $filter_sql = " `live_stream`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
- break;
- default:
- // Rien a faire
- break;
- } // end filter
- break;
- case 'playlist':
- switch ($filter) {
- case 'alpha_match':
- $filter_sql = " `playlist`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $filter_sql = " `playlist`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
- break;
- case 'playlist_type':
- $user_id = intval($GLOBALS['user']->id);
- $filter_sql = " (`playlist`.`type` = 'public' OR `playlist`.`user`='$user_id') AND ";
- break;
- default;
- // Rien a faire
- break;
- } // end filter
- break;
- case 'smartplaylist':
- switch ($filter) {
- case 'alpha_match':
- $filter_sql = " `search`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $filter_sql = " `search`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
- break;
- case 'playlist_type':
- $user_id = intval($GLOBALS['user']->id);
- $filter_sql = " (`search`.`type` = 'public' OR `search`.`user`='$user_id') AND ";
- break;
- } // end switch on $filter
- break;
- case 'tag':
- switch ($filter) {
- case 'alpha_match':
- $filter_sql = " `tag`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'exact_match':
- $filter_sql = " `tag`.`name` = '" . Dba::escape($value) . "' AND ";
- break;
- case 'tag':
- $filter_sql = " `tag`.`id` = '" . Dba::escape($value) . "' AND ";
- break;
- default:
- // Rien a faire
- break;
- } // end filter
- break;
- case 'video':
- switch ($filter) {
- case 'alpha_match':
- $filter_sql = " `video`.`title` LIKE '%" . Dba::escape($value) . "%' AND ";
- break;
- case 'starts_with':
- $filter_sql = " `video`.`title` LIKE '" . Dba::escape($value) . "%' AND ";
- break;
- default:
- // Rien a faire
- break;
- } // end filter
- break;
- } // end switch on type
-
- return $filter_sql;
-
- } // sql_filter
-
- /**
- * logic_filter
- * This runs the filters that we can't easily apply
- * to the sql so they have to be done after the fact
- * these should be limited as they are often intensive and
- * require additional queries per object... :(
- */
- private function logic_filter($object_id) {
-
- return true;
-
- } // logic_filter
-
- /**
- * sql_sort
- * This builds any order bys we need to do
- * to sort the results as best we can, there is also
- * a logic based sort that will come later as that's
- * a lot more complicated
- */
- private function sql_sort($field, $order) {
-
- if ($order != 'DESC') { $order == 'ASC'; }
-
- // Depending on the type of browsing we are doing we can apply
- // different filters that apply to different fields
- switch ($this->get_type()) {
- case 'song':
- switch($field) {
- case 'title';
- $sql = "`song`.`title`";
- break;
- case 'year':
- $sql = "`song`.`year`";
- break;
- case 'time':
- $sql = "`song`.`time`";
- break;
- case 'track':
- $sql = "`song`.`track`";
- break;
- case 'album':
- $sql = '`album`.`name`';
- $this->set_join('left', '`album`', '`album`.`id`', '`song`.`album`', 100);
- break;
- case 'artist':
- $sql = '`artist`.`name`';
- $this->set_join('left', '`artist`', '`artist`.`id`', '`song`.`artist`', 100);
- break;
- default:
- // Rien a faire
- break;
- } // end switch
- break;
- case 'album':
- switch($field) {
- case 'name':
- $sql = "`album`.`name` $order, `album`.`disk`";
- break;
- case 'artist':
- $sql = "`artist`.`name`";
- $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
- $this->set_join('left', '`artist`', '`song`.`artist`', '`artist`.`id`', 100);
- break;
- case 'year':
- $sql = "`album`.`year`";
- break;
- } // end switch
- break;
- case 'artist':
- switch ($field) {
- case 'name':
- $sql = "`artist`.`name`";
- break;
- } // end switch
- break;
- case 'playlist':
- switch ($field) {
- case 'type':
- $sql = "`playlist`.`type`";
- break;
- case 'name':
- $sql = "`playlist`.`name`";
- break;
- case 'user':
- $sql = "`playlist`.`user`";
- break;
- } // end switch
- break;
- case 'smartplaylist':
- switch ($field) {
- case 'type':
- $sql = "`search`.`type`";
- break;
- case 'name':
- $sql = "`search`.`name`";
- break;
- case 'user':
- $sql = "`search`.`user`";
- break;
- } // end switch on $field
- break;
- case 'live_stream':
- switch ($field) {
- case 'name':
- $sql = "`live_stream`.`name`";
- break;
- case 'call_sign':
- $sql = "`live_stream`.`call_sign`";
- break;
- case 'frequency':
- $sql = "`live_stream`.`frequency`";
- break;
- } // end switch
- break;
- case 'genre':
- switch ($field) {
- case 'name':
- $sql = "`genre`.`name`";
- break;
- } // end switch
- break;
- case 'user':
- switch ($field) {
- case 'username':
- $sql = "`user`.`username`";
- break;
- case 'fullname':
- $sql = "`user`.`fullname`";
- break;
- case 'last_seen':
- $sql = "`user`.`last_seen`";
- break;
- case 'create_date':
- $sql = "`user`.`create_date`";
- break;
- } // end switch
- break;
- case 'video':
- switch ($field) {
- case 'title':
- $sql = "`video`.`title`";
- break;
- case 'resolution':
- $sql = "`video`.`resolution_x`";
- break;
- case 'length':
- $sql = "`video`.`time`";
- break;
- case 'codec':
- $sql = "`video`.`video_codec`";
- break;
- } // end switch on field
- break;
- default:
- // Rien a faire
- break;
- } // end switch
-
- if ($sql) { $sql_sort = "$sql $order,"; }
-
- return $sql_sort;
-
- } // sql_sort
-
- /**
- * resort_objects
- * This takes the existing objects, looks at the current
- * sort method and then re-sorts them This is internally
- * called by the set_sort() function
- */
- private function resort_objects() {
-
- // There are two ways to do this.. the easy way...
- // and the vollmer way, hopefully we don't have to
- // do it the vollmer way
- if ($this->is_simple()) {
- $sql = $this->get_sql(true);
- }
- else {
- // First pull the objects
- $objects = $this->get_saved();
-
- // If there's nothing there don't do anything
- if (!count($objects) or !is_array($objects)) {
- return false;
- }
- $type = $this->get_type();
- $where_sql = "WHERE `$type`.`id` IN (";
-
- foreach ($objects as $object_id) {
- $object_id = Dba::escape($object_id);
- $where_sql .= "'$object_id',";
- }
- $where_sql = rtrim($where_sql,',');
-
- $where_sql .= ")";
-
- $sql = $this->get_base_sql();
-
- $order_sql = " ORDER BY ";
-
- foreach ($this->_state['sort'] as $key => $value) {
- $order_sql .= $this->sql_sort($key, $value);
- }
- // Clean her up
- $order_sql = rtrim($order_sql,"ORDER BY ");
- $order_sql = rtrim($order_sql,",");
-
- $sql = $sql . $this->get_join_sql() . $where_sql . $order_sql;
- } // if not simple
-
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
-
- $this->save_objects($results);
-
- return true;
-
- } // resort_objects
-
- /**
- * store
- * This saves the current state to the database
- */
- public function store() {
- $sid = Dba::escape(session_id());
- $id = Dba::escape($this->id);
- $data = Dba::escape(serialize($this->_state));
-
- $sql = "UPDATE `tmp_browse` SET `data`='$data' " .
- "WHERE `sid`='$sid' AND `id`='$id'";
- $db_results = Dba::write($sql);
- }
-
- /**
- * save_objects
- * This takes the full array of object ids, often passed into show and
- * if necessary it saves them
- */
- public function save_objects($object_ids) {
-
- // Saving these objects has two operations, one holds it in
- // a local variable and then second holds it in a row in the
- // tmp_browse table
-
- // Only do this if it's a not a simple browse
- if (!$this->is_simple()) {
- $this->_cache = $object_ids;
- $this->set_total(count($object_ids));
- $sid = Dba::escape(session_id());
- $id = Dba::escape($this->id);
- $data = Dba::escape(serialize($this->_cache));
-
- $sql = "UPDATE `tmp_browse` SET `object_data`='$data' " .
- "WHERE `sid`='$sid' AND `id`='$id'";
- $db_results = Dba::write($sql);
- } // save it
-
- return true;
-
- } // save_objects
-
- /**
- * get_state
- * This is a debug only function
- */
- public function get_state() {
-
- return $this->_state;
-
- } // get_state
+ break;
+ case 'update_lt':
+ $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
+ $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'update_gt':
+ $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
+ $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND ";
+ break;
+ default:
+ // Rien a faire
+ break;
+ }
+ break;
+ case 'artist':
+ switch($filter) {
+ case 'catalog':
+ if($value != 0) {
+ $this->set_join('left','`song`','`artist`.`id`','`song`.`artist`', 100);
+ $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100);
+ $filter_sql = " (`catalog`.`id` = '$value') AND ";
+ }
+ break;
+ case 'exact_match':
+ $filter_sql = " `artist`.`name` = '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'alpha_match':
+ $filter_sql = " `artist`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $this->set_join('left', '`song`', '`artist`.`id`', '`song`.`artist`', 100);
+ $filter_sql = " `artist`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
+ if( $this->catalog != 0 ) {
+ $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND ";
+ }
+ break;
+ case 'add_lt':
+ $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
+ $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'add_gt':
+ $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
+ $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'update_lt':
+ $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
+ $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'update_gt':
+ $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100);
+ $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND ";
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end filter
+ break;
+ case 'live_stream':
+ switch ($filter) {
+ case 'alpha_match':
+ $filter_sql = " `live_stream`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $filter_sql = " `live_stream`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end filter
+ break;
+ case 'playlist':
+ switch ($filter) {
+ case 'alpha_match':
+ $filter_sql = " `playlist`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $filter_sql = " `playlist`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'playlist_type':
+ $user_id = intval($GLOBALS['user']->id);
+ $filter_sql = " (`playlist`.`type` = 'public' OR `playlist`.`user`='$user_id') AND ";
+ break;
+ default;
+ // Rien a faire
+ break;
+ } // end filter
+ break;
+ case 'smartplaylist':
+ switch ($filter) {
+ case 'alpha_match':
+ $filter_sql = " `search`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $filter_sql = " `search`.`name` LIKE '" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'playlist_type':
+ $user_id = intval($GLOBALS['user']->id);
+ $filter_sql = " (`search`.`type` = 'public' OR `search`.`user`='$user_id') AND ";
+ break;
+ } // end switch on $filter
+ break;
+ case 'tag':
+ switch ($filter) {
+ case 'alpha_match':
+ $filter_sql = " `tag`.`name` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'exact_match':
+ $filter_sql = " `tag`.`name` = '" . Dba::escape($value) . "' AND ";
+ break;
+ case 'tag':
+ $filter_sql = " `tag`.`id` = '" . Dba::escape($value) . "' AND ";
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end filter
+ break;
+ case 'video':
+ switch ($filter) {
+ case 'alpha_match':
+ $filter_sql = " `video`.`title` LIKE '%" . Dba::escape($value) . "%' AND ";
+ break;
+ case 'starts_with':
+ $filter_sql = " `video`.`title` LIKE '" . Dba::escape($value) . "%' AND ";
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end filter
+ break;
+ } // end switch on type
+
+ return $filter_sql;
+
+ } // sql_filter
+
+ /**
+ * logic_filter
+ * This runs the filters that we can't easily apply
+ * to the sql so they have to be done after the fact
+ * these should be limited as they are often intensive and
+ * require additional queries per object... :(
+ */
+ private function logic_filter($object_id) {
+
+ return true;
+
+ } // logic_filter
+
+ /**
+ * sql_sort
+ * This builds any order bys we need to do
+ * to sort the results as best we can, there is also
+ * a logic based sort that will come later as that's
+ * a lot more complicated
+ */
+ private function sql_sort($field, $order) {
+
+ if ($order != 'DESC') { $order == 'ASC'; }
+
+ // Depending on the type of browsing we are doing we can apply
+ // different filters that apply to different fields
+ switch ($this->get_type()) {
+ case 'song':
+ switch($field) {
+ case 'title';
+ $sql = "`song`.`title`";
+ break;
+ case 'year':
+ $sql = "`song`.`year`";
+ break;
+ case 'time':
+ $sql = "`song`.`time`";
+ break;
+ case 'track':
+ $sql = "`song`.`track`";
+ break;
+ case 'album':
+ $sql = '`album`.`name`';
+ $this->set_join('left', '`album`', '`album`.`id`', '`song`.`album`', 100);
+ break;
+ case 'artist':
+ $sql = '`artist`.`name`';
+ $this->set_join('left', '`artist`', '`artist`.`id`', '`song`.`artist`', 100);
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end switch
+ break;
+ case 'album':
+ switch($field) {
+ case 'name':
+ $sql = "`album`.`name` $order, `album`.`disk`";
+ break;
+ case 'artist':
+ $sql = "`artist`.`name`";
+ $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100);
+ $this->set_join('left', '`artist`', '`song`.`artist`', '`artist`.`id`', 100);
+ break;
+ case 'year':
+ $sql = "`album`.`year`";
+ break;
+ } // end switch
+ break;
+ case 'artist':
+ switch ($field) {
+ case 'name':
+ $sql = "`artist`.`name`";
+ break;
+ } // end switch
+ break;
+ case 'playlist':
+ switch ($field) {
+ case 'type':
+ $sql = "`playlist`.`type`";
+ break;
+ case 'name':
+ $sql = "`playlist`.`name`";
+ break;
+ case 'user':
+ $sql = "`playlist`.`user`";
+ break;
+ } // end switch
+ break;
+ case 'smartplaylist':
+ switch ($field) {
+ case 'type':
+ $sql = "`search`.`type`";
+ break;
+ case 'name':
+ $sql = "`search`.`name`";
+ break;
+ case 'user':
+ $sql = "`search`.`user`";
+ break;
+ } // end switch on $field
+ break;
+ case 'live_stream':
+ switch ($field) {
+ case 'name':
+ $sql = "`live_stream`.`name`";
+ break;
+ case 'call_sign':
+ $sql = "`live_stream`.`call_sign`";
+ break;
+ case 'frequency':
+ $sql = "`live_stream`.`frequency`";
+ break;
+ } // end switch
+ break;
+ case 'genre':
+ switch ($field) {
+ case 'name':
+ $sql = "`genre`.`name`";
+ break;
+ } // end switch
+ break;
+ case 'user':
+ switch ($field) {
+ case 'username':
+ $sql = "`user`.`username`";
+ break;
+ case 'fullname':
+ $sql = "`user`.`fullname`";
+ break;
+ case 'last_seen':
+ $sql = "`user`.`last_seen`";
+ break;
+ case 'create_date':
+ $sql = "`user`.`create_date`";
+ break;
+ } // end switch
+ break;
+ case 'video':
+ switch ($field) {
+ case 'title':
+ $sql = "`video`.`title`";
+ break;
+ case 'resolution':
+ $sql = "`video`.`resolution_x`";
+ break;
+ case 'length':
+ $sql = "`video`.`time`";
+ break;
+ case 'codec':
+ $sql = "`video`.`video_codec`";
+ break;
+ } // end switch on field
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end switch
+
+ if ($sql) { $sql_sort = "$sql $order,"; }
+
+ return $sql_sort;
+
+ } // sql_sort
+
+ /**
+ * resort_objects
+ * This takes the existing objects, looks at the current
+ * sort method and then re-sorts them This is internally
+ * called by the set_sort() function
+ */
+ private function resort_objects() {
+
+ // There are two ways to do this.. the easy way...
+ // and the vollmer way, hopefully we don't have to
+ // do it the vollmer way
+ if ($this->is_simple()) {
+ $sql = $this->get_sql(true);
+ }
+ else {
+ // First pull the objects
+ $objects = $this->get_saved();
+
+ // If there's nothing there don't do anything
+ if (!count($objects) or !is_array($objects)) {
+ return false;
+ }
+ $type = $this->get_type();
+ $where_sql = "WHERE `$type`.`id` IN (";
+
+ foreach ($objects as $object_id) {
+ $object_id = Dba::escape($object_id);
+ $where_sql .= "'$object_id',";
+ }
+ $where_sql = rtrim($where_sql,',');
+
+ $where_sql .= ")";
+
+ $sql = $this->get_base_sql();
+
+ $order_sql = " ORDER BY ";
+
+ foreach ($this->_state['sort'] as $key => $value) {
+ $order_sql .= $this->sql_sort($key, $value);
+ }
+ // Clean her up
+ $order_sql = rtrim($order_sql,"ORDER BY ");
+ $order_sql = rtrim($order_sql,",");
+
+ $sql = $sql . $this->get_join_sql() . $where_sql . $order_sql;
+ } // if not simple
+
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
+
+ $this->save_objects($results);
+
+ return true;
+
+ } // resort_objects
+
+ /**
+ * store
+ * This saves the current state to the database
+ */
+ public function store() {
+ $sid = Dba::escape(session_id());
+ $id = Dba::escape($this->id);
+ $data = Dba::escape(serialize($this->_state));
+
+ $sql = "UPDATE `tmp_browse` SET `data`='$data' " .
+ "WHERE `sid`='$sid' AND `id`='$id'";
+ $db_results = Dba::write($sql);
+ }
+
+ /**
+ * save_objects
+ * This takes the full array of object ids, often passed into show and
+ * if necessary it saves them
+ */
+ public function save_objects($object_ids) {
+
+ // Saving these objects has two operations, one holds it in
+ // a local variable and then second holds it in a row in the
+ // tmp_browse table
+
+ // Only do this if it's a not a simple browse
+ if (!$this->is_simple()) {
+ $this->_cache = $object_ids;
+ $this->set_total(count($object_ids));
+ $sid = Dba::escape(session_id());
+ $id = Dba::escape($this->id);
+ $data = Dba::escape(serialize($this->_cache));
+
+ $sql = "UPDATE `tmp_browse` SET `object_data`='$data' " .
+ "WHERE `sid`='$sid' AND `id`='$id'";
+ $db_results = Dba::write($sql);
+ } // save it
+
+ return true;
+
+ } // save_objects
+
+ /**
+ * get_state
+ * This is a debug only function
+ */
+ public function get_state() {
+
+ return $this->_state;
+
+ } // get_state
} // query
diff --git a/lib/class/radio.class.php b/lib/class/radio.class.php
index 02ca3bc8..101f60f7 100644
--- a/lib/class/radio.class.php
+++ b/lib/class/radio.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,191 +30,191 @@
*/
class Radio extends database_object implements media {
- /* DB based variables */
- public $id;
- public $name;
- public $site_url;
- public $url;
- public $frequency;
- public $call_sign;
- public $catalog;
+ /* DB based variables */
+ public $id;
+ public $name;
+ public $site_url;
+ public $url;
+ public $frequency;
+ public $call_sign;
+ public $catalog;
- /**
- * Constructor
- * This takes a flagged.id and then pulls in the information for said flag entry
- */
- public function __construct($id) {
+ /**
+ * Constructor
+ * This takes a flagged.id and then pulls in the information for said flag entry
+ */
+ public function __construct($id) {
- $info = $this->get_info($id,'live_stream');
+ $info = $this->get_info($id,'live_stream');
- // Set the vars
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
-
- } // constructor
-
- /**
- * format
- * This takes the normal data from the database and makes it pretty
- * for the users, the new variables are put in f_??? and f_???_link
- */
- public function format() {
-
- // Default link used on the rightbar
- $this->f_link = "<a href=\"$this->url\">$this->name</a>";
+ // Set the vars
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
+
+ } // constructor
+
+ /**
+ * format
+ * This takes the normal data from the database and makes it pretty
+ * for the users, the new variables are put in f_??? and f_???_link
+ */
+ public function format() {
+
+ // Default link used on the rightbar
+ $this->f_link = "<a href=\"$this->url\">$this->name</a>";
- $this->f_name_link = "<a target=\"_blank\" href=\"$this->site_url\">$this->name</a>";
- $this->f_callsign = scrub_out($this->call_sign);
- $this->f_frequency = scrub_out($this->frequency);
+ $this->f_name_link = "<a target=\"_blank\" href=\"$this->site_url\">$this->name</a>";
+ $this->f_callsign = scrub_out($this->call_sign);
+ $this->f_frequency = scrub_out($this->frequency);
- return true;
+ return true;
- } // format
+ } // format
- /**
- * update
- * This is a static function that takes a key'd array for input
- * it depends on a ID element to determine which radio element it
- * should be updating
- */
- public static function update($data) {
+ /**
+ * update
+ * This is a static function that takes a key'd array for input
+ * it depends on a ID element to determine which radio element it
+ * should be updating
+ */
+ public static function update($data) {
- // Verify the incoming data
- if (!$data['id']) {
- Error::add('general', T_('Missing ID'));
- }
+ // Verify the incoming data
+ if (!$data['id']) {
+ Error::add('general', T_('Missing ID'));
+ }
- if (!$data['name']) {
- Error::add('general', T_('Name Required'));
- }
-
- $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp');
+ if (!$data['name']) {
+ Error::add('general', T_('Name Required'));
+ }
+
+ $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp');
- $elements = explode(":",$data['url']);
+ $elements = explode(":",$data['url']);
- if (!in_array($elements['0'],$allowed_array)) {
- Error::add('general', T_('Invalid URL must be mms:// , https:// or http://'));
- }
+ if (!in_array($elements['0'],$allowed_array)) {
+ Error::add('general', T_('Invalid URL must be mms:// , https:// or http://'));
+ }
- if (Error::occurred()) {
- return false;
- }
+ if (Error::occurred()) {
+ return false;
+ }
- // Setup the data
- $name = Dba::escape($data['name']);
- $site_url = Dba::escape($data['site_url']);
- $url = Dba::escape($data['url']);
- $frequency = Dba::escape($data['frequency']);
- $call_sign = Dba::escape($data['call_sign']);
- $id = Dba::escape($data['id']);
+ // Setup the data
+ $name = Dba::escape($data['name']);
+ $site_url = Dba::escape($data['site_url']);
+ $url = Dba::escape($data['url']);
+ $frequency = Dba::escape($data['frequency']);
+ $call_sign = Dba::escape($data['call_sign']);
+ $id = Dba::escape($data['id']);
- $sql = "UPDATE `live_stream` SET `name`='$name',`site_url`='$site_url',`url`='$url'" .
- ",`frequency`='$frequency',`call_sign`='$call_sign' WHERE `id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `live_stream` SET `name`='$name',`site_url`='$site_url',`url`='$url'" .
+ ",`frequency`='$frequency',`call_sign`='$call_sign' WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
- return $db_results;
+ return $db_results;
- } // update
+ } // update
- /**
- * create
- * This is a static function that takes a key'd array for input
- * and if everything is good creates the object.
- */
- public static function create($data) {
+ /**
+ * create
+ * This is a static function that takes a key'd array for input
+ * and if everything is good creates the object.
+ */
+ public static function create($data) {
- // Make sure we've got a name
- if (!strlen($data['name'])) {
- Error::add('name', T_('Name Required'));
- }
+ // Make sure we've got a name
+ if (!strlen($data['name'])) {
+ Error::add('name', T_('Name Required'));
+ }
- $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp');
+ $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp');
- $elements = explode(":",$data['url']);
+ $elements = explode(":",$data['url']);
- if (!in_array($elements['0'],$allowed_array)) {
- Error::add('url', T_('Invalid URL must be http:// or https://'));
- }
+ if (!in_array($elements['0'],$allowed_array)) {
+ Error::add('url', T_('Invalid URL must be http:// or https://'));
+ }
- // Make sure it's a real catalog
- $catalog = new Catalog($data['catalog']);
- if (!$catalog->name) {
- Error::add('catalog', T_('Invalid Catalog'));
- }
+ // Make sure it's a real catalog
+ $catalog = new Catalog($data['catalog']);
+ if (!$catalog->name) {
+ Error::add('catalog', T_('Invalid Catalog'));
+ }
- if (Error::occurred()) { return false; }
+ if (Error::occurred()) { return false; }
- // Clean up the input
- $name = Dba::escape($data['name']);
- $site_url = Dba::escape($data['site_url']);
- $url = Dba::escape($data['url']);
- $catalog = $catalog->id;
- $frequency = Dba::escape($data['frequency']);
- $call_sign = Dba::escape($data['call_sign']);
+ // Clean up the input
+ $name = Dba::escape($data['name']);
+ $site_url = Dba::escape($data['site_url']);
+ $url = Dba::escape($data['url']);
+ $catalog = $catalog->id;
+ $frequency = Dba::escape($data['frequency']);
+ $call_sign = Dba::escape($data['call_sign']);
- // If we've made it this far everything must be ok... I hope
- $sql = "INSERT INTO `live_stream` (`name`,`site_url`,`url`,`catalog`,`frequency`,`call_sign`) " .
- "VALUES ('$name','$site_url','$url','$catalog','$frequency','$call_sign')";
- $db_results = Dba::write($sql);
+ // If we've made it this far everything must be ok... I hope
+ $sql = "INSERT INTO `live_stream` (`name`,`site_url`,`url`,`catalog`,`frequency`,`call_sign`) " .
+ "VALUES ('$name','$site_url','$url','$catalog','$frequency','$call_sign')";
+ $db_results = Dba::write($sql);
- return $db_results;
+ return $db_results;
- } // create
+ } // create
- /**
- * delete
- * This deletes the current object from the database
- */
- public function delete() {
+ /**
+ * delete
+ * This deletes the current object from the database
+ */
+ public function delete() {
- $id = Dba::escape($this->id);
+ $id = Dba::escape($this->id);
- $sql = "DELETE FROM `live_stream` WHERE `id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `live_stream` WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // delete
+ } // delete
- /**
- * get_stream_types
- * This is needed by the media interface
- */
- public function get_stream_types() {
- return array('foreign');
- } // native_stream
+ /**
+ * get_stream_types
+ * This is needed by the media interface
+ */
+ public function get_stream_types() {
+ return array('foreign');
+ } // native_stream
- /**
- * play_url
- * This is needed by the media interface
- */
- public static function play_url($oid,$sid='',$force_http='') {
+ /**
+ * play_url
+ * This is needed by the media interface
+ */
+ public static function play_url($oid,$sid='',$force_http='') {
- $radio = new Radio($oid);
+ $radio = new Radio($oid);
- return $radio->url;
+ return $radio->url;
- } // play_url
+ } // play_url
- /**
- * has_flag
- * This is needed by the media interface
- */
- public function has_flag() {
+ /**
+ * has_flag
+ * This is needed by the media interface
+ */
+ public function has_flag() {
- } // has_flag
+ } // has_flag
- /**
- * get_transcode_settings
- *
- * This will probably never be implemented
- */
- public function get_transcode_settings() {
- return false;
- }
+ /**
+ * get_transcode_settings
+ *
+ * This will probably never be implemented
+ */
+ public function get_transcode_settings() {
+ return false;
+ }
} //end of radio class
diff --git a/lib/class/random.class.php b/lib/class/random.class.php
index 5f383c7c..c7204392 100644
--- a/lib/class/random.class.php
+++ b/lib/class/random.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,422 +30,422 @@
*/
class Random implements media {
- public $type;
- public $id;
+ public $type;
+ public $id;
- /**
- * Constructor
- * nothing to see here, move along
- */
- public function __construct($id) {
+ /**
+ * Constructor
+ * nothing to see here, move along
+ */
+ public function __construct($id) {
- $this->type = Random::get_id_type($id);
- $this->id = intval($id);
+ $this->type = Random::get_id_type($id);
+ $this->id = intval($id);
- } // constructor
+ } // constructor
- /**
- * album
- * This returns the ID of a random album, nothing special
- */
- public static function album() {
+ /**
+ * album
+ * This returns the ID of a random album, nothing special
+ */
+ public static function album() {
- $sql = "SELECT `id` FROM `album` ORDER BY RAND() LIMIT 1";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `album` ORDER BY RAND() LIMIT 1";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- return $results['id'];
+ return $results['id'];
- } // album
+ } // album
- /**
- * artist
- * This returns the ID of a random artist, nothing special here for now
- */
- public static function artist() {
+ /**
+ * artist
+ * This returns the ID of a random artist, nothing special here for now
+ */
+ public static function artist() {
- $sql = "SELECT `id` FROM `artist` ORDER BY RAND() LIMIT 1";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `artist` ORDER BY RAND() LIMIT 1";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- return $results['id'];
+ return $results['id'];
- } // artist
+ } // artist
- /**
- * playlist
- * This returns a random Playlist with songs little bit of extra
- * logic require
- */
- public static function playlist() {
+ /**
+ * playlist
+ * This returns a random Playlist with songs little bit of extra
+ * logic require
+ */
+ public static function playlist() {
- $sql = "SELECT `playlist`.`id` FROM `playlist` LEFT JOIN `playlist_data` " .
- " ON `playlist`.`id`=`playlist_data`.`playlist` WHERE `playlist_data`.`object_id` IS NOT NULL " .
- " ORDER BY RAND()";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `playlist`.`id` FROM `playlist` LEFT JOIN `playlist_data` " .
+ " ON `playlist`.`id`=`playlist_data`.`playlist` WHERE `playlist_data`.`object_id` IS NOT NULL " .
+ " ORDER BY RAND()";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- return $results['id'];
+ return $results['id'];
- } // playlist
+ } // playlist
- /**
- * play_url
- * This generates a random play url based on the passed type
- * and returns it
- */
- public static function play_url($id,$sid='',$force_http='') {
+ /**
+ * play_url
+ * This generates a random play url based on the passed type
+ * and returns it
+ */
+ public static function play_url($id,$sid='',$force_http='') {
- if (!$type = self::get_id_type($id)) {
- return false;
- }
+ if (!$type = self::get_id_type($id)) {
+ return false;
+ }
- $uid = $GLOBALS['user']->id;
+ $uid = $GLOBALS['user']->id;
- $url = Stream::get_base_url() . "random=1&type=$type&uid=$uid";
+ $url = Stream::get_base_url() . "random=1&type=$type&uid=$uid";
- return $url;
+ return $url;
- } // play_url
+ } // play_url
- /**
- * get_single_song
- * This returns a single song pulled based on the passed random method
- */
- public static function get_single_song($type) {
+ /**
+ * get_single_song
+ * This returns a single song pulled based on the passed random method
+ */
+ public static function get_single_song($type) {
- if (!$type = self::validate_type($type)) {
- return false;
- }
+ if (!$type = self::validate_type($type)) {
+ return false;
+ }
- $method_name = 'get_' . $type;
+ $method_name = 'get_' . $type;
- if (method_exists('Random',$method_name)) {
- $song_ids = self::$method_name(1);
- $song_id = array_pop($song_ids);
- }
+ if (method_exists('Random',$method_name)) {
+ $song_ids = self::$method_name(1);
+ $song_id = array_pop($song_ids);
+ }
- return $song_id;
+ return $song_id;
- } // get_single_song
+ } // get_single_song
- /**
- * get_default
- * This just randomly picks a song at whim from all catalogs
- * nothing special here...
- */
- public static function get_default($limit) {
+ /**
+ * get_default
+ * This just randomly picks a song at whim from all catalogs
+ * nothing special here...
+ */
+ public static function get_default($limit) {
- $results = array();
+ $results = array();
- $sql = "SELECT `id` FROM `song` ORDER BY RAND() LIMIT $limit";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `song` ORDER BY RAND() LIMIT $limit";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_default
+ } // get_default
- /**
- * get_album
- * This looks at the last album played by the current user and
- * picks something else in the same album
- */
- public static function get_album($limit) {
+ /**
+ * get_album
+ * This looks at the last album played by the current user and
+ * picks something else in the same album
+ */
+ public static function get_album($limit) {
- $results = array();
-
- // Get the last album playbed by us
- $data = $GLOBALS['user']->get_recently_played('1','album');
- if ($data['0']) {
- $where_sql = " WHERE `album`='" . $data['0'] . "' ";
- }
+ $results = array();
+
+ // Get the last album playbed by us
+ $data = $GLOBALS['user']->get_recently_played('1','album');
+ if ($data['0']) {
+ $where_sql = " WHERE `album`='" . $data['0'] . "' ";
+ }
- $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
-
- return $results;
-
- } // get_album
-
- /**
- * get_artist
- * This looks at the last artist played and then randomly picks a song from the
- * same artist
- */
- public static function get_artist($limit) {
-
- $results = array();
-
- $data = $GLOBALS['user']->get_recently_played('1','artist');
- if ($data['0']) {
- $where_sql = " WHERE `artist`='" . $data['0'] . "' ";
- }
-
- $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
-
- return $results;
-
- } // get_artist
-
- /**
- * advanced
- * This processes the results of a post from a form and returns an
- * array of song items that were returned from said randomness
- */
- public static function advanced($type, $data) {
-
- /* Figure out our object limit */
- $limit = intval($data['random']);
-
- // Generate our matchlist
-
- /* If they've passed -1 as limit then get everything */
- if ($data['random'] == "-1") { unset($data['random']); }
- else { $limit_sql = "LIMIT " . Dba::escape($limit); }
-
- $search_data = Search::clean_request($data);
-
- $search_info = false;
-
- if (count($search_data) > 1) {
- $search = new Search($type);
- $search->parse_rules($search_data);
- $search_info = $search->to_sql();
- }
-
- switch ($type) {
- case 'song':
- $sql = "SELECT `song`.`id`, `size`, `time` " .
- "FROM `song` ";
- if ($search_info) {
- $sql .= $search_info['table_sql'];
- $sql .= ' WHERE ' . $search_info['where_sql'];
- }
- break;
- case 'album':
- $sql = "SELECT `album`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `album` ";
- if (! $search_info || ! $search_info['join']['song']) {
- $sql .= "LEFT JOIN `song` ON `song`.`album`=`album`.`id` ";
- }
- if ($search_info) {
- $sql .= $search_info['table_sql'];
- $sql .= ' WHERE ' . $search_info['where_sql'];
- }
- $sql .= ' GROUP BY `album`.`id`';
- break;
- case 'artist':
- $sql = "SELECT `artist`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `artist` ";
- if (! $search_info || ! $search_info['join']['song']) {
- $sql .= "LEFT JOIN `song` ON `song`.`artist`=`artist`.`id` ";
- }
- if ($search_info) {
- $sql .= $search_info['table_sql'];
- $sql .= ' WHERE ' . $search_info['where_sql'];
- }
- $sql .= ' GROUP BY `artist`.`id`';
- break;
- }
- $sql .= " ORDER BY RAND() $limit_sql";
-
- // Run the query generated above so we can while it
- $db_results = Dba::read($sql);
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
-
- // If size limit is specified
- if ($data['size_limit']) {
- // Convert
- $new_size = ($row['size'] / 1024) / 1024;
-
- // Only fuzzy 100 times
- if ($fuzzy_size > 100) {
- break;
- }
-
- // Add and check, skip if over size
- if (($size_total + $new_size) > $data['size_limit']) {
- $fuzzy_size++;
- continue;
- }
-
- $size_total = $size_total + $new_size;
- $results[] = $row['id'];
-
- // If we are within 4mb of target then jump ship
- if (($data['size_limit'] - floor($size_total)) < 4) {
- break; }
- } // if size_limit
-
- // If length really does matter
- if ($data['length']) {
- // base on min, seconds are for chumps and chumpettes
- $new_time = floor($row['time'] / 60);
-
- if ($fuzzy_time > 100) {
- break;;
- }
-
- // If the new one would go over skip!
- if (($time_total + $new_time) > $data['length']) {
- $fuzzy_time++;
- continue;
- }
-
- $time_total = $time_total + $new_time;
- $results[] = $row['id'];
-
- // If there are less then 2 min of free space return
- if (($data['length'] - $time_total) < 2) {
- return $results;
- }
- } // if length does matter
-
- if (!$data['size_limit'] && !$data['length']) {
- $results[] = $row['id'];
- }
-
- } // end while results
-
- switch ($type) {
- case 'song':
- return $results;
- break;
- case 'album':
- $songs = array();
- foreach ($results as $result) {
- $album = new Album($result);
- $songs = array_merge($songs, $album->get_songs());
- }
- return $songs;
- break;
- case 'artist':
- $songs = array();
- foreach ($results as $result) {
- $artist = new Artist($result);
- $songs = array_merge($songs, $artist->get_songs());
- }
- return $songs;
- break;
- default:
- return false;
- break;
- }
- } // advanced
-
- /**
- * get_type_name
- * This returns a 'purrty' name for the different random types
- */
- public static function get_type_name($type) {
-
- switch ($type) {
- case 'album':
- return T_('Related Album');
- break;
- case 'genre':
- return T_('Related Genre');
- break;
- case 'artist':
- return T_('Related Artist');
- break;
- default:
- return T_('Pure Random');
- break;
- } // end switch
-
- } // get_type_name
-
- /**
- * get_type_id
- * This takes random type and returns the ID
- * MOTHER OF PEARL THIS MAKES BABY JESUS CRY
- * HACK HACK HACK HACK HACK HACK HACK HACK
- */
- public static function get_type_id($type) {
-
- switch ($type) {
- case 'album':
- return '1';
- break;
- case 'artist':
- return '2';
- break;
- case 'tag':
- return '3';
- break;
- default:
- return '4';
- break;
- }
-
- } // get_type_id
-
- /**
- * get_id_name
- * This takes an ID and returns the 'name' of the random dealie
- * HACK HACK HACK HACK HACK HACK HACK
- * Can you tell I don't like this code?
- */
- public static function get_id_type($id) {
-
- switch ($id) {
- case '1':
- return 'album';
- break;
- case '2':
- return 'artist';
- break;
- case '3':
- return 'tag';
- break;
- default:
- return 'default';
- break;
- } // end switch
-
- } // get_id_name
-
- /**
- * validate_type
- * this validates the random type
- */
- public static function validate_type($type) {
-
- switch ($type) {
- case 'default':
- case 'genre':
- case 'album':
- case 'artist':
- case 'rated':
- return $type;
- break;
- } // end switch
-
- return 'default';
-
- } // validate_type
-
- public function native_stream() { }
- public function stream_cmd() { }
- public function has_flag() { }
- public function format() { }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
+
+ return $results;
+
+ } // get_album
+
+ /**
+ * get_artist
+ * This looks at the last artist played and then randomly picks a song from the
+ * same artist
+ */
+ public static function get_artist($limit) {
+
+ $results = array();
+
+ $data = $GLOBALS['user']->get_recently_played('1','artist');
+ if ($data['0']) {
+ $where_sql = " WHERE `artist`='" . $data['0'] . "' ";
+ }
+
+ $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
+
+ return $results;
+
+ } // get_artist
+
+ /**
+ * advanced
+ * This processes the results of a post from a form and returns an
+ * array of song items that were returned from said randomness
+ */
+ public static function advanced($type, $data) {
+
+ /* Figure out our object limit */
+ $limit = intval($data['random']);
+
+ // Generate our matchlist
+
+ /* If they've passed -1 as limit then get everything */
+ if ($data['random'] == "-1") { unset($data['random']); }
+ else { $limit_sql = "LIMIT " . Dba::escape($limit); }
+
+ $search_data = Search::clean_request($data);
+
+ $search_info = false;
+
+ if (count($search_data) > 1) {
+ $search = new Search($type);
+ $search->parse_rules($search_data);
+ $search_info = $search->to_sql();
+ }
+
+ switch ($type) {
+ case 'song':
+ $sql = "SELECT `song`.`id`, `size`, `time` " .
+ "FROM `song` ";
+ if ($search_info) {
+ $sql .= $search_info['table_sql'];
+ $sql .= ' WHERE ' . $search_info['where_sql'];
+ }
+ break;
+ case 'album':
+ $sql = "SELECT `album`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `album` ";
+ if (! $search_info || ! $search_info['join']['song']) {
+ $sql .= "LEFT JOIN `song` ON `song`.`album`=`album`.`id` ";
+ }
+ if ($search_info) {
+ $sql .= $search_info['table_sql'];
+ $sql .= ' WHERE ' . $search_info['where_sql'];
+ }
+ $sql .= ' GROUP BY `album`.`id`';
+ break;
+ case 'artist':
+ $sql = "SELECT `artist`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `artist` ";
+ if (! $search_info || ! $search_info['join']['song']) {
+ $sql .= "LEFT JOIN `song` ON `song`.`artist`=`artist`.`id` ";
+ }
+ if ($search_info) {
+ $sql .= $search_info['table_sql'];
+ $sql .= ' WHERE ' . $search_info['where_sql'];
+ }
+ $sql .= ' GROUP BY `artist`.`id`';
+ break;
+ }
+ $sql .= " ORDER BY RAND() $limit_sql";
+
+ // Run the query generated above so we can while it
+ $db_results = Dba::read($sql);
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+
+ // If size limit is specified
+ if ($data['size_limit']) {
+ // Convert
+ $new_size = ($row['size'] / 1024) / 1024;
+
+ // Only fuzzy 100 times
+ if ($fuzzy_size > 100) {
+ break;
+ }
+
+ // Add and check, skip if over size
+ if (($size_total + $new_size) > $data['size_limit']) {
+ $fuzzy_size++;
+ continue;
+ }
+
+ $size_total = $size_total + $new_size;
+ $results[] = $row['id'];
+
+ // If we are within 4mb of target then jump ship
+ if (($data['size_limit'] - floor($size_total)) < 4) {
+ break; }
+ } // if size_limit
+
+ // If length really does matter
+ if ($data['length']) {
+ // base on min, seconds are for chumps and chumpettes
+ $new_time = floor($row['time'] / 60);
+
+ if ($fuzzy_time > 100) {
+ break;;
+ }
+
+ // If the new one would go over skip!
+ if (($time_total + $new_time) > $data['length']) {
+ $fuzzy_time++;
+ continue;
+ }
+
+ $time_total = $time_total + $new_time;
+ $results[] = $row['id'];
+
+ // If there are less then 2 min of free space return
+ if (($data['length'] - $time_total) < 2) {
+ return $results;
+ }
+ } // if length does matter
+
+ if (!$data['size_limit'] && !$data['length']) {
+ $results[] = $row['id'];
+ }
+
+ } // end while results
+
+ switch ($type) {
+ case 'song':
+ return $results;
+ break;
+ case 'album':
+ $songs = array();
+ foreach ($results as $result) {
+ $album = new Album($result);
+ $songs = array_merge($songs, $album->get_songs());
+ }
+ return $songs;
+ break;
+ case 'artist':
+ $songs = array();
+ foreach ($results as $result) {
+ $artist = new Artist($result);
+ $songs = array_merge($songs, $artist->get_songs());
+ }
+ return $songs;
+ break;
+ default:
+ return false;
+ break;
+ }
+ } // advanced
+
+ /**
+ * get_type_name
+ * This returns a 'purrty' name for the different random types
+ */
+ public static function get_type_name($type) {
+
+ switch ($type) {
+ case 'album':
+ return T_('Related Album');
+ break;
+ case 'genre':
+ return T_('Related Genre');
+ break;
+ case 'artist':
+ return T_('Related Artist');
+ break;
+ default:
+ return T_('Pure Random');
+ break;
+ } // end switch
+
+ } // get_type_name
+
+ /**
+ * get_type_id
+ * This takes random type and returns the ID
+ * MOTHER OF PEARL THIS MAKES BABY JESUS CRY
+ * HACK HACK HACK HACK HACK HACK HACK HACK
+ */
+ public static function get_type_id($type) {
+
+ switch ($type) {
+ case 'album':
+ return '1';
+ break;
+ case 'artist':
+ return '2';
+ break;
+ case 'tag':
+ return '3';
+ break;
+ default:
+ return '4';
+ break;
+ }
+
+ } // get_type_id
+
+ /**
+ * get_id_name
+ * This takes an ID and returns the 'name' of the random dealie
+ * HACK HACK HACK HACK HACK HACK HACK
+ * Can you tell I don't like this code?
+ */
+ public static function get_id_type($id) {
+
+ switch ($id) {
+ case '1':
+ return 'album';
+ break;
+ case '2':
+ return 'artist';
+ break;
+ case '3':
+ return 'tag';
+ break;
+ default:
+ return 'default';
+ break;
+ } // end switch
+
+ } // get_id_name
+
+ /**
+ * validate_type
+ * this validates the random type
+ */
+ public static function validate_type($type) {
+
+ switch ($type) {
+ case 'default':
+ case 'genre':
+ case 'album':
+ case 'artist':
+ case 'rated':
+ return $type;
+ break;
+ } // end switch
+
+ return 'default';
+
+ } // validate_type
+
+ public function native_stream() { }
+ public function stream_cmd() { }
+ public function has_flag() { }
+ public function format() { }
} //end of random class
diff --git a/lib/class/rating.class.php b/lib/class/rating.class.php
index 0943de2f..76b8c85e 100644
--- a/lib/class/rating.class.php
+++ b/lib/class/rating.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,215 +28,215 @@
*/
class Rating extends database_object {
- // Public variables
- public $id; // The ID of the object rated
- public $type; // The type of object we want
-
- /**
- * Constructor
- * This is run every time a new object is created, and requires
- * the id and type of object that we need to pull the rating for
- */
- public function __construct($id, $type) {
- $id = intval($id);
- $type = Dba::escape($type);
-
- $this->id = $id;
- $this->type = $type;
-
- return true;
-
- } // Constructor
-
- /**
- * gc
- *
- * Remove ratings for items that no longer exist.
- */
- public static function gc() {
- foreach(array('song', 'album', 'artist', 'video') as $object_type) {
- Dba::write("DELETE FROM `rating` USING `rating` LEFT JOIN `$object_type` ON `$object_type`.`id` = `rating`.`object_type` WHERE `object_type` = '$object_type` AND `$object_type`.`id` IS NULL");
- }
- }
-
- /**
- * build_cache
- * This attempts to get everything we'll need for this page load in a
- * single query, saving on connection overhead
- */
- public static function build_cache($type, $ids) {
-
- if (!is_array($ids) OR !count($ids)) { return false; }
-
- $user_id = intval($GLOBALS['user']->id);
- $ratings = array();
- $user_ratings = array();
-
- $idlist = '(' . implode(',', $ids) . ')';
- $sql = "SELECT `rating`, `object_id` FROM `rating` " .
- "WHERE `user`='$user_id' AND `object_id` IN $idlist " .
- "AND `object_type`='$type'";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $user_ratings[$row['object_id']] = $row['rating'];
- }
-
- $sql = "SELECT AVG(`rating`) as `rating`, `object_id` FROM " .
- "`rating` WHERE `object_id` IN $idlist AND " .
- "`object_type`='$type' GROUP BY `object_id`";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $ratings[$row['object_id']] = $row['rating'];
- }
-
- foreach ($ids as $id) {
- // First store the user-specific rating
- if (!isset($user_ratings[$id])) {
- $rating = 0;
- }
- else {
- $rating = intval($user_ratings[$id]);
- }
- parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating);
-
- // Then store the average
- if (!isset($ratings[$id])) {
- $rating = 0;
- }
- else {
- $rating = round($ratings[$id]['rating'], 1);
- }
- parent::add_to_cache('rating_' . $type . '_all', $id, $rating);
- }
-
- return true;
-
- } // build_cache
-
- /**
- * get_user_rating
- * Get a user's rating. If no userid is passed in, we use the currently
- * logged in user.
- */
- public function get_user_rating($user_id = null) {
-
- $id = intval($this->id);
- $type = Dba::escape($this->type);
- if (is_null($user_id)) {
- $user_id = $GLOBALS['user']->id;
- }
- $user_id = intval($user_id);
-
- $key = 'rating_' . $type . '_user' . $user_id;
- if (parent::is_cached($key, $id)) {
- return parent::get_from_cache($key, $id);
- }
-
- $sql = "SELECT `rating` FROM `rating` WHERE `user`='$user_id' ".
- "AND `object_id`='$id' AND `object_type`='$type'";
- $db_results = Dba::read($sql);
-
- $rating = 0;
-
- if ($results = Dba::fetch_assoc($db_results)) {
- $rating = $results['rating'];
- }
-
- parent::add_to_cache($key, $id, $rating);
- return $rating;
-
- } // get_user_rating
-
- /**
- * get_average_rating
- * Get the floored average rating of what everyone has rated this object
- * as. This is shown if there is no personal rating.
- */
- public function get_average_rating() {
-
- $id = intval($this->id);
- $type = Dba::escape($this->type);
-
- if (parent::is_cached('rating_' . $type . '_all', $id)) {
- return parent::get_from_cache('rating_' . $type . '_user', $id);
- }
-
- $sql = "SELECT AVG(`rating`) as `rating` FROM `rating` WHERE " .
- "`object_id`='$id' AND `object_type`='$type'";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
-
- parent::add_to_cache('rating_' . $type . '_all', $id, $results['rating']);
- return $results['rating'];
-
- } // get_average_rating
-
- /**
- * set_rating
- * This function sets the rating for the current object.
- * If no userid is passed in, we use the currently logged in user.
- */
- public function set_rating($rating, $user_id = null) {
- $id = intval($this->id);
- $type = Dba::escape($this->type);
- $rating = intval($rating);
- if (is_null($user_id)) {
- $user_id = $GLOBALS['user']->id;
- }
- $user_id = intval($user_id);
-
- debug_event('Rating', "Setting rating for $type $id to $rating", 5);
-
- // If score is -1, then remove rating
- if ($rating == '-1') {
- $sql = "DELETE FROM `rating` WHERE " .
- "`object_id`='$this->id' AND " .
- "`object_type`='$this->type' AND " .
- "`user`='$user_id'";
- }
- else {
- $sql = "REPLACE INTO `rating` " .
- "(`object_id`, `object_type`, `rating`, `user`) " .
- "VALUES ('$id', '$type', '$rating', '$user_id')";
- }
- $db_results = Dba::write($sql);
-
- parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating);
-
- foreach (Plugin::get_plugins('save_rating') as $plugin_name) {
- $plugin = new Plugin($plugin_name);
- if ($plugin->load()) {
- $plugin->_plugin->save_rating($this, $rating);
- }
- }
-
- return true;
-
- } // set_rating
-
- /**
- * show
- * This takes an id and a type and displays the rating if ratings are
- * enabled. If $static is true, the rating won't be editable.
- */
- public static function show($object_id, $type, $static=false) {
-
- // If ratings aren't enabled don't do anything
- if (!Config::get('ratings')) { return false; }
-
- $rating = new Rating($object_id, $type);
-
- if ($static) {
- require Config::get('prefix') . '/templates/show_static_object_rating.inc.php';
- }
- else {
- require Config::get('prefix') . '/templates/show_object_rating.inc.php';
- }
-
- } // show
+ // Public variables
+ public $id; // The ID of the object rated
+ public $type; // The type of object we want
+
+ /**
+ * Constructor
+ * This is run every time a new object is created, and requires
+ * the id and type of object that we need to pull the rating for
+ */
+ public function __construct($id, $type) {
+ $id = intval($id);
+ $type = Dba::escape($type);
+
+ $this->id = $id;
+ $this->type = $type;
+
+ return true;
+
+ } // Constructor
+
+ /**
+ * gc
+ *
+ * Remove ratings for items that no longer exist.
+ */
+ public static function gc() {
+ foreach(array('song', 'album', 'artist', 'video') as $object_type) {
+ Dba::write("DELETE FROM `rating` USING `rating` LEFT JOIN `$object_type` ON `$object_type`.`id` = `rating`.`object_type` WHERE `object_type` = '$object_type` AND `$object_type`.`id` IS NULL");
+ }
+ }
+
+ /**
+ * build_cache
+ * This attempts to get everything we'll need for this page load in a
+ * single query, saving on connection overhead
+ */
+ public static function build_cache($type, $ids) {
+
+ if (!is_array($ids) OR !count($ids)) { return false; }
+
+ $user_id = intval($GLOBALS['user']->id);
+ $ratings = array();
+ $user_ratings = array();
+
+ $idlist = '(' . implode(',', $ids) . ')';
+ $sql = "SELECT `rating`, `object_id` FROM `rating` " .
+ "WHERE `user`='$user_id' AND `object_id` IN $idlist " .
+ "AND `object_type`='$type'";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $user_ratings[$row['object_id']] = $row['rating'];
+ }
+
+ $sql = "SELECT AVG(`rating`) as `rating`, `object_id` FROM " .
+ "`rating` WHERE `object_id` IN $idlist AND " .
+ "`object_type`='$type' GROUP BY `object_id`";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $ratings[$row['object_id']] = $row['rating'];
+ }
+
+ foreach ($ids as $id) {
+ // First store the user-specific rating
+ if (!isset($user_ratings[$id])) {
+ $rating = 0;
+ }
+ else {
+ $rating = intval($user_ratings[$id]);
+ }
+ parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating);
+
+ // Then store the average
+ if (!isset($ratings[$id])) {
+ $rating = 0;
+ }
+ else {
+ $rating = round($ratings[$id]['rating'], 1);
+ }
+ parent::add_to_cache('rating_' . $type . '_all', $id, $rating);
+ }
+
+ return true;
+
+ } // build_cache
+
+ /**
+ * get_user_rating
+ * Get a user's rating. If no userid is passed in, we use the currently
+ * logged in user.
+ */
+ public function get_user_rating($user_id = null) {
+
+ $id = intval($this->id);
+ $type = Dba::escape($this->type);
+ if (is_null($user_id)) {
+ $user_id = $GLOBALS['user']->id;
+ }
+ $user_id = intval($user_id);
+
+ $key = 'rating_' . $type . '_user' . $user_id;
+ if (parent::is_cached($key, $id)) {
+ return parent::get_from_cache($key, $id);
+ }
+
+ $sql = "SELECT `rating` FROM `rating` WHERE `user`='$user_id' ".
+ "AND `object_id`='$id' AND `object_type`='$type'";
+ $db_results = Dba::read($sql);
+
+ $rating = 0;
+
+ if ($results = Dba::fetch_assoc($db_results)) {
+ $rating = $results['rating'];
+ }
+
+ parent::add_to_cache($key, $id, $rating);
+ return $rating;
+
+ } // get_user_rating
+
+ /**
+ * get_average_rating
+ * Get the floored average rating of what everyone has rated this object
+ * as. This is shown if there is no personal rating.
+ */
+ public function get_average_rating() {
+
+ $id = intval($this->id);
+ $type = Dba::escape($this->type);
+
+ if (parent::is_cached('rating_' . $type . '_all', $id)) {
+ return parent::get_from_cache('rating_' . $type . '_user', $id);
+ }
+
+ $sql = "SELECT AVG(`rating`) as `rating` FROM `rating` WHERE " .
+ "`object_id`='$id' AND `object_type`='$type'";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+
+ parent::add_to_cache('rating_' . $type . '_all', $id, $results['rating']);
+ return $results['rating'];
+
+ } // get_average_rating
+
+ /**
+ * set_rating
+ * This function sets the rating for the current object.
+ * If no userid is passed in, we use the currently logged in user.
+ */
+ public function set_rating($rating, $user_id = null) {
+ $id = intval($this->id);
+ $type = Dba::escape($this->type);
+ $rating = intval($rating);
+ if (is_null($user_id)) {
+ $user_id = $GLOBALS['user']->id;
+ }
+ $user_id = intval($user_id);
+
+ debug_event('Rating', "Setting rating for $type $id to $rating", 5);
+
+ // If score is -1, then remove rating
+ if ($rating == '-1') {
+ $sql = "DELETE FROM `rating` WHERE " .
+ "`object_id`='$this->id' AND " .
+ "`object_type`='$this->type' AND " .
+ "`user`='$user_id'";
+ }
+ else {
+ $sql = "REPLACE INTO `rating` " .
+ "(`object_id`, `object_type`, `rating`, `user`) " .
+ "VALUES ('$id', '$type', '$rating', '$user_id')";
+ }
+ $db_results = Dba::write($sql);
+
+ parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating);
+
+ foreach (Plugin::get_plugins('save_rating') as $plugin_name) {
+ $plugin = new Plugin($plugin_name);
+ if ($plugin->load()) {
+ $plugin->_plugin->save_rating($this, $rating);
+ }
+ }
+
+ return true;
+
+ } // set_rating
+
+ /**
+ * show
+ * This takes an id and a type and displays the rating if ratings are
+ * enabled. If $static is true, the rating won't be editable.
+ */
+ public static function show($object_id, $type, $static=false) {
+
+ // If ratings aren't enabled don't do anything
+ if (!Config::get('ratings')) { return false; }
+
+ $rating = new Rating($object_id, $type);
+
+ if ($static) {
+ require Config::get('prefix') . '/templates/show_static_object_rating.inc.php';
+ }
+ else {
+ require Config::get('prefix') . '/templates/show_object_rating.inc.php';
+ }
+
+ } // show
} //end rating class
?>
diff --git a/lib/class/recommendation.class.php b/lib/class/recommendation.class.php
index 98cd07e7..138d81b4 100644
--- a/lib/class/recommendation.class.php
+++ b/lib/class/recommendation.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,177 +22,177 @@
class Recommendation {
- /**
- * Constructor
- * Not on my watch, boyo.
- */
- private function __construct() {
- return false;
- } //constructor
-
- /**
- * get_lastfm_results
- * Runs a last.fm query and returns the parsed results
- */
- private static function get_lastfm_results($method, $query) {
- $api_key = Config::get('lastfm_api_key');
- $api_base = "http://ws.audioscrobbler.com/2.0/?method=";
- $url = $api_base . $method . '&api_key=' . $api_key . '&' . $query;
- debug_event('Recommendation', 'search url : ' . $url, 5);
-
- $snoopy = new Snoopy();
- if(Config::get('proxy_host') AND Config::get('proxy_port')) {
- $snoopy->proxy_user = Config::get('proxy_host');
- $snoopy->proxy_port = Config::get('proxy_port');
- $snoopy->proxy_user = Config::get('proxy_user');
- $snoopy->proxy_pass = Config::get('proxy_pass');
- }
- $snoopy->fetch($url);
- $content = $snoopy->results;
-
- return simplexml_load_string($content);
- } // get_lastfm_results
-
- /**
- * get_songs_like
- * Returns a list of similar songs
- */
- public static function get_songs_like($song_id, $limit = 5, $local_only = true) {
- $song = new Song($song_id);
-
- if (isset($song->mbid)) {
- $query = 'mbid=' . rawurlencode($song->mbid);
- }
- else {
- $query = 'track=' . rawurlencode($song->title);
- }
-
- if ($limit && !$local_only) {
- $query .= "&limit=$limit";
- }
-
- $xml = self::get_lastfm_results('track.getsimilar', $query);
-
- foreach ($xml->similartracks->children() as $child) {
- $name = $child->name;
- $local_id = null;
-
- $artist_name = $child->artist->name;
- $s_artist_name = Catalog::trim_prefix($artist_name);
- $s_artist_name = Dba::escape($s_artist_name['string']);
-
- $sql = "SELECT `song`.`id` FROM `song` " .
- "LEFT JOIN `artist` ON " .
- "`song`.`artist`=`artist`.`id` WHERE " .
- "`song`.`title`='" . Dba::escape($name) .
- "' AND `artist`.`name`='$s_artist_name'";
-
- $db_result = Dba::read($sql);
-
- if ($result = Dba::fetch_assoc($db_result)) {
- $local_id = $result['id'];
- }
-
- if (is_null($local_id)) {
- debug_event('Recommendation', "$name did not match any local song", 5);
- if (! $local_only) {
- $results[] = array(
- 'id' => null,
- 'title' => $name,
- 'artist' => $artist_name
- );
- }
- }
- else {
- debug_event('Recommendation', "$name matched local song $local_id", 5);
- $results[] = array(
- 'id' => $local_id,
- 'title' => $name
- );
- }
-
- if ($limit && count($results) >= $limit) {
- break;
- }
- }
-
- if (isset($results)) {
- return $results;
- }
-
- return false;
- }
-
- /**
- * get_artists_like
- * Returns a list of similar artists
- */
- public static function get_artists_like($artist_id, $limit = 5, $local_only = true) {
- $artist = new Artist($artist_id);
-
- $query = 'artist=' . rawurlencode($artist->name);
- if ($limit && !$local_only) {
- $query .= "&limit=$limit";
- }
-
- $xml = self::get_lastfm_results('artist.getsimilar', $query);
-
- foreach ($xml->similarartists->children() as $child) {
- $name = $child->name;
- $local_id = null;
-
- // First we check by MBID
- if ((string)$child->mbid) {
- $mbid = Dba::escape($child->mbid);
- $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'";
- $db_result = Dba::read($sql);
- if ($result = Dba::fetch_assoc($db_result)) {
- $local_id = $result['id'];
- }
- }
-
- // Then we fall back to the less likely to work exact
- // name match
- if (is_null($local_id)) {
- $searchname = Catalog::trim_prefix($name);
- $searchname = Dba::escape($searchname['string']);
- $sql = "SELECT `id` FROM `artist` WHERE `name`='$searchname'";
- $db_result = Dba::read($sql);
- if ($result = Dba::fetch_assoc($db_result)) {
- $local_id = $result['id'];
- }
- }
-
- // Then we give up
- if (is_null($local_id)) {
- debug_event('Recommendation', "$name did not match any local artist", 5);
- if (! $local_only) {
- $results[] = array(
- 'id' => null,
- 'name' => $name
- );
- }
- }
- else {
- debug_event('Recommendation', "$name matched local artist " . $local_id, 5);
- $results[] = array(
- 'id' => $local_id,
- 'name' => $name
- );
- }
-
- // Don't do more work than we have to
- if ($limit && count($results) >= $limit) {
- break;
- }
- }
-
- if (isset($results)) {
- return $results;
- }
-
- return false;
- } // get_artists_like
+ /**
+ * Constructor
+ * Not on my watch, boyo.
+ */
+ private function __construct() {
+ return false;
+ } //constructor
+
+ /**
+ * get_lastfm_results
+ * Runs a last.fm query and returns the parsed results
+ */
+ private static function get_lastfm_results($method, $query) {
+ $api_key = Config::get('lastfm_api_key');
+ $api_base = "http://ws.audioscrobbler.com/2.0/?method=";
+ $url = $api_base . $method . '&api_key=' . $api_key . '&' . $query;
+ debug_event('Recommendation', 'search url : ' . $url, 5);
+
+ $snoopy = new Snoopy();
+ if(Config::get('proxy_host') AND Config::get('proxy_port')) {
+ $snoopy->proxy_user = Config::get('proxy_host');
+ $snoopy->proxy_port = Config::get('proxy_port');
+ $snoopy->proxy_user = Config::get('proxy_user');
+ $snoopy->proxy_pass = Config::get('proxy_pass');
+ }
+ $snoopy->fetch($url);
+ $content = $snoopy->results;
+
+ return simplexml_load_string($content);
+ } // get_lastfm_results
+
+ /**
+ * get_songs_like
+ * Returns a list of similar songs
+ */
+ public static function get_songs_like($song_id, $limit = 5, $local_only = true) {
+ $song = new Song($song_id);
+
+ if (isset($song->mbid)) {
+ $query = 'mbid=' . rawurlencode($song->mbid);
+ }
+ else {
+ $query = 'track=' . rawurlencode($song->title);
+ }
+
+ if ($limit && !$local_only) {
+ $query .= "&limit=$limit";
+ }
+
+ $xml = self::get_lastfm_results('track.getsimilar', $query);
+
+ foreach ($xml->similartracks->children() as $child) {
+ $name = $child->name;
+ $local_id = null;
+
+ $artist_name = $child->artist->name;
+ $s_artist_name = Catalog::trim_prefix($artist_name);
+ $s_artist_name = Dba::escape($s_artist_name['string']);
+
+ $sql = "SELECT `song`.`id` FROM `song` " .
+ "LEFT JOIN `artist` ON " .
+ "`song`.`artist`=`artist`.`id` WHERE " .
+ "`song`.`title`='" . Dba::escape($name) .
+ "' AND `artist`.`name`='$s_artist_name'";
+
+ $db_result = Dba::read($sql);
+
+ if ($result = Dba::fetch_assoc($db_result)) {
+ $local_id = $result['id'];
+ }
+
+ if (is_null($local_id)) {
+ debug_event('Recommendation', "$name did not match any local song", 5);
+ if (! $local_only) {
+ $results[] = array(
+ 'id' => null,
+ 'title' => $name,
+ 'artist' => $artist_name
+ );
+ }
+ }
+ else {
+ debug_event('Recommendation', "$name matched local song $local_id", 5);
+ $results[] = array(
+ 'id' => $local_id,
+ 'title' => $name
+ );
+ }
+
+ if ($limit && count($results) >= $limit) {
+ break;
+ }
+ }
+
+ if (isset($results)) {
+ return $results;
+ }
+
+ return false;
+ }
+
+ /**
+ * get_artists_like
+ * Returns a list of similar artists
+ */
+ public static function get_artists_like($artist_id, $limit = 5, $local_only = true) {
+ $artist = new Artist($artist_id);
+
+ $query = 'artist=' . rawurlencode($artist->name);
+ if ($limit && !$local_only) {
+ $query .= "&limit=$limit";
+ }
+
+ $xml = self::get_lastfm_results('artist.getsimilar', $query);
+
+ foreach ($xml->similarartists->children() as $child) {
+ $name = $child->name;
+ $local_id = null;
+
+ // First we check by MBID
+ if ((string)$child->mbid) {
+ $mbid = Dba::escape($child->mbid);
+ $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'";
+ $db_result = Dba::read($sql);
+ if ($result = Dba::fetch_assoc($db_result)) {
+ $local_id = $result['id'];
+ }
+ }
+
+ // Then we fall back to the less likely to work exact
+ // name match
+ if (is_null($local_id)) {
+ $searchname = Catalog::trim_prefix($name);
+ $searchname = Dba::escape($searchname['string']);
+ $sql = "SELECT `id` FROM `artist` WHERE `name`='$searchname'";
+ $db_result = Dba::read($sql);
+ if ($result = Dba::fetch_assoc($db_result)) {
+ $local_id = $result['id'];
+ }
+ }
+
+ // Then we give up
+ if (is_null($local_id)) {
+ debug_event('Recommendation', "$name did not match any local artist", 5);
+ if (! $local_only) {
+ $results[] = array(
+ 'id' => null,
+ 'name' => $name
+ );
+ }
+ }
+ else {
+ debug_event('Recommendation', "$name matched local artist " . $local_id, 5);
+ $results[] = array(
+ 'id' => $local_id,
+ 'name' => $name
+ );
+ }
+
+ // Don't do more work than we have to
+ if ($limit && count($results) >= $limit) {
+ break;
+ }
+ }
+
+ if (isset($results)) {
+ return $results;
+ }
+
+ return false;
+ } // get_artists_like
} // end of recommendation class
?>
diff --git a/lib/class/registration.class.php b/lib/class/registration.class.php
index d22a23ab..5df8e563 100644
--- a/lib/class/registration.class.php
+++ b/lib/class/registration.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,29 +28,29 @@
*/
class Registration {
- /**
- * constructor
- * This is what is called when the class is loaded
- */
- public function __construct() {
+ /**
+ * constructor
+ * This is what is called when the class is loaded
+ */
+ public function __construct() {
- // Rien a faire
+ // Rien a faire
- } // constructor
+ } // constructor
- /**
- * send_confirmation
- * This sends the confirmation e-mail for the specified user
- */
- public static function send_confirmation($username, $fullname, $email, $password, $validation) {
- $mailer = new Ampache_Mail();
+ /**
+ * send_confirmation
+ * This sends the confirmation e-mail for the specified user
+ */
+ public static function send_confirmation($username, $fullname, $email, $password, $validation) {
+ $mailer = new Ampache_Mail();
- // We are the system
- $mailer->set_default_sender();
+ // We are the system
+ $mailer->set_default_sender();
- $mailer->subject = sprintf(T_("New User Registration at %s"), Config::get('site_title'));
+ $mailer->subject = sprintf(T_("New User Registration at %s"), Config::get('site_title'));
- $mailer->message = sprintf(T_("Thank you for registering\n\n
+ $mailer->message = sprintf(T_("Thank you for registering\n\n
Please keep this e-mail for your records. Your account information is as follows:
----------------------
Username: %s
@@ -64,14 +64,14 @@ Your account is currently inactive. You cannot use it until you've visited the f
Thank you for registering
"), $username, $password, Config::get('web_path') . "/register.php?action=validate&username=$username&auth=$validation");
- $mailer->recipient = $email;
- $mailer->recipient_name = $fullname;
+ $mailer->recipient = $email;
+ $mailer->recipient_name = $fullname;
- $mailer->send();
+ $mailer->send();
- // Check to see if the admin should be notified
- if (Config::get('admin_notify_reg')) {
- $mailer->message = sprintf(T_("A new user has registered
+ // Check to see if the admin should be notified
+ if (Config::get('admin_notify_reg')) {
+ $mailer->message = sprintf(T_("A new user has registered
The following values were entered.
Username: %s
@@ -80,34 +80,34 @@ E-mail: %s
"), $username, $fullname, $email);
- $mailer->send_to_group('admins');
- }
-
- return true;
+ $mailer->send_to_group('admins');
+ }
+
+ return true;
- } // send_confirmation
+ } // send_confirmation
- /**
- * show_agreement
- * This shows the registration agreement, /config/registration_agreement.php
- */
- public static function show_agreement() {
+ /**
+ * show_agreement
+ * This shows the registration agreement, /config/registration_agreement.php
+ */
+ public static function show_agreement() {
- $filename = Config::get('prefix') . '/config/registration_agreement.php';
+ $filename = Config::get('prefix') . '/config/registration_agreement.php';
- if (!file_exists($filename)) { return false; }
+ if (!file_exists($filename)) { return false; }
- /* Check for existance */
- $fp = fopen($filename,'r');
+ /* Check for existance */
+ $fp = fopen($filename,'r');
- if (!$fp) { return false; }
+ if (!$fp) { return false; }
- $data = fread($fp,filesize($filename));
+ $data = fread($fp,filesize($filename));
- /* Scrub and show */
- echo $data;
+ /* Scrub and show */
+ echo $data;
- } // show_agreement
+ } // show_agreement
} // end registration class
?>
diff --git a/lib/class/scrobbler.class.php b/lib/class/scrobbler.class.php
index 96ca84c8..f7b4482a 100644
--- a/lib/class/scrobbler.class.php
+++ b/lib/class/scrobbler.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,249 +22,249 @@
class scrobbler {
- public $error_msg;
- public $username;
- public $password;
- public $challenge;
- public $submit_host;
- public $submit_port;
- public $submit_url;
- public $queued_tracks;
- public $reset_handshake = false;
- public $scrobble_host = 'post.audioscrobbler.com';
-
- /**
- * Constructor
- * This is the constructer it takes a username and password
- */
- public function __construct($username, $password,$host='',$port='',$url='',$challenge='',$scrobble_host='') {
-
- $this->error_msg = '';
- $this->username = trim($username);
- $this->password = trim($password);
- $this->challenge = $challenge;
- $this->submit_host = $host;
- $this->submit_port = $port;
- $this->submit_url = $url;
- $this->queued_tracks = array();
- if ($scrobble_host) { $this->scrobble_host = $scrobble_host; }
-
- } // scrobbler
-
- /**
- * get_error_msg
- */
- public function get_error_msg() {
-
- return $this->error_msg;
-
- } // get_error_msg
-
- /**
- * get_queue_count
- */
- public 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
- */
- public function handshake() {
-
- $as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2);
- if(!$as_socket) {
- $this->error_msg = $errstr;
- return false;
- }
-
- $username = rawurlencode($this->username);
- $timestamp = time();
- $auth_token = rawurlencode(md5($this->password . $timestamp));
-
- $get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n";
-
- fwrite($as_socket, $get_string);
- fwrite($as_socket, "Host: $this->scrobble_host\r\n");
- fwrite($as_socket, "Accept: */*\r\n\r\n");
-
- $buffer = '';
- while(!feof($as_socket)) {
- $buffer .= fread($as_socket, 4096);
- }
- 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]);
-
- // Handle the fact Libre.FM has extranious values at the start of it's handshake response
- if(is_numeric(trim($response['0']))) {
- array_shift($response);
- debug_event('SCROBBLER','Junk in handshake, removing first line',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,7) == 'BADTIME') {
- $this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect';
- 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:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) {
- $host_parts = explode(":",$matches[1]);
- $data['submit_host'] = $host_parts[0];
- $data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80';
- $data['submit_url'] = '/' . $matches[2];
- } else {
- $this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer .
- "\n---------\nExpected:" . print_r($response, true);
- return false;
- }
-
- // Remove any extra junk around the challenge
- $data['challenge'] = trim($response[1]);
- return $data;
-
- } // 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.
- */
- public function queue_track($artist, $album, $title, $timestamp, $length,$track) {
-
- if ($length < 30) {
- debug_event('Scrobbler',"Not queuing track, too short",'5');
- return false;
- }
-
- $newtrack = array();
- $newtrack['artist'] = $artist;
- $newtrack['album'] = $album;
- $newtrack['title'] = $title;
- $newtrack['track'] = $track;
- $newtrack['length'] = $length;
- $newtrack['time'] = $timestamp;
-
- $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
- */
- public 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 = 's='.rawurlencode($this->challenge).'&';
-
- $i = 0;
-
- foreach($this->queued_tracks as $track) {
- $query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&";
- $query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&";
- $query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&";
- $i++;
- }
-
- if (!trim($this->submit_host) || !$this->submit_port) {
- $this->reset_handshake = true;
- return false;
- }
-
- $as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2);
-
- if(!$as_socket) {
- $this->error_msg = $errstr;
- $this->reset_handshake = true;
- 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, "User-Agent: Ampache/3.6\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");
- // Allow us to debug this
- debug_event('SCROBBLER','Query String:' . $query_str,6);
-
- $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';
- $this->reset_handshake = true;
- return false;
- }
- $response = explode("\n", $split_response[1]);
- if(!isset($response[0])) {
- $this->error_msg = 'Unknown error submitting tracks'.
- "\nDebug output:\n".$buffer;
- $this->reset_handshake = true;
- return false;
- }
- if(substr($response[0], 0, 6) == 'FAILED') {
- $this->error_msg = $response[0];
- $this->reset_handshake = true;
- return false;
- }
- if(substr($response[0], 0, 7) == 'BADAUTH') {
- $this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')';
- return false;
- }
- if (substr($response[0],0,10) == 'BADSESSION') {
- $this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')';
- $this->reset_handshake = true;
- return false;
- }
- if(substr($response[0], 0, 2) != 'OK') {
- $this->error_msg = 'Response Not ok, unknown error'.
- "\nDebug output:\n".$buffer;
- $this->reset_handshake = true;
- return false;
- }
-
- return true;
-
- } // submit_tracks
+ public $error_msg;
+ public $username;
+ public $password;
+ public $challenge;
+ public $submit_host;
+ public $submit_port;
+ public $submit_url;
+ public $queued_tracks;
+ public $reset_handshake = false;
+ public $scrobble_host = 'post.audioscrobbler.com';
+
+ /**
+ * Constructor
+ * This is the constructer it takes a username and password
+ */
+ public function __construct($username, $password,$host='',$port='',$url='',$challenge='',$scrobble_host='') {
+
+ $this->error_msg = '';
+ $this->username = trim($username);
+ $this->password = trim($password);
+ $this->challenge = $challenge;
+ $this->submit_host = $host;
+ $this->submit_port = $port;
+ $this->submit_url = $url;
+ $this->queued_tracks = array();
+ if ($scrobble_host) { $this->scrobble_host = $scrobble_host; }
+
+ } // scrobbler
+
+ /**
+ * get_error_msg
+ */
+ public function get_error_msg() {
+
+ return $this->error_msg;
+
+ } // get_error_msg
+
+ /**
+ * get_queue_count
+ */
+ public 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
+ */
+ public function handshake() {
+
+ $as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2);
+ if(!$as_socket) {
+ $this->error_msg = $errstr;
+ return false;
+ }
+
+ $username = rawurlencode($this->username);
+ $timestamp = time();
+ $auth_token = rawurlencode(md5($this->password . $timestamp));
+
+ $get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n";
+
+ fwrite($as_socket, $get_string);
+ fwrite($as_socket, "Host: $this->scrobble_host\r\n");
+ fwrite($as_socket, "Accept: */*\r\n\r\n");
+
+ $buffer = '';
+ while(!feof($as_socket)) {
+ $buffer .= fread($as_socket, 4096);
+ }
+ 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]);
+
+ // Handle the fact Libre.FM has extranious values at the start of it's handshake response
+ if(is_numeric(trim($response['0']))) {
+ array_shift($response);
+ debug_event('SCROBBLER','Junk in handshake, removing first line',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,7) == 'BADTIME') {
+ $this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect';
+ 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:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) {
+ $host_parts = explode(":",$matches[1]);
+ $data['submit_host'] = $host_parts[0];
+ $data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80';
+ $data['submit_url'] = '/' . $matches[2];
+ } else {
+ $this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer .
+ "\n---------\nExpected:" . print_r($response, true);
+ return false;
+ }
+
+ // Remove any extra junk around the challenge
+ $data['challenge'] = trim($response[1]);
+ return $data;
+
+ } // 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.
+ */
+ public function queue_track($artist, $album, $title, $timestamp, $length,$track) {
+
+ if ($length < 30) {
+ debug_event('Scrobbler',"Not queuing track, too short",'5');
+ return false;
+ }
+
+ $newtrack = array();
+ $newtrack['artist'] = $artist;
+ $newtrack['album'] = $album;
+ $newtrack['title'] = $title;
+ $newtrack['track'] = $track;
+ $newtrack['length'] = $length;
+ $newtrack['time'] = $timestamp;
+
+ $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
+ */
+ public 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 = 's='.rawurlencode($this->challenge).'&';
+
+ $i = 0;
+
+ foreach($this->queued_tracks as $track) {
+ $query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&";
+ $query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&";
+ $query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&";
+ $i++;
+ }
+
+ if (!trim($this->submit_host) || !$this->submit_port) {
+ $this->reset_handshake = true;
+ return false;
+ }
+
+ $as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2);
+
+ if(!$as_socket) {
+ $this->error_msg = $errstr;
+ $this->reset_handshake = true;
+ 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, "User-Agent: Ampache/3.6\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");
+ // Allow us to debug this
+ debug_event('SCROBBLER','Query String:' . $query_str,6);
+
+ $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';
+ $this->reset_handshake = true;
+ return false;
+ }
+ $response = explode("\n", $split_response[1]);
+ if(!isset($response[0])) {
+ $this->error_msg = 'Unknown error submitting tracks'.
+ "\nDebug output:\n".$buffer;
+ $this->reset_handshake = true;
+ return false;
+ }
+ if(substr($response[0], 0, 6) == 'FAILED') {
+ $this->error_msg = $response[0];
+ $this->reset_handshake = true;
+ return false;
+ }
+ if(substr($response[0], 0, 7) == 'BADAUTH') {
+ $this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')';
+ return false;
+ }
+ if (substr($response[0],0,10) == 'BADSESSION') {
+ $this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')';
+ $this->reset_handshake = true;
+ return false;
+ }
+ if(substr($response[0], 0, 2) != 'OK') {
+ $this->error_msg = 'Response Not ok, unknown error'.
+ "\nDebug output:\n".$buffer;
+ $this->reset_handshake = true;
+ return false;
+ }
+
+ return true;
+
+ } // submit_tracks
} // end audioscrobbler class
?>
diff --git a/lib/class/search.class.php b/lib/class/search.class.php
index dea0b41d..6a1c2352 100644
--- a/lib/class/search.class.php
+++ b/lib/class/search.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -27,1059 +27,1059 @@
class Search extends playlist_object {
- public $searchtype;
- public $rules;
- public $logic_operator = 'AND';
- public $type = 'public';
-
- public $basetypes;
- public $types;
-
- /**
- * constructor
- */
- public function __construct($searchtype = 'song', $id = '') {
- $this->searchtype = $searchtype;
- if ($id) {
- $info = $this->get_info($id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
-
- $this->rules = unserialize($this->rules);
- }
-
- // Define our basetypes
-
- $this->basetypes['numeric'][] = array(
- 'name' => 'gte',
- 'description' => T_('is greater than or equal to'),
- 'sql' => '>='
- );
-
- $this->basetypes['numeric'][] = array(
- 'name' => 'lte',
- 'description' => T_('is less than or equal to'),
- 'sql' => '<='
- );
-
- $this->basetypes['numeric'][] = array(
- 'name' => 'equal',
- 'description' => T_('is'),
- 'sql' => '<=>'
- );
-
- $this->basetypes['numeric'][] = array(
- 'name' => 'ne',
- 'description' => T_('is not'),
- 'sql' => '<>'
- );
-
- $this->basetypes['numeric'][] = array(
- 'name' => 'gt',
- 'description' => T_('is greater than'),
- 'sql' => '>'
- );
-
- $this->basetypes['numeric'][] = array(
- 'name' => 'lt',
- 'description' => T_('is less than'),
- 'sql' => '<'
- );
-
-
- $this->basetypes['boolean'][] = array(
- 'name' => 'true',
- 'description' => T_('is true')
- );
-
- $this->basetypes['boolean'][] = array(
- 'name' => 'false',
- 'description' => T_('is false')
- );
-
-
- $this->basetypes['text'][] = array(
- 'name' => 'contain',
- 'description' => T_('contains'),
- 'sql' => 'LIKE',
- 'preg_match' => array('/^/','/$/'),
- 'preg_replace' => array('%', '%')
- );
-
- $this->basetypes['text'][] = array(
- 'name' => 'notcontain',
- 'description' => T_('does not contain'),
- 'sql' => 'NOT LIKE',
- 'preg_match' => array('/^/','/$/'),
- 'preg_replace' => array('%', '%')
- );
-
- $this->basetypes['text'][] = array(
- 'name' => 'start',
- 'description' => T_('starts with'),
- 'sql' => 'LIKE',
- 'preg_match' => '/$/',
- 'preg_replace' => '%'
- );
-
- $this->basetypes['text'][] = array(
- 'name' => 'end',
- 'description' => T_('ends with'),
- 'sql' => 'LIKE',
- 'preg_match' => '/^/',
- 'preg_replace' => '%'
- );
-
- $this->basetypes['text'][] = array(
- 'name' => 'equal',
- 'description' => T_('is'),
- 'sql' => '='
- );
-
- $this->basetypes['text'][] = array(
- 'name' => 'sounds',
- 'description' => T_('sounds like'),
- 'sql' => 'SOUNDS LIKE'
- );
-
- $this->basetypes['text'][] = array(
- 'name' => 'notsounds',
- 'description' => T_('does not sound like'),
- 'sql' => 'NOT SOUNDS LIKE'
- );
-
-
- $this->basetypes['boolean_numeric'][] = array(
- 'name' => 'equal',
- 'description' => T_('is'),
- 'sql' => '<=>'
- );
-
- $this->basetypes['boolean_numeric'][] = array(
- 'name' => 'ne',
- 'description' => T_('is not'),
- 'sql' => '<>'
- );
-
-
- $this->basetypes['boolean_subsearch'][] = array(
- 'name' => 'equal',
- 'description' => T_('is'),
- 'sql' => ''
- );
-
- $this->basetypes['boolean_subsearch'][] = array(
- 'name' => 'ne',
- 'description' => T_('is not'),
- 'sql' => 'NOT'
- );
-
-
- $this->basetypes['date'][] = array(
- 'name' => 'lt',
- 'description' => T_('before'),
- 'sql' => '>'
- );
-
- $this->basetypes['date'][] = array(
- 'name' => 'gt',
- 'description' => T_('after'),
- 'sql' => '>'
- );
-
- switch ($searchtype) {
- case 'song':
- $this->types[] = array(
- 'name' => 'anywhere',
- 'label' => T_('Any searchable text'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'title',
- 'label' => T_('Title'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'album',
- 'label' => T_('Album'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'artist',
- 'label' => T_('Artist'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'comment',
- 'label' => T_('Comment'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
-
- $this->types[] = array(
- 'name' => 'tag',
- 'label' => T_('Tag'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'file',
- 'label' => T_('Filename'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'year',
- 'label' => T_('Year'),
- 'type' => 'numeric',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'time',
- 'label' => T_('Length (in minutes)'),
- 'type' => 'numeric',
- 'widget' => array('input', 'text')
- );
-
- if (Config::get('ratings')) {
- $this->types[] = array(
- 'name' => 'rating',
- 'label' => T_('Rating'),
- 'type' => 'numeric',
- 'widget' => array(
- 'select',
- array(
- '1 Star',
- '2 Stars',
- '3 Stars',
- '4 Stars',
- '5 Stars'
- )
- )
- );
- }
-
- $this->types[] = array(
- 'name' => 'bitrate',
- 'label' => T_('Bitrate'),
- 'type' => 'numeric',
- 'widget' => array(
- 'select',
- array(
- '32',
- '40',
- '48',
- '56',
- '64',
- '80',
- '96',
- '112',
- '128',
- '160',
- '192',
- '224',
- '256',
- '320'
- )
- )
- );
-
- $this->types[] = array(
- 'name' => 'played',
- 'label' => T_('Played'),
- 'type' => 'boolean',
- 'widget' => array('input', 'hidden')
- );
-
- $this->types[] = array(
- 'name' => 'added',
- 'label' => T_('Added'),
- 'type' => 'date',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'updated',
- 'label' => T_('Updated'),
- 'type' => 'date',
- 'widget' => array('input', 'text')
- );
-
- $catalogs = array();
- foreach (Catalog::get_catalogs() as $catid) {
- $catalog = new Catalog($catid);
- $catalog->format();
- $catalogs[$catid] = $catalog->f_name;
- }
- $this->types[] = array(
- 'name' => 'catalog',
- 'label' => T_('Catalog'),
- 'type' => 'boolean_numeric',
- 'widget' => array('select', $catalogs)
- );
-
- $playlists = array();
- foreach (Playlist::get_playlists() as $playlistid) {
- $playlist = new Playlist($playlistid);
- $playlist->format();
- $playlists[$playlistid] = $playlist->f_name;
- }
- $this->types[] = array(
- 'name' => 'playlist',
- 'label' => T_('Playlist'),
- 'type' => 'boolean_numeric',
- 'widget' => array('select', $playlists)
- );
-
- $playlists = array();
- foreach (Search::get_searches() as $playlistid) {
- // Slightly different from the above so we don't
- // instigate a vicious loop.
- $playlists[$playlistid] = Search::get_name_byid($playlistid);
- }
- $this->types[] = array(
- 'name' => 'smartplaylist',
- 'label' => T_('Smart Playlist'),
- 'type' => 'boolean_subsearch',
- 'widget' => array('select', $playlists)
- );
- break;
- case 'album':
- $this->types[] = array(
- 'name' => 'title',
- 'label' => T_('Title'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
-
- $this->types[] = array(
- 'name' => 'year',
- 'label' => T_('Year'),
- 'type' => 'numeric',
- 'widget' => array('input', 'text')
- );
-
- if (Config::get('ratings')) {
- $this->types[] = array(
- 'name' => 'rating',
- 'label' => T_('Rating'),
- 'type' => 'numeric',
- 'widget' => array(
- 'select',
- array(
- '1 Star',
- '2 Stars',
- '3 Stars',
- '4 Stars',
- '5 Stars'
- )
- )
- );
- }
-
- $catalogs = array();
- foreach (Catalog::get_catalogs() as $catid) {
- $catalog = new Catalog($catid);
- $catalog->format();
- $catalogs[$catid] = $catalog->f_name;
- }
- $this->types[] = array(
- 'name' => 'catalog',
- 'label' => T_('Catalog'),
- 'type' => 'boolean_numeric',
- 'widget' => array('select', $catalogs)
- );
-
-
- $this->types[] = array(
- 'name' => 'tag',
- 'label' => T_('Tag'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
- break;
- case 'video':
- $this->types[] = array(
- 'name' => 'filename',
- 'label' => T_('Filename'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
- break;
- case 'artist':
- $this->types[] = array(
- 'name' => 'name',
- 'label' => T_('Name'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
- $this->types[] = array(
- 'name' => 'tag',
- 'label' => T_('Tag'),
- 'type' => 'text',
- 'widget' => array('input', 'text')
- );
- break;
- } // end switch on searchtype
-
- } // end constructor
-
- /**
- * clean_request
- * Sanitizes raw search data
- */
- public static function clean_request($data) {
- foreach ($data as $key => $value) {
- $prefix = substr($key, 0, 4);
- $value = trim($value);
-
- if ($prefix == 'rule' && strlen($value)) {
- $request[$key] = Dba::escape($value);
- }
- } // end foreach $data
-
- // Figure out if they want an AND based search or an OR based
- // search
- switch($data['operator']) {
- case 'or':
- $request['operator'] = 'OR';
- break;
- default:
- $request['operator'] = 'AND';
- break;
- } // end switcn on operator
-
- // Verify the type
- switch($data['type']) {
- case 'album':
- case 'artist':
- case 'video':
- case 'song':
- $request['type'] = $data['type'];
- break;
- default:
- $request['type'] = 'song';
- break;
- }
-
- return $request;
- } // end clean_request
-
- /**
- * get_name_byid
- * Returns the name of the saved search corresponding to the given ID
- */
- public static function get_name_byid($id) {
- $sql = "SELECT `name` FROM `search` WHERE `id`='$id'";
- $db_results = Dba::read($sql);
- $r = Dba::fetch_assoc($db_results);
- return $r['name'];
- } // end get_name_byid
-
- /**
- * get_searches
- * Return the IDs of all saved searches accessible by the current user.
- */
- public static function get_searches() {
- $sql = "SELECT `id` from `search` WHERE `type`='public' OR " .
- "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
-
- return $results;
- } // end get_searches
-
- /**
- * run
- * This function actually runs the search, and returns an array of the
- * results.
- */
- public static function run($data) {
- $limit = intval($data['limit']);
- /* Create an array of the object we need to search on */
- $data = Search::clean_request($data);
-
- $search = new Search($data['type']);
- $search->parse_rules($data);
-
- /* Generate BASE SQL */
-
- if ($limit > 0) {
- $limit_sql = " LIMIT " . $limit;
- }
-
- $search_info = $search->to_sql();
- $sql = $search_info['base'] . ' ' . $search_info['table_sql'] .
- ' WHERE ' . $search_info['where_sql'] . " $limit_sql";
-
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
-
- return $results;
- } // run
-
- /**
- * delete
- * Does what it says on the tin.
- */
- public function delete() {
- $id = Dba::escape($this->id);
- $sql = "DELETE FROM `search` WHERE `id`='$id'";
- $db_results = Dba::write($sql);
-
- return true;
- } // end delete
-
- /**
- * format
- * Gussy up the data
- */
- public function format() {
- parent::format();
- $this->f_link = '<a href="' . Config::get('web_path') . '/smartplaylist.php?action=show_playlist&amp;playlist_id=' . $this->id . '">' . $this->f_name . '</a>';
- } // end format
-
- /**
- * get_items
- * return an array of the items output by our search (part of the
- * playlist interface).
- */
- public function get_items() {
- $results = array();
-
- $sql = $this->to_sql();
- $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' .
- $sql['where_sql'];
-
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = array(
- 'object_id' => $row['id'],
- 'object_type' => $this->searchtype
- );
- }
-
- return $results;
- } // end get_items
-
- /**
- * get_random_items
- * return a randomly sorted array (with an optional limit) of the items
- * output by our search (part of the playlist interface)
- */
-
- public function get_random_items($limit = null) {
- $results = array();
-
- $sql = $this->to_sql();
- $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' .
- $sql['where_sql'];
-
- $sql .= ' ORDER BY RAND()';
- $sql .= $limit ? ' LIMIT ' . intval($limit) : '';
-
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = array(
- 'object_id' => $row['id'],
- 'object_type' => $this->searchtype
- );
- }
-
- return $results;
- }
-
- /**
- * name_to_basetype
- * Iterates over our array of types to find out the basetype for
- * the passed string.
- */
- public function name_to_basetype($name) {
- foreach ($this->types as $type) {
- if ($type['name'] == $name) {
- return $type['type'];
- }
- }
- return false;
- } // end name_to_basetype
-
- /**
- * parse_rules
- * Takes an array of sanitized search data from the form and generates
- * our real array from it.
- */
- public function parse_rules($data) {
- $this->rules = array();
- foreach ($data as $rule => $value) {
- if (preg_match('/^rule_(\d+)$/', $rule, $ruleID)) {
- $ruleID = $ruleID[1];
- foreach (explode('|', $data['rule_' . $ruleID . '_input']) as $input) {
- $this->rules[] = array(
- $value,
- $this->basetypes[$this->name_to_basetype($value)][$data['rule_' . $ruleID . '_operator']]['name'],
- $input
- );
- }
- }
- }
- $this->logic_operator = $data['operator'];
- } // end parse_rules
-
- /**
- * save
- * Save this search to the database for use as a smart playlist
- */
- public function save() {
- // Make sure we have a unique name
- if (! $this->name) {
- $this->name = $GLOBALS['user']->username . ' - ' . date("Y-m-d H:i:s",time());
- }
- $sql = "SELECT `id` FROM `search` WHERE `name`='$this->name'";
- $db_results = Dba::read($sql);
- if (Dba::num_rows($db_results)) {
- $this->name .= uniqid('', true);
- }
-
- // clean up variables for insert
- $name = Dba::escape($this->name);
- $user = Dba::escape($GLOBALS['user']->id);
- $type = Dba::escape($this->type);
- $rules = serialize($this->rules);
- $logic_operator = $this->logic_operator;
-
- $sql = "INSERT INTO `search` (`name`, `type`, `user`, `rules`, `logic_operator`) VALUES ('$name', '$type', '$user', '$rules', '$logic_operator')";
- $db_results = Dba::write($sql);
- $insert_id = Dba::insert_id();
- $this->id = $insert_id;
- return $insert_id;
- } // end save
-
-
- /**
- * to_js
- * Outputs the javascript necessary to re-show the current set of
- * rules.
- */
- public function to_js() {
- foreach ($this->rules as $rule) {
- $js .= '<script type="text/javascript">' .
- 'SearchRow.add("' . $rule[0] . '","' .
- $rule[1] . '","' . $rule[2] . '"); </script>';
- }
- return $js;
- } // end to_js
-
- /**
- * to_sql
- * Call the appropriate real function
- */
- public function to_sql() {
- return call_user_func(
- array($this, $this->searchtype . "_to_sql"));
- } // end to_sql
-
- /**
- * update
- * This function updates the saved version with the current settings
- */
- public function update() {
- if (!$this->id) {
- return false;
- }
-
- $name = Dba::escape($this->name);
- $user = Dba::escape($GLOBALS['user']->id);
- $type = Dba::escape($this->type);
- $rules = serialize($this->rules);
- $logic_operator = $this->logic_operator;
-
- $sql = "UPDATE `search` SET `name`='$name', `type`='$type', `rules`='$rules', `logic_operator`='$logic_operator' WHERE `id`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::write($sql);
- return $db_results;
- } // end update
-
- /**
- * mangle_data
- * Private convenience function. Mangles the input according to a set
- * of predefined rules so that we don't have to include this logic in
- * foo_to_sql.
- */
- private function mangle_data($data, $type, $operator) {
- if ($operator['preg_match']) {
- $data = preg_replace(
- $operator['preg_match'],
- $operator['preg_replace'],
- $data
- );
- }
-
- if ($type == 'numeric') {
- return intval($data);
- }
-
- if ($type == 'boolean') {
- return make_bool($input);
- }
-
- return $data;
- } // end mangle_data
-
- /**
- * album_to_sql
- * Handles the generation of the SQL for album searches.
- */
- private function album_to_sql() {
- $sql_logic_operator = $this->logic_operator;
-
- $where = array();
- $table = array();
- $join = array();
- $join['tag'] = array();
-
- foreach ($this->rules as $rule) {
- $type = $this->name_to_basetype($rule[0]);
- foreach ($this->basetypes[$type] as $operator) {
- if ($operator['name'] == $rule[1]) {
- break;
- }
- }
- $input = $this->mangle_data($rule[2], $type, $operator);
- $sql_match_operator = $operator['sql'];
-
- switch ($rule[0]) {
- case 'title':
- $where[] = "`album`.`name` $sql_match_operator '$input'";
- break;
- case 'year':
- $where[] = "`album`.`year` $sql_match_operator '$input'";
- break;
- case 'rating':
- $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'";
- $join['rating'] = true;
- break;
- case 'catalog':
- $where[] = "`song`.`catalog` $sql_match_operator '$input'";
- $join['song'] = true;
- break;
- case 'tag':
- $key = md5($input . $sql_match_operator);
- $where[] = "`realtag_$key`.`match` > 0";
- $join['tag'][$key] = "$sql_match_operator '$input'";
- break;
- default:
- // Nae laird!
- break;
- } // switch on ruletype
- } // foreach rule
-
- $where_sql = implode(" $sql_logic_operator ", $where);
-
- foreach ($join['tag'] as $key => $value) {
- $table['tag_' . $key] =
- "LEFT JOIN (" .
- "SELECT `object_id`, COUNT(`name`) AS `match` ".
- "FROM `tag` LEFT JOIN `tag_map` " .
- "ON `tag`.`id`=`tag_map`.`tag_id` " .
- "WHERE `tag_map`.`object_type`='album' " .
- "AND `tag`.`name` $value GROUP BY `object_id`" .
- ") AS realtag_$key " .
- "ON `album`.`id`=`realtag_$key`.`object_id`";
- }
- if ($join['song']) {
- $table['song'] = "LEFT JOIN `song` ON `song`.`album`=`album`.`id`";
- }
- if ($join['rating']) {
- $userid = $GLOBALS['user']->id;
- $table['rating'] = "LEFT JOIN `rating` ON " .
- "`rating`.`object_type`='album' " .
- "AND `rating`.`user`='$userid' " .
- "AND `rating`.`object_id`=`album`.`id`";
- }
-
- $table_sql = implode(' ', $table);
-
- return array(
- 'base' => 'SELECT DISTINCT(`album`.`id`) FROM `album`',
- 'join' => $join,
- 'where' => $where,
- 'where_sql' => $where_sql,
- 'table' => $table,
- 'table_sql' => $table_sql
- );
- } // album_to_sql
-
- /**
- * artist_to_sql
- * Handles the generation of the SQL for artist searches.
- */
- private function artist_to_sql() {
- $sql_logic_operator = $this->logic_operator;
- $where = array();
- $table = array();
- $join = array();
- $join['tag'] = array();
-
- foreach ($this->rules as $rule) {
- $type = $this->name_to_basetype($rule[0]);
- foreach ($this->basetypes[$type] as $operator) {
- if ($operator['name'] == $rule[1]) {
- break;
- }
- }
- $input = $this->mangle_data($rule[2], $type, $operator);
- $sql_match_operator = $operator['sql'];
-
- switch ($rule[0]) {
- case 'name':
- $where[] = "`artist`.`name` $sql_match_operator '$input'";
- break;
- case 'tag':
- $key = md5($input . $sql_match_operator);
- $where[] = "`realtag_$key`.`match` > 0";
- $join['tag'][$key] = "$sql_match_operator '$input'";
- break;
- default:
- // Nihil
- break;
- } // switch on ruletype
- } // foreach rule
-
- $where_sql = implode(" $sql_logic_operator ", $where);
-
- foreach ($join['tag'] as $key => $value) {
- $table['tag_' . $key] =
- "LEFT JOIN (" .
- "SELECT `object_id`, COUNT(`name`) AS `match` ".
- "FROM `tag` LEFT JOIN `tag_map` " .
- "ON `tag`.`id`=`tag_map`.`tag_id` " .
- "WHERE `tag_map`.`object_type`='artist' " .
- "AND `tag`.`name` $value GROUP BY `object_id`".
- ") AS realtag_$key " .
- "ON `artist`.`id`=`realtag_$key`.`object_id`";
- }
-
- $table_sql = implode(' ', $table);
-
- return array(
- 'base' => 'SELECT DISTINCT(`artist`.`id`) FROM `artist`',
- 'join' => $join,
- 'where' => $where,
- 'where_sql' => $where_sql,
- 'table' => $table,
- 'table_sql' => $table_sql
- );
- } // artist_to_sql
-
- /**
- * song_to_sql
- * Handles the generation of the SQL for song searches.
- */
- private function song_to_sql() {
- $sql_logic_operator = $this->logic_operator;
-
- $where = array();
- $table = array();
- $join = array();
- $join['tag'] = array();
-
- foreach ($this->rules as $rule) {
- $type = $this->name_to_basetype($rule[0]);
- foreach ($this->basetypes[$type] as $operator) {
- if ($operator['name'] == $rule[1]) {
- break;
- }
- }
- $input = $this->mangle_data($rule[2], $type, $operator);
- $sql_match_operator = $operator['sql'];
-
- switch ($rule[0]) {
- case 'anywhere':
- $where[] = "(`artist`.`name` $sql_match_operator '$input' OR `album`.`name` $sql_match_operator '$input' OR `song_data`.`comment` $sql_match_operator '$input' OR `song`.`file` $sql_match_operator '$input' OR `song`.`title` $sql_match_operator '$input')";
- $join['album'] = true;
- $join['artist'] = true;
- $join['song_data'] = true;
- break;
- case 'tag':
- $key = md5($input . $sql_match_operator);
- $where[] = "`realtag_$key`.`match` > 0";
- $join['tag'][$key] = "$sql_match_operator '$input'";
- break;
- case 'title':
- $where[] = "`song`.`title` $sql_match_operator '$input'";
- break;
- case 'album':
- $where[] = "`album`.`name` $sql_match_operator '$input'";
- $join['album'] = true;
- break;
- case 'artist':
- $where[] = "`artist`.`name` $sql_match_operator '$input'";
- $join['artist'] = true;
- break;
- case 'time':
- $input = $input * 60;
- $where[] = "`song`.`time` $sql_match_operator '$input'";
- break;
- case 'file':
- $where[] = "`song`.`file` $sql_match_operator '$input'";
- break;
- case 'year':
- $where[] = "`song`.`year` $sql_match_operator '$input'";
- break;
- case 'comment':
- $where[] = "`song_data`.`comment` $sql_match_operator '$input'";
- $join['song_data'] = true;
- break;
- case 'played':
- $where[] = " `song`.`played` = '$input'";
- break;
- case 'bitrate':
- $input = $input * 1000;
- $where[] = "`song`.`bitrate` $sql_match_operator '$input'";
- break;
- case 'rating':
- $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'";
- $join['rating'] = true;
- break;
- case 'catalog':
- $where[] = "`song`.`catalog` $sql_match_operator '$input'";
- break;
- case 'playlist':
- $join['playlist_data'] = true;
- $where[] = "`playlist_data`.`playlist` $sql_match_operator '$input'";
- break;
- case 'smartplaylist':
- $subsearch = new Search('song', $input);
- $subsql = $subsearch->to_sql();
- $where[] = "$sql_match_operator (" . $subsql['where_sql'] . ")";
- // HACK: array_merge would potentially
- // lose tags, since it overwrites.
- // Save our merged tag joins in a temp
- // variable, even though that's ugly.
- $tagjoin = array_merge($subsql['join']['tag'], $join['tag']);
- $join = array_merge($subsql['join'], $join);
- $join['tag'] = $tagjoin;
- break;
- case 'added':
- $input = strtotime($input);
- $where[] = "`song`.`addition_time` $sql_match_operator $input";
- break;
- case 'updated':
- $input = strtotime($input);
- $where[] = "`song`.`update_time` $sql_match_operator $input";
- default:
- // NOSSINK!
- break;
- } // end switch on type
- } // end foreach over rules
-
- $where_sql = implode(" $sql_logic_operator ", $where);
-
- // now that we know which things we want to JOIN...
- if ($join['artist']) {
- $table['artist'] = "LEFT JOIN `artist` ON `song`.`artist`=`artist`.`id`";
- }
- if ($join['album']) {
- $table['album'] = "LEFT JOIN `album` ON `song`.`album`=`album`.`id`";
- }
- if ($join['song_data']) {
- $table['song_data'] = "LEFT JOIN `song_data` ON `song`.`id`=`song_data`.`song_id`";
- }
- foreach ($join['tag'] as $key => $value) {
- $table['tag_' . $key] =
- "LEFT JOIN (" .
- "SELECT `object_id`, COUNT(`name`) AS `match` ".
- "FROM `tag` LEFT JOIN `tag_map` " .
- "ON `tag`.`id`=`tag_map`.`tag_id` " .
- "WHERE `tag_map`.`object_type`='song' " .
- "AND `tag`.`name` $value GROUP BY `object_id`" .
- ") AS realtag_$key " .
- "ON `song`.`id`=`realtag_$key`.`object_id`";
- }
- if ($join['rating']) {
- $userid = $GLOBALS['user']->id;
- $table['rating'] = "LEFT JOIN `rating` ON " .
- "`rating`.`object_type`='song' AND " .
- "`rating`.`user`='$userid' AND " .
- "`rating`.`object_id`=`song`.`id`";
- }
- if ($join['playlist_data']) {
- $table['playlist_data'] = "LEFT JOIN `playlist_data` ON `song`.`id`=`playlist_data`.`object_id` AND `playlist_data`.`object_type`='song'";
- }
-
- $table_sql = implode(' ', $table);
-
- return array(
- 'base' => 'SELECT DISTINCT(`song`.`id`) FROM `song`',
- 'join' => $join,
- 'where' => $where,
- 'where_sql' => $where_sql,
- 'table' => $table,
- 'table_sql' => $table_sql
- );
- } // end song_to_sql
-
- /**
- * video_to_sql
- * Handles the generation of the SQL for video searches.
- */
- private function video_to_sql() {
- $sql_logic_operator = $this->logic_operator;
-
- $where = array();
-
-
- foreach ($this->rules as $rule) {
- $type = $this->name_to_basetype($rule[0]);
- foreach ($this->basetypes[$type] as $operator) {
- if ($operator['name'] == $rule[1]) {
- break;
- }
- }
- $input = $this->mangle_data($rule[2], $type, $operator);
- $sql_match_operator = $operator['sql'];
-
- switch ($rule[0]) {
- case 'filename':
- $where[] = "`video`.`file` $sql_match_operator '$input'";
- break;
- default:
- // WE WILLNA BE FOOLED AGAIN!
- } // switch on ruletype
- } // foreach rule
-
- $where_sql = implode(" $sql_logic_operator ", $where);
-
- return array(
- 'base' => 'SELECT DISTINCT(`video`.`id`) FROM `video`',
- 'where' => $where,
- 'where_sql' => $where_sql
- );
- } // end video_to_sql
+ public $searchtype;
+ public $rules;
+ public $logic_operator = 'AND';
+ public $type = 'public';
+
+ public $basetypes;
+ public $types;
+
+ /**
+ * constructor
+ */
+ public function __construct($searchtype = 'song', $id = '') {
+ $this->searchtype = $searchtype;
+ if ($id) {
+ $info = $this->get_info($id);
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
+
+ $this->rules = unserialize($this->rules);
+ }
+
+ // Define our basetypes
+
+ $this->basetypes['numeric'][] = array(
+ 'name' => 'gte',
+ 'description' => T_('is greater than or equal to'),
+ 'sql' => '>='
+ );
+
+ $this->basetypes['numeric'][] = array(
+ 'name' => 'lte',
+ 'description' => T_('is less than or equal to'),
+ 'sql' => '<='
+ );
+
+ $this->basetypes['numeric'][] = array(
+ 'name' => 'equal',
+ 'description' => T_('is'),
+ 'sql' => '<=>'
+ );
+
+ $this->basetypes['numeric'][] = array(
+ 'name' => 'ne',
+ 'description' => T_('is not'),
+ 'sql' => '<>'
+ );
+
+ $this->basetypes['numeric'][] = array(
+ 'name' => 'gt',
+ 'description' => T_('is greater than'),
+ 'sql' => '>'
+ );
+
+ $this->basetypes['numeric'][] = array(
+ 'name' => 'lt',
+ 'description' => T_('is less than'),
+ 'sql' => '<'
+ );
+
+
+ $this->basetypes['boolean'][] = array(
+ 'name' => 'true',
+ 'description' => T_('is true')
+ );
+
+ $this->basetypes['boolean'][] = array(
+ 'name' => 'false',
+ 'description' => T_('is false')
+ );
+
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'contain',
+ 'description' => T_('contains'),
+ 'sql' => 'LIKE',
+ 'preg_match' => array('/^/','/$/'),
+ 'preg_replace' => array('%', '%')
+ );
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'notcontain',
+ 'description' => T_('does not contain'),
+ 'sql' => 'NOT LIKE',
+ 'preg_match' => array('/^/','/$/'),
+ 'preg_replace' => array('%', '%')
+ );
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'start',
+ 'description' => T_('starts with'),
+ 'sql' => 'LIKE',
+ 'preg_match' => '/$/',
+ 'preg_replace' => '%'
+ );
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'end',
+ 'description' => T_('ends with'),
+ 'sql' => 'LIKE',
+ 'preg_match' => '/^/',
+ 'preg_replace' => '%'
+ );
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'equal',
+ 'description' => T_('is'),
+ 'sql' => '='
+ );
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'sounds',
+ 'description' => T_('sounds like'),
+ 'sql' => 'SOUNDS LIKE'
+ );
+
+ $this->basetypes['text'][] = array(
+ 'name' => 'notsounds',
+ 'description' => T_('does not sound like'),
+ 'sql' => 'NOT SOUNDS LIKE'
+ );
+
+
+ $this->basetypes['boolean_numeric'][] = array(
+ 'name' => 'equal',
+ 'description' => T_('is'),
+ 'sql' => '<=>'
+ );
+
+ $this->basetypes['boolean_numeric'][] = array(
+ 'name' => 'ne',
+ 'description' => T_('is not'),
+ 'sql' => '<>'
+ );
+
+
+ $this->basetypes['boolean_subsearch'][] = array(
+ 'name' => 'equal',
+ 'description' => T_('is'),
+ 'sql' => ''
+ );
+
+ $this->basetypes['boolean_subsearch'][] = array(
+ 'name' => 'ne',
+ 'description' => T_('is not'),
+ 'sql' => 'NOT'
+ );
+
+
+ $this->basetypes['date'][] = array(
+ 'name' => 'lt',
+ 'description' => T_('before'),
+ 'sql' => '>'
+ );
+
+ $this->basetypes['date'][] = array(
+ 'name' => 'gt',
+ 'description' => T_('after'),
+ 'sql' => '>'
+ );
+
+ switch ($searchtype) {
+ case 'song':
+ $this->types[] = array(
+ 'name' => 'anywhere',
+ 'label' => T_('Any searchable text'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'title',
+ 'label' => T_('Title'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'album',
+ 'label' => T_('Album'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'artist',
+ 'label' => T_('Artist'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'comment',
+ 'label' => T_('Comment'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+
+ $this->types[] = array(
+ 'name' => 'tag',
+ 'label' => T_('Tag'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'file',
+ 'label' => T_('Filename'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'year',
+ 'label' => T_('Year'),
+ 'type' => 'numeric',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'time',
+ 'label' => T_('Length (in minutes)'),
+ 'type' => 'numeric',
+ 'widget' => array('input', 'text')
+ );
+
+ if (Config::get('ratings')) {
+ $this->types[] = array(
+ 'name' => 'rating',
+ 'label' => T_('Rating'),
+ 'type' => 'numeric',
+ 'widget' => array(
+ 'select',
+ array(
+ '1 Star',
+ '2 Stars',
+ '3 Stars',
+ '4 Stars',
+ '5 Stars'
+ )
+ )
+ );
+ }
+
+ $this->types[] = array(
+ 'name' => 'bitrate',
+ 'label' => T_('Bitrate'),
+ 'type' => 'numeric',
+ 'widget' => array(
+ 'select',
+ array(
+ '32',
+ '40',
+ '48',
+ '56',
+ '64',
+ '80',
+ '96',
+ '112',
+ '128',
+ '160',
+ '192',
+ '224',
+ '256',
+ '320'
+ )
+ )
+ );
+
+ $this->types[] = array(
+ 'name' => 'played',
+ 'label' => T_('Played'),
+ 'type' => 'boolean',
+ 'widget' => array('input', 'hidden')
+ );
+
+ $this->types[] = array(
+ 'name' => 'added',
+ 'label' => T_('Added'),
+ 'type' => 'date',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'updated',
+ 'label' => T_('Updated'),
+ 'type' => 'date',
+ 'widget' => array('input', 'text')
+ );
+
+ $catalogs = array();
+ foreach (Catalog::get_catalogs() as $catid) {
+ $catalog = new Catalog($catid);
+ $catalog->format();
+ $catalogs[$catid] = $catalog->f_name;
+ }
+ $this->types[] = array(
+ 'name' => 'catalog',
+ 'label' => T_('Catalog'),
+ 'type' => 'boolean_numeric',
+ 'widget' => array('select', $catalogs)
+ );
+
+ $playlists = array();
+ foreach (Playlist::get_playlists() as $playlistid) {
+ $playlist = new Playlist($playlistid);
+ $playlist->format();
+ $playlists[$playlistid] = $playlist->f_name;
+ }
+ $this->types[] = array(
+ 'name' => 'playlist',
+ 'label' => T_('Playlist'),
+ 'type' => 'boolean_numeric',
+ 'widget' => array('select', $playlists)
+ );
+
+ $playlists = array();
+ foreach (Search::get_searches() as $playlistid) {
+ // Slightly different from the above so we don't
+ // instigate a vicious loop.
+ $playlists[$playlistid] = Search::get_name_byid($playlistid);
+ }
+ $this->types[] = array(
+ 'name' => 'smartplaylist',
+ 'label' => T_('Smart Playlist'),
+ 'type' => 'boolean_subsearch',
+ 'widget' => array('select', $playlists)
+ );
+ break;
+ case 'album':
+ $this->types[] = array(
+ 'name' => 'title',
+ 'label' => T_('Title'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+
+ $this->types[] = array(
+ 'name' => 'year',
+ 'label' => T_('Year'),
+ 'type' => 'numeric',
+ 'widget' => array('input', 'text')
+ );
+
+ if (Config::get('ratings')) {
+ $this->types[] = array(
+ 'name' => 'rating',
+ 'label' => T_('Rating'),
+ 'type' => 'numeric',
+ 'widget' => array(
+ 'select',
+ array(
+ '1 Star',
+ '2 Stars',
+ '3 Stars',
+ '4 Stars',
+ '5 Stars'
+ )
+ )
+ );
+ }
+
+ $catalogs = array();
+ foreach (Catalog::get_catalogs() as $catid) {
+ $catalog = new Catalog($catid);
+ $catalog->format();
+ $catalogs[$catid] = $catalog->f_name;
+ }
+ $this->types[] = array(
+ 'name' => 'catalog',
+ 'label' => T_('Catalog'),
+ 'type' => 'boolean_numeric',
+ 'widget' => array('select', $catalogs)
+ );
+
+
+ $this->types[] = array(
+ 'name' => 'tag',
+ 'label' => T_('Tag'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+ break;
+ case 'video':
+ $this->types[] = array(
+ 'name' => 'filename',
+ 'label' => T_('Filename'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+ break;
+ case 'artist':
+ $this->types[] = array(
+ 'name' => 'name',
+ 'label' => T_('Name'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+ $this->types[] = array(
+ 'name' => 'tag',
+ 'label' => T_('Tag'),
+ 'type' => 'text',
+ 'widget' => array('input', 'text')
+ );
+ break;
+ } // end switch on searchtype
+
+ } // end constructor
+
+ /**
+ * clean_request
+ * Sanitizes raw search data
+ */
+ public static function clean_request($data) {
+ foreach ($data as $key => $value) {
+ $prefix = substr($key, 0, 4);
+ $value = trim($value);
+
+ if ($prefix == 'rule' && strlen($value)) {
+ $request[$key] = Dba::escape($value);
+ }
+ } // end foreach $data
+
+ // Figure out if they want an AND based search or an OR based
+ // search
+ switch($data['operator']) {
+ case 'or':
+ $request['operator'] = 'OR';
+ break;
+ default:
+ $request['operator'] = 'AND';
+ break;
+ } // end switcn on operator
+
+ // Verify the type
+ switch($data['type']) {
+ case 'album':
+ case 'artist':
+ case 'video':
+ case 'song':
+ $request['type'] = $data['type'];
+ break;
+ default:
+ $request['type'] = 'song';
+ break;
+ }
+
+ return $request;
+ } // end clean_request
+
+ /**
+ * get_name_byid
+ * Returns the name of the saved search corresponding to the given ID
+ */
+ public static function get_name_byid($id) {
+ $sql = "SELECT `name` FROM `search` WHERE `id`='$id'";
+ $db_results = Dba::read($sql);
+ $r = Dba::fetch_assoc($db_results);
+ return $r['name'];
+ } // end get_name_byid
+
+ /**
+ * get_searches
+ * Return the IDs of all saved searches accessible by the current user.
+ */
+ public static function get_searches() {
+ $sql = "SELECT `id` from `search` WHERE `type`='public' OR " .
+ "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
+
+ return $results;
+ } // end get_searches
+
+ /**
+ * run
+ * This function actually runs the search, and returns an array of the
+ * results.
+ */
+ public static function run($data) {
+ $limit = intval($data['limit']);
+ /* Create an array of the object we need to search on */
+ $data = Search::clean_request($data);
+
+ $search = new Search($data['type']);
+ $search->parse_rules($data);
+
+ /* Generate BASE SQL */
+
+ if ($limit > 0) {
+ $limit_sql = " LIMIT " . $limit;
+ }
+
+ $search_info = $search->to_sql();
+ $sql = $search_info['base'] . ' ' . $search_info['table_sql'] .
+ ' WHERE ' . $search_info['where_sql'] . " $limit_sql";
+
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
+
+ return $results;
+ } // run
+
+ /**
+ * delete
+ * Does what it says on the tin.
+ */
+ public function delete() {
+ $id = Dba::escape($this->id);
+ $sql = "DELETE FROM `search` WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
+
+ return true;
+ } // end delete
+
+ /**
+ * format
+ * Gussy up the data
+ */
+ public function format() {
+ parent::format();
+ $this->f_link = '<a href="' . Config::get('web_path') . '/smartplaylist.php?action=show_playlist&amp;playlist_id=' . $this->id . '">' . $this->f_name . '</a>';
+ } // end format
+
+ /**
+ * get_items
+ * return an array of the items output by our search (part of the
+ * playlist interface).
+ */
+ public function get_items() {
+ $results = array();
+
+ $sql = $this->to_sql();
+ $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' .
+ $sql['where_sql'];
+
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = array(
+ 'object_id' => $row['id'],
+ 'object_type' => $this->searchtype
+ );
+ }
+
+ return $results;
+ } // end get_items
+
+ /**
+ * get_random_items
+ * return a randomly sorted array (with an optional limit) of the items
+ * output by our search (part of the playlist interface)
+ */
+
+ public function get_random_items($limit = null) {
+ $results = array();
+
+ $sql = $this->to_sql();
+ $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' .
+ $sql['where_sql'];
+
+ $sql .= ' ORDER BY RAND()';
+ $sql .= $limit ? ' LIMIT ' . intval($limit) : '';
+
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = array(
+ 'object_id' => $row['id'],
+ 'object_type' => $this->searchtype
+ );
+ }
+
+ return $results;
+ }
+
+ /**
+ * name_to_basetype
+ * Iterates over our array of types to find out the basetype for
+ * the passed string.
+ */
+ public function name_to_basetype($name) {
+ foreach ($this->types as $type) {
+ if ($type['name'] == $name) {
+ return $type['type'];
+ }
+ }
+ return false;
+ } // end name_to_basetype
+
+ /**
+ * parse_rules
+ * Takes an array of sanitized search data from the form and generates
+ * our real array from it.
+ */
+ public function parse_rules($data) {
+ $this->rules = array();
+ foreach ($data as $rule => $value) {
+ if (preg_match('/^rule_(\d+)$/', $rule, $ruleID)) {
+ $ruleID = $ruleID[1];
+ foreach (explode('|', $data['rule_' . $ruleID . '_input']) as $input) {
+ $this->rules[] = array(
+ $value,
+ $this->basetypes[$this->name_to_basetype($value)][$data['rule_' . $ruleID . '_operator']]['name'],
+ $input
+ );
+ }
+ }
+ }
+ $this->logic_operator = $data['operator'];
+ } // end parse_rules
+
+ /**
+ * save
+ * Save this search to the database for use as a smart playlist
+ */
+ public function save() {
+ // Make sure we have a unique name
+ if (! $this->name) {
+ $this->name = $GLOBALS['user']->username . ' - ' . date("Y-m-d H:i:s",time());
+ }
+ $sql = "SELECT `id` FROM `search` WHERE `name`='$this->name'";
+ $db_results = Dba::read($sql);
+ if (Dba::num_rows($db_results)) {
+ $this->name .= uniqid('', true);
+ }
+
+ // clean up variables for insert
+ $name = Dba::escape($this->name);
+ $user = Dba::escape($GLOBALS['user']->id);
+ $type = Dba::escape($this->type);
+ $rules = serialize($this->rules);
+ $logic_operator = $this->logic_operator;
+
+ $sql = "INSERT INTO `search` (`name`, `type`, `user`, `rules`, `logic_operator`) VALUES ('$name', '$type', '$user', '$rules', '$logic_operator')";
+ $db_results = Dba::write($sql);
+ $insert_id = Dba::insert_id();
+ $this->id = $insert_id;
+ return $insert_id;
+ } // end save
+
+
+ /**
+ * to_js
+ * Outputs the javascript necessary to re-show the current set of
+ * rules.
+ */
+ public function to_js() {
+ foreach ($this->rules as $rule) {
+ $js .= '<script type="text/javascript">' .
+ 'SearchRow.add("' . $rule[0] . '","' .
+ $rule[1] . '","' . $rule[2] . '"); </script>';
+ }
+ return $js;
+ } // end to_js
+
+ /**
+ * to_sql
+ * Call the appropriate real function
+ */
+ public function to_sql() {
+ return call_user_func(
+ array($this, $this->searchtype . "_to_sql"));
+ } // end to_sql
+
+ /**
+ * update
+ * This function updates the saved version with the current settings
+ */
+ public function update() {
+ if (!$this->id) {
+ return false;
+ }
+
+ $name = Dba::escape($this->name);
+ $user = Dba::escape($GLOBALS['user']->id);
+ $type = Dba::escape($this->type);
+ $rules = serialize($this->rules);
+ $logic_operator = $this->logic_operator;
+
+ $sql = "UPDATE `search` SET `name`='$name', `type`='$type', `rules`='$rules', `logic_operator`='$logic_operator' WHERE `id`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::write($sql);
+ return $db_results;
+ } // end update
+
+ /**
+ * mangle_data
+ * Private convenience function. Mangles the input according to a set
+ * of predefined rules so that we don't have to include this logic in
+ * foo_to_sql.
+ */
+ private function mangle_data($data, $type, $operator) {
+ if ($operator['preg_match']) {
+ $data = preg_replace(
+ $operator['preg_match'],
+ $operator['preg_replace'],
+ $data
+ );
+ }
+
+ if ($type == 'numeric') {
+ return intval($data);
+ }
+
+ if ($type == 'boolean') {
+ return make_bool($input);
+ }
+
+ return $data;
+ } // end mangle_data
+
+ /**
+ * album_to_sql
+ * Handles the generation of the SQL for album searches.
+ */
+ private function album_to_sql() {
+ $sql_logic_operator = $this->logic_operator;
+
+ $where = array();
+ $table = array();
+ $join = array();
+ $join['tag'] = array();
+
+ foreach ($this->rules as $rule) {
+ $type = $this->name_to_basetype($rule[0]);
+ foreach ($this->basetypes[$type] as $operator) {
+ if ($operator['name'] == $rule[1]) {
+ break;
+ }
+ }
+ $input = $this->mangle_data($rule[2], $type, $operator);
+ $sql_match_operator = $operator['sql'];
+
+ switch ($rule[0]) {
+ case 'title':
+ $where[] = "`album`.`name` $sql_match_operator '$input'";
+ break;
+ case 'year':
+ $where[] = "`album`.`year` $sql_match_operator '$input'";
+ break;
+ case 'rating':
+ $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'";
+ $join['rating'] = true;
+ break;
+ case 'catalog':
+ $where[] = "`song`.`catalog` $sql_match_operator '$input'";
+ $join['song'] = true;
+ break;
+ case 'tag':
+ $key = md5($input . $sql_match_operator);
+ $where[] = "`realtag_$key`.`match` > 0";
+ $join['tag'][$key] = "$sql_match_operator '$input'";
+ break;
+ default:
+ // Nae laird!
+ break;
+ } // switch on ruletype
+ } // foreach rule
+
+ $where_sql = implode(" $sql_logic_operator ", $where);
+
+ foreach ($join['tag'] as $key => $value) {
+ $table['tag_' . $key] =
+ "LEFT JOIN (" .
+ "SELECT `object_id`, COUNT(`name`) AS `match` ".
+ "FROM `tag` LEFT JOIN `tag_map` " .
+ "ON `tag`.`id`=`tag_map`.`tag_id` " .
+ "WHERE `tag_map`.`object_type`='album' " .
+ "AND `tag`.`name` $value GROUP BY `object_id`" .
+ ") AS realtag_$key " .
+ "ON `album`.`id`=`realtag_$key`.`object_id`";
+ }
+ if ($join['song']) {
+ $table['song'] = "LEFT JOIN `song` ON `song`.`album`=`album`.`id`";
+ }
+ if ($join['rating']) {
+ $userid = $GLOBALS['user']->id;
+ $table['rating'] = "LEFT JOIN `rating` ON " .
+ "`rating`.`object_type`='album' " .
+ "AND `rating`.`user`='$userid' " .
+ "AND `rating`.`object_id`=`album`.`id`";
+ }
+
+ $table_sql = implode(' ', $table);
+
+ return array(
+ 'base' => 'SELECT DISTINCT(`album`.`id`) FROM `album`',
+ 'join' => $join,
+ 'where' => $where,
+ 'where_sql' => $where_sql,
+ 'table' => $table,
+ 'table_sql' => $table_sql
+ );
+ } // album_to_sql
+
+ /**
+ * artist_to_sql
+ * Handles the generation of the SQL for artist searches.
+ */
+ private function artist_to_sql() {
+ $sql_logic_operator = $this->logic_operator;
+ $where = array();
+ $table = array();
+ $join = array();
+ $join['tag'] = array();
+
+ foreach ($this->rules as $rule) {
+ $type = $this->name_to_basetype($rule[0]);
+ foreach ($this->basetypes[$type] as $operator) {
+ if ($operator['name'] == $rule[1]) {
+ break;
+ }
+ }
+ $input = $this->mangle_data($rule[2], $type, $operator);
+ $sql_match_operator = $operator['sql'];
+
+ switch ($rule[0]) {
+ case 'name':
+ $where[] = "`artist`.`name` $sql_match_operator '$input'";
+ break;
+ case 'tag':
+ $key = md5($input . $sql_match_operator);
+ $where[] = "`realtag_$key`.`match` > 0";
+ $join['tag'][$key] = "$sql_match_operator '$input'";
+ break;
+ default:
+ // Nihil
+ break;
+ } // switch on ruletype
+ } // foreach rule
+
+ $where_sql = implode(" $sql_logic_operator ", $where);
+
+ foreach ($join['tag'] as $key => $value) {
+ $table['tag_' . $key] =
+ "LEFT JOIN (" .
+ "SELECT `object_id`, COUNT(`name`) AS `match` ".
+ "FROM `tag` LEFT JOIN `tag_map` " .
+ "ON `tag`.`id`=`tag_map`.`tag_id` " .
+ "WHERE `tag_map`.`object_type`='artist' " .
+ "AND `tag`.`name` $value GROUP BY `object_id`".
+ ") AS realtag_$key " .
+ "ON `artist`.`id`=`realtag_$key`.`object_id`";
+ }
+
+ $table_sql = implode(' ', $table);
+
+ return array(
+ 'base' => 'SELECT DISTINCT(`artist`.`id`) FROM `artist`',
+ 'join' => $join,
+ 'where' => $where,
+ 'where_sql' => $where_sql,
+ 'table' => $table,
+ 'table_sql' => $table_sql
+ );
+ } // artist_to_sql
+
+ /**
+ * song_to_sql
+ * Handles the generation of the SQL for song searches.
+ */
+ private function song_to_sql() {
+ $sql_logic_operator = $this->logic_operator;
+
+ $where = array();
+ $table = array();
+ $join = array();
+ $join['tag'] = array();
+
+ foreach ($this->rules as $rule) {
+ $type = $this->name_to_basetype($rule[0]);
+ foreach ($this->basetypes[$type] as $operator) {
+ if ($operator['name'] == $rule[1]) {
+ break;
+ }
+ }
+ $input = $this->mangle_data($rule[2], $type, $operator);
+ $sql_match_operator = $operator['sql'];
+
+ switch ($rule[0]) {
+ case 'anywhere':
+ $where[] = "(`artist`.`name` $sql_match_operator '$input' OR `album`.`name` $sql_match_operator '$input' OR `song_data`.`comment` $sql_match_operator '$input' OR `song`.`file` $sql_match_operator '$input' OR `song`.`title` $sql_match_operator '$input')";
+ $join['album'] = true;
+ $join['artist'] = true;
+ $join['song_data'] = true;
+ break;
+ case 'tag':
+ $key = md5($input . $sql_match_operator);
+ $where[] = "`realtag_$key`.`match` > 0";
+ $join['tag'][$key] = "$sql_match_operator '$input'";
+ break;
+ case 'title':
+ $where[] = "`song`.`title` $sql_match_operator '$input'";
+ break;
+ case 'album':
+ $where[] = "`album`.`name` $sql_match_operator '$input'";
+ $join['album'] = true;
+ break;
+ case 'artist':
+ $where[] = "`artist`.`name` $sql_match_operator '$input'";
+ $join['artist'] = true;
+ break;
+ case 'time':
+ $input = $input * 60;
+ $where[] = "`song`.`time` $sql_match_operator '$input'";
+ break;
+ case 'file':
+ $where[] = "`song`.`file` $sql_match_operator '$input'";
+ break;
+ case 'year':
+ $where[] = "`song`.`year` $sql_match_operator '$input'";
+ break;
+ case 'comment':
+ $where[] = "`song_data`.`comment` $sql_match_operator '$input'";
+ $join['song_data'] = true;
+ break;
+ case 'played':
+ $where[] = " `song`.`played` = '$input'";
+ break;
+ case 'bitrate':
+ $input = $input * 1000;
+ $where[] = "`song`.`bitrate` $sql_match_operator '$input'";
+ break;
+ case 'rating':
+ $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'";
+ $join['rating'] = true;
+ break;
+ case 'catalog':
+ $where[] = "`song`.`catalog` $sql_match_operator '$input'";
+ break;
+ case 'playlist':
+ $join['playlist_data'] = true;
+ $where[] = "`playlist_data`.`playlist` $sql_match_operator '$input'";
+ break;
+ case 'smartplaylist':
+ $subsearch = new Search('song', $input);
+ $subsql = $subsearch->to_sql();
+ $where[] = "$sql_match_operator (" . $subsql['where_sql'] . ")";
+ // HACK: array_merge would potentially
+ // lose tags, since it overwrites.
+ // Save our merged tag joins in a temp
+ // variable, even though that's ugly.
+ $tagjoin = array_merge($subsql['join']['tag'], $join['tag']);
+ $join = array_merge($subsql['join'], $join);
+ $join['tag'] = $tagjoin;
+ break;
+ case 'added':
+ $input = strtotime($input);
+ $where[] = "`song`.`addition_time` $sql_match_operator $input";
+ break;
+ case 'updated':
+ $input = strtotime($input);
+ $where[] = "`song`.`update_time` $sql_match_operator $input";
+ default:
+ // NOSSINK!
+ break;
+ } // end switch on type
+ } // end foreach over rules
+
+ $where_sql = implode(" $sql_logic_operator ", $where);
+
+ // now that we know which things we want to JOIN...
+ if ($join['artist']) {
+ $table['artist'] = "LEFT JOIN `artist` ON `song`.`artist`=`artist`.`id`";
+ }
+ if ($join['album']) {
+ $table['album'] = "LEFT JOIN `album` ON `song`.`album`=`album`.`id`";
+ }
+ if ($join['song_data']) {
+ $table['song_data'] = "LEFT JOIN `song_data` ON `song`.`id`=`song_data`.`song_id`";
+ }
+ foreach ($join['tag'] as $key => $value) {
+ $table['tag_' . $key] =
+ "LEFT JOIN (" .
+ "SELECT `object_id`, COUNT(`name`) AS `match` ".
+ "FROM `tag` LEFT JOIN `tag_map` " .
+ "ON `tag`.`id`=`tag_map`.`tag_id` " .
+ "WHERE `tag_map`.`object_type`='song' " .
+ "AND `tag`.`name` $value GROUP BY `object_id`" .
+ ") AS realtag_$key " .
+ "ON `song`.`id`=`realtag_$key`.`object_id`";
+ }
+ if ($join['rating']) {
+ $userid = $GLOBALS['user']->id;
+ $table['rating'] = "LEFT JOIN `rating` ON " .
+ "`rating`.`object_type`='song' AND " .
+ "`rating`.`user`='$userid' AND " .
+ "`rating`.`object_id`=`song`.`id`";
+ }
+ if ($join['playlist_data']) {
+ $table['playlist_data'] = "LEFT JOIN `playlist_data` ON `song`.`id`=`playlist_data`.`object_id` AND `playlist_data`.`object_type`='song'";
+ }
+
+ $table_sql = implode(' ', $table);
+
+ return array(
+ 'base' => 'SELECT DISTINCT(`song`.`id`) FROM `song`',
+ 'join' => $join,
+ 'where' => $where,
+ 'where_sql' => $where_sql,
+ 'table' => $table,
+ 'table_sql' => $table_sql
+ );
+ } // end song_to_sql
+
+ /**
+ * video_to_sql
+ * Handles the generation of the SQL for video searches.
+ */
+ private function video_to_sql() {
+ $sql_logic_operator = $this->logic_operator;
+
+ $where = array();
+
+
+ foreach ($this->rules as $rule) {
+ $type = $this->name_to_basetype($rule[0]);
+ foreach ($this->basetypes[$type] as $operator) {
+ if ($operator['name'] == $rule[1]) {
+ break;
+ }
+ }
+ $input = $this->mangle_data($rule[2], $type, $operator);
+ $sql_match_operator = $operator['sql'];
+
+ switch ($rule[0]) {
+ case 'filename':
+ $where[] = "`video`.`file` $sql_match_operator '$input'";
+ break;
+ default:
+ // WE WILLNA BE FOOLED AGAIN!
+ } // switch on ruletype
+ } // foreach rule
+
+ $where_sql = implode(" $sql_logic_operator ", $where);
+
+ return array(
+ 'base' => 'SELECT DISTINCT(`video`.`id`) FROM `video`',
+ 'where' => $where,
+ 'where_sql' => $where_sql
+ );
+ } // end video_to_sql
} // end of Search class
?>
diff --git a/lib/class/shoutbox.class.php b/lib/class/shoutbox.class.php
index 42adec08..0bd12070 100644
--- a/lib/class/shoutbox.class.php
+++ b/lib/class/shoutbox.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,211 +22,211 @@
class Shoutbox {
- public $id;
+ public $id;
- /**
- * Constructor
- * This pulls the shoutbox information from the database and returns
- * a constructed object, uses user_shout table
- */
- public function __construct($shout_id) {
+ /**
+ * Constructor
+ * This pulls the shoutbox information from the database and returns
+ * a constructed object, uses user_shout table
+ */
+ public function __construct($shout_id) {
- // Load the data from the database
- $this->_get_info($shout_id);
+ // Load the data from the database
+ $this->_get_info($shout_id);
- return true;
+ return true;
- } // Constructor
+ } // Constructor
- /**
- * _get_info
- * does the db call, reads from the user_shout table
- */
- private function _get_info($shout_id) {
+ /**
+ * _get_info
+ * does the db call, reads from the user_shout table
+ */
+ private function _get_info($shout_id) {
- $sticky_id = Dba::escape($shout_id);
+ $sticky_id = Dba::escape($shout_id);
- $sql = "SELECT * FROM `user_shout` WHERE `id`='$shout_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `user_shout` WHERE `id`='$shout_id'";
+ $db_results = Dba::read($sql);
- $data = Dba::fetch_assoc($db_results);
+ $data = Dba::fetch_assoc($db_results);
- foreach ($data as $key=>$value) {
- $this->$key = $value;
- }
+ foreach ($data as $key=>$value) {
+ $this->$key = $value;
+ }
- return true;
+ return true;
- } // _get_info
+ } // _get_info
- /**
- * gc
- *
- * Cleans out orphaned shoutbox items
- */
- public static function gc() {
- foreach(array('song', 'album', 'artist') as $object_type) {
- Dba::write("DELETE FROM `user_shout` USING `user_shout` LEFT JOIN `$object_type` ON `$object_type`.`id` = `user_shout`.`object_id` WHERE `$object_type`.`id` IS NULL AND `user_shout`.`object_type` = '$object_type'");
- }
- }
+ /**
+ * gc
+ *
+ * Cleans out orphaned shoutbox items
+ */
+ public static function gc() {
+ foreach(array('song', 'album', 'artist') as $object_type) {
+ Dba::write("DELETE FROM `user_shout` USING `user_shout` LEFT JOIN `$object_type` ON `$object_type`.`id` = `user_shout`.`object_id` WHERE `$object_type`.`id` IS NULL AND `user_shout`.`object_type` = '$object_type'");
+ }
+ }
- /**
- * get_top
- * This returns the top user_shouts, shoutbox objects are always shown regardless and count against the total
- * number of objects shown
- */
- public static function get_top($limit) {
+ /**
+ * get_top
+ * This returns the top user_shouts, shoutbox objects are always shown regardless and count against the total
+ * number of objects shown
+ */
+ public static function get_top($limit) {
- $shouts = self::get_sticky();
+ $shouts = self::get_sticky();
- // If we've already got too many stop here
- if (count($shouts) > $limit) {
- $shouts = array_slice($shouts,0,$limit);
- return $shouts;
- }
+ // If we've already got too many stop here
+ if (count($shouts) > $limit) {
+ $shouts = array_slice($shouts,0,$limit);
+ return $shouts;
+ }
- // Only get as many as we need
- $limit = intval($limit) - count($shouts);
- $sql = "SELECT * FROM `user_shout` WHERE `sticky`='0' ORDER BY `date` DESC LIMIT $limit";
- $db_results = Dba::read($sql);
+ // Only get as many as we need
+ $limit = intval($limit) - count($shouts);
+ $sql = "SELECT * FROM `user_shout` WHERE `sticky`='0' ORDER BY `date` DESC LIMIT $limit";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $shouts[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $shouts[] = $row['id'];
+ }
- return $shouts;
+ return $shouts;
- } // get_top
+ } // get_top
- /**
- * get_sticky
- * This returns all current sticky shoutbox items
- */
- public static function get_sticky() {
+ /**
+ * get_sticky
+ * This returns all current sticky shoutbox items
+ */
+ public static function get_sticky() {
- $sql = "SELECT * FROM `user_shout` WHERE `sticky`='1' ORDER BY `date` DESC";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `user_shout` WHERE `sticky`='1' ORDER BY `date` DESC";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['id'];
+ }
- return $results;
+ return $results;
- } // get_sticky
+ } // get_sticky
- /**
- * get_object
- * This takes a type and an ID and returns a created object
- */
- public static function get_object($type,$object_id) {
+ /**
+ * get_object
+ * This takes a type and an ID and returns a created object
+ */
+ public static function get_object($type,$object_id) {
- $allowed_objects = array('song','genre','album','artist','radio');
+ $allowed_objects = array('song','genre','album','artist','radio');
- if (!in_array($type,$allowed_objects)) {
- return false;
- }
+ if (!in_array($type,$allowed_objects)) {
+ return false;
+ }
- $object = new $type($object_id);
+ $object = new $type($object_id);
- return $object;
+ return $object;
- } // get_object
+ } // get_object
- /**
- * get_image
- * This returns an image tag if the type of object we're currently rolling with
- * has an image associated with it
- */
- public function get_image() {
+ /**
+ * get_image
+ * This returns an image tag if the type of object we're currently rolling with
+ * has an image associated with it
+ */
+ public function get_image() {
- switch ($this->object_type) {
- case 'album':
- $image_string = "<img class=\"shoutboximage\" height=\"75\" width=\"75\" src=\"" . Config::get('web_path') . "/image.php?id=" . $this->object_id . "&amp;thumb=1\" />";
- break;
- case 'artist':
+ switch ($this->object_type) {
+ case 'album':
+ $image_string = "<img class=\"shoutboximage\" height=\"75\" width=\"75\" src=\"" . Config::get('web_path') . "/image.php?id=" . $this->object_id . "&amp;thumb=1\" />";
+ break;
+ case 'artist':
- break;
- case 'song':
- $song = new Song($this->object_id);
- $image_string = "<img class=\"shoutboximage\" height=\"75\" width=\"75\" src=\"" . Config::get('web_path') . "/image.php?id=" . $song->album . "&amp;thumb=1\" />";
- break;
- default:
- // Rien a faire
- break;
- } // end switch
+ break;
+ case 'song':
+ $song = new Song($this->object_id);
+ $image_string = "<img class=\"shoutboximage\" height=\"75\" width=\"75\" src=\"" . Config::get('web_path') . "/image.php?id=" . $song->album . "&amp;thumb=1\" />";
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end switch
- return $image_string;
+ return $image_string;
- } // get_image
+ } // get_image
- /**
- * create
- * This takes a key'd array of data as input and inserts a new shoutbox entry, it returns the auto_inc id
- */
- public static function create($data) {
+ /**
+ * create
+ * This takes a key'd array of data as input and inserts a new shoutbox entry, it returns the auto_inc id
+ */
+ public static function create($data) {
- $user = Dba::escape($GLOBALS['user']->id);
- $text = Dba::escape(strip_tags($data['comment']));
- $date = time();
- $sticky = isset($data['sticky']) ? 1 : 0;
- $object_id = Dba::escape($data['object_id']);
- $object_type = Dba::escape($data['object_type']);
+ $user = Dba::escape($GLOBALS['user']->id);
+ $text = Dba::escape(strip_tags($data['comment']));
+ $date = time();
+ $sticky = isset($data['sticky']) ? 1 : 0;
+ $object_id = Dba::escape($data['object_id']);
+ $object_type = Dba::escape($data['object_type']);
- $sql = "INSERT INTO `user_shout` (`user`,`date`,`text`,`sticky`,`object_id`,`object_type`) " .
- "VALUES ('$user','$date','$text','$sticky','$object_id','$object_type')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `user_shout` (`user`,`date`,`text`,`sticky`,`object_id`,`object_type`) " .
+ "VALUES ('$user','$date','$text','$sticky','$object_id','$object_type')";
+ $db_results = Dba::write($sql);
- $insert_id = Dba::insert_id();
+ $insert_id = Dba::insert_id();
- return $insert_id;
+ return $insert_id;
- } // create
+ } // create
- /**
- * update
- * This takes a key'd array of data as input and updates a shoutbox entry
- */
- public static function update($data) {
+ /**
+ * update
+ * This takes a key'd array of data as input and updates a shoutbox entry
+ */
+ public static function update($data) {
- $id = Dba::escape($data['shout_id']);
- $text = Dba::escape(strip_tags($data['comment']));
- $sticky = make_bool($data['sticky']);
+ $id = Dba::escape($data['shout_id']);
+ $text = Dba::escape(strip_tags($data['comment']));
+ $sticky = make_bool($data['sticky']);
- $sql = "UPDATE `user_shout` SET `text`='$text', `sticky`='$sticky' WHERE `id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `user_shout` SET `text`='$text', `sticky`='$sticky' WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // create
+ } // create
- /**
- * format
- * this function takes the object and reformats some values
- */
+ /**
+ * format
+ * this function takes the object and reformats some values
+ */
- public function format() {
- $this->sticky = ($this->sticky == "0") ? 'No' : 'Yes';
- $this->date = date("m\/d\/Y - H:i", $this->date);
- return true;
+ public function format() {
+ $this->sticky = ($this->sticky == "0") ? 'No' : 'Yes';
+ $this->date = date("m\/d\/Y - H:i", $this->date);
+ return true;
- } //format
+ } //format
- /**
- * delete
- * this function deletes a specific shoutbox entry
- */
+ /**
+ * delete
+ * this function deletes a specific shoutbox entry
+ */
- public function delete($shout_id) {
+ public function delete($shout_id) {
- // Delete the shoutbox post
- $shout_id = Dba::escape($shout_id);
- $sql = "DELETE FROM `user_shout` WHERE `id`='$shout_id'";
- $db_results = Dba::write($sql);
+ // Delete the shoutbox post
+ $shout_id = Dba::escape($shout_id);
+ $sql = "DELETE FROM `user_shout` WHERE `id`='$shout_id'";
+ $db_results = Dba::write($sql);
- } // delete
+ } // delete
} // Shoutbox class
?>
diff --git a/lib/class/song.class.php b/lib/class/song.class.php
index ac25b1a0..3d865b25 100644
--- a/lib/class/song.class.php
+++ b/lib/class/song.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,1012 +22,1012 @@
class Song extends database_object implements media {
- /* Variables from DB */
- public $id;
- public $file;
- public $album; // album.id (Int)
- public $artist; // artist.id (Int)
- public $title;
- public $year;
- public $bitrate;
- public $rate;
- public $mode;
- public $size;
- public $time;
- public $track;
- public $album_mbid;
- public $artist_mbid;
- public $type;
- public $mime;
- public $played;
- public $enabled;
- public $addition_time;
- public $update_time;
- public $mbid; // MusicBrainz ID
-
- /* Setting Variables */
- public $_fake = false; // If this is a 'construct_from_array' object
-
- /**
- * Constructor
- * Song class, for modifing a song.
- */
- public function __construct($id='') {
-
- if (!$id) { return false; }
-
- /* Assign id for use in get_info() */
- $this->id = intval($id);
-
- /* Get the information from the db */
- if ($info = $this->_get_info()) {
-
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
- $data = pathinfo($this->file);
- $this->type = strtolower($data['extension']);
- $this->mime = self::type_to_mime($this->type);
- }
-
- return true;
-
- } // constructor
-
- /**
- * gc
- *
- * Cleans up the song_data table
- */
- public static function gc() {
- Dba::write('DELETE FROM `song_data` USING `song_data` LEFT JOIN `song` ON `song`.`id` = `song_data`.`song_id` WHERE `song`.`id` IS NULL');
- }
-
- /**
- * build_cache
- *
- * This attempts to reduce queries by asking for everything in the
- * browse all at once and storing it in the cache, this can help if the
- * db connection is the slow point.
- */
- public static function build_cache($song_ids) {
-
- if (!is_array($song_ids) || !count($song_ids)) { return false; }
-
- $idlist = '(' . implode(',', $song_ids) . ')';
-
- // Callers might have passed array(false) because they are dumb
- if ($idlist == '()') { return false; }
-
- // Song data cache
- $sql = 'SELECT `song`.`id`, `file`, `catalog`, `album`, ' .
- '`year`, `artist`, `title`, `bitrate`, `rate`, ' .
- '`mode`, `size`, `time`, `track`, `played`, ' .
- '`song`.`enabled`, `update_time`, `tag_map`.`tag_id`, '.
- '`mbid`, `addition_time` ' .
- 'FROM `song` LEFT JOIN `tag_map` ' .
- 'ON `tag_map`.`object_id`=`song`.`id` ' .
- "AND `tag_map`.`object_type`='song' " .
- "WHERE `song`.`id` IN $idlist";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('song', $row['id'], $row);
- $artists[$row['artist']] = $row['artist'];
- $albums[$row['album']] = $row['album'];
- if ($row['tag_id']) {
- $tags[$row['tag_id']] = $row['tag_id'];
- }
- }
-
- Artist::build_cache($artists);
- Album::build_cache($albums);
- Tag::build_cache($tags);
- Tag::build_map_cache('song',$song_ids);
- Art::build_cache($albums);
-
- // If we're rating this then cache them as well
- if (Config::get('ratings')) {
- Rating::build_cache('song', $song_ids);
- }
-
- // Build a cache for the song's extended table
- $sql = "SELECT * FROM `song_data` WHERE `song_id` IN $idlist";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('song_data', $row['song_id'], $row);
- }
-
- return true;
-
- } // build_cache
-
- /**
- * _get_info
- * get's the vars for $this out of the database
- * Taken from the object
- */
- private function _get_info() {
-
- $id = intval($this->id);
-
- if (parent::is_cached('song',$id)) {
- return parent::get_from_cache('song',$id);
- }
-
- /* Grab the basic information from the catalog and return it */
- $sql = "SELECT song.id,file,catalog,album,year,artist,".
- "title,bitrate,rate,mode,size,time,track,played,song.enabled,update_time,".
- "mbid,".
- "addition_time FROM `song` WHERE `song`.`id` = '$id'";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
-
- parent::add_to_cache('song',$id,$results);
-
- return $results;
-
- } // _get_info
-
- /**
- * _get_ext_info
- * This function gathers information from the song_ext_info table and adds it to the
- * current object
- */
- public function _get_ext_info() {
-
- $id = intval($this->id);
-
- if (parent::is_cached('song_data',$id)) {
- return parent::get_from_cache('song_data',$id);
- }
-
- $sql = "SELECT * FROM song_data WHERE `song_id`='$id'";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
-
- parent::add_to_cache('song_data',$id,$results);
-
- return $results;
-
- } // _get_ext_info
-
- /**
- * fill_ext_info
- * This calls the _get_ext_info and then sets the correct vars
- */
- public function fill_ext_info() {
-
- $info = $this->_get_ext_info();
-
- foreach ($info as $key=>$value) {
- if ($key != 'song_id') {
- $this->$key = $value;
- }
- } // end foreach
-
- } // fill_ext_info
-
- /**
- * type_to_mime
- *
- * Returns the mime type for the specified file extension/type
- */
- public static function type_to_mime($type) {
- // FIXME: This should really be done the other way around.
- // Store the mime type in the database, and provide a function
- // to make it a human-friendly type.
- switch ($type) {
- case 'spx':
- case 'ogg':
- return 'application/ogg';
- break;
- case 'wma':
- case 'asf':
- return 'audio/x-ms-wma';
- break;
- case 'mp3':
- case 'mpeg3':
- return 'audio/mpeg';
- break;
- case 'rm':
- case 'ra':
- return 'audio/x-realaudio';
- break;
- case 'flac';
- return 'audio/x-flac';
- break;
- case 'wv':
- return 'audio/x-wavpack';
- break;
- case 'aac':
- case 'mp4':
- case 'm4a':
- return 'audio/mp4';
- break;
- case 'mpc':
- return 'audio/x-musepack';
- break;
- default:
- return 'audio/mpeg';
- break;
- }
-
- return true;
-
- }
-
- /**
- * get_disabled
- *
- * Gets a list of the disabled songs for and returns an array of Songs
- */
- public static function get_disabled($count = 0) {
-
- $results = array();
-
- $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'";
- if ($count) { $sql .= " LIMIT $count"; }
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = new Song($r['id']);
- }
-
- return $results;
-
- }
-
- /**
- * find_duplicates
- *
- * This function takes a search type and returns a list of probable
- * duplicates
- */
- public static function find_duplicates($search_type) {
- $where_sql = $_REQUEST['search_disabled'] ? '' : "WHERE `enabled` != '0'";
- $sql = 'SELECT `id`, `artist`, `album`, `title`, ' .
- 'COUNT(`title`) FROM `song` ' . $where_sql .
- ' GROUP BY `title`';
-
- if ($search_type == 'artist_title' ||
- $search_type == 'artist_album_title') {
- $sql .= ',`artist`';
- }
- if ($search_type == 'artist_album_title') {
- $sql .= ',`album`';
- }
-
- $sql .= ' HAVING COUNT(`title`) > 1 ORDER BY `title`';
-
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($item = Dba::fetch_assoc($db_results)) {
- $results[] = $item;
- } // end while
-
- return $results;
- }
-
- public static function get_duplicate_info($dupe, $search_type) {
- $sql = 'SELECT `id` FROM `song` ' .
- "WHERE `title`='" . Dba::escape($item['title']) . "' ";
-
- if ($search_type == 'artist_title' ||
- $search_type == 'artist_album_title') {
- $sql .= "AND `artist`='" . Dba::escape($item['artist']) . "' ";
- }
- if ($search_type == 'artist_album_title') {
- $sql .= "AND `album` = '" . Dba::escape($item['album']) . "' ";
- }
-
- $sql .= 'ORDER BY `time`,`bitrate`,`size`';
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($item = Dba::fetch_assoc($db_results)) {
- $results[] = $item['id'];
- } // end while
-
- return $results;
- }
-
- /**
- * get_album_name
- * gets the name of $this->album, allows passing of id
- */
- public function get_album_name($album_id=0) {
- if (!$album_id) { $album_id = $this->album; }
- $album = new Album($album_id);
- if ($album->prefix)
- return $album->prefix . " " . $album->name;
- else
- return $album->name;
- } // get_album_name
-
- /**
- * get_artist_name
- * gets the name of $this->artist, allows passing of id
- */
- public function get_artist_name($artist_id=0) {
-
- if (!$artist_id) { $artist_id = $this->artist; }
- $artist = new Artist($artist_id);
- if ($artist->prefix)
- return $artist->prefix . " " . $artist->name;
- else
- return $artist->name;
-
- } // get_album_name
-
- /**
- * has_flag
- * This just returns true or false depending on if this song is flagged for something
- * We don't care what so we limit the SELECT to 1
- */
- public function has_flag() {
-
- $sql = "SELECT `id` FROM `flagged` WHERE `object_type`='song' AND `object_id`='$this->id' LIMIT 1";
- $db_results = Dba::read($sql);
-
- if (Dba::fetch_assoc($db_results)) {
- return true;
- }
-
- return false;
-
- } // has_flag
-
- /**
- * set_played
- * this checks to see if the current object has been played
- * if not then it sets it to played
- */
- public function set_played() {
-
- if ($this->played) {
- return true;
- }
-
- /* If it hasn't been played, set it! */
- self::update_played('1',$this->id);
-
- return true;
-
- } // set_played
-
- /**
- * compare_song_information
- * this compares the new ID3 tags of a file against
- * the ones in the database to see if they have changed
- * it returns false if nothing has changes, or the true
- * if they have. Static because it doesn't need this
- */
- public static function compare_song_information($song,$new_song) {
-
- // Remove some stuff we don't care about
- unset($song->catalog,$song->played,$song->enabled,$song->addition_time,$song->update_time,$song->type);
-
- $string_array = array('title','comment','lyrics');
- $skip_array = array('id','tag_id','mime','mb_artistid','mbid');
-
- // Pull out all the currently set vars
- $fields = get_object_vars($song);
-
- // Foreach them
- foreach ($fields as $key=>$value) {
- if (in_array($key,$skip_array)) { continue; }
- // If it's a stringie thing
- if (in_array($key,$string_array)) {
- if (trim(stripslashes($song->$key)) != trim(stripslashes($new_song->$key))) {
- $array['change'] = true;
- $array['element'][$key] = 'OLD: ' . $song->$key . ' --> ' . $new_song->$key;
- }
- } // in array of stringies
- else {
- if ($song->$key != $new_song->$key) {
- $array['change'] = true;
- $array['element'][$key] = 'OLD:' . $song->$key . ' --> ' . $new_song->$key;
- }
- } // end else
-
- } // end foreach
-
- if ($array['change']) {
- debug_event('song-diff', json_encode($array['element']), 5, 'ampache-catalog');
- }
-
- return $array;
-
- } // compare_song_information
-
-
- /**
- * update
- * This takes a key'd array of data does any cleaning it needs to
- * do and then calls the helper functions as needed. This will also
- * cause the song to be flagged
- */
- public function update($data) {
-
- foreach ($data as $key=>$value) {
- switch ($key) {
- case 'artist':
- // Don't do anything if we've negative one'd this baby
- if ($value == '-1') {
- $value = Catalog::check_artist($data['artist_name'], $data['mb_artistid']);
- }
- case 'album':
- if ($value == '-1') {
- $value = Catalog::check_album($data['album_name'], $data['year'], $data['disk'], $data['mb_albumid']);
- }
- case 'title':
- case 'track':
- // Check to see if it needs to be updated
- if ($value != $this->$key) {
- $function = 'update_' . $key;
- self::$function($value,$this->id);
- $this->$key = $value;
- $updated = 1;
- }
- break;
- default:
- // Rien a faire
- break;
- } // end whitelist
- } // end foreach
-
- // If a field was changed then we need to flag this mofo
- if ($updated) {
- Flag::add($this->id,'song','retag','Interface Update');
- }
-
- return true;
-
- } // update
-
- /**
- * update_song
- * this is the main updater for a song it actually
- * calls a whole bunch of mini functions to update
- * each little part of the song... lastly it updates
- * the "update_time" of the song
- */
- public static function update_song($song_id, $new_song) {
-
- $title = Dba::escape($new_song->title);
- $bitrate = Dba::escape($new_song->bitrate);
- $rate = Dba::escape($new_song->rate);
- $mode = Dba::escape($new_song->mode);
- $size = Dba::escape($new_song->size);
- $time = Dba::escape($new_song->time);
- $track = Dba::escape($new_song->track);
- $mbid = Dba::escape($new_song->mbid);
- $artist = Dba::escape($new_song->artist);
- $album = Dba::escape($new_song->album);
- $year = Dba::escape($new_song->year);
- $song_id = Dba::escape($song_id);
- $update_time = time();
-
-
- $sql = "UPDATE `song` SET `album`='$album', `year`='$year', `artist`='$artist', " .
- "`title`='$title', `bitrate`='$bitrate', `rate`='$rate', `mode`='$mode', " .
- "`size`='$size', `time`='$time', `track`='$track', " .
- "`mbid`='$mbid', " .
- "`update_time`='$update_time' WHERE `id`='$song_id'";
- $db_results = Dba::write($sql);
-
-
- $comment = Dba::escape($new_song->comment);
- $language = Dba::escape($new_song->language);
- $lyrics = Dba::escape($new_song->lyrics);
-
- $sql = "UPDATE `song_data` SET `lyrics`='$lyrics', `language`='$language', `comment`='$comment' " .
- "WHERE `song_id`='$song_id'";
- $db_results = Dba::write($sql);
-
- } // update_song
-
- /**
- * update_year
- * update the year tag
- */
- public static function update_year($new_year,$song_id) {
-
- self::_update_item('year',$new_year,$song_id,'50');
-
- } // update_year
-
- /**
- * update_language
- * This updates the language tag of the song
- */
- public static function update_language($new_lang,$song_id) {
-
- self::_update_ext_item('language',$new_lang,$song_id,'50');
-
- } // update_language
-
- /**
- * update_comment
- * updates the comment field
- */
- public static function update_comment($new_comment,$song_id) {
+ /* Variables from DB */
+ public $id;
+ public $file;
+ public $album; // album.id (Int)
+ public $artist; // artist.id (Int)
+ public $title;
+ public $year;
+ public $bitrate;
+ public $rate;
+ public $mode;
+ public $size;
+ public $time;
+ public $track;
+ public $album_mbid;
+ public $artist_mbid;
+ public $type;
+ public $mime;
+ public $played;
+ public $enabled;
+ public $addition_time;
+ public $update_time;
+ public $mbid; // MusicBrainz ID
+
+ /* Setting Variables */
+ public $_fake = false; // If this is a 'construct_from_array' object
+
+ /**
+ * Constructor
+ * Song class, for modifing a song.
+ */
+ public function __construct($id='') {
+
+ if (!$id) { return false; }
+
+ /* Assign id for use in get_info() */
+ $this->id = intval($id);
+
+ /* Get the information from the db */
+ if ($info = $this->_get_info()) {
+
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
+ $data = pathinfo($this->file);
+ $this->type = strtolower($data['extension']);
+ $this->mime = self::type_to_mime($this->type);
+ }
+
+ return true;
+
+ } // constructor
+
+ /**
+ * gc
+ *
+ * Cleans up the song_data table
+ */
+ public static function gc() {
+ Dba::write('DELETE FROM `song_data` USING `song_data` LEFT JOIN `song` ON `song`.`id` = `song_data`.`song_id` WHERE `song`.`id` IS NULL');
+ }
+
+ /**
+ * build_cache
+ *
+ * This attempts to reduce queries by asking for everything in the
+ * browse all at once and storing it in the cache, this can help if the
+ * db connection is the slow point.
+ */
+ public static function build_cache($song_ids) {
+
+ if (!is_array($song_ids) || !count($song_ids)) { return false; }
+
+ $idlist = '(' . implode(',', $song_ids) . ')';
+
+ // Callers might have passed array(false) because they are dumb
+ if ($idlist == '()') { return false; }
+
+ // Song data cache
+ $sql = 'SELECT `song`.`id`, `file`, `catalog`, `album`, ' .
+ '`year`, `artist`, `title`, `bitrate`, `rate`, ' .
+ '`mode`, `size`, `time`, `track`, `played`, ' .
+ '`song`.`enabled`, `update_time`, `tag_map`.`tag_id`, '.
+ '`mbid`, `addition_time` ' .
+ 'FROM `song` LEFT JOIN `tag_map` ' .
+ 'ON `tag_map`.`object_id`=`song`.`id` ' .
+ "AND `tag_map`.`object_type`='song' " .
+ "WHERE `song`.`id` IN $idlist";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('song', $row['id'], $row);
+ $artists[$row['artist']] = $row['artist'];
+ $albums[$row['album']] = $row['album'];
+ if ($row['tag_id']) {
+ $tags[$row['tag_id']] = $row['tag_id'];
+ }
+ }
+
+ Artist::build_cache($artists);
+ Album::build_cache($albums);
+ Tag::build_cache($tags);
+ Tag::build_map_cache('song',$song_ids);
+ Art::build_cache($albums);
+
+ // If we're rating this then cache them as well
+ if (Config::get('ratings')) {
+ Rating::build_cache('song', $song_ids);
+ }
+
+ // Build a cache for the song's extended table
+ $sql = "SELECT * FROM `song_data` WHERE `song_id` IN $idlist";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('song_data', $row['song_id'], $row);
+ }
+
+ return true;
+
+ } // build_cache
+
+ /**
+ * _get_info
+ * get's the vars for $this out of the database
+ * Taken from the object
+ */
+ private function _get_info() {
+
+ $id = intval($this->id);
+
+ if (parent::is_cached('song',$id)) {
+ return parent::get_from_cache('song',$id);
+ }
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT song.id,file,catalog,album,year,artist,".
+ "title,bitrate,rate,mode,size,time,track,played,song.enabled,update_time,".
+ "mbid,".
+ "addition_time FROM `song` WHERE `song`.`id` = '$id'";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+
+ parent::add_to_cache('song',$id,$results);
+
+ return $results;
+
+ } // _get_info
+
+ /**
+ * _get_ext_info
+ * This function gathers information from the song_ext_info table and adds it to the
+ * current object
+ */
+ public function _get_ext_info() {
+
+ $id = intval($this->id);
+
+ if (parent::is_cached('song_data',$id)) {
+ return parent::get_from_cache('song_data',$id);
+ }
+
+ $sql = "SELECT * FROM song_data WHERE `song_id`='$id'";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+
+ parent::add_to_cache('song_data',$id,$results);
+
+ return $results;
+
+ } // _get_ext_info
+
+ /**
+ * fill_ext_info
+ * This calls the _get_ext_info and then sets the correct vars
+ */
+ public function fill_ext_info() {
+
+ $info = $this->_get_ext_info();
+
+ foreach ($info as $key=>$value) {
+ if ($key != 'song_id') {
+ $this->$key = $value;
+ }
+ } // end foreach
+
+ } // fill_ext_info
+
+ /**
+ * type_to_mime
+ *
+ * Returns the mime type for the specified file extension/type
+ */
+ public static function type_to_mime($type) {
+ // FIXME: This should really be done the other way around.
+ // Store the mime type in the database, and provide a function
+ // to make it a human-friendly type.
+ switch ($type) {
+ case 'spx':
+ case 'ogg':
+ return 'application/ogg';
+ break;
+ case 'wma':
+ case 'asf':
+ return 'audio/x-ms-wma';
+ break;
+ case 'mp3':
+ case 'mpeg3':
+ return 'audio/mpeg';
+ break;
+ case 'rm':
+ case 'ra':
+ return 'audio/x-realaudio';
+ break;
+ case 'flac';
+ return 'audio/x-flac';
+ break;
+ case 'wv':
+ return 'audio/x-wavpack';
+ break;
+ case 'aac':
+ case 'mp4':
+ case 'm4a':
+ return 'audio/mp4';
+ break;
+ case 'mpc':
+ return 'audio/x-musepack';
+ break;
+ default:
+ return 'audio/mpeg';
+ break;
+ }
+
+ return true;
+
+ }
+
+ /**
+ * get_disabled
+ *
+ * Gets a list of the disabled songs for and returns an array of Songs
+ */
+ public static function get_disabled($count = 0) {
+
+ $results = array();
+
+ $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'";
+ if ($count) { $sql .= " LIMIT $count"; }
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = new Song($r['id']);
+ }
+
+ return $results;
+
+ }
+
+ /**
+ * find_duplicates
+ *
+ * This function takes a search type and returns a list of probable
+ * duplicates
+ */
+ public static function find_duplicates($search_type) {
+ $where_sql = $_REQUEST['search_disabled'] ? '' : "WHERE `enabled` != '0'";
+ $sql = 'SELECT `id`, `artist`, `album`, `title`, ' .
+ 'COUNT(`title`) FROM `song` ' . $where_sql .
+ ' GROUP BY `title`';
+
+ if ($search_type == 'artist_title' ||
+ $search_type == 'artist_album_title') {
+ $sql .= ',`artist`';
+ }
+ if ($search_type == 'artist_album_title') {
+ $sql .= ',`album`';
+ }
+
+ $sql .= ' HAVING COUNT(`title`) > 1 ORDER BY `title`';
+
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($item = Dba::fetch_assoc($db_results)) {
+ $results[] = $item;
+ } // end while
+
+ return $results;
+ }
+
+ public static function get_duplicate_info($dupe, $search_type) {
+ $sql = 'SELECT `id` FROM `song` ' .
+ "WHERE `title`='" . Dba::escape($item['title']) . "' ";
+
+ if ($search_type == 'artist_title' ||
+ $search_type == 'artist_album_title') {
+ $sql .= "AND `artist`='" . Dba::escape($item['artist']) . "' ";
+ }
+ if ($search_type == 'artist_album_title') {
+ $sql .= "AND `album` = '" . Dba::escape($item['album']) . "' ";
+ }
+
+ $sql .= 'ORDER BY `time`,`bitrate`,`size`';
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($item = Dba::fetch_assoc($db_results)) {
+ $results[] = $item['id'];
+ } // end while
+
+ return $results;
+ }
+
+ /**
+ * get_album_name
+ * gets the name of $this->album, allows passing of id
+ */
+ public function get_album_name($album_id=0) {
+ if (!$album_id) { $album_id = $this->album; }
+ $album = new Album($album_id);
+ if ($album->prefix)
+ return $album->prefix . " " . $album->name;
+ else
+ return $album->name;
+ } // get_album_name
+
+ /**
+ * get_artist_name
+ * gets the name of $this->artist, allows passing of id
+ */
+ public function get_artist_name($artist_id=0) {
+
+ if (!$artist_id) { $artist_id = $this->artist; }
+ $artist = new Artist($artist_id);
+ if ($artist->prefix)
+ return $artist->prefix . " " . $artist->name;
+ else
+ return $artist->name;
+
+ } // get_album_name
+
+ /**
+ * has_flag
+ * This just returns true or false depending on if this song is flagged for something
+ * We don't care what so we limit the SELECT to 1
+ */
+ public function has_flag() {
+
+ $sql = "SELECT `id` FROM `flagged` WHERE `object_type`='song' AND `object_id`='$this->id' LIMIT 1";
+ $db_results = Dba::read($sql);
+
+ if (Dba::fetch_assoc($db_results)) {
+ return true;
+ }
+
+ return false;
+
+ } // has_flag
+
+ /**
+ * set_played
+ * this checks to see if the current object has been played
+ * if not then it sets it to played
+ */
+ public function set_played() {
+
+ if ($this->played) {
+ return true;
+ }
+
+ /* If it hasn't been played, set it! */
+ self::update_played('1',$this->id);
+
+ return true;
+
+ } // set_played
+
+ /**
+ * compare_song_information
+ * this compares the new ID3 tags of a file against
+ * the ones in the database to see if they have changed
+ * it returns false if nothing has changes, or the true
+ * if they have. Static because it doesn't need this
+ */
+ public static function compare_song_information($song,$new_song) {
+
+ // Remove some stuff we don't care about
+ unset($song->catalog,$song->played,$song->enabled,$song->addition_time,$song->update_time,$song->type);
+
+ $string_array = array('title','comment','lyrics');
+ $skip_array = array('id','tag_id','mime','mb_artistid','mbid');
+
+ // Pull out all the currently set vars
+ $fields = get_object_vars($song);
+
+ // Foreach them
+ foreach ($fields as $key=>$value) {
+ if (in_array($key,$skip_array)) { continue; }
+ // If it's a stringie thing
+ if (in_array($key,$string_array)) {
+ if (trim(stripslashes($song->$key)) != trim(stripslashes($new_song->$key))) {
+ $array['change'] = true;
+ $array['element'][$key] = 'OLD: ' . $song->$key . ' --> ' . $new_song->$key;
+ }
+ } // in array of stringies
+ else {
+ if ($song->$key != $new_song->$key) {
+ $array['change'] = true;
+ $array['element'][$key] = 'OLD:' . $song->$key . ' --> ' . $new_song->$key;
+ }
+ } // end else
+
+ } // end foreach
+
+ if ($array['change']) {
+ debug_event('song-diff', json_encode($array['element']), 5, 'ampache-catalog');
+ }
+
+ return $array;
+
+ } // compare_song_information
+
+
+ /**
+ * update
+ * This takes a key'd array of data does any cleaning it needs to
+ * do and then calls the helper functions as needed. This will also
+ * cause the song to be flagged
+ */
+ public function update($data) {
+
+ foreach ($data as $key=>$value) {
+ switch ($key) {
+ case 'artist':
+ // Don't do anything if we've negative one'd this baby
+ if ($value == '-1') {
+ $value = Catalog::check_artist($data['artist_name'], $data['mb_artistid']);
+ }
+ case 'album':
+ if ($value == '-1') {
+ $value = Catalog::check_album($data['album_name'], $data['year'], $data['disk'], $data['mb_albumid']);
+ }
+ case 'title':
+ case 'track':
+ // Check to see if it needs to be updated
+ if ($value != $this->$key) {
+ $function = 'update_' . $key;
+ self::$function($value,$this->id);
+ $this->$key = $value;
+ $updated = 1;
+ }
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end whitelist
+ } // end foreach
+
+ // If a field was changed then we need to flag this mofo
+ if ($updated) {
+ Flag::add($this->id,'song','retag','Interface Update');
+ }
+
+ return true;
+
+ } // update
+
+ /**
+ * update_song
+ * this is the main updater for a song it actually
+ * calls a whole bunch of mini functions to update
+ * each little part of the song... lastly it updates
+ * the "update_time" of the song
+ */
+ public static function update_song($song_id, $new_song) {
+
+ $title = Dba::escape($new_song->title);
+ $bitrate = Dba::escape($new_song->bitrate);
+ $rate = Dba::escape($new_song->rate);
+ $mode = Dba::escape($new_song->mode);
+ $size = Dba::escape($new_song->size);
+ $time = Dba::escape($new_song->time);
+ $track = Dba::escape($new_song->track);
+ $mbid = Dba::escape($new_song->mbid);
+ $artist = Dba::escape($new_song->artist);
+ $album = Dba::escape($new_song->album);
+ $year = Dba::escape($new_song->year);
+ $song_id = Dba::escape($song_id);
+ $update_time = time();
+
+
+ $sql = "UPDATE `song` SET `album`='$album', `year`='$year', `artist`='$artist', " .
+ "`title`='$title', `bitrate`='$bitrate', `rate`='$rate', `mode`='$mode', " .
+ "`size`='$size', `time`='$time', `track`='$track', " .
+ "`mbid`='$mbid', " .
+ "`update_time`='$update_time' WHERE `id`='$song_id'";
+ $db_results = Dba::write($sql);
+
+
+ $comment = Dba::escape($new_song->comment);
+ $language = Dba::escape($new_song->language);
+ $lyrics = Dba::escape($new_song->lyrics);
+
+ $sql = "UPDATE `song_data` SET `lyrics`='$lyrics', `language`='$language', `comment`='$comment' " .
+ "WHERE `song_id`='$song_id'";
+ $db_results = Dba::write($sql);
+
+ } // update_song
+
+ /**
+ * update_year
+ * update the year tag
+ */
+ public static function update_year($new_year,$song_id) {
+
+ self::_update_item('year',$new_year,$song_id,'50');
+
+ } // update_year
+
+ /**
+ * update_language
+ * This updates the language tag of the song
+ */
+ public static function update_language($new_lang,$song_id) {
+
+ self::_update_ext_item('language',$new_lang,$song_id,'50');
+
+ } // update_language
+
+ /**
+ * update_comment
+ * updates the comment field
+ */
+ public static function update_comment($new_comment,$song_id) {
- self::_update_ext_item('comment',$new_comment,$song_id,'50');
+ self::_update_ext_item('comment',$new_comment,$song_id,'50');
- } // update_comment
+ } // update_comment
- /**
- * update_lyrics
- * updates the lyrics field
- */
- public static function update_lyrics($new_lyrics,$song_id) {
+ /**
+ * update_lyrics
+ * updates the lyrics field
+ */
+ public static function update_lyrics($new_lyrics,$song_id) {
- self::_update_ext_item('lyrics',$new_lyrics,$song_id,'50');
+ self::_update_ext_item('lyrics',$new_lyrics,$song_id,'50');
- } // update_lyrics
+ } // update_lyrics
- /**
- * update_title
- * updates the title field
- */
- public static function update_title($new_title,$song_id) {
+ /**
+ * update_title
+ * updates the title field
+ */
+ public static function update_title($new_title,$song_id) {
- self::_update_item('title',$new_title,$song_id,'50');
+ self::_update_item('title',$new_title,$song_id,'50');
- } // update_title
+ } // update_title
- /**
- * update_bitrate
- * updates the bitrate field
- */
- public static function update_bitrate($new_bitrate,$song_id) {
+ /**
+ * update_bitrate
+ * updates the bitrate field
+ */
+ public static function update_bitrate($new_bitrate,$song_id) {
- self::_update_item('bitrate',$new_bitrate,$song_id,'50');
+ self::_update_item('bitrate',$new_bitrate,$song_id,'50');
- } // update_bitrate
+ } // update_bitrate
- /**
- * update_rate
- * updates the rate field
- */
- public static function update_rate($new_rate,$song_id) {
+ /**
+ * update_rate
+ * updates the rate field
+ */
+ public static function update_rate($new_rate,$song_id) {
- self::_update_item('rate',$new_rate,$song_id,'50');
+ self::_update_item('rate',$new_rate,$song_id,'50');
- } // update_rate
+ } // update_rate
- /**
- * update_mode
- * updates the mode field
- */
- public static function update_mode($new_mode,$song_id) {
+ /**
+ * update_mode
+ * updates the mode field
+ */
+ public static function update_mode($new_mode,$song_id) {
- self::_update_item('mode',$new_mode,$song_id,'50');
+ self::_update_item('mode',$new_mode,$song_id,'50');
- } // update_mode
+ } // update_mode
- /**
- * update_size
- * updates the size field
- */
- public static function update_size($new_size,$song_id) {
+ /**
+ * update_size
+ * updates the size field
+ */
+ public static function update_size($new_size,$song_id) {
- self::_update_item('size',$new_size,$song_id,'50');
+ self::_update_item('size',$new_size,$song_id,'50');
- } // update_size
+ } // update_size
- /**
- * update_time
- * updates the time field
- */
- public static function update_time($new_time,$song_id) {
+ /**
+ * update_time
+ * updates the time field
+ */
+ public static function update_time($new_time,$song_id) {
- self::_update_item('time',$new_time,$song_id,'50');
+ self::_update_item('time',$new_time,$song_id,'50');
- } // update_time
+ } // update_time
- /**
- * update_track
- * this updates the track field
- */
- public static function update_track($new_track,$song_id) {
+ /**
+ * update_track
+ * this updates the track field
+ */
+ public static function update_track($new_track,$song_id) {
- self::_update_item('track',$new_track,$song_id,'50');
+ self::_update_item('track',$new_track,$song_id,'50');
- } // update_track
+ } // update_track
- public static function update_mbid($new_mbid,$song_id) {
+ public static function update_mbid($new_mbid,$song_id) {
- self::_update_item('mbid',$new_mbid,$song_id,'50');
+ self::_update_item('mbid',$new_mbid,$song_id,'50');
- } // update_mbid
+ } // update_mbid
- /**
- * update_artist
- * updates the artist field
- */
- public static function update_artist($new_artist,$song_id) {
+ /**
+ * update_artist
+ * updates the artist field
+ */
+ public static function update_artist($new_artist,$song_id) {
- self::_update_item('artist',$new_artist,$song_id,'50');
+ self::_update_item('artist',$new_artist,$song_id,'50');
- } // update_artist
+ } // update_artist
- /**
- * update_album
- * updates the album field
- */
- public static function update_album($new_album,$song_id) {
+ /**
+ * update_album
+ * updates the album field
+ */
+ public static function update_album($new_album,$song_id) {
- self::_update_item('album',$new_album,$song_id,'50');
+ self::_update_item('album',$new_album,$song_id,'50');
- } // update_album
+ } // update_album
- /**
- * update_utime
- * sets a new update time
- */
- public static function update_utime($song_id,$time=0) {
+ /**
+ * update_utime
+ * sets a new update time
+ */
+ public static function update_utime($song_id,$time=0) {
- if (!$time) { $time = time(); }
+ if (!$time) { $time = time(); }
- self::_update_item('update_time',$time,$song_id,'75');
+ self::_update_item('update_time',$time,$song_id,'75');
- } // update_utime
+ } // update_utime
- /**
- * update_played
- * sets the played flag
- */
- public static function update_played($new_played,$song_id) {
+ /**
+ * update_played
+ * sets the played flag
+ */
+ public static function update_played($new_played,$song_id) {
- self::_update_item('played',$new_played,$song_id,'25');
+ self::_update_item('played',$new_played,$song_id,'25');
- } // update_played
+ } // update_played
- /**
- * update_enabled
- * sets the enabled flag
- */
- public static function update_enabled($new_enabled,$song_id) {
+ /**
+ * update_enabled
+ * sets the enabled flag
+ */
+ public static function update_enabled($new_enabled,$song_id) {
- self::_update_item('enabled',$new_enabled,$song_id,'75');
+ self::_update_item('enabled',$new_enabled,$song_id,'75');
- } // update_enabled
+ } // update_enabled
- /**
- * _update_item
- * This is a private function that should only be called from within the song class.
- * It takes a field, value song id and level. first and foremost it checks the level
- * against $GLOBALS['user'] to make sure they are allowed to update this record
- * it then updates it and sets $this->{$field} to the new value
- */
- private static function _update_item($field,$value,$song_id,$level) {
+ /**
+ * _update_item
+ * This is a private function that should only be called from within the song class.
+ * It takes a field, value song id and level. first and foremost it checks the level
+ * against $GLOBALS['user'] to make sure they are allowed to update this record
+ * it then updates it and sets $this->{$field} to the new value
+ */
+ private static function _update_item($field,$value,$song_id,$level) {
- /* Check them Rights! */
- if (!Access::check('interface',$level)) { return false; }
+ /* Check them Rights! */
+ if (!Access::check('interface',$level)) { return false; }
- /* Can't update to blank */
- if (!strlen(trim($value)) && $field != 'comment') { return false; }
+ /* Can't update to blank */
+ if (!strlen(trim($value)) && $field != 'comment') { return false; }
- $value = Dba::escape($value);
+ $value = Dba::escape($value);
- $sql = "UPDATE `song` SET `$field`='$value' WHERE `id`='$song_id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `song` SET `$field`='$value' WHERE `id`='$song_id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // _update_item
+ } // _update_item
- /**
- * _update_ext_item
- * This updates a song record that is housed in the song_ext_info table
- * These are items that aren't used normally, and often large/informational only
- */
- private static function _update_ext_item($field,$value,$song_id,$level) {
+ /**
+ * _update_ext_item
+ * This updates a song record that is housed in the song_ext_info table
+ * These are items that aren't used normally, and often large/informational only
+ */
+ private static function _update_ext_item($field,$value,$song_id,$level) {
- /* Check them rights boy! */
- if (!Access::check('interface',$level)) { return false; }
+ /* Check them rights boy! */
+ if (!Access::check('interface',$level)) { return false; }
- $value = Dba::escape($value);
+ $value = Dba::escape($value);
- $sql = "UPDATE `song_data` SET `$field`='$value' WHERE `song_id`='$song_id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `song_data` SET `$field`='$value' WHERE `song_id`='$song_id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // _update_ext_item
+ } // _update_ext_item
- /**
- * format
- * This takes the current song object
- * and does a ton of formating on it creating f_??? variables on the current
- * object
- */
- public function format() {
+ /**
+ * format
+ * This takes the current song object
+ * and does a ton of formating on it creating f_??? variables on the current
+ * object
+ */
+ public function format() {
- $this->fill_ext_info();
+ $this->fill_ext_info();
- // Format the filename
- preg_match("/^.*\/(.*?)$/",$this->file, $short);
- $this->f_file = htmlspecialchars($short[1]);
+ // Format the filename
+ preg_match("/^.*\/(.*?)$/",$this->file, $short);
+ $this->f_file = htmlspecialchars($short[1]);
- // Format the album name
- $this->f_album_full = $this->get_album_name();
- $this->f_album = UI::truncate($this->f_album_full,Config::get('ellipse_threshold_album'));
+ // Format the album name
+ $this->f_album_full = $this->get_album_name();
+ $this->f_album = UI::truncate($this->f_album_full,Config::get('ellipse_threshold_album'));
- // Format the artist name
- $this->f_artist_full = $this->get_artist_name();
- $this->f_artist = UI::truncate($this->f_artist_full,Config::get('ellipse_threshold_artist'));
+ // Format the artist name
+ $this->f_artist_full = $this->get_artist_name();
+ $this->f_artist = UI::truncate($this->f_artist_full,Config::get('ellipse_threshold_artist'));
- // Format the title
- $this->f_title_full = $this->title;
- $this->f_title = UI::truncate($this->title,Config::get('ellipse_threshold_title'));
+ // Format the title
+ $this->f_title_full = $this->title;
+ $this->f_title = UI::truncate($this->title,Config::get('ellipse_threshold_title'));
- // Create Links for the different objects
- $this->link = Config::get('web_path') . "/song.php?action=show_song&song_id=" . $this->id;
- $this->f_link = "<a href=\"" . scrub_out($this->link) . "\" title=\"" . scrub_out($this->title) . "\"> " . scrub_out($this->f_title) . "</a>";
- $this->f_album_link = "<a href=\"" . Config::get('web_path') . "/albums.php?action=show&amp;album=" . $this->album . "\" title=\"" . scrub_out($this->f_album_full) . "\"> " . scrub_out($this->f_album) . "</a>";
- $this->f_artist_link = "<a href=\"" . Config::get('web_path') . "/artists.php?action=show&amp;artist=" . $this->artist . "\" title=\"" . scrub_out($this->f_artist_full) . "\"> " . scrub_out($this->f_artist) . "</a>";
+ // Create Links for the different objects
+ $this->link = Config::get('web_path') . "/song.php?action=show_song&song_id=" . $this->id;
+ $this->f_link = "<a href=\"" . scrub_out($this->link) . "\" title=\"" . scrub_out($this->title) . "\"> " . scrub_out($this->f_title) . "</a>";
+ $this->f_album_link = "<a href=\"" . Config::get('web_path') . "/albums.php?action=show&amp;album=" . $this->album . "\" title=\"" . scrub_out($this->f_album_full) . "\"> " . scrub_out($this->f_album) . "</a>";
+ $this->f_artist_link = "<a href=\"" . Config::get('web_path') . "/artists.php?action=show&amp;artist=" . $this->artist . "\" title=\"" . scrub_out($this->f_artist_full) . "\"> " . scrub_out($this->f_artist) . "</a>";
- // Format the Bitrate
- $this->f_bitrate = intval($this->bitrate/1000) . "-" . strtoupper($this->mode);
+ // Format the Bitrate
+ $this->f_bitrate = intval($this->bitrate/1000) . "-" . strtoupper($this->mode);
- // Format the Time
- $min = floor($this->time/60);
- $sec = sprintf("%02d", ($this->time%60) );
- $this->f_time = $min . ":" . $sec;
+ // Format the Time
+ $min = floor($this->time/60);
+ $sec = sprintf("%02d", ($this->time%60) );
+ $this->f_time = $min . ":" . $sec;
- // Format the track (there isn't really anything to do here)
- $this->f_track = $this->track;
+ // Format the track (there isn't really anything to do here)
+ $this->f_track = $this->track;
- // Get the top tags
- $tags = Tag::get_top_tags('song',$this->id);
- $this->tags = $tags;
+ // Get the top tags
+ $tags = Tag::get_top_tags('song',$this->id);
+ $this->tags = $tags;
- $this->f_tags = Tag::get_display($tags,$this->id,'song');
+ $this->f_tags = Tag::get_display($tags,$this->id,'song');
- // Format the size
- $this->f_size = UI::format_bytes($this->size);
+ // Format the size
+ $this->f_size = UI::format_bytes($this->size);
- return true;
+ return true;
- } // format
+ } // format
- /**
- * format_pattern
- * This reformats the song information based on the catalog
- * rename patterns
- */
- public function format_pattern() {
+ /**
+ * format_pattern
+ * This reformats the song information based on the catalog
+ * rename patterns
+ */
+ public function format_pattern() {
- $extension = ltrim(substr($this->file,strlen($this->file)-4,4),".");
+ $extension = ltrim(substr($this->file,strlen($this->file)-4,4),".");
- $catalog = new Catalog($this->catalog);
+ $catalog = new Catalog($this->catalog);
- // If we don't have a rename pattern then just return it
- if (!trim($catalog->rename_pattern)) {
- $this->f_pattern = $this->title;
- $this->f_file = $this->title . '.' . $extension;
- return;
- }
+ // If we don't have a rename pattern then just return it
+ if (!trim($catalog->rename_pattern)) {
+ $this->f_pattern = $this->title;
+ $this->f_file = $this->title . '.' . $extension;
+ return;
+ }
- /* Create the filename that this file should have */
- $album = $this->f_album_full;
- $artist = $this->f_artist_full;
- $track = sprintf('%02d', $this->track);
- $title = $this->title;
- $year = $this->year;
+ /* Create the filename that this file should have */
+ $album = $this->f_album_full;
+ $artist = $this->f_artist_full;
+ $track = sprintf('%02d', $this->track);
+ $title = $this->title;
+ $year = $this->year;
- /* Start replacing stuff */
- $replace_array = array('%a','%A','%t','%T','%y','/','\\');
- $content_array = array($artist,$album,$title,$track,$year,'-','-');
+ /* Start replacing stuff */
+ $replace_array = array('%a','%A','%t','%T','%y','/','\\');
+ $content_array = array($artist,$album,$title,$track,$year,'-','-');
- $rename_pattern = str_replace($replace_array,$content_array,$catalog->rename_pattern);
+ $rename_pattern = str_replace($replace_array,$content_array,$catalog->rename_pattern);
- $rename_pattern = preg_replace("[\-\:\!]","_",$rename_pattern);
+ $rename_pattern = preg_replace("[\-\:\!]","_",$rename_pattern);
- $this->f_pattern = $rename_pattern;
- $this->f_file = $rename_pattern . "." . $extension;
+ $this->f_pattern = $rename_pattern;
+ $this->f_file = $rename_pattern . "." . $extension;
- } // format_pattern
+ } // format_pattern
- /**
- * get_fields
- * This returns all of the 'data' fields for this object, we need to filter out some that we don't
- * want to present to a user, and add some that don't exist directly on the object but are related
- */
- public static function get_fields() {
+ /**
+ * get_fields
+ * This returns all of the 'data' fields for this object, we need to filter out some that we don't
+ * want to present to a user, and add some that don't exist directly on the object but are related
+ */
+ public static function get_fields() {
- $fields = get_class_vars('Song');
+ $fields = get_class_vars('Song');
- unset($fields['id'],$fields['_transcoded'],$fields['_fake'],$fields['cache_hit'],$fields['mime'],$fields['type']);
+ unset($fields['id'],$fields['_transcoded'],$fields['_fake'],$fields['cache_hit'],$fields['mime'],$fields['type']);
- // Some additional fields
- $fields['tag'] = true;
- $fields['catalog'] = true;
+ // Some additional fields
+ $fields['tag'] = true;
+ $fields['catalog'] = true;
//FIXME: These are here to keep the ideas, don't want to have to worry about them for now
-// $fields['rating'] = true;
-// $fields['recently Played'] = true;
+// $fields['rating'] = true;
+// $fields['recently Played'] = true;
- return $fields;
+ return $fields;
- } // get_fields
+ } // get_fields
- /**
- * get_from_path
- * This returns all of the songs that exist under the specified path
- */
- public static function get_from_path($path) {
+ /**
+ * get_from_path
+ * This returns all of the songs that exist under the specified path
+ */
+ public static function get_from_path($path) {
- $path = Dba::escape($path);
+ $path = Dba::escape($path);
- $sql = "SELECT * FROM `song` WHERE `file` LIKE '$path%'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `song` WHERE `file` LIKE '$path%'";
+ $db_results = Dba::read($sql);
- $songs = array();
+ $songs = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $songs[] = $row['id'];
- }
-
- return $songs;
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $songs[] = $row['id'];
+ }
+
+ return $songs;
- } // get_from_path
+ } // get_from_path
- /**
- * @function get_rel_path
- * @discussion returns the path of the song file stripped of the catalog path
- * used for mpd playback
- */
- public function get_rel_path($file_path=0,$catalog_id=0) {
+ /**
+ * @function get_rel_path
+ * @discussion returns the path of the song file stripped of the catalog path
+ * used for mpd playback
+ */
+ public function get_rel_path($file_path=0,$catalog_id=0) {
- if (!$file_path) {
- $info = $this->_get_info();
- $file_path = $info->file;
- }
- if (!$catalog_id) {
- $catalog_id = $info->catalog;
- }
- $catalog = new Catalog( $catalog_id );
- $info = $catalog->_get_info();
- $catalog_path = $info->path;
- $catalog_path = rtrim($catalog_path, "/");
- return( str_replace( $catalog_path . "/", "", $file_path ) );
+ if (!$file_path) {
+ $info = $this->_get_info();
+ $file_path = $info->file;
+ }
+ if (!$catalog_id) {
+ $catalog_id = $info->catalog;
+ }
+ $catalog = new Catalog( $catalog_id );
+ $info = $catalog->_get_info();
+ $catalog_path = $info->path;
+ $catalog_path = rtrim($catalog_path, "/");
+ return( str_replace( $catalog_path . "/", "", $file_path ) );
- } // get_rel_path
+ } // get_rel_path
- /**
- * play_url
- * This function takes all the song information and correctly formats a
- * a stream URL taking into account the downsmapling mojo and everything
- * else, this is the true function
- */
- public static function play_url($oid) {
-
- $song = new Song($oid);
- $user_id = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1';
- $type = $song->type;
-
- // Required for some versions of winamp that won't work if the
- // stream doesn't end in .ogg This will not break any properly
- // working player, don't report this as a bug!
- if ($song->type == 'flac') { $type = 'ogg'; }
-
- $song_name = rawurlencode($song->get_artist_name() . " - " . $song->title . "." . $type);
-
- $url = Stream::get_base_url() . "oid=$song->id&uid=$user_id&name=/$song_name";
-
- return $url;
-
- } // play_url
-
- /**
- * parse_song_url
- * Takes a URL from this ampache install and returns the song that the url represents
- * used by the API, and used to parse out stream urls for localplay
- * right now just gets song id might do more later, hence the complexity
- */
- public static function parse_song_url($url) {
-
- // We only care about the question mark stuff
- $query = parse_url($url,PHP_URL_QUERY);
-
- $elements = explode("&",$query);
-
- foreach ($elements as $items) {
- list($key,$value) = explode("=",$items);
- if ($key == 'oid') {
- return $value;
- }
- } // end foreach
-
- return false;
-
- } // parse_song_url
-
- /**
- * get_recently_played
- * This function returns the last X songs that have been played
- * it uses the popular threshold to figure out how many to pull
- * it will only return unique object
- */
- public static function get_recently_played($user_id='') {
-
- $user_id = Dba::escape($user_id);
-
- $sql = "SELECT `object_id`, `user`, `object_type`, `date` " .
- "FROM `object_count` WHERE `object_type`='song' ";
- if ($user_id) {
- $sql .= "AND `user`='$user_id' ";
- }
- $sql .= "ORDER BY `date` DESC ";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
- if (isset($results[$row['object_id']])) { continue; }
- $results[$row['object_id']] = $row;
- if (count($results) >= Config::get('popular_threshold')) { break; }
- }
-
- return $results;
-
- } // get_recently_played
-
- public function get_stream_types() {
- $types = array();
- $transcode = Config::get('transcode_' . $this->type);
-
- if ($transcode != 'required') {
- $types[] = 'native';
- }
- if (make_bool($transcode)) {
- $types[] = 'transcode';
- }
-
- return $types;
- } // end stream_types
-
- public function get_transcode_settings($target = null) {
- $source = $this->type;
-
- if ($target) {
- debug_event('transcode', 'Explicit format request', 5);
- }
- else if ($target = Config::get('encode_target_' . $source)) {
- debug_event('transcode', 'Defaulting to configured target format for ' . $source, 5);
- }
- else if ($target = Config::get('encode_target')) {
- debug_event('transcode', 'Using default target format', 5);
- }
- else {
- $target = $source;
- debug_event('transcode', 'No default target for ' . $source . ', choosing to resample', 5);
- }
-
- debug_event('transcode', 'Transcoding from ' . $source . ' to ' . $target, 5);
-
- $cmd = Config::get('transcode_cmd_' . $source) ?: Config::get('transcode_cmd');
- $args = Config::get('encode_args_' . $target);
-
- if (!$args) {
- debug_event('transcode', 'Target format ' . $target . ' is not properly configured', 2);
- return false;
- }
-
- debug_event('transcode', 'Command: ' . $cmd . ' Arguments: ' . $args, 5);
- return array('format' => $target,
- 'command' => $cmd . ' ' . $args);
- }
+ /**
+ * play_url
+ * This function takes all the song information and correctly formats a
+ * a stream URL taking into account the downsmapling mojo and everything
+ * else, this is the true function
+ */
+ public static function play_url($oid) {
+
+ $song = new Song($oid);
+ $user_id = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1';
+ $type = $song->type;
+
+ // Required for some versions of winamp that won't work if the
+ // stream doesn't end in .ogg This will not break any properly
+ // working player, don't report this as a bug!
+ if ($song->type == 'flac') { $type = 'ogg'; }
+
+ $song_name = rawurlencode($song->get_artist_name() . " - " . $song->title . "." . $type);
+
+ $url = Stream::get_base_url() . "oid=$song->id&uid=$user_id&name=/$song_name";
+
+ return $url;
+
+ } // play_url
+
+ /**
+ * parse_song_url
+ * Takes a URL from this ampache install and returns the song that the url represents
+ * used by the API, and used to parse out stream urls for localplay
+ * right now just gets song id might do more later, hence the complexity
+ */
+ public static function parse_song_url($url) {
+
+ // We only care about the question mark stuff
+ $query = parse_url($url,PHP_URL_QUERY);
+
+ $elements = explode("&",$query);
+
+ foreach ($elements as $items) {
+ list($key,$value) = explode("=",$items);
+ if ($key == 'oid') {
+ return $value;
+ }
+ } // end foreach
+
+ return false;
+
+ } // parse_song_url
+
+ /**
+ * get_recently_played
+ * This function returns the last X songs that have been played
+ * it uses the popular threshold to figure out how many to pull
+ * it will only return unique object
+ */
+ public static function get_recently_played($user_id='') {
+
+ $user_id = Dba::escape($user_id);
+
+ $sql = "SELECT `object_id`, `user`, `object_type`, `date` " .
+ "FROM `object_count` WHERE `object_type`='song' ";
+ if ($user_id) {
+ $sql .= "AND `user`='$user_id' ";
+ }
+ $sql .= "ORDER BY `date` DESC ";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ if (isset($results[$row['object_id']])) { continue; }
+ $results[$row['object_id']] = $row;
+ if (count($results) >= Config::get('popular_threshold')) { break; }
+ }
+
+ return $results;
+
+ } // get_recently_played
+
+ public function get_stream_types() {
+ $types = array();
+ $transcode = Config::get('transcode_' . $this->type);
+
+ if ($transcode != 'required') {
+ $types[] = 'native';
+ }
+ if (make_bool($transcode)) {
+ $types[] = 'transcode';
+ }
+
+ return $types;
+ } // end stream_types
+
+ public function get_transcode_settings($target = null) {
+ $source = $this->type;
+
+ if ($target) {
+ debug_event('transcode', 'Explicit format request', 5);
+ }
+ else if ($target = Config::get('encode_target_' . $source)) {
+ debug_event('transcode', 'Defaulting to configured target format for ' . $source, 5);
+ }
+ else if ($target = Config::get('encode_target')) {
+ debug_event('transcode', 'Using default target format', 5);
+ }
+ else {
+ $target = $source;
+ debug_event('transcode', 'No default target for ' . $source . ', choosing to resample', 5);
+ }
+
+ debug_event('transcode', 'Transcoding from ' . $source . ' to ' . $target, 5);
+
+ $cmd = Config::get('transcode_cmd_' . $source) ?: Config::get('transcode_cmd');
+ $args = Config::get('encode_args_' . $target);
+
+ if (!$args) {
+ debug_event('transcode', 'Target format ' . $target . ' is not properly configured', 2);
+ return false;
+ }
+
+ debug_event('transcode', 'Command: ' . $cmd . ' Arguments: ' . $args, 5);
+ return array('format' => $target,
+ 'command' => $cmd . ' ' . $args);
+ }
} // end of song class
?>
diff --git a/lib/class/stats.class.php b/lib/class/stats.class.php
index 4ff676e9..23b17b20 100644
--- a/lib/class/stats.class.php
+++ b/lib/class/stats.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,234 +30,234 @@
*/
class Stats {
- /* Base vars */
- var $id;
- var $object_type;
- var $object_id;
- var $date;
- var $user;
+ /* Base vars */
+ var $id;
+ var $object_type;
+ var $object_id;
+ var $date;
+ var $user;
- /**
- * Constructor
- * This doesn't do anything currently
- */
- public function __construct() {
+ /**
+ * Constructor
+ * This doesn't do anything currently
+ */
+ public function __construct() {
- return true;
+ return true;
- } // Constructor
+ } // Constructor
- /**
- * clear
- *
- * This clears all stats for _everything_.
- */
- public static function clear() {
- Dba::write('TRUNCATE `object_count`');
- Dba::write('UPDATE `song` SET `played` = 0');
- }
+ /**
+ * clear
+ *
+ * This clears all stats for _everything_.
+ */
+ public static function clear() {
+ Dba::write('TRUNCATE `object_count`');
+ Dba::write('UPDATE `song` SET `played` = 0');
+ }
- /**
- * gc
- *
- * This removes stats for things that no longer exist.
- */
- public static function gc() {
- foreach(array('song', 'album', 'artist', 'live_stream', 'video') as $object_type) {
- Dba::write("DELETE FROM `object_count` USING `object_count` LEFT JOIN `$object_type` ON `$object_type`.`id` = `object_count`.`object_id` WHERE `object_type` = '$object_type' AND `$object_type`.`id` IS NULL");
- }
- }
+ /**
+ * gc
+ *
+ * This removes stats for things that no longer exist.
+ */
+ public static function gc() {
+ foreach(array('song', 'album', 'artist', 'live_stream', 'video') as $object_type) {
+ Dba::write("DELETE FROM `object_count` USING `object_count` LEFT JOIN `$object_type` ON `$object_type`.`id` = `object_count`.`object_id` WHERE `object_type` = '$object_type' AND `$object_type`.`id` IS NULL");
+ }
+ }
- /**
- * insert
- * This inserts a new record for the specified object
- * with the specified information, amazing!
- */
- public static function insert($type,$oid,$user) {
+ /**
+ * insert
+ * This inserts a new record for the specified object
+ * with the specified information, amazing!
+ */
+ public static function insert($type,$oid,$user) {
- $type = self::validate_type($type);
- $oid = Dba::escape($oid);
- $user = Dba::escape($user);
- $date = time();
+ $type = self::validate_type($type);
+ $oid = Dba::escape($oid);
+ $user = Dba::escape($user);
+ $date = time();
- $sql = "INSERT INTO `object_count` (`object_type`,`object_id`,`date`,`user`) " .
- " VALUES ('$type','$oid','$date','$user')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `object_count` (`object_type`,`object_id`,`date`,`user`) " .
+ " VALUES ('$type','$oid','$date','$user')";
+ $db_results = Dba::write($sql);
- if (!$db_results) {
- debug_event('statistics','Unabled to insert statistics:' . $sql,'3');
- }
+ if (!$db_results) {
+ debug_event('statistics','Unabled to insert statistics:' . $sql,'3');
+ }
- } // insert
+ } // insert
- /**
- * get_last_song
- * This returns the full data for the last song that was played, including when it
- * was played, this is used by, among other things, the LastFM plugin to figure out
- * if we should re-submit or if this is a duplicate / if it's too soon. This takes an
- * optional user_id because when streaming we don't have $GLOBALS()
- */
- public static function get_last_song($user_id='') {
-
- $user_id = $user_id ? $user_id : $GLOBALS['user']->id;
-
- $user_id = Dba::escape($user_id);
+ /**
+ * get_last_song
+ * This returns the full data for the last song that was played, including when it
+ * was played, this is used by, among other things, the LastFM plugin to figure out
+ * if we should re-submit or if this is a duplicate / if it's too soon. This takes an
+ * optional user_id because when streaming we don't have $GLOBALS()
+ */
+ public static function get_last_song($user_id='') {
+
+ $user_id = $user_id ? $user_id : $GLOBALS['user']->id;
+
+ $user_id = Dba::escape($user_id);
- $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' ORDER BY `date` DESC LIMIT 1";
- $db_results = Dba::read($sql);
-
- $results = Dba::fetch_assoc($db_results);
-
- return $results;
+ $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' ORDER BY `date` DESC LIMIT 1";
+ $db_results = Dba::read($sql);
+
+ $results = Dba::fetch_assoc($db_results);
+
+ return $results;
- } // get_last_song
+ } // get_last_song
- /**
- * get_object_history
- * This returns the objects that have happened for $user_id sometime after $time
- * used primarly by the democratic cooldown code
- */
- public static function get_object_history($user_id='',$time) {
+ /**
+ * get_object_history
+ * This returns the objects that have happened for $user_id sometime after $time
+ * used primarly by the democratic cooldown code
+ */
+ public static function get_object_history($user_id='',$time) {
- $user_id = $user_id ? $user_id : $GLOBALS['user']->id;
-
- $user_id = Dba::escape($user_id);
-
- $time = Dba::escape($time);
-
- $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' AND `date`>='$time' " .
- "ORDER BY `date` DESC";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['object_id'];
- }
-
- return $results;
-
- } // get_object_history
-
- /**
- * get_top
- * This returns the top X for type Y from the
- * last stats_threshold days
- */
- public static function get_top($type,$count='',$threshold = '') {
-
- /* If they don't pass one, then use the preference */
- if (!$threshold) {
- $threshold = Config::get('stats_threshold');
- }
-
- if (!$count) {
- $count = Config::get('popular_threshold');
- }
-
- $count = intval($count);
- $type = self::validate_type($type);
- $date = time() - (86400*$threshold);
+ $user_id = $user_id ? $user_id : $GLOBALS['user']->id;
+
+ $user_id = Dba::escape($user_id);
+
+ $time = Dba::escape($time);
+
+ $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' AND `date`>='$time' " .
+ "ORDER BY `date` DESC";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['object_id'];
+ }
+
+ return $results;
+
+ } // get_object_history
+
+ /**
+ * get_top
+ * This returns the top X for type Y from the
+ * last stats_threshold days
+ */
+ public static function get_top($type,$count='',$threshold = '') {
+
+ /* If they don't pass one, then use the preference */
+ if (!$threshold) {
+ $threshold = Config::get('stats_threshold');
+ }
+
+ if (!$count) {
+ $count = Config::get('popular_threshold');
+ }
+
+ $count = intval($count);
+ $type = self::validate_type($type);
+ $date = time() - (86400*$threshold);
- /* Select Top objects counting by # of rows */
- $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" .
- " WHERE object_type='$type' AND date >= '$date'" .
- " GROUP BY object_id ORDER BY `count` DESC LIMIT $count";
- $db_results = Dba::read($sql);
+ /* Select Top objects counting by # of rows */
+ $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" .
+ " WHERE object_type='$type' AND date >= '$date'" .
+ " GROUP BY object_id ORDER BY `count` DESC LIMIT $count";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['object_id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['object_id'];
+ }
- return $results;
+ return $results;
- } // get_top
+ } // get_top
- /**
- * get_user
- * This gets all stats for atype based on user with thresholds and all
- * If full is passed, doesn't limit based on date
- */
- public static function get_user($count,$type,$user,$full='') {
+ /**
+ * get_user
+ * This gets all stats for atype based on user with thresholds and all
+ * If full is passed, doesn't limit based on date
+ */
+ public static function get_user($count,$type,$user,$full='') {
- $count = intval($count);
- $type = self::validate_type($type);
- $user = Dba::escape($user);
+ $count = intval($count);
+ $type = self::validate_type($type);
+ $user = Dba::escape($user);
- /* If full then don't limit on date */
- if ($full) {
- $date = '0';
- }
- else {
- $date = time() - (86400*Config::get('stats_threshold'));
- }
+ /* If full then don't limit on date */
+ if ($full) {
+ $date = '0';
+ }
+ else {
+ $date = time() - (86400*Config::get('stats_threshold'));
+ }
- /* Select Objects based on user */
- //FIXME:: Requires table scan, look at improving
- $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" .
- " WHERE object_type='$type' AND date >= '$date' AND user = '$user'" .
- " GROUP BY object_id ORDER BY `count` DESC LIMIT $count";
- $db_results = Dba::read($sql);
+ /* Select Objects based on user */
+ //FIXME:: Requires table scan, look at improving
+ $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" .
+ " WHERE object_type='$type' AND date >= '$date' AND user = '$user'" .
+ " GROUP BY object_id ORDER BY `count` DESC LIMIT $count";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r;
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r;
+ }
- return $results;
+ return $results;
- } // get_user
+ } // get_user
- /**
- * validate_type
- * This function takes a type and returns only those
- * which are allowed, ensures good data gets put into the db
- */
- public static function validate_type($type) {
+ /**
+ * validate_type
+ * This function takes a type and returns only those
+ * which are allowed, ensures good data gets put into the db
+ */
+ public static function validate_type($type) {
- switch ($type) {
- case 'artist':
- case 'album':
- case 'genre':
- case 'song':
- case 'video':
- return $type;
- default:
- return 'song';
- break;
- } // end switch
-
- } // validate_type
-
- /**
- * get_newest
- * This returns an array of the newest artists/albums/whatever
- * in this ampache instance
- */
- public static function get_newest($type,$limit='') {
-
- if (!$limit) { $limit = Config::get('popular_threshold'); }
-
- $type = self::validate_type($type);
- $object_name = ucfirst($type);
-
- $sql = "SELECT DISTINCT(`$type`), MIN(`addition_time`) AS `real_atime` FROM `song` GROUP BY `$type` ORDER BY `real_atime` DESC " .
- "LIMIT $limit";
- $db_results = Dba::read($sql);
-
- $items = array();
-
- while ($row = Dba::fetch_row($db_results)) {
- $items[] = $row['0'];
- } // end while results
-
- return $items;
-
- } // get_newest
+ switch ($type) {
+ case 'artist':
+ case 'album':
+ case 'genre':
+ case 'song':
+ case 'video':
+ return $type;
+ default:
+ return 'song';
+ break;
+ } // end switch
+
+ } // validate_type
+
+ /**
+ * get_newest
+ * This returns an array of the newest artists/albums/whatever
+ * in this ampache instance
+ */
+ public static function get_newest($type,$limit='') {
+
+ if (!$limit) { $limit = Config::get('popular_threshold'); }
+
+ $type = self::validate_type($type);
+ $object_name = ucfirst($type);
+
+ $sql = "SELECT DISTINCT(`$type`), MIN(`addition_time`) AS `real_atime` FROM `song` GROUP BY `$type` ORDER BY `real_atime` DESC " .
+ "LIMIT $limit";
+ $db_results = Dba::read($sql);
+
+ $items = array();
+
+ while ($row = Dba::fetch_row($db_results)) {
+ $items[] = $row['0'];
+ } // end while results
+
+ return $items;
+
+ } // get_newest
} // Stats class
?>
diff --git a/lib/class/stream.class.php b/lib/class/stream.class.php
index 428f5a4a..338898a2 100644
--- a/lib/class/stream.class.php
+++ b/lib/class/stream.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -23,409 +23,409 @@
class Stream {
- public static $session;
- private static $session_inserted;
+ public static $session;
+ private static $session_inserted;
- private function __construct() {
- // Static class, do nothing.
- }
+ private function __construct() {
+ // Static class, do nothing.
+ }
- /**
- * get_session
- * This returns the current stream session
- */
- public static function get_session() {
+ /**
+ * get_session
+ * This returns the current stream session
+ */
+ public static function get_session() {
- if (!self::$session_inserted) {
- self::insert_session(self::$session);
- }
+ if (!self::$session_inserted) {
+ self::insert_session(self::$session);
+ }
- return self::$session;
+ return self::$session;
- } // get_session
+ } // get_session
- /**
- * set_session
- * This overrides the normal session value, without adding
- * an additional session into the database, should be called
- * with care
- */
- public static function set_session($sid) {
+ /**
+ * set_session
+ * This overrides the normal session value, without adding
+ * an additional session into the database, should be called
+ * with care
+ */
+ public static function set_session($sid) {
- self::$session_inserted = true;
- self::$session=$sid;
+ self::$session_inserted = true;
+ self::$session=$sid;
- } // set_session
+ } // set_session
- /**
- * insert_session
- * This inserts a row into the session_stream table
- */
- public static function insert_session($sid='',$uid='') {
+ /**
+ * insert_session
+ * This inserts a row into the session_stream table
+ */
+ public static function insert_session($sid='',$uid='') {
- $sid = $sid ? Dba::escape($sid) : Dba::escape(self::$session);
- $uid = $uid ? Dba::escape($uid) : Dba::escape($GLOBALS['user']->id);
+ $sid = $sid ? Dba::escape($sid) : Dba::escape(self::$session);
+ $uid = $uid ? Dba::escape($uid) : Dba::escape($GLOBALS['user']->id);
- $expire = time() + Config::get('stream_length');
+ $expire = time() + Config::get('stream_length');
- $sql = "INSERT INTO `session_stream` (`id`,`expire`,`user`) " .
- "VALUES('$sid','$expire','$uid')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `session_stream` (`id`,`expire`,`user`) " .
+ "VALUES('$sid','$expire','$uid')";
+ $db_results = Dba::write($sql);
- if (!$db_results) { return false; }
+ if (!$db_results) { return false; }
- self::$session_inserted = true;
+ self::$session_inserted = true;
- return true;
+ return true;
- } // insert_session
+ } // insert_session
- /**
- * session_exists
- * This checks to see if the passed stream session exists and is valid
- */
- public static function session_exists($sid) {
+ /**
+ * session_exists
+ * This checks to see if the passed stream session exists and is valid
+ */
+ public static function session_exists($sid) {
- $sid = Dba::escape($sid);
- $time = time();
+ $sid = Dba::escape($sid);
+ $time = time();
- $sql = "SELECT * FROM `session_stream` WHERE `id`='$sid' AND `expire` > '$time'";
- $db_results = Dba::write($sql);
+ $sql = "SELECT * FROM `session_stream` WHERE `id`='$sid' AND `expire` > '$time'";
+ $db_results = Dba::write($sql);
- if ($row = Dba::fetch_assoc($db_results)) {
- return true;
- }
+ if ($row = Dba::fetch_assoc($db_results)) {
+ return true;
+ }
- return false;
-
- } // session_exists
-
- /**
- * gc
- * This function performes the garbage collection stuff, run on extend
- * and on now playing refresh.
- */
- public static function gc() {
+ return false;
+
+ } // session_exists
+
+ /**
+ * gc
+ * This function performes the garbage collection stuff, run on extend
+ * and on now playing refresh.
+ */
+ public static function gc() {
- $time = time();
- $sql = "DELETE FROM `session_stream` WHERE `expire` < '$time'";
- $db_results = Dba::write($sql);
-
- Stream_Playlist::gc();
+ $time = time();
+ $sql = "DELETE FROM `session_stream` WHERE `expire` < '$time'";
+ $db_results = Dba::write($sql);
+
+ Stream_Playlist::gc();
- }
+ }
- /**
- * extend_session
- * This takes the passed sid and does a replace into also setting the user
- * agent and IP also do a little GC in this function
- */
- public static function extend_session($sid,$uid) {
+ /**
+ * extend_session
+ * This takes the passed sid and does a replace into also setting the user
+ * agent and IP also do a little GC in this function
+ */
+ public static function extend_session($sid,$uid) {
- $expire = time() + Config::get('stream_length');
- $sid = Dba::escape($sid);
- $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']);
- $ip = Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']));
- $uid = Dba::escape($uid);
-
- $sql = "UPDATE `session_stream` SET `expire`='$expire', `agent`='$agent', `ip`='$ip' " .
- "WHERE `id`='$sid'";
- $db_results = Dba::write($sql);
-
- self::gc();
+ $expire = time() + Config::get('stream_length');
+ $sid = Dba::escape($sid);
+ $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']);
+ $ip = Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']));
+ $uid = Dba::escape($uid);
+
+ $sql = "UPDATE `session_stream` SET `expire`='$expire', `agent`='$agent', `ip`='$ip' " .
+ "WHERE `id`='$sid'";
+ $db_results = Dba::write($sql);
+
+ self::gc();
- return true;
+ return true;
- } // extend_session
+ } // extend_session
- /**
- * start_transcode
- *
- * This is a rather complex function that starts the transcoding or
- * resampling of a song and returns the opened file handle.
- */
- public static function start_transcode($song) {
- $transcode_settings = $song->get_transcode_settings();
- // Bail out early if we're unutterably broken
- if ($transcode_settings == false) {
- debug_event('stream', 'Transcode requested, but get_transcode_settings failed', 2);
- return false;
- }
+ /**
+ * start_transcode
+ *
+ * This is a rather complex function that starts the transcoding or
+ * resampling of a song and returns the opened file handle.
+ */
+ public static function start_transcode($song) {
+ $transcode_settings = $song->get_transcode_settings();
+ // Bail out early if we're unutterably broken
+ if ($transcode_settings == false) {
+ debug_event('stream', 'Transcode requested, but get_transcode_settings failed', 2);
+ return false;
+ }
- $max_bitrate = Config::get('max_bit_rate');
- $min_bitrate = Config::get('min_bit_rate');
- // FIXME: This should be configurable for each output type
- $user_sample_rate = Config::get('sample_rate');
+ $max_bitrate = Config::get('max_bit_rate');
+ $min_bitrate = Config::get('min_bit_rate');
+ // FIXME: This should be configurable for each output type
+ $user_sample_rate = Config::get('sample_rate');
- // If the user's crazy, that's no skin off our back
- if ($user_sample_rate < $min_bitrate) {
- $min_bitrate = $user_sample_rate;
- }
+ // If the user's crazy, that's no skin off our back
+ if ($user_sample_rate < $min_bitrate) {
+ $min_bitrate = $user_sample_rate;
+ }
- // Are there site-wide constraints? (Dynamic downsampling.)
- if ($max_bitrate > 1 ) {
- $sql = 'SELECT COUNT(*) FROM `now_playing` ' .
- 'WHERE `user` IN ' .
- '(SELECT DISTINCT `user_preference`.`user` ' .
- 'FROM `preference` JOIN `user_preference` ' .
- 'ON `preference`.`id` = ' .
- '`user_preferece`.`preference` ' .
- "WHERE `preference`.`name` = 'play_type' " .
- "AND `user_preference`.`value` = 'downsample')";
-
- $db_results = Dba::read($sql);
- $results = Dba::fetch_row($db_results);
-
- $active_streams = intval($results[0]) ?: 0;
- debug_event('stream', 'Active transcoding streams: ' . $active_streams, 5);
-
- // We count as one for the algorithm
- // FIXME: Should this reflect the actual bit rates?
- $active_streams++;
- $sample_rate = floor($max_bitrate / $active_streams);
-
- // Exit if this would be insane
- if ($sample_rate < ($min_bitrate ?: 8)) {
- debug_event('stream', 'Max transcode bandwidth already allocated. Active streams: ' . $active_streams, 2);
- header('HTTP/1.1 503 Service Temporarily Unavailable');
- exit();
- }
-
- // Never go over the user's sample rate
- if ($sample_rate > $user_sample_rate) {
- $sample_rate = $user_sample_rate;
- }
-
- } // end if we've got bitrates
- else {
- $sample_rate = $user_sample_rate;
- }
-
- debug_event('stream', 'Configured bitrate is ' . $sample_rate, 5);
-
- // Validate the bitrate
- $sample_rate = self::validate_bitrate($sample_rate);
-
- // Never upsample a song
- if ($song->type == $transcode_settings['format'] && ($sample_rate * 1000) > $song->bitrate) {
- debug_event('stream', 'Clamping bitrate to avoid upsampling to ' . $sample_rate, 5);
- $sample_rate = self::validate_bitrate($song->bitrate / 1000);
- }
-
- debug_event('stream', 'Final transcode bitrate is ' . $sample_rate, 5);
-
- $song_file = scrub_arg($song->file);
-
- // Finalise the command line
- $command = $transcode_settings['command'];
-
- $string_map = array(
- '%FILE%' => $song_file,
- '%SAMPLE%' => $sample_rate
- );
-
- foreach ($string_map as $search => $replace) {
- $command = str_replace($search, $replace, $command, $ret);
- if (!$ret) {
- debug_event('downsample', "$search not in downsample command", 5);
- }
- }
-
- debug_event('downsample', "Downsample command: $command", 3);
-
- return array(
- 'handle' => popen($command, 'rb'),
- 'format' => $transcode_settings['format']
- );
-
- }
-
- /**
- * validate_bitrate
- * this function takes a bitrate and returns a valid one
- */
- public static function validate_bitrate($bitrate) {
-
- /* Round to standard bitrates */
- $sample_rate = 16*(floor($bitrate/16));
-
- return $sample_rate;
-
- } // validate_bitrate
-
-
- /**
- * gc_now_playing
- * This will garbage collect the now playing data,
- * this is done on every play start
- */
- public static function gc_now_playing() {
+ // Are there site-wide constraints? (Dynamic downsampling.)
+ if ($max_bitrate > 1 ) {
+ $sql = 'SELECT COUNT(*) FROM `now_playing` ' .
+ 'WHERE `user` IN ' .
+ '(SELECT DISTINCT `user_preference`.`user` ' .
+ 'FROM `preference` JOIN `user_preference` ' .
+ 'ON `preference`.`id` = ' .
+ '`user_preferece`.`preference` ' .
+ "WHERE `preference`.`name` = 'play_type' " .
+ "AND `user_preference`.`value` = 'downsample')";
+
+ $db_results = Dba::read($sql);
+ $results = Dba::fetch_row($db_results);
+
+ $active_streams = intval($results[0]) ?: 0;
+ debug_event('stream', 'Active transcoding streams: ' . $active_streams, 5);
+
+ // We count as one for the algorithm
+ // FIXME: Should this reflect the actual bit rates?
+ $active_streams++;
+ $sample_rate = floor($max_bitrate / $active_streams);
+
+ // Exit if this would be insane
+ if ($sample_rate < ($min_bitrate ?: 8)) {
+ debug_event('stream', 'Max transcode bandwidth already allocated. Active streams: ' . $active_streams, 2);
+ header('HTTP/1.1 503 Service Temporarily Unavailable');
+ exit();
+ }
+
+ // Never go over the user's sample rate
+ if ($sample_rate > $user_sample_rate) {
+ $sample_rate = $user_sample_rate;
+ }
+
+ } // end if we've got bitrates
+ else {
+ $sample_rate = $user_sample_rate;
+ }
+
+ debug_event('stream', 'Configured bitrate is ' . $sample_rate, 5);
+
+ // Validate the bitrate
+ $sample_rate = self::validate_bitrate($sample_rate);
+
+ // Never upsample a song
+ if ($song->type == $transcode_settings['format'] && ($sample_rate * 1000) > $song->bitrate) {
+ debug_event('stream', 'Clamping bitrate to avoid upsampling to ' . $sample_rate, 5);
+ $sample_rate = self::validate_bitrate($song->bitrate / 1000);
+ }
+
+ debug_event('stream', 'Final transcode bitrate is ' . $sample_rate, 5);
+
+ $song_file = scrub_arg($song->file);
+
+ // Finalise the command line
+ $command = $transcode_settings['command'];
+
+ $string_map = array(
+ '%FILE%' => $song_file,
+ '%SAMPLE%' => $sample_rate
+ );
+
+ foreach ($string_map as $search => $replace) {
+ $command = str_replace($search, $replace, $command, $ret);
+ if (!$ret) {
+ debug_event('downsample', "$search not in downsample command", 5);
+ }
+ }
+
+ debug_event('downsample', "Downsample command: $command", 3);
+
+ return array(
+ 'handle' => popen($command, 'rb'),
+ 'format' => $transcode_settings['format']
+ );
+
+ }
+
+ /**
+ * validate_bitrate
+ * this function takes a bitrate and returns a valid one
+ */
+ public static function validate_bitrate($bitrate) {
+
+ /* Round to standard bitrates */
+ $sample_rate = 16*(floor($bitrate/16));
+
+ return $sample_rate;
+
+ } // validate_bitrate
+
+
+ /**
+ * gc_now_playing
+ * This will garbage collect the now playing data,
+ * this is done on every play start
+ */
+ public static function gc_now_playing() {
- // Remove any now playing entries for session_streams that have been GC'd
- $sql = "DELETE FROM `now_playing` USING `now_playing` " .
- "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " .
- "WHERE `session_stream`.`id` IS NULL OR `now_playing`.`expire` < '" . time() . "'";
- $db_results = Dba::write($sql);
-
- } // gc_now_playing
-
- /**
- * insert_now_playing
- * This will insert the now playing data
- * This fucntion is used by the /play/index.php song
- * primarily, but could be used by other people
- */
- public static function insert_now_playing($oid,$uid,$length,$sid,$type) {
+ // Remove any now playing entries for session_streams that have been GC'd
+ $sql = "DELETE FROM `now_playing` USING `now_playing` " .
+ "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " .
+ "WHERE `session_stream`.`id` IS NULL OR `now_playing`.`expire` < '" . time() . "'";
+ $db_results = Dba::write($sql);
+
+ } // gc_now_playing
+
+ /**
+ * insert_now_playing
+ * This will insert the now playing data
+ * This fucntion is used by the /play/index.php song
+ * primarily, but could be used by other people
+ */
+ public static function insert_now_playing($oid,$uid,$length,$sid,$type) {
- $time = intval(time()+$length);
- $session_id = Dba::escape($sid);
- $object_type = Dba::escape(strtolower($type));
-
- // Do a replace into ensuring that this client always only has a single row
- $sql = "REPLACE INTO `now_playing` (`id`,`object_id`,`object_type`, `user`, `expire`)" .
- " VALUES ('$session_id','$oid','$object_type', '$uid', '$time')";
- $db_result = Dba::write($sql);
-
- } // insert_now_playing
-
- /**
- * clear_now_playing
- * There really isn't anywhere else for this function, shouldn't have deleted it in the first
- * place
- */
- public static function clear_now_playing() {
-
- $sql = "TRUNCATE `now_playing`";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // clear_now_playing
-
- /**
- * get_now_playing
- * This returns the now playing information
- */
- public static function get_now_playing($filter=NULL) {
-
- $sql = "SELECT `session_stream`.`agent`,`now_playing`.* " .
- "FROM `now_playing` " .
- "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " .
- "ORDER BY `now_playing`.`expire` DESC";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $type = $row['object_type'];
- $media = new $type($row['object_id']);
- $media->format();
- $client = new User($row['user']);
- $results[] = array('media'=>$media,'client'=>$client,'agent'=>$row['agent'],'expire'=>$row['expire']);
- } // end while
-
- return $results;
-
- } // get_now_playing
-
- /**
- * check_lock_media
- * This checks to see if the media is already being played, if it is then it returns false
- * else return true
- */
- public static function check_lock_media($media_id,$type) {
-
- $media_id = Dba::escape($media_id);
- $type = Dba::escape($type);
-
- $sql = "SELECT `object_id` FROM `now_playing` WHERE `object_id`='$media_id' AND `object_type`='$type'";
- $db_results = Dba::read($sql);
-
- if (Dba::num_rows($db_results)) {
- debug_event('Stream','Unable to play media currently locked by another user','3');
- return false;
- }
-
- return true;
-
- } // check_lock_media
-
- /**
- * auto_init
- * This is called on class load it sets the session
- */
- public static function _auto_init() {
-
- // Generate the session ID
- self::$session = md5(uniqid(rand(), true));
-
- } // auto_init
-
- /**
- * run_playlist_method
- * This takes care of the different types of 'playlist methods'. The
- * reason this is here is because it deals with streaming rather than
- * playlist mojo. If something needs to happen this will echo the
- * javascript required to cause a reload of the iframe.
- */
- public static function run_playlist_method() {
-
- // If this wasn't ajax included run away
- if (!defined('AJAX_INCLUDE')) { return false; }
-
- // If we're doin the flash magic then run away as well
- if (Config::get('play_type') == 'xspf_player') { return false; }
-
- switch (Config::get('playlist_method')) {
- default:
- case 'clear':
- case 'default':
- return true;
- break;
- case 'send':
- $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket';
- break;
- case 'send_clear':
- $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket&playlist_method=clear';
- break;
- } // end switch on method
-
- // Load our javascript
- echo "<script type=\"text/javascript\">";
- echo "reloadUtil('".$_SESSION['iframe']['target']."');";
- echo "</script>";
-
- } // run_playlist_method
-
- /**
- * get_base_url
- * This returns the base requirements for a stream URL this does not include anything after the index.php?sid=????
- */
- public static function get_base_url() {
-
- if (Config::get('require_session')) {
- $session_string = 'ssid=' . Stream::get_session() . '&';
- }
-
- $web_path = Config::get('web_path');
-
- if (Config::get('force_http_play') OR !empty(self::$force_http)) {
- $web_path = str_replace("https://", "http://",$web_path);
- }
- if (Config::get('http_port') != '80') {
- if (preg_match("/:(\d+)/",$web_path,$matches)) {
- $web_path = str_replace(':' . $matches['1'],':' . Config::get('http_port'),$web_path);
- }
- else {
- $web_path = str_replace($_SERVER['HTTP_HOST'],$_SERVER['HTTP_HOST'] . ':' . Config::get('http_port'),$web_path);
- }
- }
-
- $url = $web_path . "/play/index.php?$session_string";
-
- return $url;
-
- } // get_base_url
+ $time = intval(time()+$length);
+ $session_id = Dba::escape($sid);
+ $object_type = Dba::escape(strtolower($type));
+
+ // Do a replace into ensuring that this client always only has a single row
+ $sql = "REPLACE INTO `now_playing` (`id`,`object_id`,`object_type`, `user`, `expire`)" .
+ " VALUES ('$session_id','$oid','$object_type', '$uid', '$time')";
+ $db_result = Dba::write($sql);
+
+ } // insert_now_playing
+
+ /**
+ * clear_now_playing
+ * There really isn't anywhere else for this function, shouldn't have deleted it in the first
+ * place
+ */
+ public static function clear_now_playing() {
+
+ $sql = "TRUNCATE `now_playing`";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // clear_now_playing
+
+ /**
+ * get_now_playing
+ * This returns the now playing information
+ */
+ public static function get_now_playing($filter=NULL) {
+
+ $sql = "SELECT `session_stream`.`agent`,`now_playing`.* " .
+ "FROM `now_playing` " .
+ "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " .
+ "ORDER BY `now_playing`.`expire` DESC";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $type = $row['object_type'];
+ $media = new $type($row['object_id']);
+ $media->format();
+ $client = new User($row['user']);
+ $results[] = array('media'=>$media,'client'=>$client,'agent'=>$row['agent'],'expire'=>$row['expire']);
+ } // end while
+
+ return $results;
+
+ } // get_now_playing
+
+ /**
+ * check_lock_media
+ * This checks to see if the media is already being played, if it is then it returns false
+ * else return true
+ */
+ public static function check_lock_media($media_id,$type) {
+
+ $media_id = Dba::escape($media_id);
+ $type = Dba::escape($type);
+
+ $sql = "SELECT `object_id` FROM `now_playing` WHERE `object_id`='$media_id' AND `object_type`='$type'";
+ $db_results = Dba::read($sql);
+
+ if (Dba::num_rows($db_results)) {
+ debug_event('Stream','Unable to play media currently locked by another user','3');
+ return false;
+ }
+
+ return true;
+
+ } // check_lock_media
+
+ /**
+ * auto_init
+ * This is called on class load it sets the session
+ */
+ public static function _auto_init() {
+
+ // Generate the session ID
+ self::$session = md5(uniqid(rand(), true));
+
+ } // auto_init
+
+ /**
+ * run_playlist_method
+ * This takes care of the different types of 'playlist methods'. The
+ * reason this is here is because it deals with streaming rather than
+ * playlist mojo. If something needs to happen this will echo the
+ * javascript required to cause a reload of the iframe.
+ */
+ public static function run_playlist_method() {
+
+ // If this wasn't ajax included run away
+ if (!defined('AJAX_INCLUDE')) { return false; }
+
+ // If we're doin the flash magic then run away as well
+ if (Config::get('play_type') == 'xspf_player') { return false; }
+
+ switch (Config::get('playlist_method')) {
+ default:
+ case 'clear':
+ case 'default':
+ return true;
+ break;
+ case 'send':
+ $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket';
+ break;
+ case 'send_clear':
+ $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket&playlist_method=clear';
+ break;
+ } // end switch on method
+
+ // Load our javascript
+ echo "<script type=\"text/javascript\">";
+ echo "reloadUtil('".$_SESSION['iframe']['target']."');";
+ echo "</script>";
+
+ } // run_playlist_method
+
+ /**
+ * get_base_url
+ * This returns the base requirements for a stream URL this does not include anything after the index.php?sid=????
+ */
+ public static function get_base_url() {
+
+ if (Config::get('require_session')) {
+ $session_string = 'ssid=' . Stream::get_session() . '&';
+ }
+
+ $web_path = Config::get('web_path');
+
+ if (Config::get('force_http_play') OR !empty(self::$force_http)) {
+ $web_path = str_replace("https://", "http://",$web_path);
+ }
+ if (Config::get('http_port') != '80') {
+ if (preg_match("/:(\d+)/",$web_path,$matches)) {
+ $web_path = str_replace(':' . $matches['1'],':' . Config::get('http_port'),$web_path);
+ }
+ else {
+ $web_path = str_replace($_SERVER['HTTP_HOST'],$_SERVER['HTTP_HOST'] . ':' . Config::get('http_port'),$web_path);
+ }
+ }
+
+ $url = $web_path . "/play/index.php?$session_string";
+
+ return $url;
+
+ } // get_base_url
} //end of stream class
diff --git a/lib/class/stream_playlist.class.php b/lib/class/stream_playlist.class.php
index 917b543c..6d85f8f0 100644
--- a/lib/class/stream_playlist.class.php
+++ b/lib/class/stream_playlist.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,426 +30,426 @@
class Stream_Playlist {
- public $id;
- public $urls = array();
- public $user;
-
- /**
- * Stream_Playlist constructor
- * If an ID is passed, it should be a stream session ID.
- */
- public function __construct($id = null) {
-
- if($id) {
- Stream::set_session($id);
- }
-
- $this->id = Dba::escape(Stream::get_session());
-
- if (!Stream::session_exists($this->id)) {
- debug_event('stream_playlist', 'Stream::session_exists failed', 2);
- return false;
- }
-
- $this->user = intval($GLOBALS['user']->id);
-
- $sql = "SELECT * FROM `stream_playlist` WHERE `sid`='" .
- $this->id . "' ORDER BY `id`";
-
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- $this->urls[] = new Stream_URL($row);
- }
-
- return true;
- }
-
- private function _add_url($url) {
- $this->urls[] = $url;
-
- $sql = 'INSERT INTO `stream_playlist` ';
-
- $fields[] = '`sid`';
- $values[] = Dba::escape($this->id);
-
- foreach ($url->properties as $field) {
- if ($url->$field) {
- $fields[] = '`' . $field . '`';
- $values[] = Dba::escape($url->$field);
- }
- }
- $sql .= '(' . implode(', ', $fields) . ') ';
- $sql .= "VALUES('" . implode("', '", $values) . "')";
-
- return Dba::write($sql);
- }
-
- public static function gc() {
- $sql = 'DELETE FROM `stream_playlist` ' .
- 'USING `stream_playlist` LEFT JOIN `session_stream` ' .
- 'ON `session_stream`.`id`=`stream_playlist`.`sid` ' .
- 'WHERE `session_stream`.`id` IS NULL';
- return Dba::write($sql);
- }
-
- /**
- * _media_to_urlarray
- * Formats the URL and media information and adds it to the object
- */
- private static function _media_to_urlarray($media) {
- $urls = array();
- foreach($media as $medium) {
- debug_event('stream_playlist', 'Adding ' . json_encode($media), 5);
- $url = array();
-
- $type = $medium['object_type'];
- $array['type'] = $type;
-
- $object = new $type($medium['object_id']);
- $object->format();
- //FIXME: play_url shouldn't be static
- $url['url'] = $type::play_url($object->id);
-
- // Set a default which can be overridden
- $url['author'] = 'Ampache';
- $url['time'] = $object->time;
- switch($type) {
- case 'song':
- $url['title'] = $object->title;
- $url['author'] = $object->f_artist_full;
- $url['info_url'] = $object->f_link;
- $url['image_url'] = Art::url($object->album, 'album');
- $url['album'] = $object->f_album_full;
- break;
- case 'video':
- $url['title'] = 'Video - ' . $object->title;
- $url['author'] = $object->f_artist_full;
- break;
- case 'radio':
- $url['title'] = 'Radio - ' . $object->name .
- ' [' . $object->frequency .
- '] (' . $object->site_url . ')';
- break;
- case 'random':
- $url['title'] = 'Random URL';
- break;
- default:
- $url['title'] = 'URL-Add';
- $url['time'] = -1;
- break;
- }
-
- $urls[] = new Stream_URL($url);
- }
-
- return $urls;
- }
-
- public function generate_playlist($type, $redirect = false) {
-
- if (!count($this->urls)) {
- debug_event('stream_playlist', 'Error: Empty URL array for ' . $this->id, 2);
- return false;
- }
-
- debug_event('stream_playlist', 'generating a ' . $type, 5);
-
- $ext = $type;
- switch($type) {
- case 'democratic':
- case 'localplay':
- case 'xspf_player':
- // These are valid, but witchy
- $redirect = false;
- unset($ext);
- break;
- case 'asx':
- $ct = 'video/x-ms-wmv';
- break;
- case 'pls':
- $ct = 'audio/x-scpls';
- break;
- case 'ram':
- $ct = 'audio/x-pn-realaudio ram';
- break;
- case 'simple_m3u':
- $ext = 'm3u';
- $ct = 'audio/x-mpegurl';
- break;
- case 'xspf':
- $ct = 'application/xspf+xml';
- break;
- case 'm3u':
- default:
- // Assume M3U if the pooch is screwed
- $ext = $type = 'm3u';
- $ct = 'audio/x-mpegurl';
- break;
- }
-
- if ($redirect) {
- // Our ID is the SID, so we always want to include it
- Config::set('require_session', true, true);
- header('Location: ' . Stream::get_base_url() . 'uid=' . scrub_out($this->user) . '&type=playlist&playlist_type=' . scrub_out($type));
- exit;
- }
-
- if (isset($ext)) {
- header('Cache-control: public');
- header('Content-Disposition: filename=ampache_playlist.' . $ext);
- header('Content-Type: ' . $ct . ';');
- }
-
- $this->{'create_' . $type}();
- }
-
- /**
- * add
- * Adds an array of media
- */
- public function add($media = array()) {
- $urls = $this->_media_to_urlarray($media);
- foreach ($urls as $url) {
- $this->_add_url($url);
- }
- }
-
- /**
- * add_urls
- * Add an array of urls. This is used for things that aren't coming
- * from media objects
- */
- public function add_urls($urls = array()) {
-
- if (!is_array($urls)) { return false; }
-
- foreach ($urls as $url) {
- $this->_add_url(new Stream_URL(array(
- 'url' => $url,
- 'title' => 'URL-Add',
- 'author' => 'Ampache',
- 'time' => '-1'
- )));
- }
- }
-
- /**
- * create_simplem3u
- * this creates a simple m3u without any of the extended information
- */
- public function create_simple_m3u() {
-
- foreach ($this->urls as $url) {
- echo $url->url . "\n";
- }
-
- } // simple_m3u
-
- /**
- * create_m3u
- * creates an m3u file, this includes the EXTINFO and as such can be
- * large with very long playlsits
- */
- public function create_m3u() {
-
- echo "#EXTM3U\n";
-
- foreach ($this->urls as $url) {
- echo '#EXTINF:' . $url->time, ',' . $url->author .
- ' - ' . $url->title . "\n";
- echo $url->url . "\n";
- }
-
- } // create_m3u
-
- /**
- * create_pls
- */
- public function create_pls() {
-
- echo "[playlist]\n";
- echo 'NumberOfEntries=' . count($this->urls) . "\n";
- foreach ($this->urls as $url) {
- $i++;
- echo 'File' . $i . '='. $url->url . "\n";
- echo 'Title' . $i . '=' . $url->author . ' - ' .
- $url->title . "\n";
- echo 'Length' . $i . '=' . $url->time . "\n";
- }
-
- echo "Version=2\n";
- } // create_pls
-
- /**
- * create_asx
- * This should really only be used if all of the content is ASF files.
- */
- public function create_asx() {
-
- echo '<ASX version = "3.0" BANNERBAR="AUTO">' . "\n";
- echo "<TITLE>Ampache ASX Playlist</TITLE>";
-
- foreach ($this->urls as $url) {
- echo "<ENTRY>\n";
- echo '<TITLE>' . $url->title . "</TITLE>\n";
- echo '<AUTHOR>' . $url->author . "</AUTHOR>\n";
- echo "\t\t" . '<DURATION VALUE="00:00:' . $url->time . '" />' . "\n";
- echo "\t\t" . '<PARAM NAME="Album" Value="' . $url->album . '" />' . "\n";
- echo "\t\t" . '<PARAM NAME="Composer" Value="' . $url->author . '" />' . "\n";
- echo "\t\t" . '<PARAM NAME="Prebuffer" Value="false" />' . "\n";
- echo '<REF HREF = "' . $url->url . '" />' . "\n";
- echo "</ENTRY>\n";
- }
-
- echo "</ASX>\n";
-
- } // create_asx
-
- /**
- * create_xspf
- */
- public function create_xspf() {
-
- foreach ($this->urls as $url) {
- $xml = array();
-
- $xml['track'] = array(
- 'title' => $url->title,
- 'creator' => $url->author,
- 'duration' => $url->time * 1000,
- 'location' => $url->url,
- 'identifier' => $url->url
- );
- if ($url->type == 'video') {
- $xml['track']['meta'] =
- array(
- 'attribute' => 'rel="provider"',
- 'value' => 'video'
- );
- }
- if ($url->info_url) {
- $xml['track']['info'] = $url->info_url;
- }
- if ($url->image_url) {
- $xml['track']['image'] = $url->image_url;
- }
- if ($url->album) {
- $xml['track']['album'] = $url->album;
- }
-
- $result .= XML_Data::keyed_array($xml, true);
-
- } // end foreach
-
- XML_Data::set_type('xspf');
- echo XML_Data::header();
- echo $result;
- echo XML_Data::footer();
-
- } // create_xspf
-
- /**
- * create_xspf_player
- * Due to the fact that this is an integrated player (flash) we actually
- * have to do a little 'cheating' to make this work.
- * We are going to take advantage of tmp_playlists to do all of this
- * hotness
- */
- public function create_xspf_player() {
- debug_event('stream_playlist', 'Creating XSPF player', 5);
- /* Build the extra info we need to have it pass */
- $play_info = "?action=show&tmpplaylist_id=" . $GLOBALS['user']->playlist->id;
-
- // start ugly evil javascript code
- //FIXME: This needs to go in a template, here for now though
- //FIXME: This preference doesn't even exists, we'll eventually
- //FIXME: just make it the default
- if (Config::get('embed_xspf') == 1 ){
- header("Location: ".Config::get('web_path')."/index.php?xspf&play_info=".$GLOBALS['user']->playlist->id);
- }
- else {
- echo "<html><head>\n";
- echo "<title>" . Config::get('site_title') . "</title>\n";
- echo "<script language=\"javascript\" type=\"text/javascript\">\n";
- echo "<!-- begin\n";
- echo "function PlayerPopUp(URL) {\n";
- // We do a little check here to see if it's a Wii!
- if (false !== stristr($_SERVER['HTTP_USER_AGENT'], 'Nintendo Wii')) {
- echo "window.location=URL;\n";
- }
- // Else go ahead and do the normal stuff
- else {
- echo "window.open(URL, 'XSPF_player', 'width=400,height=170,scrollbars=0,toolbar=0,location=0,directories=0,status=0,resizable=0');\n";
- echo "window.location = '" . return_referer() . "';\n";
- echo "return false;\n";
- }
- echo "}\n";
- echo "// end -->\n";
- echo "</script>\n";
- echo "</head>\n";
-
- echo "<body onLoad=\"javascript:PlayerPopUp('" . Config::get('web_path') . "/modules/flash/xspf_player.php" . $play_info . "')\">\n";
- echo "</body>\n";
- echo "</html>\n";
- }
- } // create_xspf_player
-
- /**
- * create_localplay
- * This calls the Localplay API to add the URLs and then start playback
- */
- public function create_localplay() {
-
- $localplay = new Localplay(Config::get('localplay_controller'));
- $localplay->connect();
- foreach ($this->urls as $url) {
- $localplay->add_url($url);
- }
-
- $localplay->play();
-
- } // create_localplay
-
- /**
- * create_democratic
- * This 'votes' on the songs it inserts them into
- * a tmp_playlist with user of -1 (System)
- */
- public function create_democratic() {
-
- $democratic = Democratic::get_current_playlist();
- $democratic->set_parent();
- $democratic->add_vote($this->media);
-
- } // create_democratic
-
- /**
- * create_download
- * This prompts for a download of the song
- */
- private function create_download() {
-
- // There should only be one here...
- if (count($this->urls) != 1) {
- debug_event('stream_playlist', 'Download called, but $urls contains ' . json_encode($this->urls), 2);
- }
-
- // Header redirect baby!
- $url = current($this->urls);
- header('Location: ' . $url->url . '&action=download');
- exit;
- } //create_download
-
- /**
- * create_ram
- *this functions creates a RAM file for use by Real Player
- */
- public function create_ram() {
- foreach ($this->urls as $url) {
- echo $url->url . "\n";
- }
- } // create_ram
+ public $id;
+ public $urls = array();
+ public $user;
+
+ /**
+ * Stream_Playlist constructor
+ * If an ID is passed, it should be a stream session ID.
+ */
+ public function __construct($id = null) {
+
+ if($id) {
+ Stream::set_session($id);
+ }
+
+ $this->id = Dba::escape(Stream::get_session());
+
+ if (!Stream::session_exists($this->id)) {
+ debug_event('stream_playlist', 'Stream::session_exists failed', 2);
+ return false;
+ }
+
+ $this->user = intval($GLOBALS['user']->id);
+
+ $sql = "SELECT * FROM `stream_playlist` WHERE `sid`='" .
+ $this->id . "' ORDER BY `id`";
+
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $this->urls[] = new Stream_URL($row);
+ }
+
+ return true;
+ }
+
+ private function _add_url($url) {
+ $this->urls[] = $url;
+
+ $sql = 'INSERT INTO `stream_playlist` ';
+
+ $fields[] = '`sid`';
+ $values[] = Dba::escape($this->id);
+
+ foreach ($url->properties as $field) {
+ if ($url->$field) {
+ $fields[] = '`' . $field . '`';
+ $values[] = Dba::escape($url->$field);
+ }
+ }
+ $sql .= '(' . implode(', ', $fields) . ') ';
+ $sql .= "VALUES('" . implode("', '", $values) . "')";
+
+ return Dba::write($sql);
+ }
+
+ public static function gc() {
+ $sql = 'DELETE FROM `stream_playlist` ' .
+ 'USING `stream_playlist` LEFT JOIN `session_stream` ' .
+ 'ON `session_stream`.`id`=`stream_playlist`.`sid` ' .
+ 'WHERE `session_stream`.`id` IS NULL';
+ return Dba::write($sql);
+ }
+
+ /**
+ * _media_to_urlarray
+ * Formats the URL and media information and adds it to the object
+ */
+ private static function _media_to_urlarray($media) {
+ $urls = array();
+ foreach($media as $medium) {
+ debug_event('stream_playlist', 'Adding ' . json_encode($media), 5);
+ $url = array();
+
+ $type = $medium['object_type'];
+ $array['type'] = $type;
+
+ $object = new $type($medium['object_id']);
+ $object->format();
+ //FIXME: play_url shouldn't be static
+ $url['url'] = $type::play_url($object->id);
+
+ // Set a default which can be overridden
+ $url['author'] = 'Ampache';
+ $url['time'] = $object->time;
+ switch($type) {
+ case 'song':
+ $url['title'] = $object->title;
+ $url['author'] = $object->f_artist_full;
+ $url['info_url'] = $object->f_link;
+ $url['image_url'] = Art::url($object->album, 'album');
+ $url['album'] = $object->f_album_full;
+ break;
+ case 'video':
+ $url['title'] = 'Video - ' . $object->title;
+ $url['author'] = $object->f_artist_full;
+ break;
+ case 'radio':
+ $url['title'] = 'Radio - ' . $object->name .
+ ' [' . $object->frequency .
+ '] (' . $object->site_url . ')';
+ break;
+ case 'random':
+ $url['title'] = 'Random URL';
+ break;
+ default:
+ $url['title'] = 'URL-Add';
+ $url['time'] = -1;
+ break;
+ }
+
+ $urls[] = new Stream_URL($url);
+ }
+
+ return $urls;
+ }
+
+ public function generate_playlist($type, $redirect = false) {
+
+ if (!count($this->urls)) {
+ debug_event('stream_playlist', 'Error: Empty URL array for ' . $this->id, 2);
+ return false;
+ }
+
+ debug_event('stream_playlist', 'generating a ' . $type, 5);
+
+ $ext = $type;
+ switch($type) {
+ case 'democratic':
+ case 'localplay':
+ case 'xspf_player':
+ // These are valid, but witchy
+ $redirect = false;
+ unset($ext);
+ break;
+ case 'asx':
+ $ct = 'video/x-ms-wmv';
+ break;
+ case 'pls':
+ $ct = 'audio/x-scpls';
+ break;
+ case 'ram':
+ $ct = 'audio/x-pn-realaudio ram';
+ break;
+ case 'simple_m3u':
+ $ext = 'm3u';
+ $ct = 'audio/x-mpegurl';
+ break;
+ case 'xspf':
+ $ct = 'application/xspf+xml';
+ break;
+ case 'm3u':
+ default:
+ // Assume M3U if the pooch is screwed
+ $ext = $type = 'm3u';
+ $ct = 'audio/x-mpegurl';
+ break;
+ }
+
+ if ($redirect) {
+ // Our ID is the SID, so we always want to include it
+ Config::set('require_session', true, true);
+ header('Location: ' . Stream::get_base_url() . 'uid=' . scrub_out($this->user) . '&type=playlist&playlist_type=' . scrub_out($type));
+ exit;
+ }
+
+ if (isset($ext)) {
+ header('Cache-control: public');
+ header('Content-Disposition: filename=ampache_playlist.' . $ext);
+ header('Content-Type: ' . $ct . ';');
+ }
+
+ $this->{'create_' . $type}();
+ }
+
+ /**
+ * add
+ * Adds an array of media
+ */
+ public function add($media = array()) {
+ $urls = $this->_media_to_urlarray($media);
+ foreach ($urls as $url) {
+ $this->_add_url($url);
+ }
+ }
+
+ /**
+ * add_urls
+ * Add an array of urls. This is used for things that aren't coming
+ * from media objects
+ */
+ public function add_urls($urls = array()) {
+
+ if (!is_array($urls)) { return false; }
+
+ foreach ($urls as $url) {
+ $this->_add_url(new Stream_URL(array(
+ 'url' => $url,
+ 'title' => 'URL-Add',
+ 'author' => 'Ampache',
+ 'time' => '-1'
+ )));
+ }
+ }
+
+ /**
+ * create_simplem3u
+ * this creates a simple m3u without any of the extended information
+ */
+ public function create_simple_m3u() {
+
+ foreach ($this->urls as $url) {
+ echo $url->url . "\n";
+ }
+
+ } // simple_m3u
+
+ /**
+ * create_m3u
+ * creates an m3u file, this includes the EXTINFO and as such can be
+ * large with very long playlsits
+ */
+ public function create_m3u() {
+
+ echo "#EXTM3U\n";
+
+ foreach ($this->urls as $url) {
+ echo '#EXTINF:' . $url->time, ',' . $url->author .
+ ' - ' . $url->title . "\n";
+ echo $url->url . "\n";
+ }
+
+ } // create_m3u
+
+ /**
+ * create_pls
+ */
+ public function create_pls() {
+
+ echo "[playlist]\n";
+ echo 'NumberOfEntries=' . count($this->urls) . "\n";
+ foreach ($this->urls as $url) {
+ $i++;
+ echo 'File' . $i . '='. $url->url . "\n";
+ echo 'Title' . $i . '=' . $url->author . ' - ' .
+ $url->title . "\n";
+ echo 'Length' . $i . '=' . $url->time . "\n";
+ }
+
+ echo "Version=2\n";
+ } // create_pls
+
+ /**
+ * create_asx
+ * This should really only be used if all of the content is ASF files.
+ */
+ public function create_asx() {
+
+ echo '<ASX version = "3.0" BANNERBAR="AUTO">' . "\n";
+ echo "<TITLE>Ampache ASX Playlist</TITLE>";
+
+ foreach ($this->urls as $url) {
+ echo "<ENTRY>\n";
+ echo '<TITLE>' . $url->title . "</TITLE>\n";
+ echo '<AUTHOR>' . $url->author . "</AUTHOR>\n";
+ echo "\t\t" . '<DURATION VALUE="00:00:' . $url->time . '" />' . "\n";
+ echo "\t\t" . '<PARAM NAME="Album" Value="' . $url->album . '" />' . "\n";
+ echo "\t\t" . '<PARAM NAME="Composer" Value="' . $url->author . '" />' . "\n";
+ echo "\t\t" . '<PARAM NAME="Prebuffer" Value="false" />' . "\n";
+ echo '<REF HREF = "' . $url->url . '" />' . "\n";
+ echo "</ENTRY>\n";
+ }
+
+ echo "</ASX>\n";
+
+ } // create_asx
+
+ /**
+ * create_xspf
+ */
+ public function create_xspf() {
+
+ foreach ($this->urls as $url) {
+ $xml = array();
+
+ $xml['track'] = array(
+ 'title' => $url->title,
+ 'creator' => $url->author,
+ 'duration' => $url->time * 1000,
+ 'location' => $url->url,
+ 'identifier' => $url->url
+ );
+ if ($url->type == 'video') {
+ $xml['track']['meta'] =
+ array(
+ 'attribute' => 'rel="provider"',
+ 'value' => 'video'
+ );
+ }
+ if ($url->info_url) {
+ $xml['track']['info'] = $url->info_url;
+ }
+ if ($url->image_url) {
+ $xml['track']['image'] = $url->image_url;
+ }
+ if ($url->album) {
+ $xml['track']['album'] = $url->album;
+ }
+
+ $result .= XML_Data::keyed_array($xml, true);
+
+ } // end foreach
+
+ XML_Data::set_type('xspf');
+ echo XML_Data::header();
+ echo $result;
+ echo XML_Data::footer();
+
+ } // create_xspf
+
+ /**
+ * create_xspf_player
+ * Due to the fact that this is an integrated player (flash) we actually
+ * have to do a little 'cheating' to make this work.
+ * We are going to take advantage of tmp_playlists to do all of this
+ * hotness
+ */
+ public function create_xspf_player() {
+ debug_event('stream_playlist', 'Creating XSPF player', 5);
+ /* Build the extra info we need to have it pass */
+ $play_info = "?action=show&tmpplaylist_id=" . $GLOBALS['user']->playlist->id;
+
+ // start ugly evil javascript code
+ //FIXME: This needs to go in a template, here for now though
+ //FIXME: This preference doesn't even exists, we'll eventually
+ //FIXME: just make it the default
+ if (Config::get('embed_xspf') == 1 ){
+ header("Location: ".Config::get('web_path')."/index.php?xspf&play_info=".$GLOBALS['user']->playlist->id);
+ }
+ else {
+ echo "<html><head>\n";
+ echo "<title>" . Config::get('site_title') . "</title>\n";
+ echo "<script language=\"javascript\" type=\"text/javascript\">\n";
+ echo "<!-- begin\n";
+ echo "function PlayerPopUp(URL) {\n";
+ // We do a little check here to see if it's a Wii!
+ if (false !== stristr($_SERVER['HTTP_USER_AGENT'], 'Nintendo Wii')) {
+ echo "window.location=URL;\n";
+ }
+ // Else go ahead and do the normal stuff
+ else {
+ echo "window.open(URL, 'XSPF_player', 'width=400,height=170,scrollbars=0,toolbar=0,location=0,directories=0,status=0,resizable=0');\n";
+ echo "window.location = '" . return_referer() . "';\n";
+ echo "return false;\n";
+ }
+ echo "}\n";
+ echo "// end -->\n";
+ echo "</script>\n";
+ echo "</head>\n";
+
+ echo "<body onLoad=\"javascript:PlayerPopUp('" . Config::get('web_path') . "/modules/flash/xspf_player.php" . $play_info . "')\">\n";
+ echo "</body>\n";
+ echo "</html>\n";
+ }
+ } // create_xspf_player
+
+ /**
+ * create_localplay
+ * This calls the Localplay API to add the URLs and then start playback
+ */
+ public function create_localplay() {
+
+ $localplay = new Localplay(Config::get('localplay_controller'));
+ $localplay->connect();
+ foreach ($this->urls as $url) {
+ $localplay->add_url($url);
+ }
+
+ $localplay->play();
+
+ } // create_localplay
+
+ /**
+ * create_democratic
+ * This 'votes' on the songs it inserts them into
+ * a tmp_playlist with user of -1 (System)
+ */
+ public function create_democratic() {
+
+ $democratic = Democratic::get_current_playlist();
+ $democratic->set_parent();
+ $democratic->add_vote($this->media);
+
+ } // create_democratic
+
+ /**
+ * create_download
+ * This prompts for a download of the song
+ */
+ private function create_download() {
+
+ // There should only be one here...
+ if (count($this->urls) != 1) {
+ debug_event('stream_playlist', 'Download called, but $urls contains ' . json_encode($this->urls), 2);
+ }
+
+ // Header redirect baby!
+ $url = current($this->urls);
+ header('Location: ' . $url->url . '&action=download');
+ exit;
+ } //create_download
+
+ /**
+ * create_ram
+ *this functions creates a RAM file for use by Real Player
+ */
+ public function create_ram() {
+ foreach ($this->urls as $url) {
+ echo $url->url . "\n";
+ }
+ } // create_ram
}
diff --git a/lib/class/stream_url.class.php b/lib/class/stream_url.class.php
index e590dd49..d651ca59 100644
--- a/lib/class/stream_url.class.php
+++ b/lib/class/stream_url.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -25,6 +25,6 @@
class Stream_URL extends memory_object {
- public $properties = array('url', 'title', 'author', 'time', 'info_url', 'image_url', 'album', 'type');
+ public $properties = array('url', 'title', 'author', 'time', 'info_url', 'image_url', 'album', 'type');
}
diff --git a/lib/class/tag.class.php b/lib/class/tag.class.php
index 36c25648..373a7cbc 100644
--- a/lib/class/tag.class.php
+++ b/lib/class/tag.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,594 +28,594 @@
*/
class Tag extends database_object {
- public $id;
- public $name;
+ public $id;
+ public $name;
- // constructed
- public $weight=0;
- public $count=0;
- public $owner=0;
+ // constructed
+ public $weight=0;
+ public $count=0;
+ public $owner=0;
- /**
- * constructor
- * This takes a tag id and returns all of the relevent information
- */
- public function __construct($id) {
+ /**
+ * constructor
+ * This takes a tag id and returns all of the relevent information
+ */
+ public function __construct($id) {
- if (!$id) { return false; }
+ if (!$id) { return false; }
- $info = $this->get_info($id);
+ $info = $this->get_info($id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- } // end foreach
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ } // end foreach
- } // constructor
+ } // constructor
- /**
- * construct_from_name
- * This attempts to construct the tag from a name, rather then the ID
- */
- public static function construct_from_name($name) {
+ /**
+ * construct_from_name
+ * This attempts to construct the tag from a name, rather then the ID
+ */
+ public static function construct_from_name($name) {
- $tag_id = self::tag_exists($name);
+ $tag_id = self::tag_exists($name);
- $tag = new Tag($tag_id);
+ $tag = new Tag($tag_id);
- return $tag;
+ return $tag;
- } // construct_from_name
+ } // construct_from_name
- /**
- * format
- * This makes the tag presentable to the great humans that use this program, other life forms
- * will just have to fend for themselves
- */
- public function format($type=0,$object_id=0) {
+ /**
+ * format
+ * This makes the tag presentable to the great humans that use this program, other life forms
+ * will just have to fend for themselves
+ */
+ public function format($type=0,$object_id=0) {
- if ($type AND !self::validate_type($type)) { return false; }
+ if ($type AND !self::validate_type($type)) { return false; }
- if ($type) {
- $this->set_object($type,$object_id);
- }
+ if ($type) {
+ $this->set_object($type,$object_id);
+ }
- $size = 3 + ($this->weight-1) - ($this->count-1);
- if (abs($size) > 4) { $size = 4; }
- if (abs($size) < 1) { $size = 1; }
+ $size = 3 + ($this->weight-1) - ($this->count-1);
+ if (abs($size) > 4) { $size = 4; }
+ if (abs($size) < 1) { $size = 1; }
- if ($this->owner == $GLOBALS['user']->id) {
- $action = '?page=tag&action=remove_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id);
- $class = "hover-remove ";
- }
- else {
- $action = '?page=tag&action=add_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id);
- $class = "hover-add ";
- }
+ if ($this->owner == $GLOBALS['user']->id) {
+ $action = '?page=tag&action=remove_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id);
+ $class = "hover-remove ";
+ }
+ else {
+ $action = '?page=tag&action=add_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id);
+ $class = "hover-add ";
+ }
- $class .= 'tag_size' . $size;
- $this->f_class = $class;
+ $class .= 'tag_size' . $size;
+ $this->f_class = $class;
- $this->f_name = Ajax::text($action,$this->name,'modify_tag_' . $this->id . '_' . $object_id,'',$class);
+ $this->f_name = Ajax::text($action,$this->name,'modify_tag_' . $this->id . '_' . $object_id,'',$class);
- } // format
+ } // format
- /**
- * set_object
- * This associates the tag with a specified object, we try to get the
- * data from the map cache, otherwise I guess we'll just have to look it
- * up.
- */
- public function set_object($type,$object_id) {
+ /**
+ * set_object
+ * This associates the tag with a specified object, we try to get the
+ * data from the map cache, otherwise I guess we'll just have to look it
+ * up.
+ */
+ public function set_object($type,$object_id) {
- if (parent::is_cached('tag_top_' . $type,$object_id)) {
- $data = parent::get_from_cache('tag_top_' . $type,$object_id);
- }
- else {
- $data = self::get_top_tags($type,$object_id);
- }
+ if (parent::is_cached('tag_top_' . $type,$object_id)) {
+ $data = parent::get_from_cache('tag_top_' . $type,$object_id);
+ }
+ else {
+ $data = self::get_top_tags($type,$object_id);
+ }
- // If nothing is found, then go ahead and return false
- if (!is_array($data) OR !count($data)) { return false; }
+ // If nothing is found, then go ahead and return false
+ if (!is_array($data) OR !count($data)) { return false; }
- $this->weight = count($data[$this->id]['users']);
+ $this->weight = count($data[$this->id]['users']);
- if (in_array($GLOBALS['user']->id,$data[$this->id]['users'])) {
- $this->owner = $GLOBALS['user']->id;
- }
+ if (in_array($GLOBALS['user']->id,$data[$this->id]['users'])) {
+ $this->owner = $GLOBALS['user']->id;
+ }
- $this->count = count($data);
+ $this->count = count($data);
- } // set_object
+ } // set_object
- /**
- * build_cache
- * This takes an array of object ids and caches all of their information
- * in a single query, cuts down on the connections
- */
- public static function build_cache($ids) {
+ /**
+ * build_cache
+ * This takes an array of object ids and caches all of their information
+ * in a single query, cuts down on the connections
+ */
+ public static function build_cache($ids) {
- if (!is_array($ids) OR !count($ids)) { return false; }
+ if (!is_array($ids) OR !count($ids)) { return false; }
- $idlist = '(' . implode(',',$ids) . ')';
+ $idlist = '(' . implode(',',$ids) . ')';
- $sql = "SELECT * FROM `tag` WHERE `id` IN $idlist";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `tag` WHERE `id` IN $idlist";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('tag',$row['id'],$row);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('tag',$row['id'],$row);
+ }
- return true;
- } // build_cache
+ return true;
+ } // build_cache
- /**
- * build_map_cache
- * This builds a cache of the mappings for the specified object, no limit is given
- */
- public static function build_map_cache($type,$ids) {
+ /**
+ * build_map_cache
+ * This builds a cache of the mappings for the specified object, no limit is given
+ */
+ public static function build_map_cache($type,$ids) {
- if (!is_array($ids) OR !count($ids)) { return false; }
+ if (!is_array($ids) OR !count($ids)) { return false; }
- $type = self::validate_type($type);
- $idlist = '(' . implode(',',$ids) . ')';
+ $type = self::validate_type($type);
+ $idlist = '(' . implode(',',$ids) . ')';
- $sql = "SELECT `tag_map`.`id`,`tag_map`.`tag_id`,`tag_map`.`object_id`,`tag_map`.`user` FROM `tag_map` " .
- "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id` IN $idlist ";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `tag_map`.`id`,`tag_map`.`tag_id`,`tag_map`.`object_id`,`tag_map`.`user` FROM `tag_map` " .
+ "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id` IN $idlist ";
+ $db_results = Dba::read($sql);
- $tags = array();
+ $tags = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $tags[$row['object_id']][$row['tag_id']]['users'][] = $row['user'];
- $tag_map[$row['object_id']] = array('id'=>$row['id'],'tag_id'=>$row['tag_id'],'user'=>$row['user'],'object_type'=>$type,'object_id'=>$row['object_id']);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $tags[$row['object_id']][$row['tag_id']]['users'][] = $row['user'];
+ $tag_map[$row['object_id']] = array('id'=>$row['id'],'tag_id'=>$row['tag_id'],'user'=>$row['user'],'object_type'=>$type,'object_id'=>$row['object_id']);
+ }
- // Run through our original ids as we also want to cache NULL
- // results
- foreach ($ids as $id) {
- if (!isset($tags[$id])) {
- $tags[$id] = null;
- $tag_map[$id] = null;
- }
- parent::add_to_cache('tag_top_' . $type, $id, $tags[$id]);
- parent::add_to_cache('tag_map_' . $type, $id, $tag_map[$id]);
- }
+ // Run through our original ids as we also want to cache NULL
+ // results
+ foreach ($ids as $id) {
+ if (!isset($tags[$id])) {
+ $tags[$id] = null;
+ $tag_map[$id] = null;
+ }
+ parent::add_to_cache('tag_top_' . $type, $id, $tags[$id]);
+ parent::add_to_cache('tag_map_' . $type, $id, $tag_map[$id]);
+ }
- return true;
+ return true;
- } // build_map_cache
+ } // build_map_cache
- /**
- * add
- * This is a wrapper function, it figures out what we need to add, be it a tag
- * and map, or just the mapping
- */
- public static function add($type,$id,$value,$user=false) {
+ /**
+ * add
+ * This is a wrapper function, it figures out what we need to add, be it a tag
+ * and map, or just the mapping
+ */
+ public static function add($type,$id,$value,$user=false) {
- // Validate the tag type
- if (!self::validate_type($type)) { return false; }
+ // Validate the tag type
+ if (!self::validate_type($type)) { return false; }
- if (!is_numeric($id)) { return false; }
+ if (!is_numeric($id)) { return false; }
- $cleaned_value = self::clean_tag($value);
+ $cleaned_value = self::clean_tag($value);
- if (!strlen($cleaned_value)) { return false; }
+ if (!strlen($cleaned_value)) { return false; }
- $uid = ($user === false) ? intval($user) : intval($GLOBALS['user']->id);
+ $uid = ($user === false) ? intval($user) : intval($GLOBALS['user']->id);
- // Check and see if the tag exists, if not create it, we need the tag id from this
- if (!$tag_id = self::tag_exists($cleaned_value)) {
- $tag_id = self::add_tag($cleaned_value);
- }
+ // Check and see if the tag exists, if not create it, we need the tag id from this
+ if (!$tag_id = self::tag_exists($cleaned_value)) {
+ $tag_id = self::add_tag($cleaned_value);
+ }
- if (!$tag_id) {
- debug_event('Error','Error unable to create tag value:' . $cleaned_value . ' unknown error','1');
- return false;
- }
+ if (!$tag_id) {
+ debug_event('Error','Error unable to create tag value:' . $cleaned_value . ' unknown error','1');
+ return false;
+ }
- // We've got the tag id, let's see if it's already got a map, if not then create the map and return the value
- if (!$map_id = self::tag_map_exists($type,$id,$tag_id,$user)) {
- $map_id = self::add_tag_map($type,$id,$tag_id,$user);
- }
+ // We've got the tag id, let's see if it's already got a map, if not then create the map and return the value
+ if (!$map_id = self::tag_map_exists($type,$id,$tag_id,$user)) {
+ $map_id = self::add_tag_map($type,$id,$tag_id,$user);
+ }
- return $map_id;
+ return $map_id;
- } // add
+ } // add
- /**
- * add_tag
- * This function adds a new tag, for now we're going to limit the tagging a bit
- */
- public static function add_tag($value) {
+ /**
+ * add_tag
+ * This function adds a new tag, for now we're going to limit the tagging a bit
+ */
+ public static function add_tag($value) {
- // Clean it up and make it tagish
- $value = self::clean_tag($value);
+ // Clean it up and make it tagish
+ $value = self::clean_tag($value);
- if (!strlen($value)) { return false; }
+ if (!strlen($value)) { return false; }
- $value = Dba::escape($value);
+ $value = Dba::escape($value);
- $sql = "REPLACE INTO `tag` SET `name`='$value'";
- $db_results = Dba::write($sql);
- $insert_id = Dba::insert_id();
+ $sql = "REPLACE INTO `tag` SET `name`='$value'";
+ $db_results = Dba::write($sql);
+ $insert_id = Dba::insert_id();
- parent::add_to_cache('tag_name',$value,$insert_id);
+ parent::add_to_cache('tag_name',$value,$insert_id);
- return $insert_id;
+ return $insert_id;
- } // add_tag
+ } // add_tag
- /**
- * add_tag_map
- * This adds a specific tag to the map for specified object
- */
- public static function add_tag_map($type,$object_id,$tag_id,$user='') {
+ /**
+ * add_tag_map
+ * This adds a specific tag to the map for specified object
+ */
+ public static function add_tag_map($type,$object_id,$tag_id,$user='') {
- $uid = ($user == '') ? intval($GLOBALS['user']->id) : intval($user);
- $tag_id = intval($tag_id);
- if (!self::validate_type($type)) { return false; }
- $id = intval($object_id);
+ $uid = ($user == '') ? intval($GLOBALS['user']->id) : intval($user);
+ $tag_id = intval($tag_id);
+ if (!self::validate_type($type)) { return false; }
+ $id = intval($object_id);
- if (!$tag_id || !$id) { return false; }
+ if (!$tag_id || !$id) { return false; }
- $sql = "INSERT INTO `tag_map` (`tag_id`,`user`,`object_type`,`object_id`) " .
- "VALUES ('$tag_id','$uid','$type','$id')";
- $db_results = Dba::write($sql);
- $insert_id = Dba::insert_id();
+ $sql = "INSERT INTO `tag_map` (`tag_id`,`user`,`object_type`,`object_id`) " .
+ "VALUES ('$tag_id','$uid','$type','$id')";
+ $db_results = Dba::write($sql);
+ $insert_id = Dba::insert_id();
- parent::add_to_cache('tag_map_' . $type,$insert_id,array('tag_id'=>$tag_id,'user'=>$uid,'object_type'=>$type,'object_id'=>$id));
+ parent::add_to_cache('tag_map_' . $type,$insert_id,array('tag_id'=>$tag_id,'user'=>$uid,'object_type'=>$type,'object_id'=>$id));
- return $insert_id;
+ return $insert_id;
- } // add_tag_map
+ } // add_tag_map
- /**
- * gc
- *
- * This cleans out tag_maps that are obsolete and then removes tags that
- * have no maps.
- */
- public static function gc() {
- $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `song` ON `song`.`id`=`tag_map`.`object_id` " .
- "WHERE `tag_map`.`object_type`='song' AND `song`.`id` IS NULL";
- $db_results = Dba::write($sql);
+ /**
+ * gc
+ *
+ * This cleans out tag_maps that are obsolete and then removes tags that
+ * have no maps.
+ */
+ public static function gc() {
+ $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `song` ON `song`.`id`=`tag_map`.`object_id` " .
+ "WHERE `tag_map`.`object_type`='song' AND `song`.`id` IS NULL";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `album` ON `album`.`id`=`tag_map`.`object_id` " .
- "WHERE `tag_map`.`object_type`='album' AND `album`.`id` IS NULL";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `album` ON `album`.`id`=`tag_map`.`object_id` " .
+ "WHERE `tag_map`.`object_type`='album' AND `album`.`id` IS NULL";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `artist` ON `artist`.`id`=`tag_map`.`object_id` " .
- "WHERE `tag_map`.`object_type`='artist' AND `artist`.`id` IS NULL";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `artist` ON `artist`.`id`=`tag_map`.`object_id` " .
+ "WHERE `tag_map`.`object_type`='artist' AND `artist`.`id` IS NULL";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `video` ON `video`.`id`=`tag_map`.`object_id` " .
- "WHERE `tag_map`.`object_type`='video' AND `video`.`id` IS NULL";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `video` ON `video`.`id`=`tag_map`.`object_id` " .
+ "WHERE `tag_map`.`object_type`='video' AND `video`.`id` IS NULL";
+ $db_results = Dba::write($sql);
- // Now nuke the tags themselves
- $sql = "DELETE FROM `tag` USING `tag` LEFT JOIN `tag_map` ON `tag`.`id`=`tag_map`.`tag_id` " .
- "WHERE `tag_map`.`id` IS NULL";
- $db_results = Dba::write($sql);
- }
+ // Now nuke the tags themselves
+ $sql = "DELETE FROM `tag` USING `tag` LEFT JOIN `tag_map` ON `tag`.`id`=`tag_map`.`tag_id` " .
+ "WHERE `tag_map`.`id` IS NULL";
+ $db_results = Dba::write($sql);
+ }
- /**
- * tag_exists
- * This checks to see if a tag exists, this has nothing to do with objects or maps
- */
- public static function tag_exists($value) {
+ /**
+ * tag_exists
+ * This checks to see if a tag exists, this has nothing to do with objects or maps
+ */
+ public static function tag_exists($value) {
- if (parent::is_cached('tag_name',$value)) {
- return parent::get_from_cache('tag_name',$value);
- }
+ if (parent::is_cached('tag_name',$value)) {
+ return parent::get_from_cache('tag_name',$value);
+ }
- $value = Dba::escape($value);
- $sql = "SELECT * FROM `tag` WHERE `name`='$value'";
- $db_results = Dba::read($sql);
+ $value = Dba::escape($value);
+ $sql = "SELECT * FROM `tag` WHERE `name`='$value'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- parent::add_to_cache('tag_name',$results['name'],$results['id']);
+ parent::add_to_cache('tag_name',$results['name'],$results['id']);
- return $results['id'];
+ return $results['id'];
- } // tag_exists
+ } // tag_exists
- /**
- * tag_map_exists
- * This looks to see if the current mapping of the current object of the current tag of the current
- * user exists, lots of currents... taste good in scones.
- */
- public static function tag_map_exists($type,$object_id,$tag_id,$user) {
+ /**
+ * tag_map_exists
+ * This looks to see if the current mapping of the current object of the current tag of the current
+ * user exists, lots of currents... taste good in scones.
+ */
+ public static function tag_map_exists($type,$object_id,$tag_id,$user) {
- if (!self::validate_type($type)) { return false; }
+ if (!self::validate_type($type)) { return false; }
- if (parent::is_cached('tag_map_' . $type,$object_id)) {
- $data = parent::get_from_cache('tag_map_' . $type,$object_id);
- return $data['id'];
- }
+ if (parent::is_cached('tag_map_' . $type,$object_id)) {
+ $data = parent::get_from_cache('tag_map_' . $type,$object_id);
+ return $data['id'];
+ }
- $object_id = Dba::escape($object_id);
- $tag_id = Dba::escape($tag_id);
- $user = Dba::escape($user);
- $type = Dba::escape($type);
+ $object_id = Dba::escape($object_id);
+ $tag_id = Dba::escape($tag_id);
+ $user = Dba::escape($user);
+ $type = Dba::escape($type);
- $sql = "SELECT * FROM `tag_map` WHERE `tag_id`='$tag_id' AND `user`='$user' AND `object_id`='$object_id' AND `object_type`='$type'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `tag_map` WHERE `tag_id`='$tag_id' AND `user`='$user' AND `object_id`='$object_id' AND `object_type`='$type'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- parent::add_to_cache('tag_map_' . $type,$results['id'],$results);
+ parent::add_to_cache('tag_map_' . $type,$results['id'],$results);
- return $results['id'];
+ return $results['id'];
- } // tag_map_exists
+ } // tag_map_exists
- /**
- * get_top_tags
- * This gets the top tags for the specified object using limit
- */
- public static function get_top_tags($type, $object_id, $limit = 10) {
+ /**
+ * get_top_tags
+ * This gets the top tags for the specified object using limit
+ */
+ public static function get_top_tags($type, $object_id, $limit = 10) {
- if (!self::validate_type($type)) { return false; }
+ if (!self::validate_type($type)) { return false; }
- if (parent::is_cached('tag_top_' . $type,$object_id)) {
- return parent::get_from_cache('tag_top_' . $type,$object_id);
- }
+ if (parent::is_cached('tag_top_' . $type,$object_id)) {
+ return parent::get_from_cache('tag_top_' . $type,$object_id);
+ }
- $object_id = intval($object_id);
- $limit = intval($limit);
+ $object_id = intval($object_id);
+ $limit = intval($limit);
- $sql = "SELECT `tag_id`, `user` FROM `tag_map` " .
- "WHERE `object_type`='$type' AND `object_id`='$object_id' " .
- "LIMIT $limit";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `tag_id`, `user` FROM `tag_map` " .
+ "WHERE `object_type`='$type' AND `object_id`='$object_id' " .
+ "LIMIT $limit";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[$row['tag_id']]['users'][] = $row['user'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[$row['tag_id']]['users'][] = $row['user'];
+ }
- parent::add_to_cache('tag_top_' . $type,$object_id,$results);
+ parent::add_to_cache('tag_top_' . $type,$object_id,$results);
- return $results;
+ return $results;
- } // get_top_tags
+ } // get_top_tags
- /**
- * get_object_tags
- * Display all tags that apply to maching target type of the specified id
- * UNUSED
- */
- public static function get_object_tags($type, $id) {
+ /**
+ * get_object_tags
+ * Display all tags that apply to maching target type of the specified id
+ * UNUSED
+ */
+ public static function get_object_tags($type, $id) {
- if (!self::validate_type($type)) { return array(); }
+ if (!self::validate_type($type)) { return array(); }
- $id = Dba::escape($id);
+ $id = Dba::escape($id);
- $sql = "SELECT `tag_map`.`id`, `tag`.`name`, `tag_map`.`user` FROM `tag` " .
- "LEFT JOIN `tag_map` ON `tag_map`.`tag_id`=`tag`.`id` " .
- "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id`='$id'";
+ $sql = "SELECT `tag_map`.`id`, `tag`.`name`, `tag_map`.`user` FROM `tag` " .
+ "LEFT JOIN `tag_map` ON `tag_map`.`tag_id`=`tag`.`id` " .
+ "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id`='$id'";
- $results = array();
- $db_results = Dba::read($sql);
+ $results = array();
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row;
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row;
+ }
- return $results;
+ return $results;
- } // get_object_tags
+ } // get_object_tags
- /**
- * get_tag_objects
- * This gets the objects from a specified tag and returns an array of object ids, nothing more
- */
- public static function get_tag_objects($type,$tag_id) {
+ /**
+ * get_tag_objects
+ * This gets the objects from a specified tag and returns an array of object ids, nothing more
+ */
+ public static function get_tag_objects($type,$tag_id) {
- if (!self::validate_type($type)) { return array(); }
+ if (!self::validate_type($type)) { return array(); }
- $tag_id = Dba::escape($tag_id);
+ $tag_id = Dba::escape($tag_id);
- $sql = "SELECT DISTINCT `tag_map`.`object_id` FROM `tag_map` " .
- "WHERE `tag_map`.`tag_id`='$tag_id' AND `tag_map`.`object_type`='$type'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT DISTINCT `tag_map`.`object_id` FROM `tag_map` " .
+ "WHERE `tag_map`.`tag_id`='$tag_id' AND `tag_map`.`object_type`='$type'";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['object_id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['object_id'];
+ }
- return $results;
+ return $results;
- } // get_tag_objects
+ } // get_tag_objects
- /**
- * get_tags
- * This is a non-object non type depedent function that just returns tags
- * we've got, it can take filters (this is used by the tag cloud)
- */
- public static function get_tags($limit,$filters=array()) {
+ /**
+ * get_tags
+ * This is a non-object non type depedent function that just returns tags
+ * we've got, it can take filters (this is used by the tag cloud)
+ */
+ public static function get_tags($limit,$filters=array()) {
- $sql = "SELECT `tag_map`.`tag_id`,COUNT(`tag_map`.`object_id`) AS `count` " .
- "FROM `tag_map` " .
- "LEFT JOIN `tag` ON `tag`.`id`=`tag_map`.`tag_id` " .
- "GROUP BY `tag`.`name` ORDER BY `count` DESC " .
- "LIMIT $limit";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `tag_map`.`tag_id`,COUNT(`tag_map`.`object_id`) AS `count` " .
+ "FROM `tag_map` " .
+ "LEFT JOIN `tag` ON `tag`.`id`=`tag_map`.`tag_id` " .
+ "GROUP BY `tag`.`name` ORDER BY `count` DESC " .
+ "LIMIT $limit";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- if ($row['count'] > $top) { $top = $row['count']; }
- $results[$row['tag_id']] = array('id'=>$row['tag_id'],'count'=>$row['count']);
- $count+= $row['count'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ if ($row['count'] > $top) { $top = $row['count']; }
+ $results[$row['tag_id']] = array('id'=>$row['tag_id'],'count'=>$row['count']);
+ $count+= $row['count'];
+ }
- // Do something with this
- $min = $row['count'];
+ // Do something with this
+ $min = $row['count'];
- return $results;
+ return $results;
- } // get_tags
+ } // get_tags
- /**
- * get_display
- * This returns a human formated version of the tags that we are given
- * it also takes a type so that it knows how to return it, this is used
- * by the formating functions of the different objects
- */
- public static function get_display($tags,$element_id,$type='song') {
+ /**
+ * get_display
+ * This returns a human formated version of the tags that we are given
+ * it also takes a type so that it knows how to return it, this is used
+ * by the formating functions of the different objects
+ */
+ public static function get_display($tags,$element_id,$type='song') {
- if (!is_array($tags)) { return ''; }
+ if (!is_array($tags)) { return ''; }
- $results = '';
+ $results = '';
- // Itterate through the tags, format them according to type and element id
- foreach ($tags as $tag_id=>$value) {
- $tag = new Tag($tag_id);
- $tag->format($type,$element_id);
- $results .= $tag->f_name . ', ';
- }
+ // Itterate through the tags, format them according to type and element id
+ foreach ($tags as $tag_id=>$value) {
+ $tag = new Tag($tag_id);
+ $tag->format($type,$element_id);
+ $results .= $tag->f_name . ', ';
+ }
- $results = rtrim($results,', ');
+ $results = rtrim($results,', ');
- return $results;
+ return $results;
- } // get_display
+ } // get_display
- /**
- * count
- * This returns the count for the all objects associated with this tag
- * If a type is specific only counts for said type are returned
- */
- public function count($type='') {
+ /**
+ * count
+ * This returns the count for the all objects associated with this tag
+ * If a type is specific only counts for said type are returned
+ */
+ public function count($type='') {
- if ($type) {
- $filter_sql = " AND `object_type`='" . Dba::escape($type) . "'";
- }
+ if ($type) {
+ $filter_sql = " AND `object_type`='" . Dba::escape($type) . "'";
+ }
- $results = array();
+ $results = array();
- $sql = "SELECT COUNT(`id`) AS `count`,`object_type` FROM `tag_map` WHERE `tag_id`='" . Dba::escape($this->id) . "'" . $filter_sql . " GROUP BY `object_type`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT COUNT(`id`) AS `count`,`object_type` FROM `tag_map` WHERE `tag_id`='" . Dba::escape($this->id) . "'" . $filter_sql . " GROUP BY `object_type`";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[$row['object_type']] = $row['count'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[$row['object_type']] = $row['count'];
+ }
- return $results;
+ return $results;
- } // count
+ } // count
- /**
- * filter_with_prefs
- * This filters the tags based on the users preference
- */
- public static function filter_with_prefs($l) {
+ /**
+ * filter_with_prefs
+ * This filters the tags based on the users preference
+ */
+ public static function filter_with_prefs($l) {
- $colors = array('#0000FF',
- '#00FF00', '#FFFF00', '#00FFFF','#FF00FF','#FF0000');
- $prefs = 'tag company';
-// $prefs = Config::get('tags_userlist');
+ $colors = array('#0000FF',
+ '#00FF00', '#FFFF00', '#00FFFF','#FF00FF','#FF0000');
+ $prefs = 'tag company';
+// $prefs = Config::get('tags_userlist');
- $ulist = explode(' ', $prefs);
- $req = '';
+ $ulist = explode(' ', $prefs);
+ $req = '';
- foreach($ulist as $i) {
- $req .= "'" . Dba::escape($i) . "',";
- }
- $req = rtrim($req, ',');
+ foreach($ulist as $i) {
+ $req .= "'" . Dba::escape($i) . "',";
+ }
+ $req = rtrim($req, ',');
- $sql = 'SELECT `id`,`username` FROM `user` WHERE ';
+ $sql = 'SELECT `id`,`username` FROM `user` WHERE ';
- if ($prefs=='all') {
- $sql .= '1';
- }
- else {
- $sql .= 'username in ('.$req.')';
- }
+ if ($prefs=='all') {
+ $sql .= '1';
+ }
+ else {
+ $sql .= 'username in ('.$req.')';
+ }
- $db_results = Dba::read($sql);
+ $db_results = Dba::read($sql);
- $uids=array();
- $usernames = array();
- $p = 0;
- while ($r = Dba::fetch_assoc($db_results)) {
- $usernames[$r['id']] = $r['username'];
- $uids[$r['id']] = $colors[$p];
- $p++;
- if ($p == sizeof($colors)) {
- $p = 0;
- }
- }
+ $uids=array();
+ $usernames = array();
+ $p = 0;
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $usernames[$r['id']] = $r['username'];
+ $uids[$r['id']] = $colors[$p];
+ $p++;
+ if ($p == sizeof($colors)) {
+ $p = 0;
+ }
+ }
- $res = array();
+ $res = array();
- foreach ($l as $i) {
- if ($GLOBALS['user']->id == $i['user']) {
- $res[] = $i;
- }
- elseif (isset($uids[$i['user']])) {
- $i['color'] = $uids[$i['user']];
- $i['username'] = $usernames[$i['user']];
- $res[] = $i;
- }
- }
+ foreach ($l as $i) {
+ if ($GLOBALS['user']->id == $i['user']) {
+ $res[] = $i;
+ }
+ elseif (isset($uids[$i['user']])) {
+ $i['color'] = $uids[$i['user']];
+ $i['username'] = $usernames[$i['user']];
+ $res[] = $i;
+ }
+ }
- return $res;
+ return $res;
- } // filter_with_prefs
+ } // filter_with_prefs
- /**
- * remove_map
- * This will only remove tag maps for the current user
- */
- public function remove_map($type,$object_id) {
+ /**
+ * remove_map
+ * This will only remove tag maps for the current user
+ */
+ public function remove_map($type,$object_id) {
- if (!self::validate_type($type)) { return false; }
+ if (!self::validate_type($type)) { return false; }
- $type = Dba::escape($type);
- $tag_id = Dba::escape($this->id);
- $object_id = Dba::escape($object_id);
- $user_id = Dba::escape($GLOBALS['user']->id);
+ $type = Dba::escape($type);
+ $tag_id = Dba::escape($this->id);
+ $object_id = Dba::escape($object_id);
+ $user_id = Dba::escape($GLOBALS['user']->id);
- $sql = "DELETE FROM `tag_map` WHERE `tag_id`='$tag_id' AND `object_type`='$type' AND `object_id`='$object_id' AND `user`='$user_id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tag_map` WHERE `tag_id`='$tag_id' AND `object_type`='$type' AND `object_id`='$object_id' AND `user`='$user_id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // remove_map
+ } // remove_map
- /**
- * validate_type
- * This validates the type of the object the user wants to tag, we limit this to types
- * we currently support
- */
- public static function validate_type($type) {
+ /**
+ * validate_type
+ * This validates the type of the object the user wants to tag, we limit this to types
+ * we currently support
+ */
+ public static function validate_type($type) {
- $valid_array = array('song','artist','album','video','playlist','live_stream');
+ $valid_array = array('song','artist','album','video','playlist','live_stream');
- if (in_array($type,$valid_array)) { return $type; }
+ if (in_array($type,$valid_array)) { return $type; }
- return false;
+ return false;
- } // validate_type
+ } // validate_type
- /**
- * clean_tag
- * This takes a string and makes it Tagish
- */
- public static function clean_tag($value) {
+ /**
+ * clean_tag
+ * This takes a string and makes it Tagish
+ */
+ public static function clean_tag($value) {
- $tag = preg_replace("/[^\w\_\-\s\&]/","",$value);
+ $tag = preg_replace("/[^\w\_\-\s\&]/","",$value);
- return $tag;
+ return $tag;
- } // clean_tag
+ } // clean_tag
} // end of Tag class
?>
diff --git a/lib/class/tmp_playlist.class.php b/lib/class/tmp_playlist.class.php
index 129a8d1a..9022c15e 100644
--- a/lib/class/tmp_playlist.class.php
+++ b/lib/class/tmp_playlist.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,345 +30,345 @@
*/
class Tmp_Playlist extends database_object {
- /* Variables from the Datbase */
- public $id;
- public $session;
- public $type;
- public $object_type;
- public $base_playlist;
+ /* Variables from the Datbase */
+ public $id;
+ public $session;
+ public $type;
+ public $object_type;
+ public $base_playlist;
- /* Generated Elements */
- public $items = array();
+ /* Generated Elements */
+ public $items = array();
- /**
- * Constructor
- * This takes a playlist_id as an optional argument and gathers the
- * information. If no playlist_id is passed or the requested one isn't
- * found, return false.
- */
- public function __construct($playlist_id='') {
+ /**
+ * Constructor
+ * This takes a playlist_id as an optional argument and gathers the
+ * information. If no playlist_id is passed or the requested one isn't
+ * found, return false.
+ */
+ public function __construct($playlist_id='') {
- if (!$playlist_id) { return false; }
+ if (!$playlist_id) { return false; }
- $this->id = intval($playlist_id);
- $info = $this->_get_info();
+ $this->id = intval($playlist_id);
+ $info = $this->_get_info();
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
- return true;
+ return true;
- } // __construct
+ } // __construct
- /**
- * _get_info
- * This is an internal (private) function that gathers the information
- * for this object from the playlist_id that was passed in.
- */
- private function _get_info() {
+ /**
+ * _get_info
+ * This is an internal (private) function that gathers the information
+ * for this object from the playlist_id that was passed in.
+ */
+ private function _get_info() {
- $sql = "SELECT * FROM `tmp_playlist` WHERE `id`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `tmp_playlist` WHERE `id`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- return $results;
+ return $results;
- } // _get_info
+ } // _get_info
- /**
- * get_from_session
- * This returns a playlist object based on the session that is passed to
- * us. This is used by the load_playlist on user for the most part.
- */
- public static function get_from_session($session_id) {
+ /**
+ * get_from_session
+ * This returns a playlist object based on the session that is passed to
+ * us. This is used by the load_playlist on user for the most part.
+ */
+ public static function get_from_session($session_id) {
- $session_id = Dba::escape($session_id);
+ $session_id = Dba::escape($session_id);
- $sql = "SELECT `id` FROM `tmp_playlist` WHERE `session`='$session_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `tmp_playlist` WHERE `session`='$session_id'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_row($db_results);
+ $results = Dba::fetch_row($db_results);
- if (!$results['0']) {
- $results['0'] = Tmp_Playlist::create(array(
- 'session_id' => $session_id,
- 'type' => 'user',
- 'object_type' => 'song'
- ));
- }
+ if (!$results['0']) {
+ $results['0'] = Tmp_Playlist::create(array(
+ 'session_id' => $session_id,
+ 'type' => 'user',
+ 'object_type' => 'song'
+ ));
+ }
- $playlist = new Tmp_Playlist($results['0']);
+ $playlist = new Tmp_Playlist($results['0']);
- return $playlist;
+ return $playlist;
- } // get_from_session
+ } // get_from_session
- /**
- * get_from_userid
- * This returns a tmp playlist object based on a userid passed
- * this is used for the user profiles page
- */
- public static function get_from_userid($user_id) {
+ /**
+ * get_from_userid
+ * This returns a tmp playlist object based on a userid passed
+ * this is used for the user profiles page
+ */
+ public static function get_from_userid($user_id) {
- // This is a little stupid, but because we don't have the
- // user_id in the session or in the tmp_playlist table we have
- // to do it this way.
- $client = new User($user_id);
- $username = Dba::escape($client->username);
+ // This is a little stupid, but because we don't have the
+ // user_id in the session or in the tmp_playlist table we have
+ // to do it this way.
+ $client = new User($user_id);
+ $username = Dba::escape($client->username);
- $sql = "SELECT `tmp_playlist`.`id` FROM `tmp_playlist` " .
- "LEFT JOIN `session` ON " .
- "`session`.`id`=`tmp_playlist`.`session` " .
- "WHERE `session`.`username`='$username' " .
- "ORDER BY `session`.`expire` DESC";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `tmp_playlist`.`id` FROM `tmp_playlist` " .
+ "LEFT JOIN `session` ON " .
+ "`session`.`id`=`tmp_playlist`.`session` " .
+ "WHERE `session`.`username`='$username' " .
+ "ORDER BY `session`.`expire` DESC";
+ $db_results = Dba::read($sql);
- $data = Dba::fetch_assoc($db_results);
+ $data = Dba::fetch_assoc($db_results);
- return $data['id'];
+ return $data['id'];
- } // get_from_userid
+ } // get_from_userid
- /**
- * get_items
- * Returns an array of all object_ids currently in this Tmp_Playlist.
- */
- public function get_items() {
+ /**
+ * get_items
+ * Returns an array of all object_ids currently in this Tmp_Playlist.
+ */
+ public function get_items() {
- $id = Dba::escape($this->id);
+ $id = Dba::escape($this->id);
- /* Select all objects from this playlist */
- $sql = "SELECT `object_type`, `id`, `object_id` " .
- "FROM `tmp_playlist_data` " .
- "WHERE `tmp_playlist`='$id' ORDER BY `id` ASC";
- $db_results = Dba::read($sql);
+ /* Select all objects from this playlist */
+ $sql = "SELECT `object_type`, `id`, `object_id` " .
+ "FROM `tmp_playlist_data` " .
+ "WHERE `tmp_playlist`='$id' ORDER BY `id` ASC";
+ $db_results = Dba::read($sql);
- /* Define the array */
- $items = array();
+ /* Define the array */
+ $items = array();
- while ($results = Dba::fetch_assoc($db_results)) {
- $key = $results['id'];
- $items[$key] = array(
- 'object_type' => $results['object_type'],
- 'object_id' => $results['object_id']
- );
- }
+ while ($results = Dba::fetch_assoc($db_results)) {
+ $key = $results['id'];
+ $items[$key] = array(
+ 'object_type' => $results['object_type'],
+ 'object_id' => $results['object_id']
+ );
+ }
- return $items;
+ return $items;
- } // get_items
+ } // get_items
- /**
- * get_next_object
- * This returns the next object in the tmp_playlist.
- */
- public function get_next_object() {
+ /**
+ * get_next_object
+ * This returns the next object in the tmp_playlist.
+ */
+ public function get_next_object() {
- $id = Dba::escape($this->id);
+ $id = Dba::escape($this->id);
- $sql = "SELECT `object_id` FROM `tmp_playlist_data` " .
- "WHERE `tmp_playlist`='$id' ORDER BY `id` LIMIT 1";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `object_id` FROM `tmp_playlist_data` " .
+ "WHERE `tmp_playlist`='$id' ORDER BY `id` LIMIT 1";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $results = Dba::fetch_assoc($db_results);
- return $results['object_id'];
+ return $results['object_id'];
- } // get_next_object
+ } // get_next_object
- /**
- * count_items
- * This returns a count of the total number of tracks that are in this
- * tmp playlist
- */
- public function count_items() {
+ /**
+ * count_items
+ * This returns a count of the total number of tracks that are in this
+ * tmp playlist
+ */
+ public function count_items() {
- $id = Dba::escape($this->id);
+ $id = Dba::escape($this->id);
- $sql = "SELECT COUNT(`id`) FROM `tmp_playlist_data` WHERE " .
- "`tmp_playlist`='$id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT COUNT(`id`) FROM `tmp_playlist_data` WHERE " .
+ "`tmp_playlist`='$id'";
+ $db_results = Dba::read($sql);
- $results = Dba::fetch_row($db_results);
+ $results = Dba::fetch_row($db_results);
- return $results['0'];
+ return $results['0'];
- } // count_items
+ } // count_items
- /**
- * clear
- * This clears all the objects out of a single playlist
- */
- public function clear() {
+ /**
+ * clear
+ * This clears all the objects out of a single playlist
+ */
+ public function clear() {
- $id = Dba::escape($this->id);
+ $id = Dba::escape($this->id);
- $sql = "DELETE FROM `tmp_playlist_data` WHERE " .
- "`tmp_playlist`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tmp_playlist_data` WHERE " .
+ "`tmp_playlist`='$id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // clear
+ } // clear
- /**
- * create
- * This function initializes a new Tmp_Playlist. It is associated with
- * the current session rather than a user, as you could have the same
- * user logged in from multiple locations.
- */
- public static function create($data) {
+ /**
+ * create
+ * This function initializes a new Tmp_Playlist. It is associated with
+ * the current session rather than a user, as you could have the same
+ * user logged in from multiple locations.
+ */
+ public static function create($data) {
- $sessid = Dba::escape($data['session_id']);
- $type = Dba::escape($data['type']);
- $object_type = Dba::escape($data['object_type']);
+ $sessid = Dba::escape($data['session_id']);
+ $type = Dba::escape($data['type']);
+ $object_type = Dba::escape($data['object_type']);
- $sql = "INSERT INTO `tmp_playlist` " .
- "(`session`,`type`,`object_type`) " .
- " VALUES ('$sessid','$type','$object_type')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `tmp_playlist` " .
+ "(`session`,`type`,`object_type`) " .
+ " VALUES ('$sessid','$type','$object_type')";
+ $db_results = Dba::write($sql);
- $id = Dba::insert_id();
+ $id = Dba::insert_id();
- /* Clean any other playlists associated with this session */
- self::session_clean($sessid, $id);
+ /* Clean any other playlists associated with this session */
+ self::session_clean($sessid, $id);
- return $id;
+ return $id;
- } // create
+ } // create
- /**
- * update_playlist
- * This updates the base_playlist on this tmp_playlist
- */
- public function update_playlist($playlist_id) {
+ /**
+ * update_playlist
+ * This updates the base_playlist on this tmp_playlist
+ */
+ public function update_playlist($playlist_id) {
- $playlist_id = Dba::escape($playlist_id);
- $id = Dba::escape($this->id);
+ $playlist_id = Dba::escape($playlist_id);
+ $id = Dba::escape($this->id);
- $sql = "UPDATE `tmp_playlist` SET " .
- "`base_playlist`='$playlist_id' WHERE `id`='$id'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `tmp_playlist` SET " .
+ "`base_playlist`='$playlist_id' WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // update_playlist
+ } // update_playlist
- /**
- * session_clean
- * This deletes any other tmp_playlists associated with this
- * session
- */
- public static function session_clean($sessid, $id) {
+ /**
+ * session_clean
+ * This deletes any other tmp_playlists associated with this
+ * session
+ */
+ public static function session_clean($sessid, $id) {
- $sessid = Dba::escape($sessid);
- $id = Dba::escape($id);
+ $sessid = Dba::escape($sessid);
+ $id = Dba::escape($id);
- $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$sessid' " .
- "AND `id` != '$id'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$sessid' " .
+ "AND `id` != '$id'";
+ $db_results = Dba::write($sql);
- /* Remove associated tracks */
- self::prune_tracks();
+ /* Remove associated tracks */
+ self::prune_tracks();
- return true;
+ return true;
- } // session_clean
+ } // session_clean
- /**
- * gc
- * This cleans up old data
- */
- public static function gc() {
- self::prune_playlists();
- self::prune_tracks();
- Dba::write("DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` LEFT JOIN `song` ON `tmp_playlist_data`.`object_id` = `song`.`id` WHERE `song`.`id` IS NULL");
- }
+ /**
+ * gc
+ * This cleans up old data
+ */
+ public static function gc() {
+ self::prune_playlists();
+ self::prune_tracks();
+ Dba::write("DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` LEFT JOIN `song` ON `tmp_playlist_data`.`object_id` = `song`.`id` WHERE `song`.`id` IS NULL");
+ }
- /**
- * prune_playlists
- * This deletes any playlists that don't have an associated session
- */
- public static function prune_playlists() {
+ /**
+ * prune_playlists
+ * This deletes any playlists that don't have an associated session
+ */
+ public static function prune_playlists() {
- /* Just delete if no matching session row */
- $sql = "DELETE FROM `tmp_playlist` USING `tmp_playlist` " .
- "LEFT JOIN `session` " .
- "ON `session`.`id`=`tmp_playlist`.`session` " .
- "WHERE `session`.`id` IS NULL " .
- "AND `tmp_playlist`.`type` != 'vote'";
- $db_results = Dba::write($sql);
+ /* Just delete if no matching session row */
+ $sql = "DELETE FROM `tmp_playlist` USING `tmp_playlist` " .
+ "LEFT JOIN `session` " .
+ "ON `session`.`id`=`tmp_playlist`.`session` " .
+ "WHERE `session`.`id` IS NULL " .
+ "AND `tmp_playlist`.`type` != 'vote'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // prune_playlists
+ } // prune_playlists
- /**
- * prune_tracks
- * This prunes tracks that don't have playlists or don't have votes
- */
- public static function prune_tracks() {
+ /**
+ * prune_tracks
+ * This prunes tracks that don't have playlists or don't have votes
+ */
+ public static function prune_tracks() {
- // This prune is always run and clears data for playlists that
- // don't exist anymore
- $sql = "DELETE FROM `tmp_playlist_data` USING " .
- "`tmp_playlist_data` LEFT JOIN `tmp_playlist` ON " .
- "`tmp_playlist_data`.`tmp_playlist`=`tmp_playlist`.`id` " .
- "WHERE `tmp_playlist`.`id` IS NULL";
- $db_results = Dba::write($sql);
+ // This prune is always run and clears data for playlists that
+ // don't exist anymore
+ $sql = "DELETE FROM `tmp_playlist_data` USING " .
+ "`tmp_playlist_data` LEFT JOIN `tmp_playlist` ON " .
+ "`tmp_playlist_data`.`tmp_playlist`=`tmp_playlist`.`id` " .
+ "WHERE `tmp_playlist`.`id` IS NULL";
+ $db_results = Dba::write($sql);
- } // prune_tracks
+ } // prune_tracks
- /**
- * add_object
- * This adds the object of $this->object_type to this tmp playlist
- * it takes an optional type, default is song
- */
- public function add_object($object_id,$object_type) {
+ /**
+ * add_object
+ * This adds the object of $this->object_type to this tmp playlist
+ * it takes an optional type, default is song
+ */
+ public function add_object($object_id,$object_type) {
- $object_id = Dba::escape($object_id);
- $playlist_id = Dba::escape($this->id);
- $object_type = $object_type ? Dba::escape($object_type) : 'song';
+ $object_id = Dba::escape($object_id);
+ $playlist_id = Dba::escape($this->id);
+ $object_type = $object_type ? Dba::escape($object_type) : 'song';
- $sql = "INSERT INTO `tmp_playlist_data` " .
- "(`object_id`,`tmp_playlist`,`object_type`) " .
- " VALUES ('$object_id','$playlist_id','$object_type')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `tmp_playlist_data` " .
+ "(`object_id`,`tmp_playlist`,`object_type`) " .
+ " VALUES ('$object_id','$playlist_id','$object_type')";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // add_object
+ } // add_object
- /**
- * vote_active
- * This checks to see if this playlist is a voting playlist
- * and if it is active
- */
- public function vote_active() {
+ /**
+ * vote_active
+ * This checks to see if this playlist is a voting playlist
+ * and if it is active
+ */
+ public function vote_active() {
- /* Going to do a little more here later */
- if ($this->type == 'vote') { return true; }
+ /* Going to do a little more here later */
+ if ($this->type == 'vote') { return true; }
- return false;
+ return false;
- } // vote_active
-
- /**
- * delete_track
- * This deletes a track from the tmpplaylist
- */
- public function delete_track($id) {
+ } // vote_active
+
+ /**
+ * delete_track
+ * This deletes a track from the tmpplaylist
+ */
+ public function delete_track($id) {
- $id = Dba::escape($id);
+ $id = Dba::escape($id);
- /* delete the track its self */
- $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$id'";
- $db_results = Dba::write($sql);
-
- return true;
+ /* delete the track its self */
+ $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
+
+ return true;
- } // delete_track
+ } // delete_track
} // class Tmp_Playlist
diff --git a/lib/class/ui.class.php b/lib/class/ui.class.php
index ae4ec091..ff9ef0cd 100644
--- a/lib/class/ui.class.php
+++ b/lib/class/ui.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -25,281 +25,281 @@
class UI {
- private static $_classes;
- private static $_ticker;
- private static $_icon_cache;
-
- public function __construct($data) {
- return false;
- }
-
- /**
- * access_denied
- *
- * Throw an error when they try to do something naughty.
- */
- public static function access_denied($error = 'Access Denied') {
- // Clear any buffered crap
- ob_end_clean();
- header("HTTP/1.1 403 $error");
- require_once Config::get('prefix') . '/templates/show_denied.inc.php';
- exit;
- }
-
- /**
- * ajax_include
- *
- * Does some trickery with the output buffer to return the output of a
- * template.
- */
- public static function ajax_include($template) {
- ob_start();
- require Config::get('prefix') . '/templates/' . $template;
- $output = ob_get_contents();
- ob_end_clean();
-
- return $output;
- }
-
- /**
- * check_iconv
- *
- * Checks to see whether iconv is available;
- */
- public static function check_iconv() {
- if (function_exists('iconv') && function_exists('iconv_substr')) {
- return true;
- }
- return false;
- }
-
- /**
- * check_ticker
- *
- * Stupid little cutesie thing to ratelimit output of long-running
- * operations.
- */
- public static function check_ticker() {
- if (!isset(self::$_ticker) || (time() > self::$_ticker + 1)) {
- self::$_ticker = time();
- return true;
- }
-
- return false;
- }
-
- /**
- * flip_class
- *
- * First initialised with an array of two class names. Subsequent calls
- * reverse the array then return the first element.
- */
- public static function flip_class($classes = null) {
- if (is_array($classes)) {
- self::$_classes = $array;
- }
- else {
- self::$_classes = array_reverse(self::$_classes);
- }
- return self::$_classes[0];
- }
-
- /**
- * format_bytes
- *
- * Turns a size in bytes into the best human-readable value
- */
- public static function format_bytes($value, $precision = 2) {
- $pass = 0;
- while (strlen(floor($value)) > 3) {
- $value /= 1024;
- $pass++;
- }
-
- switch ($pass) {
- case 1: $unit = 'kB'; break;
- case 2: $unit = 'MB'; break;
- case 3: $unit = 'GB'; break;
- case 4: $unit = 'TB'; break;
- case 5: $unit = 'PB'; break;
- default: $unit = 'B'; break;
- }
-
- return round($value, $precision) . ' ' . $unit;
- }
-
- /**
- * unformat_bytes
- *
- * Parses a human-readable size
- */
- public static function unformat_bytes($value) {
- if (preg_match('/^([0-9]+) *([[:alpha:]]+)$/', $value, $matches)) {
- $value = $matches[1];
- $unit = strtolower(substr($matches[2], 0, 1));
- }
- else {
- return $value;
- }
-
- switch($unit) {
- case 'p':
- $value *= 1024;
- case 't':
- $value *= 1024;
- case 'g':
- $value *= 1024;
- case 'm':
- $value *= 1024;
- case 'k':
- $value *= 1024;
- }
-
- return $value;
- }
-
- /**
- * get_icon
- *
- * Returns an <img> tag for the specified icon
- */
- public static function get_icon($name, $title = null, $id = null) {
- if (is_array($name)) {
- $hover_name = $name[1];
- $name = $name[0];
- }
-
- $title = $title ?: T_(ucfirst($name));
-
- $icon_url = self::_find_icon($name);
- if ($hover_name) {
- $hover_url = self::_find_icon($hover_text);
- }
-
- $tag = '<img src="' . $icon_url . '" ';
-
- if ($id) {
- $tag .= 'id="' . $id . '" ';
- }
-
- $tag .= 'alt="' . $title . '" ';
- $tag .= 'title="' . $title . '" ';
-
- if ($hover_name) {
- $tag .= 'onmouseover="this.src=\'' . $hover_url . '\'; return true;"';
- $tag .= 'onmouseout="this.src=\'' . $icon_url . '\'; return true;" ';
- }
-
- $tag .= '/>';
- return $tag;
- }
-
- /**
- * _find_icon
- *
- * Does the finding icon thing
- */
- private static function _find_icon($name) {
- if ($url = self::$_icon_cache[$name]) {
- return $url;
- }
-
- $filename = 'icon_' . $name . '.png';
- $path = Config::get('theme_path') . '/images/icons/';
- if (!file_exists(Config::get('prefix') . $path . $filename)) {
- $path = '/images/';
- }
- $url = Config::get('web_path') . $path . $filename;
- self::$_icon_cache[$name] = $url;
-
- return $url;
- }
-
-
- /**
- * show_header
- *
- * For now this just shows the header template
- */
- public static function show_header() {
- require_once Config::get('prefix') . '/templates/header.inc.php';
- }
-
- /**
- * show_footer
- *
- * Shows the footer template and possibly profiling info.
- */
- public static function show_footer() {
- require_once Config::get('prefix') . '/templates/footer.inc.php';
- if (isset($_REQUEST['profiling'])) {
- Dba::show_profile();
- }
- }
-
- /**
- * show_box_top
- *
- * This shows the top of the box.
- */
- public static function show_box_top($title = '', $class = '') {
- require Config::get('prefix') . '/templates/show_box_top.inc.php';
- }
-
- /**
- * show_box_bottom
- *
- * This shows the bottom of the box
- */
- public static function show_box_bottom() {
- require Config::get('prefix') . '/templates/show_box_bottom.inc.php';
- }
-
- /**
- * truncate
- *
- * Limit text to a certain length; adds an ellipsis if truncation was
- * required.
- */
- public static function truncate($text, $max = 27) {
- // If they want <3, we're having none of that
- if ($max <= 3) {
- debug_event('UI', "truncate called with $max, refusing to do stupid things to $text", 2);
- return $text;
- }
-
- if (self::check_iconv()) {
- $charset = Config::get('site_charset');
- if (iconv_strlen($text, $charset) > $max) {
- $text = iconv_substr($text, 0, $max - 3, $charset);
- $text .= iconv('ISO-8859-1', $charset, '...');
- }
- }
- else {
- if (strlen($text) > $max) {
- $text = substr($text, 0, $max - 3) . '...';
- }
- }
-
- return $text;
- }
-
- /**
- * update_text
- *
- * Convenience function that, if the output is going to a browser,
- * blarfs JS to do a fancy update. Otherwise it just outputs the text.
- */
- public static function update_text($field, $value) {
- if (defined('CLI')) {
- echo $value . "\n";
- return;
- }
-
- echo '<script type="text/javascript">';
- echo "updateText('$field', '$value');";
- echo "</script>\n";
- ob_flush();
- flush();
- }
+ private static $_classes;
+ private static $_ticker;
+ private static $_icon_cache;
+
+ public function __construct($data) {
+ return false;
+ }
+
+ /**
+ * access_denied
+ *
+ * Throw an error when they try to do something naughty.
+ */
+ public static function access_denied($error = 'Access Denied') {
+ // Clear any buffered crap
+ ob_end_clean();
+ header("HTTP/1.1 403 $error");
+ require_once Config::get('prefix') . '/templates/show_denied.inc.php';
+ exit;
+ }
+
+ /**
+ * ajax_include
+ *
+ * Does some trickery with the output buffer to return the output of a
+ * template.
+ */
+ public static function ajax_include($template) {
+ ob_start();
+ require Config::get('prefix') . '/templates/' . $template;
+ $output = ob_get_contents();
+ ob_end_clean();
+
+ return $output;
+ }
+
+ /**
+ * check_iconv
+ *
+ * Checks to see whether iconv is available;
+ */
+ public static function check_iconv() {
+ if (function_exists('iconv') && function_exists('iconv_substr')) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * check_ticker
+ *
+ * Stupid little cutesie thing to ratelimit output of long-running
+ * operations.
+ */
+ public static function check_ticker() {
+ if (!isset(self::$_ticker) || (time() > self::$_ticker + 1)) {
+ self::$_ticker = time();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * flip_class
+ *
+ * First initialised with an array of two class names. Subsequent calls
+ * reverse the array then return the first element.
+ */
+ public static function flip_class($classes = null) {
+ if (is_array($classes)) {
+ self::$_classes = $array;
+ }
+ else {
+ self::$_classes = array_reverse(self::$_classes);
+ }
+ return self::$_classes[0];
+ }
+
+ /**
+ * format_bytes
+ *
+ * Turns a size in bytes into the best human-readable value
+ */
+ public static function format_bytes($value, $precision = 2) {
+ $pass = 0;
+ while (strlen(floor($value)) > 3) {
+ $value /= 1024;
+ $pass++;
+ }
+
+ switch ($pass) {
+ case 1: $unit = 'kB'; break;
+ case 2: $unit = 'MB'; break;
+ case 3: $unit = 'GB'; break;
+ case 4: $unit = 'TB'; break;
+ case 5: $unit = 'PB'; break;
+ default: $unit = 'B'; break;
+ }
+
+ return round($value, $precision) . ' ' . $unit;
+ }
+
+ /**
+ * unformat_bytes
+ *
+ * Parses a human-readable size
+ */
+ public static function unformat_bytes($value) {
+ if (preg_match('/^([0-9]+) *([[:alpha:]]+)$/', $value, $matches)) {
+ $value = $matches[1];
+ $unit = strtolower(substr($matches[2], 0, 1));
+ }
+ else {
+ return $value;
+ }
+
+ switch($unit) {
+ case 'p':
+ $value *= 1024;
+ case 't':
+ $value *= 1024;
+ case 'g':
+ $value *= 1024;
+ case 'm':
+ $value *= 1024;
+ case 'k':
+ $value *= 1024;
+ }
+
+ return $value;
+ }
+
+ /**
+ * get_icon
+ *
+ * Returns an <img> tag for the specified icon
+ */
+ public static function get_icon($name, $title = null, $id = null) {
+ if (is_array($name)) {
+ $hover_name = $name[1];
+ $name = $name[0];
+ }
+
+ $title = $title ?: T_(ucfirst($name));
+
+ $icon_url = self::_find_icon($name);
+ if ($hover_name) {
+ $hover_url = self::_find_icon($hover_text);
+ }
+
+ $tag = '<img src="' . $icon_url . '" ';
+
+ if ($id) {
+ $tag .= 'id="' . $id . '" ';
+ }
+
+ $tag .= 'alt="' . $title . '" ';
+ $tag .= 'title="' . $title . '" ';
+
+ if ($hover_name) {
+ $tag .= 'onmouseover="this.src=\'' . $hover_url . '\'; return true;"';
+ $tag .= 'onmouseout="this.src=\'' . $icon_url . '\'; return true;" ';
+ }
+
+ $tag .= '/>';
+ return $tag;
+ }
+
+ /**
+ * _find_icon
+ *
+ * Does the finding icon thing
+ */
+ private static function _find_icon($name) {
+ if ($url = self::$_icon_cache[$name]) {
+ return $url;
+ }
+
+ $filename = 'icon_' . $name . '.png';
+ $path = Config::get('theme_path') . '/images/icons/';
+ if (!file_exists(Config::get('prefix') . $path . $filename)) {
+ $path = '/images/';
+ }
+ $url = Config::get('web_path') . $path . $filename;
+ self::$_icon_cache[$name] = $url;
+
+ return $url;
+ }
+
+
+ /**
+ * show_header
+ *
+ * For now this just shows the header template
+ */
+ public static function show_header() {
+ require_once Config::get('prefix') . '/templates/header.inc.php';
+ }
+
+ /**
+ * show_footer
+ *
+ * Shows the footer template and possibly profiling info.
+ */
+ public static function show_footer() {
+ require_once Config::get('prefix') . '/templates/footer.inc.php';
+ if (isset($_REQUEST['profiling'])) {
+ Dba::show_profile();
+ }
+ }
+
+ /**
+ * show_box_top
+ *
+ * This shows the top of the box.
+ */
+ public static function show_box_top($title = '', $class = '') {
+ require Config::get('prefix') . '/templates/show_box_top.inc.php';
+ }
+
+ /**
+ * show_box_bottom
+ *
+ * This shows the bottom of the box
+ */
+ public static function show_box_bottom() {
+ require Config::get('prefix') . '/templates/show_box_bottom.inc.php';
+ }
+
+ /**
+ * truncate
+ *
+ * Limit text to a certain length; adds an ellipsis if truncation was
+ * required.
+ */
+ public static function truncate($text, $max = 27) {
+ // If they want <3, we're having none of that
+ if ($max <= 3) {
+ debug_event('UI', "truncate called with $max, refusing to do stupid things to $text", 2);
+ return $text;
+ }
+
+ if (self::check_iconv()) {
+ $charset = Config::get('site_charset');
+ if (iconv_strlen($text, $charset) > $max) {
+ $text = iconv_substr($text, 0, $max - 3, $charset);
+ $text .= iconv('ISO-8859-1', $charset, '...');
+ }
+ }
+ else {
+ if (strlen($text) > $max) {
+ $text = substr($text, 0, $max - 3) . '...';
+ }
+ }
+
+ return $text;
+ }
+
+ /**
+ * update_text
+ *
+ * Convenience function that, if the output is going to a browser,
+ * blarfs JS to do a fancy update. Otherwise it just outputs the text.
+ */
+ public static function update_text($field, $value) {
+ if (defined('CLI')) {
+ echo $value . "\n";
+ return;
+ }
+
+ echo '<script type="text/javascript">';
+ echo "updateText('$field', '$value');";
+ echo "</script>\n";
+ ob_flush();
+ flush();
+ }
}
diff --git a/lib/class/update.class.php b/lib/class/update.class.php
index 0e7ce44c..bfaefc65 100644
--- a/lib/class/update.class.php
+++ b/lib/class/update.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -41,2068 +41,2068 @@
*/
class Update {
- public $key;
- public $value;
- public static $versions; // array containing version information
+ public $key;
+ public $value;
+ public static $versions; // array containing version information
- /**
- * Update
- * Constructor, pulls out information about the desired key
- */
- function Update ( $key=0 ) {
+ /**
+ * Update
+ * Constructor, pulls out information about the desired key
+ */
+ function Update ( $key=0 ) {
- if (!$key) { return false; }
+ if (!$key) { return false; }
- $this->key = intval($key);
- $info = $this->_get_info();
- $this->value = $info['value'];
- $this->versions = $this->populate_version();
+ $this->key = intval($key);
+ $info = $this->_get_info();
+ $this->value = $info['value'];
+ $this->versions = $this->populate_version();
- } // constructor
+ } // constructor
- /**
- * _get_info
- * gets the information for the zone
- */
- private function _get_info() {
+ /**
+ * _get_info
+ * gets the information for the zone
+ */
+ private function _get_info() {
- $sql = "SELECT * FROM `update_info` WHERE `key`='$this->key'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `update_info` WHERE `key`='$this->key'";
+ $db_results = Dba::read($sql);
- return Dba::fetch_assoc($db_results);
+ return Dba::fetch_assoc($db_results);
- } // _get_info
+ } // _get_info
- /**
- * get_version
- * this checks to see what version you are currently running
- * because we may not have the update_info table we have to check
- * for it's existance first.
- */
- public static function get_version() {
+ /**
+ * get_version
+ * this checks to see what version you are currently running
+ * because we may not have the update_info table we have to check
+ * for it's existance first.
+ */
+ public static function get_version() {
- /* Make sure that update_info exits */
- $sql = "SHOW TABLES LIKE 'update_info'";
- $db_results = Dba::read($sql);
- if (!is_resource(Dba::dbh())) { header("Location: test.php"); }
+ /* Make sure that update_info exits */
+ $sql = "SHOW TABLES LIKE 'update_info'";
+ $db_results = Dba::read($sql);
+ if (!is_resource(Dba::dbh())) { header("Location: test.php"); }
- // If no table
- if (!Dba::num_rows($db_results)) {
- // They can't upgrade, they are too old
- header("Location: test.php");
+ // If no table
+ if (!Dba::num_rows($db_results)) {
+ // They can't upgrade, they are too old
+ header("Location: test.php");
- } // if table isn't found
+ } // if table isn't found
- else {
- // If we've found the update_info table, let's get the version from it
- $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'";
- $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
- $version = $results['value'];
- }
+ else {
+ // If we've found the update_info table, let's get the version from it
+ $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'";
+ $db_results = Dba::read($sql);
+ $results = Dba::fetch_assoc($db_results);
+ $version = $results['value'];
+ }
- return $version;
+ return $version;
- } // get_version
+ } // get_version
- /**
- * format_version
- * make the version number pretty
- */
- public static function format_version($data) {
+ /**
+ * format_version
+ * make the version number pretty
+ */
+ public static function format_version($data) {
- $new_version = substr($data,0,strlen($data) - 5) . "." . substr($data,strlen($data)-5,1) . " Build:" .
- substr($data,strlen($data)-4,strlen($data));
+ $new_version = substr($data,0,strlen($data) - 5) . "." . substr($data,strlen($data)-5,1) . " Build:" .
+ substr($data,strlen($data)-4,strlen($data));
- return $new_version;
+ return $new_version;
- } // format_version
+ } // format_version
- /**
- * need_update
- * checks to see if we need to update
- * ampache at all
- */
- public static function need_update() {
+ /**
+ * need_update
+ * checks to see if we need to update
+ * ampache at all
+ */
+ public static function need_update() {
- $current_version = self::get_version();
+ $current_version = self::get_version();
- if (!is_array(self::$versions)) {
- self::$versions = self::populate_version();
- }
+ if (!is_array(self::$versions)) {
+ self::$versions = self::populate_version();
+ }
- /*
- Go through the versions we have and see if
- we need to apply any updates
- */
- foreach (self::$versions as $update) {
- if ($update['version'] > $current_version) {
- return true;
- }
+ /*
+ Go through the versions we have and see if
+ we need to apply any updates
+ */
+ foreach (self::$versions as $update) {
+ if ($update['version'] > $current_version) {
+ return true;
+ }
- } // end foreach version
+ } // end foreach version
- return false;
+ return false;
- } // need_update
+ } // need_update
- /**
- * plugins_installed
- * This function checks to make sure that there are no plugins
- * installed before allowing you to run the update. this is
- * to protect the integrity of the database
- */
- public static function plugins_installed() {
+ /**
+ * plugins_installed
+ * This function checks to make sure that there are no plugins
+ * installed before allowing you to run the update. this is
+ * to protect the integrity of the database
+ */
+ public static function plugins_installed() {
- /* Pull all version info */
- $sql = "SELECT * FROM `update_info`";
- $db_results = Dba::read($sql);
+ /* Pull all version info */
+ $sql = "SELECT * FROM `update_info`";
+ $db_results = Dba::read($sql);
- while ($results = Dba::fetch_assoc($db_results)) {
+ while ($results = Dba::fetch_assoc($db_results)) {
- /* We have only one allowed string */
- if ($results['key'] != 'db_version') {
- return false;
- }
+ /* We have only one allowed string */
+ if ($results['key'] != 'db_version') {
+ return false;
+ }
- } // while update_info results
+ } // while update_info results
- return true;
+ return true;
- } // plugins_installed
+ } // plugins_installed
- /**
- * populate_version
- * just sets an array the current differences
- * that require an update
- */
- public static function populate_version() {
+ /**
+ * populate_version
+ * just sets an array the current differences
+ * that require an update
+ */
+ public static function populate_version() {
- /* Define the array */
- $version = array();
+ /* Define the array */
+ $version = array();
- $update_string = '- Moved back to ID for user tracking internally.<br />' .
- '- Added date to user_vote to allow sorting by vote time.<br />' .
- '- Added Random Method and Object Count Preferences.<br />' .
- '- Removed some unused tables/fields.<br />' .
- '- Added Label, Catalog # and Language to Extended Song Data Table.';
+ $update_string = '- Moved back to ID for user tracking internally.<br />' .
+ '- Added date to user_vote to allow sorting by vote time.<br />' .
+ '- Added Random Method and Object Count Preferences.<br />' .
+ '- Removed some unused tables/fields.<br />' .
+ '- Added Label, Catalog # and Language to Extended Song Data Table.';
- $version[] = array('version' => '340001','description' => $update_string);
+ $version[] = array('version' => '340001','description' => $update_string);
- $update_string = '- Added Offset Limit to Preferences and removed from user table.';
+ $update_string = '- Added Offset Limit to Preferences and removed from user table.';
- $version[] = array('version' => '340002','description' => $update_string);
+ $version[] = array('version' => '340002','description' => $update_string);
- $update_string = '- Moved Art from the Album table into album_data to improve performance.<br />' .
- '- Made some minor changes to song table to reduce size of each row.<br />' .
- '- Moved song_ext_data to song_data to match album_data pattern.<br />' .
- '- Added Playlist Method and Rate Limit Preferences.<br />' .
- '- Renamed preferences and ratings to preference and rating to fit table pattern.<br />' .
- '- Fixed rating table, renamed user_rating to rating and switched 00 for -1.<br />';
+ $update_string = '- Moved Art from the Album table into album_data to improve performance.<br />' .
+ '- Made some minor changes to song table to reduce size of each row.<br />' .
+ '- Moved song_ext_data to song_data to match album_data pattern.<br />' .
+ '- Added Playlist Method and Rate Limit Preferences.<br />' .
+ '- Renamed preferences and ratings to preference and rating to fit table pattern.<br />' .
+ '- Fixed rating table, renamed user_rating to rating and switched 00 for -1.<br />';
- $version[] = array('version' => '340003','description' => $update_string);
+ $version[] = array('version' => '340003','description' => $update_string);
- $update_string = '- Alter the Session.id to be VARCHAR(64) to account for all potential configs.<br />' .
- '- Added new user_shout table for Sticky objects / shoutbox.<br />' .
- '- Added new playlist preferences, and new preference catagory of playlist.<br />' .
- '- Tweaked Now Playing Table.<br />';
+ $update_string = '- Alter the Session.id to be VARCHAR(64) to account for all potential configs.<br />' .
+ '- Added new user_shout table for Sticky objects / shoutbox.<br />' .
+ '- Added new playlist preferences, and new preference catagory of playlist.<br />' .
+ '- Tweaked Now Playing Table.<br />';
- $version[] = array('version' => '340004','description' => $update_string);
+ $version[] = array('version' => '340004','description' => $update_string);
- $update_string = '- Altered Ratings table so the fields make more sense.<br />' .
- '- Moved Random Method to Playlist catagory.<br />' .
- '- Added Transcode Method to Streaming.<br />';
+ $update_string = '- Altered Ratings table so the fields make more sense.<br />' .
+ '- Moved Random Method to Playlist catagory.<br />' .
+ '- Added Transcode Method to Streaming.<br />';
- $version[] = array('version' => '340005','description' => $update_string);
+ $version[] = array('version' => '340005','description' => $update_string);
- $update_string = '- Remove Random Method config option, ended up being useless.<br />' .
- '- Check and change album_data.art to a MEDIUMBLOB if needed.<br />';
+ $update_string = '- Remove Random Method config option, ended up being useless.<br />' .
+ '- Check and change album_data.art to a MEDIUMBLOB if needed.<br />';
- $version[] = array('version' => '340006','description' => $update_string);
+ $version[] = array('version' => '340006','description' => $update_string);
- $update_string = '- Added new session_stream table for sessions tied directly to stream instances.<br />' .
- '- Altered the session table, making value a LONGTEXT.<br />';
+ $update_string = '- Added new session_stream table for sessions tied directly to stream instances.<br />' .
+ '- Altered the session table, making value a LONGTEXT.<br />';
- $version[] = array('version' => '340007','description' => $update_string);
+ $version[] = array('version' => '340007','description' => $update_string);
- $update_string = '- Modified Playlist_Data table to account for multiple object types.<br />' .
- '- Verified previous updates, adjusting as needed.<br />' .
- '- Dropped Allow Downsampling pref, configured in cfg file.<br />' .
- '- Renamed Downsample Rate --> Transcode Rate to reflect new terminiology.<br />';
+ $update_string = '- Modified Playlist_Data table to account for multiple object types.<br />' .
+ '- Verified previous updates, adjusting as needed.<br />' .
+ '- Dropped Allow Downsampling pref, configured in cfg file.<br />' .
+ '- Renamed Downsample Rate --> Transcode Rate to reflect new terminiology.<br />';
- $version[] = array('version' => '340008','description' => $update_string);
+ $version[] = array('version' => '340008','description' => $update_string);
- $update_string = '- Added disk to Album table.<br />' .
- '- Added artist_data for artist images and bios.<br />' .
- '- Added DNS to access list to allow for dns based ACLs.<br />';
+ $update_string = '- Added disk to Album table.<br />' .
+ '- Added artist_data for artist images and bios.<br />' .
+ '- Added DNS to access list to allow for dns based ACLs.<br />';
- $version[] = array('version' => '340009','description' => $update_string);
+ $version[] = array('version' => '340009','description' => $update_string);
- $update_string = '- Removed Playlist Add preference.<br />' .
- '- Moved Localplay* preferences to options.<br />' .
- '- Tweaked Default Playlist Method.<br />' .
- '- Change wording on Localplay preferences.<br />';
- $version[] = array('version' => '340010','description'=>$update_string);
+ $update_string = '- Removed Playlist Add preference.<br />' .
+ '- Moved Localplay* preferences to options.<br />' .
+ '- Tweaked Default Playlist Method.<br />' .
+ '- Change wording on Localplay preferences.<br />';
+ $version[] = array('version' => '340010','description'=>$update_string);
- $update_string = '- Added api session table, will eventually recombine with others.<br />';
+ $update_string = '- Added api session table, will eventually recombine with others.<br />';
- $version[] = array('version' => '340011','description'=>$update_string);
+ $version[] = array('version' => '340011','description'=>$update_string);
- $update_string = '- Added Democratic Table for new democratic play features.<br />' .
- '- Added Add Path to Catalog to improve add speeds on large catalogs.<br />';
+ $update_string = '- Added Democratic Table for new democratic play features.<br />' .
+ '- Added Add Path to Catalog to improve add speeds on large catalogs.<br />';
- $version[] = array('version' => '340012','description'=>$update_string);
+ $version[] = array('version' => '340012','description'=>$update_string);
- $update_string = '- Removed Unused Preferences.<br />' .
- '- Changed Localplay Config to Localplay Access.<br />' .
- '- Changed all XML-RPC acls to RPC to reflect inclusion of new API.<br />';
+ $update_string = '- Removed Unused Preferences.<br />' .
+ '- Changed Localplay Config to Localplay Access.<br />' .
+ '- Changed all XML-RPC acls to RPC to reflect inclusion of new API.<br />';
- $version[] = array('version' => '340013','description'=>$update_string);
+ $version[] = array('version' => '340013','description'=>$update_string);
- $update_string = '- Removed API Session table, been a nice run....<br />' .
- '- Alterted Session table to handle API sessions correctly.<br />';
+ $update_string = '- Removed API Session table, been a nice run....<br />' .
+ '- Alterted Session table to handle API sessions correctly.<br />';
- $version[] = array('version' => '340014','description'=>$update_string);
+ $version[] = array('version' => '340014','description'=>$update_string);
- $update_string = '- Alter Playlist Date Field to fix issues with some MySQL configurations.<br />' .
- '- Alter Rating type to correct AVG issue on searching.<br />';
+ $update_string = '- Alter Playlist Date Field to fix issues with some MySQL configurations.<br />' .
+ '- Alter Rating type to correct AVG issue on searching.<br />';
- $version[] = array('version' => '340015','description'=>$update_string);
+ $version[] = array('version' => '340015','description'=>$update_string);
- $update_string = '- Alter the Democratic Playlist table, adding base_playlist.<br />' .
- '- Alter tmp_playlist to account for Democratic changes.<br />' .
- '- Cleared Existing Democratic playlists due to changes.<br />';
+ $update_string = '- Alter the Democratic Playlist table, adding base_playlist.<br />' .
+ '- Alter tmp_playlist to account for Democratic changes.<br />' .
+ '- Cleared Existing Democratic playlists due to changes.<br />';
- $version[] = array('version' => '340016','description'=>$update_string);
+ $version[] = array('version' => '340016','description'=>$update_string);
- $update_string = '- Fix Tables for new Democratic Play methodology.<br />';
+ $update_string = '- Fix Tables for new Democratic Play methodology.<br />';
- $version[] = array('version' => '340017','description'=>$update_string);
+ $version[] = array('version' => '340017','description'=>$update_string);
- $update_string = '- Attempt to detect and correct charset issues between filesystem and database.<br />';
+ $update_string = '- Attempt to detect and correct charset issues between filesystem and database.<br />';
- $version[] = array('version' => '340018','description'=>$update_string);
+ $version[] = array('version' => '340018','description'=>$update_string);
- $update_string = '- Modify the Tag tables so that they actually work.<br />' .
- '- Alter the Prefix fields to allow for more prefixs.<br />';
+ $update_string = '- Modify the Tag tables so that they actually work.<br />' .
+ '- Alter the Prefix fields to allow for more prefixs.<br />';
- $version[] = array('version' => '350001','description'=>$update_string);
+ $version[] = array('version' => '350001','description'=>$update_string);
- $update_string = '- Remove Genre Field from song table.<br />' .
- '- Add user_catalog table for tracking user<-->catalog mappings.<br />' .
- '- Add tmp_browse to handle caching rather then session table.<br />';
+ $update_string = '- Remove Genre Field from song table.<br />' .
+ '- Add user_catalog table for tracking user<-->catalog mappings.<br />' .
+ '- Add tmp_browse to handle caching rather then session table.<br />';
- $version[] = array('version' => '350002','description'=>$update_string);
+ $version[] = array('version' => '350002','description'=>$update_string);
- $update_string = '- Modify Tag tables.<br />' .
- '- Remove useless config preferences.<br />';
+ $update_string = '- Modify Tag tables.<br />' .
+ '- Remove useless config preferences.<br />';
- $version[] = array('version'=> '350003','description'=>$update_string);
+ $version[] = array('version'=> '350003','description'=>$update_string);
- $update_string = '- Modify ACL table to enable IPv6 ACL support<br />' .
- '- Modify Session Tables to store IPv6 addresses if provided<br />' .
- '- Modify IP History table to store IPv6 addresses and User Agent<br />';
+ $update_string = '- Modify ACL table to enable IPv6 ACL support<br />' .
+ '- Modify Session Tables to store IPv6 addresses if provided<br />' .
+ '- Modify IP History table to store IPv6 addresses and User Agent<br />';
- $version[] = array('version'=>'350004','description'=>$update_string);
+ $version[] = array('version'=>'350004','description'=>$update_string);
- $update_string = "- Add table for Video files<br />";
+ $update_string = "- Add table for Video files<br />";
- $version[] = array('version'=>'350005','description'=>$update_string);
+ $version[] = array('version'=>'350005','description'=>$update_string);
- $update_string = "- Add data for Lyrics<br />";
+ $update_string = "- Add data for Lyrics<br />";
- $version[] = array('version'=>'350006','description'=>$update_string);
+ $version[] = array('version'=>'350006','description'=>$update_string);
- $update_string = '- Remove unused fields from catalog, playlist, playlist_data<br />' .
- '- Add tables for dynamic playlists<br />' .
- '- Add last_clean to catalog table<br />' .
- '- Add track to tmp_playlist_data<br />' .
- '- Increase Thumbnail blob size<br />';
+ $update_string = '- Remove unused fields from catalog, playlist, playlist_data<br />' .
+ '- Add tables for dynamic playlists<br />' .
+ '- Add last_clean to catalog table<br />' .
+ '- Add track to tmp_playlist_data<br />' .
+ '- Increase Thumbnail blob size<br />';
- $version[] = array('version'=>'350007','description'=>$update_string);
+ $version[] = array('version'=>'350007','description'=>$update_string);
- $update_string = '- Modify Now Playing table to handle Videos<br />' .
- '- Modify tmp_browse to make it easier to prune<br />' .
- '- Add missing indexes to the _data tables<br />' .
- '- Drop unused song.hash<br />' .
- '- Add addition_time and update_time to video table<br />';
+ $update_string = '- Modify Now Playing table to handle Videos<br />' .
+ '- Modify tmp_browse to make it easier to prune<br />' .
+ '- Add missing indexes to the _data tables<br />' .
+ '- Drop unused song.hash<br />' .
+ '- Add addition_time and update_time to video table<br />';
- $version[] = array('version'=>'350008','description'=>$update_string);
+ $version[] = array('version'=>'350008','description'=>$update_string);
- $update_string = '- Add MBID (MusicBrainz ID) fields<br />' .
- '- Remove useless preferences<br />';
+ $update_string = '- Add MBID (MusicBrainz ID) fields<br />' .
+ '- Remove useless preferences<br />';
- $version[] = array('version'=>'360001','description'=>$update_string);
+ $version[] = array('version'=>'360001','description'=>$update_string);
- $update_string = '- Add Bandwidth and Feature preferences to simplify how interface is presented<br />' .
- '- Change Tables to FULLTEXT() for improved searching<br />' .
- '- Increase Filename lengths to 4096<br />' .
- '- Remove useless "KEY" reference from ACL and Catalog tables<br />' .
- '- Add new Remote User / Remote Password fields to Catalog<br />';
+ $update_string = '- Add Bandwidth and Feature preferences to simplify how interface is presented<br />' .
+ '- Change Tables to FULLTEXT() for improved searching<br />' .
+ '- Increase Filename lengths to 4096<br />' .
+ '- Remove useless "KEY" reference from ACL and Catalog tables<br />' .
+ '- Add new Remote User / Remote Password fields to Catalog<br />';
- $version[] = array('version'=>'360002','description'=>$update_string);
+ $version[] = array('version'=>'360002','description'=>$update_string);
- $update_string = '- Add image table to store images.<br />' .
- '- Drop album_data and artist_data.<br />';
- $version[] = array('version'=>'360003','description'=>$update_string);
+ $update_string = '- Add image table to store images.<br />' .
+ '- Drop album_data and artist_data.<br />';
+ $version[] = array('version'=>'360003','description'=>$update_string);
- $update_string = '- Add uniqueness constraint to ratings.<br />';
- $version[] = array('version' => '360004','description' => $update_string);
+ $update_string = '- Add uniqueness constraint to ratings.<br />';
+ $version[] = array('version' => '360004','description' => $update_string);
- $update_string = '- Modify tmp_browse to allow caching of multiple browses per session.<br />';
- $version[] = array('version' => '360005','description' => $update_string);
+ $update_string = '- Modify tmp_browse to allow caching of multiple browses per session.<br />';
+ $version[] = array('version' => '360005','description' => $update_string);
- $update_string = '- Add table for dynamic playlists.<br />';
- $version[] = array('version' => '360006','description' => $update_string);
+ $update_string = '- Add table for dynamic playlists.<br />';
+ $version[] = array('version' => '360006','description' => $update_string);
- $update_string = '- Add local auth method to session.type.<br />';
- $version[] = array('version' => '360007','description' => $update_string);
+ $update_string = '- Add local auth method to session.type.<br />';
+ $version[] = array('version' => '360007','description' => $update_string);
- $update_string = '- Verify remote_username and remote_password were added correctly to catalog table.<br />';
- $version[] = array('version' => '360008','description' => $update_string);
+ $update_string = '- Verify remote_username and remote_password were added correctly to catalog table.<br />';
+ $version[] = array('version' => '360008','description' => $update_string);
- $update_string = '- Allow long sessionids in tmp_playlist table.<br />';
- $version[] = array('version' => '360009', 'description' => $update_string);
+ $update_string = '- Allow long sessionids in tmp_playlist table.<br />';
+ $version[] = array('version' => '360009', 'description' => $update_string);
- $update_string = '- Allow compound MBIDs in the artist table.<br />';
- $version[] = array('version' => '360010', 'description' => $update_string);
+ $update_string = '- Allow compound MBIDs in the artist table.<br />';
+ $version[] = array('version' => '360010', 'description' => $update_string);
- $update_string = '- Add table to store stream session playlist.<br />';
- $version[] = array('version' => '360011', 'description' => $update_string);
+ $update_string = '- Add table to store stream session playlist.<br />';
+ $version[] = array('version' => '360011', 'description' => $update_string);
- return $version;
+ return $version;
- } // populate_version
+ } // populate_version
- /**
- * display_update
- * This displays a list of the needed
- * updates to the database. This will actually
- * echo out the list...
- */
- public static function display_update() {
+ /**
+ * display_update
+ * This displays a list of the needed
+ * updates to the database. This will actually
+ * echo out the list...
+ */
+ public static function display_update() {
- $current_version = self::get_version();
- if (!is_array(self::$versions)) {
- self::$versions = self::populate_version();
- }
- $update_needed = false;
+ $current_version = self::get_version();
+ if (!is_array(self::$versions)) {
+ self::$versions = self::populate_version();
+ }
+ $update_needed = false;
- if (!defined('CLI')) { echo "<ul>\n"; }
+ if (!defined('CLI')) { echo "<ul>\n"; }
- foreach (self::$versions as $update) {
+ foreach (self::$versions as $update) {
- if ($update['version'] > $current_version) {
- $update_needed = true;
- if (!defined('CLI')) { echo '<li><b>'; }
- echo 'Version: ', self::format_version($update['version']);
- if (defined('CLI')) {
- echo "\n", str_replace('<br />', "\n", $update['description']), "\n";
- }
- else {
- echo '</b><br />', $update['description'], "<br /></li>\n";
- }
- } // if newer
+ if ($update['version'] > $current_version) {
+ $update_needed = true;
+ if (!defined('CLI')) { echo '<li><b>'; }
+ echo 'Version: ', self::format_version($update['version']);
+ if (defined('CLI')) {
+ echo "\n", str_replace('<br />', "\n", $update['description']), "\n";
+ }
+ else {
+ echo '</b><br />', $update['description'], "<br /></li>\n";
+ }
+ } // if newer
- } // foreach versions
+ } // foreach versions
- if (!defined('CLI')) { echo "</ul>\n"; }
+ if (!defined('CLI')) { echo "</ul>\n"; }
- if (!$update_needed) {
- if (!defined('CLI')) { echo '<p align="center">'; }
- echo T_('No updates needed.');
- if (!defined('CLI')) {
- echo '[<a href="', Config::get('web_path'), '">Return</a>]</p>';
- }
- else {
- echo "\n";
- }
- }
- } // display_update
+ if (!$update_needed) {
+ if (!defined('CLI')) { echo '<p align="center">'; }
+ echo T_('No updates needed.');
+ if (!defined('CLI')) {
+ echo '[<a href="', Config::get('web_path'), '">Return</a>]</p>';
+ }
+ else {
+ echo "\n";
+ }
+ }
+ } // display_update
- /**
- * run_update
- * This function actually updates the db.
- * it goes through versions and finds the ones
- * that need to be run. Checking to make sure
- * the function exists first.
- */
- public static function run_update() {
+ /**
+ * run_update
+ * This function actually updates the db.
+ * it goes through versions and finds the ones
+ * that need to be run. Checking to make sure
+ * the function exists first.
+ */
+ public static function run_update() {
- /* Nuke All Active session before we start the mojo */
- $sql = "TRUNCATE session";
- $db_results = Dba::write($sql);
-
- // Prevent the script from timing out, which could be bad
- set_time_limit(0);
-
- /* Verify that there are no plugins installed
- //FIXME: provide a link to remove all plugins, otherwise this could turn into a catch 22
- if (!$self::plugins_installed()) {
- $GLOBALS['error']->add_error('general', T_('Plugins detected, please remove all Plugins and try again'));
- return false;
- } */
-
- $methods = array();
+ /* Nuke All Active session before we start the mojo */
+ $sql = "TRUNCATE session";
+ $db_results = Dba::write($sql);
+
+ // Prevent the script from timing out, which could be bad
+ set_time_limit(0);
+
+ /* Verify that there are no plugins installed
+ //FIXME: provide a link to remove all plugins, otherwise this could turn into a catch 22
+ if (!$self::plugins_installed()) {
+ $GLOBALS['error']->add_error('general', T_('Plugins detected, please remove all Plugins and try again'));
+ return false;
+ } */
+
+ $methods = array();
- $current_version = self::get_version();
-
- // Run a check to make sure that they don't try to upgrade from a version that
- // won't work.
- if ($current_version < '340001') {
- echo "<p align=\"center\">Database version too old, please upgrade to <a href=\"http://ampache.org/downloads/ampache-3.3.3.5.tar.gz\">Ampache-3.3.3.5</a> first</p>";
- return false;
- }
-
-
- $methods = get_class_methods('Update');
-
- if (!is_array((self::$versions))) {
- self::$versions = self::populate_version();
- }
-
- foreach (self::$versions as $version) {
+ $current_version = self::get_version();
+
+ // Run a check to make sure that they don't try to upgrade from a version that
+ // won't work.
+ if ($current_version < '340001') {
+ echo "<p align=\"center\">Database version too old, please upgrade to <a href=\"http://ampache.org/downloads/ampache-3.3.3.5.tar.gz\">Ampache-3.3.3.5</a> first</p>";
+ return false;
+ }
+
+
+ $methods = get_class_methods('Update');
+
+ if (!is_array((self::$versions))) {
+ self::$versions = self::populate_version();
+ }
+
+ foreach (self::$versions as $version) {
- // If it's newer than our current version
- // let's see if a function exists and run the
- // bugger
- if ($version['version'] > $current_version) {
- $update_function = "update_" . $version['version'];
- if (in_array($update_function,$methods)) {
- $success = call_user_func(array('Update',$update_function));
-
- // If the update fails drop out
- if (!$success) {
- Error::display('update');
- return false;
- }
- }
-
- }
-
- } // end foreach version
+ // If it's newer than our current version
+ // let's see if a function exists and run the
+ // bugger
+ if ($version['version'] > $current_version) {
+ $update_function = "update_" . $version['version'];
+ if (in_array($update_function,$methods)) {
+ $success = call_user_func(array('Update',$update_function));
+
+ // If the update fails drop out
+ if (!$success) {
+ Error::display('update');
+ return false;
+ }
+ }
+
+ }
+
+ } // end foreach version
- // Once we've run all of the updates let's re-sync the character set as the user
- // can change this between updates and cause mis-matches on any new tables
- Dba::reset_db_charset();
+ // Once we've run all of the updates let's re-sync the character set as the user
+ // can change this between updates and cause mis-matches on any new tables
+ Dba::reset_db_charset();
- } // run_update
+ } // run_update
- /**
- * set_version
- * This updates the 'update_info' which is used by the updater
- * and plugins
- */
- private static function set_version($key,$value) {
+ /**
+ * set_version
+ * This updates the 'update_info' which is used by the updater
+ * and plugins
+ */
+ private static function set_version($key,$value) {
- $sql = "UPDATE update_info SET value='$value' WHERE `key`='$key'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE update_info SET value='$value' WHERE `key`='$key'";
+ $db_results = Dba::write($sql);
- } //set_version
+ } //set_version
- /**
- * update_340001
- * This update moves back to the ID for user UID and
- * adds date to the user_vote so that it can be sorted
- * correctly
- */
- private function update_340001() {
+ /**
+ * update_340001
+ * This update moves back to the ID for user UID and
+ * adds date to the user_vote so that it can be sorted
+ * correctly
+ */
+ private function update_340001() {
- // Build the User -> ID map using the username as the key
- $sql = "SELECT `id`,`username` FROM `user`";
- $db_results = Dba::read($sql);
+ // Build the User -> ID map using the username as the key
+ $sql = "SELECT `id`,`username` FROM `user`";
+ $db_results = Dba::read($sql);
- $user_array = array();
+ $user_array = array();
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['username'];
- $user_array[$username] = Dba::escape($r['id']);
- } // end while
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['username'];
+ $user_array[$username] = Dba::escape($r['id']);
+ } // end while
- // Alter the user table so that you can't have an ID beyond the
- // range of the other tables which have to allow for -1
- $sql = "ALTER TABLE `user` CHANGE `id` `id` INT ( 11 ) NOT NULL AUTO_INCREMENT";
- $db_results = Dba::write($sql);
+ // Alter the user table so that you can't have an ID beyond the
+ // range of the other tables which have to allow for -1
+ $sql = "ALTER TABLE `user` CHANGE `id` `id` INT ( 11 ) NOT NULL AUTO_INCREMENT";
+ $db_results = Dba::write($sql);
- // Now pull the access list users, alter table and then re-insert
- $sql = "SELECT DISTINCT(`user`) FROM `access_list`";
- $db_results = Dba::read($sql);
+ // Now pull the access list users, alter table and then re-insert
+ $sql = "SELECT DISTINCT(`user`) FROM `access_list`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- // Build the new SQL
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ // Build the new SQL
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `access_list` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `access_list` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while access_list
+ } // end while access_list
- // Alter the table
- $sql = "ALTER TABLE `access_list` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `access_list` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Now pull flagged users, update and alter
- $sql = "SELECT DISTINCT(`user`) FROM `flagged`";
- $db_results = Dba::read($sql);
+ // Now pull flagged users, update and alter
+ $sql = "SELECT DISTINCT(`user`) FROM `flagged`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `flagged` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `flagged` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while
+ } // end while
- // Alter the table
- $sql = "ALTER TABLE `flagged` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `flagged` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Now fix up the ip history
- $sql = "SELECT DISTINCT(`user`) FROM `ip_history`";
- $db_results = Dba::read($sql);
+ // Now fix up the ip history
+ $sql = "SELECT DISTINCT(`user`) FROM `ip_history`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `ip_history` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `ip_history` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while
+ } // end while
- // Alter the table
- $sql = "ALTER TABLE `ip_history` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `ip_history` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Now fix now playing
- $sql = "SELECT DISTINCT(`user`) FROM `now_playing`";
- $db_results = Dba::read($sql);
+ // Now fix now playing
+ $sql = "SELECT DISTINCT(`user`) FROM `now_playing`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `now_playing` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `now_playing` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while
+ } // end while
- // Alter the table
- $sql = "ALTER TABLE `now_playing` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `now_playing` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Now fix the playlist table
- $sql = "SELECT DISTINCT(`user`) FROM `playlist`";
- $db_results = Dba::read($sql);
+ // Now fix the playlist table
+ $sql = "SELECT DISTINCT(`user`) FROM `playlist`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `playlist` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `playlist` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while
+ } // end while
- // Alter the table
- $sql = "ALTER TABLE `playlist` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `playlist` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Drop unused table
- $sql = "DROP TABLE `playlist_permission`";
- $db_results = Dba::write($sql);
+ // Drop unused table
+ $sql = "DROP TABLE `playlist_permission`";
+ $db_results = Dba::write($sql);
- // Now fix the ratings table
- $sql = "SELECT DISTINCT(`user`) FROM `ratings`";
- $db_results = Dba::read($sql);
+ // Now fix the ratings table
+ $sql = "SELECT DISTINCT(`user`) FROM `ratings`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `ratings` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `ratings` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while
+ } // end while
- $sql = "ALTER TABLE `ratings` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `ratings` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Now work on the tag_map
- $sql = "ALTER TABLE `tag_map` CHANGE `user_id` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Now work on the tag_map
+ $sql = "ALTER TABLE `tag_map` CHANGE `user_id` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Now fix user preferences
- $sql = "SELECT DISTINCT(`user`) FROM `user_preference`";
- $db_results = Dba::read($sql);
+ // Now fix user preferences
+ $sql = "SELECT DISTINCT(`user`) FROM `user_preference`";
+ $db_results = Dba::read($sql);
- while ($r = Dba::fetch_assoc($db_results)) {
- $username = $r['user'];
- $user_id = $user_array[$username];
- $username = Dba::escape($username);
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $username = $r['user'];
+ $user_id = $user_array[$username];
+ $username = Dba::escape($username);
- $sql = "UPDATE `user_preference` SET `user`='$user_id' WHERE `user`='$username'";
- $update_results = Dba::write($sql);
+ $sql = "UPDATE `user_preference` SET `user`='$user_id' WHERE `user`='$username'";
+ $update_results = Dba::write($sql);
- } // end while
+ } // end while
- // Alter the table
- $sql = "ALTER TABLE `user_preference` CHANGE `user` `user` INT ( 11 ) NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `user_preference` CHANGE `user` `user` INT ( 11 ) NOT NULL";
+ $db_results = Dba::write($sql);
- // Add a date to the user_vote
- $sql = "ALTER TABLE `user_vote` ADD `date` INT( 11 ) UNSIGNED NOT NULL";
- $db_results = Dba::write($sql);
+ // Add a date to the user_vote
+ $sql = "ALTER TABLE `user_vote` ADD `date` INT( 11 ) UNSIGNED NOT NULL";
+ $db_results = Dba::write($sql);
- // Add the index for said field
- $sql = "ALTER TABLE `user_vote` ADD INDEX(`date`)";
- $db_results = Dba::write($sql);
+ // Add the index for said field
+ $sql = "ALTER TABLE `user_vote` ADD INDEX(`date`)";
+ $db_results = Dba::write($sql);
- // Add the thumb fields to album
- $sql = "ALTER TABLE `album` ADD `thumb` TINYBLOB NULL ,ADD `thumb_mime` VARCHAR( 128 ) NULL";
- $db_results = Dba::write($sql);
+ // Add the thumb fields to album
+ $sql = "ALTER TABLE `album` ADD `thumb` TINYBLOB NULL ,ADD `thumb_mime` VARCHAR( 128 ) NULL";
+ $db_results = Dba::write($sql);
- // Now add in the min_object_count preference and the random_method
- $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES('min_object_count','1','Min Element Count','5','integer','interface')";
- $db_results = Dba::write($sql);
+ // Now add in the min_object_count preference and the random_method
+ $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES('min_object_count','1','Min Element Count','5','integer','interface')";
+ $db_results = Dba::write($sql);
- $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES('random_method','default','Random Method','5','string','interface')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES('random_method','default','Random Method','5','string','interface')";
+ $db_results = Dba::write($sql);
- // Delete old preference
- $sql = "DELETE FROM `preferences` WHERE `name`='min_album_size'";
- $db_results = Dba::write($sql);
+ // Delete old preference
+ $sql = "DELETE FROM `preferences` WHERE `name`='min_album_size'";
+ $db_results = Dba::write($sql);
- // Make Hash a non-required field and smaller
- $sql = "ALTER TABLE `song` CHANGE `hash` `hash` VARCHAR ( 64 ) NULL";
- $db_results = Dba::write($sql);
+ // Make Hash a non-required field and smaller
+ $sql = "ALTER TABLE `song` CHANGE `hash` `hash` VARCHAR ( 64 ) NULL";
+ $db_results = Dba::write($sql);
- // Make user access an int, nothing else
- $sql = "UPDATE `user` SET `access`='100' WHERE `access`='admin'";
- $db_results = Dba::write($sql);
+ // Make user access an int, nothing else
+ $sql = "UPDATE `user` SET `access`='100' WHERE `access`='admin'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `user` SET `access`='25' WHERE `access`='user'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `user` SET `access`='25' WHERE `access`='user'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `user` SET `access`='5' WHERE `access`='guest'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `user` SET `access`='5' WHERE `access`='guest'";
+ $db_results = Dba::write($sql);
- // Alter the table
- $sql = "ALTER TABLE `user` CHANGE `access` `access` TINYINT ( 4 ) UNSIGNED NOT NULL";
- $db_results = Dba::write($sql);
+ // Alter the table
+ $sql = "ALTER TABLE `user` CHANGE `access` `access` TINYINT ( 4 ) UNSIGNED NOT NULL";
+ $db_results = Dba::write($sql);
- // Add in Label and Catalog # and language
- $sql = "ALTER TABLE `song_ext_data` ADD `label` VARCHAR ( 128 ) NULL, ADD `catalog_number` VARCHAR ( 128 ) NULL, ADD `language` VARCHAR ( 128 ) NULL";
- $db_results = Dba::write($sql);
+ // Add in Label and Catalog # and language
+ $sql = "ALTER TABLE `song_ext_data` ADD `label` VARCHAR ( 128 ) NULL, ADD `catalog_number` VARCHAR ( 128 ) NULL, ADD `language` VARCHAR ( 128 ) NULL";
+ $db_results = Dba::write($sql);
- /* Fix every users preferences */
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ /* Fix every users preferences */
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- } // while results
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ } // while results
- self::set_version('db_version','340001');
+ self::set_version('db_version','340001');
- return true;
+ return true;
- } //update_340001
+ } //update_340001
- /**
- * update_340002
- * This update tweaks the preferences a little more and make sure that the
- * min_object_count has a rational value
- */
- private function update_340002() {
+ /**
+ * update_340002
+ * This update tweaks the preferences a little more and make sure that the
+ * min_object_count has a rational value
+ */
+ private function update_340002() {
- /* Add the offset_limit preference and remove it from the user table */
- $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('offset_limit','50','Offset Limit','5','integer','interface')";
- $db_results = Dba::write($sql);
+ /* Add the offset_limit preference and remove it from the user table */
+ $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('offset_limit','50','Offset Limit','5','integer','interface')";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','340002');
+ self::set_version('db_version','340002');
- return true;
+ return true;
- } // update_340002
+ } // update_340002
- /**
- * update_340003
- * This update moves the album art out of the album table
- * and puts it in an album_data table. It also makes some
- * minor changes to the song table in an attempt to reduce
- * the size of each row
- */
- public static function update_340003() {
+ /**
+ * update_340003
+ * This update moves the album art out of the album table
+ * and puts it in an album_data table. It also makes some
+ * minor changes to the song table in an attempt to reduce
+ * the size of each row
+ */
+ public static function update_340003() {
- $sql = "ALTER TABLE `song` CHANGE `mode` `mode` ENUM( 'abr', 'vbr', 'cbr' ) NULL DEFAULT 'cbr'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` CHANGE `mode` `mode` ENUM( 'abr', 'vbr', 'cbr' ) NULL DEFAULT 'cbr'";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` CHANGE `time` `time` SMALLINT( 5 ) UNSIGNED NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` CHANGE `time` `time` SMALLINT( 5 ) UNSIGNED NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` CHANGE `rate` `rate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` CHANGE `rate` `rate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` CHANGE `bitrate` `bitrate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` CHANGE `bitrate` `bitrate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` CHANGE `track` `track` SMALLINT( 5 ) UNSIGNED NULL DEFAULT NULL ";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` CHANGE `track` `track` SMALLINT( 5 ) UNSIGNED NULL DEFAULT NULL ";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `user` CHANGE `disabled` `disabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `user` CHANGE `disabled` `disabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- $sql = "CREATE TABLE `album_data` (" .
- "`album_id` INT( 11 ) UNSIGNED NOT NULL , " .
- "`art` MEDIUMBLOB NULL , " .
- "`art_mime` VARCHAR( 64 ) NULL , " .
- "`thumb` BLOB NULL , " .
- "`thumb_mime` VARCHAR( 64 ) NULL , " .
- "UNIQUE ( `album_id` )" .
- ") ENGINE = MYISAM";
- $db_results = Dba::write($sql);
+ $sql = "CREATE TABLE `album_data` (" .
+ "`album_id` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`art` MEDIUMBLOB NULL , " .
+ "`art_mime` VARCHAR( 64 ) NULL , " .
+ "`thumb` BLOB NULL , " .
+ "`thumb_mime` VARCHAR( 64 ) NULL , " .
+ "UNIQUE ( `album_id` )" .
+ ") ENGINE = MYISAM";
+ $db_results = Dba::write($sql);
- /* Foreach the Albums and move the data into the new album_data table */
- $sql = "SELECT * FROM album";
- $db_results = Dba::write($sql);
+ /* Foreach the Albums and move the data into the new album_data table */
+ $sql = "SELECT * FROM album";
+ $db_results = Dba::write($sql);
- while ($data = Dba::fetch_assoc($db_results)) {
- $id = $data['id'];
- $art = Dba::escape($data['art']);
- $art_mime = Dba::escape($data['art_mime']);
- $thumb = Dba::escape($data['thumb']);
- $thumb_mime = Dba::escape($data['thumb_mime']);
- $sql = "INSERT INTO `album_data` (`album_id`,`art`,`art_mime`,`thumb`,`thumb_mime`)" .
- " VALUES ('$id','$art','$art_mime','$thumb','$thumb_mime')";
- $insert_results = Dba::write($sql);
- } // end while
+ while ($data = Dba::fetch_assoc($db_results)) {
+ $id = $data['id'];
+ $art = Dba::escape($data['art']);
+ $art_mime = Dba::escape($data['art_mime']);
+ $thumb = Dba::escape($data['thumb']);
+ $thumb_mime = Dba::escape($data['thumb_mime']);
+ $sql = "INSERT INTO `album_data` (`album_id`,`art`,`art_mime`,`thumb`,`thumb_mime`)" .
+ " VALUES ('$id','$art','$art_mime','$thumb','$thumb_mime')";
+ $insert_results = Dba::write($sql);
+ } // end while
- $sql = "RENAME TABLE `song_ext_data` TO `song_data`";
- $db_results = Dba::write($sql);
+ $sql = "RENAME TABLE `song_ext_data` TO `song_data`";
+ $db_results = Dba::write($sql);
- $sql = "RENAME TABLE `preferences` TO `preference`";
- $db_results = Dba::write($sql);
+ $sql = "RENAME TABLE `preferences` TO `preference`";
+ $db_results = Dba::write($sql);
- $sql = "RENAME TABLE `ratings` TO `rating`";
- $db_results = Dba::write($sql);
+ $sql = "RENAME TABLE `ratings` TO `rating`";
+ $db_results = Dba::write($sql);
- // Go ahead and drop the art/thumb stuff
- $sql = "ALTER TABLE `album` DROP `art`, DROP `art_mime`, DROP `thumb`, DROP `thumb_mime`";
- $db_results = Dba::write($sql);
+ // Go ahead and drop the art/thumb stuff
+ $sql = "ALTER TABLE `album` DROP `art`, DROP `art_mime`, DROP `thumb`, DROP `thumb_mime`";
+ $db_results = Dba::write($sql);
- // We need to fix the user_vote table
- $sql = "ALTER TABLE `user_vote` CHANGE `user` `user` INT( 11 ) UNSIGNED NOT NULL";
- $db_results = Dba::write($sql);
+ // We need to fix the user_vote table
+ $sql = "ALTER TABLE `user_vote` CHANGE `user` `user` INT( 11 ) UNSIGNED NOT NULL";
+ $db_results = Dba::write($sql);
- // Remove offset limit from the user
- $sql = "ALTER TABLE `user` DROP `offset_limit`";
- $db_results = Dba::write($sql);
+ // Remove offset limit from the user
+ $sql = "ALTER TABLE `user` DROP `offset_limit`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `rating` CHANGE `user_rating` `rating` ENUM( '-1', '0', '1', '2', '3', '4', '5' ) NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `rating` CHANGE `user_rating` `rating` ENUM( '-1', '0', '1', '2', '3', '4', '5' ) NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- /* Add the rate_limit preference */
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('rate_limit','8192','Rate Limit','100','integer','streaming')";
- $db_results = Dba::write($sql);
+ /* Add the rate_limit preference */
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('rate_limit','8192','Rate Limit','100','integer','streaming')";
+ $db_results = Dba::write($sql);
- /* Add the playlist_method preference and remove it from the user table */
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('playlist_method','normal','Playlist Method','5','string','streaming')";
- $db_results = Dba::write($sql);
+ /* Add the playlist_method preference and remove it from the user table */
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('playlist_method','normal','Playlist Method','5','string','streaming')";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `update_info` ADD UNIQUE (`key`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `update_info` ADD UNIQUE (`key`)";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ }
- self::set_version('db_version','340003');
-
- return true;
-
- } // update_340003
-
- /**
- * update_340004
- * Update the session.id to varchar(64) to handle
- * newer configs
- */
- public static function update_340004() {
+ self::set_version('db_version','340003');
+
+ return true;
+
+ } // update_340003
+
+ /**
+ * update_340004
+ * Update the session.id to varchar(64) to handle
+ * newer configs
+ */
+ public static function update_340004() {
- /* Alter the session.id so that it's 64 */
- $sql = "ALTER TABLE `session` CHANGE `id` `id` VARCHAR( 64 ) NOT NULL";
- $db_results = Dba::write($sql);
+ /* Alter the session.id so that it's 64 */
+ $sql = "ALTER TABLE `session` CHANGE `id` `id` VARCHAR( 64 ) NOT NULL";
+ $db_results = Dba::write($sql);
- /* Add Playlist Related Preferences */
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('playlist_add','append','Add Behavior','5','string','playlist')";
- $db_results = Dba::write($sql);
+ /* Add Playlist Related Preferences */
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('playlist_add','append','Add Behavior','5','string','playlist')";
+ $db_results = Dba::write($sql);
- // Switch the existing preferences over to this new catagory
- $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='playlist_method' " .
- " OR `name`='playlist_type'";
- $db_results = Dba::write($sql);
+ // Switch the existing preferences over to this new catagory
+ $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='playlist_method' " .
+ " OR `name`='playlist_type'";
+ $db_results = Dba::write($sql);
- // Change the default value for playlist_method
- $sql = "UPDATE `preference` SET `value`='normal' WHERE `name`='playlist_method'";
- $db_results = Dba::write($sql);
+ // Change the default value for playlist_method
+ $sql = "UPDATE `preference` SET `value`='normal' WHERE `name`='playlist_method'";
+ $db_results = Dba::write($sql);
- // Add in the shoutbox
- $sql = "CREATE TABLE `user_shout` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , " .
- "`user` INT( 11 ) NOT NULL , " .
- "`text` TEXT NOT NULL , " .
- "`date` INT( 11 ) UNSIGNED NOT NULL , " .
- "`sticky` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0', " .
- "`object_id` INT( 11 ) UNSIGNED NOT NULL , " .
- "`object_type` VARCHAR( 32 ) NOT NULL " .
- ") ENGINE = MYISAM";
- $db_results = Dba::write($sql);
+ // Add in the shoutbox
+ $sql = "CREATE TABLE `user_shout` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , " .
+ "`user` INT( 11 ) NOT NULL , " .
+ "`text` TEXT NOT NULL , " .
+ "`date` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`sticky` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0', " .
+ "`object_id` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`object_type` VARCHAR( 32 ) NOT NULL " .
+ ") ENGINE = MYISAM";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `user_shout` ADD INDEX ( `sticky` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `user_shout` ADD INDEX ( `sticky` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `user_shout` ADD INDEX ( `date` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `user_shout` ADD INDEX ( `date` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `user_shout` ADD INDEX ( `user` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `user_shout` ADD INDEX ( `user` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `now_playing` CHANGE `start_time` `expire` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `now_playing` CHANGE `start_time` `expire` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- $sql = "OPTIMIZE TABLE `album`";
- $db_results = Dba::write($sql);
+ $sql = "OPTIMIZE TABLE `album`";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ }
- // Update our database version now that we are all done
- self::set_version('db_version','340004');
+ // Update our database version now that we are all done
+ self::set_version('db_version','340004');
- return true;
+ return true;
- } // update_340004
+ } // update_340004
- /**
- * update_340005
- * This update fixes the preferences types
- */
- public static function update_340005() {
+ /**
+ * update_340005
+ * This update fixes the preferences types
+ */
+ public static function update_340005() {
- // Turn user_rating into a tinyint and call it score
- $sql = "ALTER TABLE `rating` CHANGE `user_rating` `score` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '0'";
- $db_results = Dba::write($sql);
+ // Turn user_rating into a tinyint and call it score
+ $sql = "ALTER TABLE `rating` CHANGE `user_rating` `score` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '0'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='random_method'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='random_method'";
+ $db_results = Dba::write($sql);
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('transcode','default','Transcoding','25','string','streaming')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('transcode','default','Transcoding','25','string','streaming')";
+ $db_results = Dba::write($sql);
- /* We need to check for playlist_method here because I fubar'd an earlier update */
- $sql = "SELECT * FROM `preference` WHERE `name`='playlist_method'";
- $db_results = Dba::read($sql);
- if (!Dba::num_rows($db_results)) {
- /* Add the playlist_method preference and remove it from the user table */
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('playlist_method','default','Playlist Method','5','string','playlist')";
- $db_results = Dba::write($sql);
- }
+ /* We need to check for playlist_method here because I fubar'd an earlier update */
+ $sql = "SELECT * FROM `preference` WHERE `name`='playlist_method'";
+ $db_results = Dba::read($sql);
+ if (!Dba::num_rows($db_results)) {
+ /* Add the playlist_method preference and remove it from the user table */
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('playlist_method','default','Playlist Method','5','string','playlist')";
+ $db_results = Dba::write($sql);
+ }
- // Add in the object_type to the tmpplaylist data table so that we can have non-songs in there
- $sql = "ALTER TABLE `tmp_playlist_data` ADD `object_type` VARCHAR( 32 ) NULL AFTER `tmp_playlist`";
- $db_results = Dba::write($sql);
+ // Add in the object_type to the tmpplaylist data table so that we can have non-songs in there
+ $sql = "ALTER TABLE `tmp_playlist_data` ADD `object_type` VARCHAR( 32 ) NULL AFTER `tmp_playlist`";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ }
- self::set_version('db_version','340005');
+ self::set_version('db_version','340005');
- return true;
+ return true;
- } // update_340005
+ } // update_340005
- /**
- * update_340006
- * This just updates the size of the album_data table
- * and removes the random_method config option
- */
- public static function update_340006() {
+ /**
+ * update_340006
+ * This just updates the size of the album_data table
+ * and removes the random_method config option
+ */
+ public static function update_340006() {
- $sql = "DESCRIBE `album_data`";
- $db_results = Dba::read($sql);
+ $sql = "DESCRIBE `album_data`";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- if ($row['Field'] == 'art' AND $row['Type'] == 'blob') {
- $blob_needed = true;
- }
- } // end while
- if ($blob_needed) {
- $sql = "ALTER TABLE `album_data` CHANGE `art` `art` MEDIUMBLOB NULL DEFAULT NULL";
- $db_results = Dba::write($sql);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ if ($row['Field'] == 'art' AND $row['Type'] == 'blob') {
+ $blob_needed = true;
+ }
+ } // end while
+ if ($blob_needed) {
+ $sql = "ALTER TABLE `album_data` CHANGE `art` `art` MEDIUMBLOB NULL DEFAULT NULL";
+ $db_results = Dba::write($sql);
+ }
- // No matter what remove that random method preference
- $sql = "DELETE FROM `preference` WHERE `name`='random_method'";
- $db_results = Dba::write($sql);
+ // No matter what remove that random method preference
+ $sql = "DELETE FROM `preference` WHERE `name`='random_method'";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ }
- self::set_version('db_version','340006');
+ self::set_version('db_version','340006');
- return true;
+ return true;
- } // update_340006
+ } // update_340006
- /**
- * update_340007
- * This update converts the session.value to a longtext
- * and adds a session_stream table
- */
- public static function update_340007() {
+ /**
+ * update_340007
+ * This update converts the session.value to a longtext
+ * and adds a session_stream table
+ */
+ public static function update_340007() {
- // Tweak the session table to handle larger session vars for my page-a-nation hotness
- $sql = "ALTER TABLE `session` CHANGE `value` `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL";
- $db_results = Dba::write($sql);
+ // Tweak the session table to handle larger session vars for my page-a-nation hotness
+ $sql = "ALTER TABLE `session` CHANGE `value` `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL";
+ $db_results = Dba::write($sql);
- // Create the new stream table where we will store stream SIDs
- $sql = "CREATE TABLE `session_stream` ( " .
- "`id` VARCHAR( 64 ) NOT NULL , " .
- "`user` INT( 11 ) UNSIGNED NOT NULL , " .
- "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " .
- "`expire` INT( 11 ) UNSIGNED NOT NULL , " .
- "`ip` INT( 11 ) UNSIGNED NULL , " .
- "PRIMARY KEY ( `id` ) " .
- ") ENGINE = MYISAM";
- $db_results = Dba::write($sql);
+ // Create the new stream table where we will store stream SIDs
+ $sql = "CREATE TABLE `session_stream` ( " .
+ "`id` VARCHAR( 64 ) NOT NULL , " .
+ "`user` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " .
+ "`expire` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`ip` INT( 11 ) UNSIGNED NULL , " .
+ "PRIMARY KEY ( `id` ) " .
+ ") ENGINE = MYISAM";
+ $db_results = Dba::write($sql);
- // Change the now playing to use stream session ids for its ID
- $sql = "ALTER TABLE `now_playing` CHANGE `id` `id` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL";
- $db_results = Dba::write($sql);
+ // Change the now playing to use stream session ids for its ID
+ $sql = "ALTER TABLE `now_playing` CHANGE `id` `id` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL";
+ $db_results = Dba::write($sql);
- // Now longer needed because of the new hotness
- $sql = "ALTER TABLE `now_playing` DROP `session`";
- $db_results = Dba::write($sql);
+ // Now longer needed because of the new hotness
+ $sql = "ALTER TABLE `now_playing` DROP `session`";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','340007');
+ self::set_version('db_version','340007');
- return true;
+ return true;
- } // update_340007
+ } // update_340007
- /**
- * update_340008
- * This modifies the playlist table to handle the different types of objects that it needs to be able to
- * store, and tweaks how dynamic playlist stuff works
- */
- public static function update_340008() {
+ /**
+ * update_340008
+ * This modifies the playlist table to handle the different types of objects that it needs to be able to
+ * store, and tweaks how dynamic playlist stuff works
+ */
+ public static function update_340008() {
- $sql = "ALTER TABLE `playlist_data` CHANGE `song` `object_id` INT( 11 ) UNSIGNED NULL DEFAULT NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist_data` CHANGE `song` `object_id` INT( 11 ) UNSIGNED NULL DEFAULT NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `playlist_data` CHANGE `dyn_song` `dynamic_song` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist_data` CHANGE `dyn_song` `dynamic_song` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `playlist_data` ADD `object_type` VARCHAR( 32 ) NOT NULL DEFAULT 'song' AFTER `object_id`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist_data` ADD `object_type` VARCHAR( 32 ) NOT NULL DEFAULT 'song' AFTER `object_id`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `playlist` ADD `genre` INT( 11 ) UNSIGNED NOT NULL AFTER `type`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist` ADD `genre` INT( 11 ) UNSIGNED NOT NULL AFTER `type`";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `preference` WHERE `name`='allow_downsample_playback'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `preference` WHERE `name`='allow_downsample_playback'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `preference` SET `description`='Transcode Bitrate' WHERE `name`='sample_rate'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `description`='Transcode Bitrate' WHERE `name`='sample_rate'";
+ $db_results = Dba::write($sql);
- // Check for old tables and drop if found, seems like there was a glitch that caused them
- // not to get droped.. *shrug*
- $sql = "DROP TABLE IF EXISTS `preferences`";
- $db_results = Dba::write($sql);
+ // Check for old tables and drop if found, seems like there was a glitch that caused them
+ // not to get droped.. *shrug*
+ $sql = "DROP TABLE IF EXISTS `preferences`";
+ $db_results = Dba::write($sql);
- $sql = "DROP TABLE IF EXISTS `song_ext_data`";
- $db_results = Dba::write($sql);
+ $sql = "DROP TABLE IF EXISTS `song_ext_data`";
+ $db_results = Dba::write($sql);
- $sql = "DROP TABLE IF EXISTS `ratings`";
- $db_results = Dba::write($sql);
+ $sql = "DROP TABLE IF EXISTS `ratings`";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- }
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ }
- self::set_version('db_version','340008');
+ self::set_version('db_version','340008');
- return true;
+ return true;
- } // update_340008
+ } // update_340008
- /**
- * update_340009
- * This modifies the song table to handle pos fields
- */
- public static function update_340009() {
+ /**
+ * update_340009
+ * This modifies the song table to handle pos fields
+ */
+ public static function update_340009() {
- $sql = "ALTER TABLE `album` ADD `disk` smallint(5) UNSIGNED DEFAULT NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `album` ADD `disk` smallint(5) UNSIGNED DEFAULT NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `album` ADD INDEX (`disk`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `album` ADD INDEX (`disk`)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `access_list` ADD `dns` VARCHAR( 255 ) NOT NULL AFTER `end`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `access_list` ADD `dns` VARCHAR( 255 ) NOT NULL AFTER `end`";
+ $db_results = Dba::write($sql);
- $sql = "CREATE TABLE `artist_data` (" .
- "`artist_id` INT( 11 ) UNSIGNED NOT NULL ," .
- "`art` MEDIUMBLOB NOT NULL ," .
- "`art_mime` VARCHAR( 32 ) NOT NULL ," .
- "`thumb` BLOB NOT NULL ," .
- "`thumb_mime` VARCHAR( 32 ) NOT NULL ," .
- "`bio` TEXT NOT NULL , " .
- "UNIQUE (`artist_id`) ) ENGINE = MYISAM";
- $db_results = Dba::write($sql);
+ $sql = "CREATE TABLE `artist_data` (" .
+ "`artist_id` INT( 11 ) UNSIGNED NOT NULL ," .
+ "`art` MEDIUMBLOB NOT NULL ," .
+ "`art_mime` VARCHAR( 32 ) NOT NULL ," .
+ "`thumb` BLOB NOT NULL ," .
+ "`thumb_mime` VARCHAR( 32 ) NOT NULL ," .
+ "`bio` TEXT NOT NULL , " .
+ "UNIQUE (`artist_id`) ) ENGINE = MYISAM";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','340009');
+ self::set_version('db_version','340009');
- return true;
+ return true;
- } // update_340009
+ } // update_340009
- /**
- * update_340010
- * Bunch of minor tweaks to the preference table
- */
- public static function update_340010() {
+ /**
+ * update_340010
+ * Bunch of minor tweaks to the preference table
+ */
+ public static function update_340010() {
- $sql = "UPDATE `preference` SET `catagory`='options' WHERE `name` LIKE 'localplay_%'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `catagory`='options' WHERE `name` LIKE 'localplay_%'";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `preference` WHERE `name`='playlist_add'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `preference` WHERE `name`='playlist_add'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `preference` SET `catagory`='plugins' WHERE (`name` LIKE 'mystrands_%' OR `name` LIKE 'lastfm_%') AND `catagory`='options'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `catagory`='plugins' WHERE (`name` LIKE 'mystrands_%' OR `name` LIKE 'lastfm_%') AND `catagory`='options'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `preference` SET `value`='default' WHERE `name`='playlist_method'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `value`='default' WHERE `name`='playlist_method'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `preference` SET `description`='Localplay Config' WHERE `name`='localplay_level'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `description`='Localplay Config' WHERE `name`='localplay_level'";
+ $db_results = Dba::write($sql);
- /* Fix every users preferences */
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ /* Fix every users preferences */
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- } // while results
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ } // while results
- self::set_version('db_version','340010');
+ self::set_version('db_version','340010');
- return true;
+ return true;
- } // update_340010
+ } // update_340010
- /**
- * update_340011
- * This updates the democratic play stuff so that can handle a little more complext mojo
- * It also adds yet another table to the db to handle the sessions for API access. Eventually
- * should combine all of the session tables, but I'll do that later
- */
- public static function update_340011() {
+ /**
+ * update_340011
+ * This updates the democratic play stuff so that can handle a little more complext mojo
+ * It also adds yet another table to the db to handle the sessions for API access. Eventually
+ * should combine all of the session tables, but I'll do that later
+ */
+ public static function update_340011() {
- // First add the new table for the new session stuff
- $sql = "CREATE TABLE `session_api` ( " .
- "`id` VARCHAR( 64 ) NOT NULL , " .
- "`user` INT( 11 ) UNSIGNED NOT NULL , " .
- "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " .
- "`level` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', " .
- "`expire` INT( 11 ) UNSIGNED NOT NULL , " .
- "`ip` INT( 11 ) UNSIGNED NULL , " .
- "PRIMARY KEY ( `id` ) " .
- ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
- $db_results = Dba::write($sql);
+ // First add the new table for the new session stuff
+ $sql = "CREATE TABLE `session_api` ( " .
+ "`id` VARCHAR( 64 ) NOT NULL , " .
+ "`user` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " .
+ "`level` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', " .
+ "`expire` INT( 11 ) UNSIGNED NOT NULL , " .
+ "`ip` INT( 11 ) UNSIGNED NULL , " .
+ "PRIMARY KEY ( `id` ) " .
+ ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','340011');
+ self::set_version('db_version','340011');
- return true;
+ return true;
- } // 340011
+ } // 340011
- /**
- * update_340012
- * This update adds in the democratic stuff, checks for some potentially screwed up indexes
- * and removes the timestamp from the playlist, and adds the field to the catalog for the upload dir
- */
- public static function update_340012() {
+ /**
+ * update_340012
+ * This update adds in the democratic stuff, checks for some potentially screwed up indexes
+ * and removes the timestamp from the playlist, and adds the field to the catalog for the upload dir
+ */
+ public static function update_340012() {
- $sql = "ALTER TABLE `catalog` ADD `add_path` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER `path`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `catalog` ADD `add_path` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER `path`";
+ $db_results = Dba::write($sql);
- $sql = "CREATE TABLE `democratic` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
- "`name` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ," .
- "`cooldown` TINYINT( 4 ) UNSIGNED NULL ," .
- "`level` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '25'," .
- "`user` INT( 11 ) NOT NULL ," .
- "`primary` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'" .
- ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
- $db_results = Dba::write($sql);
+ $sql = "CREATE TABLE `democratic` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
+ "`name` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ," .
+ "`cooldown` TINYINT( 4 ) UNSIGNED NULL ," .
+ "`level` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '25'," .
+ "`user` INT( 11 ) NOT NULL ," .
+ "`primary` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'" .
+ ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `democratic` ADD INDEX (`primary`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `democratic` ADD INDEX (`primary`)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `democratic` ADD INDEX (`level`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `democratic` ADD INDEX (`level`)";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','340012');
+ self::set_version('db_version','340012');
- return true;
+ return true;
- } // update_340012
+ } // update_340012
- /**
- * update_340013
- * This update removes a whole bunch of preferences that are no longer
- * being used in any way, and changes the ACL XML-RPC to just RPC
- */
- public static function update_340013() {
+ /**
+ * update_340013
+ * This update removes a whole bunch of preferences that are no longer
+ * being used in any way, and changes the ACL XML-RPC to just RPC
+ */
+ public static function update_340013() {
- $sql = "DELETE FROM `preference` WHERE `name`='localplay_mpd_hostname' OR `name`='localplay_mpd_port' " .
- "OR `name`='direct_link' OR `name`='localplay_mpd_password' OR `name`='catalog_echo_count'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `preference` WHERE `name`='localplay_mpd_hostname' OR `name`='localplay_mpd_port' " .
+ "OR `name`='direct_link' OR `name`='localplay_mpd_password' OR `name`='catalog_echo_count'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `preference` SET `description`='Localplay Access' WHERE `name`='localplay_level'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `preference` SET `description`='Localplay Access' WHERE `name`='localplay_level'";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `access_list` SET `type`='rpc' WHERE `type`='xml-rpc'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `access_list` SET `type`='rpc' WHERE `type`='xml-rpc'";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- } // while we're fixing the useres stuff
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ } // while we're fixing the useres stuff
- self::set_version('db_version','340013');
+ self::set_version('db_version','340013');
- return true;
+ return true;
- } // update_340013
+ } // update_340013
- /**
- * update_340014
- * This update drops the session_api table that I added just two updates ago
- * it's been nice while it lasted but it's time to pack your stuff and GTFO
- * at the same time it updates the core session table to handle the additional
- * stuff we're going to ask it to do.
- */
- public static function update_340014() {
+ /**
+ * update_340014
+ * This update drops the session_api table that I added just two updates ago
+ * it's been nice while it lasted but it's time to pack your stuff and GTFO
+ * at the same time it updates the core session table to handle the additional
+ * stuff we're going to ask it to do.
+ */
+ public static function update_340014() {
- $sql = "DROP TABLE `session_api`";
- $db_results = Dba::write($sql);
+ $sql = "DROP TABLE `session_api`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `session` CHANGE `type` `type` ENUM ('mysql','ldap','http','api','xml-rpc') NOT NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `session` CHANGE `type` `type` ENUM ('mysql','ldap','http','api','xml-rpc') NOT NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `session` ADD `agent` VARCHAR ( 255 ) NOT NULL AFTER `type`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `session` ADD `agent` VARCHAR ( 255 ) NOT NULL AFTER `type`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `session` ADD INDEX (`type`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `session` ADD INDEX (`type`)";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','340014');
+ self::set_version('db_version','340014');
- return true;
+ return true;
- } // update_340014
+ } // update_340014
- /**
- * update_340015
- * This update tweaks the playlist table responding to complaints from usres
- * who say it doesn't work, unreproduceable. This also adds an index to the
- * album art table to try to make the random album art faster
- */
- public static function update_340015() {
+ /**
+ * update_340015
+ * This update tweaks the playlist table responding to complaints from usres
+ * who say it doesn't work, unreproduceable. This also adds an index to the
+ * album art table to try to make the random album art faster
+ */
+ public static function update_340015() {
- $sql = "ALTER TABLE `playlist` DROP `date`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist` DROP `date`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `playlist` ADD `date` INT ( 11 ) UNSIGNED NOT NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist` ADD `date` INT ( 11 ) UNSIGNED NOT NULL";
+ $db_results = Dba::write($sql);
- // Pull all of the rating information
- $sql = "SELECT `id`,`rating` FROM `rating`";
- $db_results = Dba::read($sql);
+ // Pull all of the rating information
+ $sql = "SELECT `id`,`rating` FROM `rating`";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row;
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row;
+ }
- $sql = "ALTER TABLE `rating` DROP `rating`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `rating` DROP `rating`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `rating` ADD `rating` TINYINT ( 4 ) NOT NULL";
- $db_results = Dba::write($sql);
-
- foreach ($results as $row) {
- $rating = Dba::escape($row['rating']);
- $id = Dba::escape($row['id']);
- $sql = "UPDATE `rating` SET `rating`='$rating' WHERE `id`='$id'";
- $db_results = Dba::write($sql);
- }
-
- self::set_version('db_version','340015');
-
- return true;
-
- } // update_340015
-
- /**
- * update_340016
- * This adds in the base_playlist to the democratic table... should have
- * done this in the previous one but I screwed up... sigh
- */
- public static function update_340016() {
-
- $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT ( 11 ) UNSIGNED NOT NULL";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','340016');
-
- return true;
-
- } // update_340016
-
- /**
- * update_340017
- * This finalizes the democratic table.
- * and fixes the charset crap
- */
- public static function update_340017() {
-
- $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT( 11 ) UNSIGNED NOT NULL AFTER `name`";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `tmp_playlist` DROP `base_playlist`";
- $db_results = Dba::write($sql);
-
- $sql = "DELETE FROM `tmp_playlist` WHERE `session`='-1'";
- $db_results = Dba::write($sql);
-
- $sql = "TRUNCATE `democratic`";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','340017');
-
- return true;
-
- } // update_340017
-
- /**
- * update_340018
- * This attempts to correct the charset on your database, it does some checking
- * to make sure that if we do this it will actually will work. We will fail this update
- * if it would cause problems
- */
- public static function update_340018() {
-
- // MySQL translate real charset names into fancy smancy MySQL land names
- switch (strtoupper(Config::get('site_charset'))) {
- case 'CP1250':
- case 'WINDOWS-1250':
- case 'WINDOWS-1252':
- $target_charset = 'cp1250';
- $target_collation = 'cp1250_general_ci';
- break;
- case 'ISO-8859':
- case 'ISO-8859-2':
- $target_charset = 'latin2';
- $target_collation = 'latin2_general_ci';
- break;
- case 'ISO-8859-1':
- $target_charset = 'latin1';
- $target_charset = 'latin1_general_ci';
- break;
- case 'EUC-KR':
- $target_charset = 'euckr';
- $target_collation = 'euckr_korean_ci';
- break;
- case 'CP932':
- $target_charset = 'sjis';
- $target_collation = 'sjis_japanese_ci';
- break;
- case 'KOI8-U':
- $target_charset = 'koi8u';
- $target_collation = 'koi8u_general_ci';
- break;
- case 'KOI8-R':
- $target_charset = 'koi8r';
- $target_collation = 'koi8r_general_ci';
- break;
- case 'ISO-8859':
- $target_charset = 'latin2';
- $target_collation = 'latin2_general_ci';
- break;
- default;
- case 'UTF-8':
- $target_charset = 'utf8';
- $target_collation = 'utf8_unicode_ci';
- break;
- } // end mysql charset translation
-
- // Alter the charset for the entire database
- $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
- $db_results = Dba::write($sql);
-
- $sql = "SHOW TABLES";
- $db_results = Dba::read($sql);
-
- // Go through the tables!
- while ($row = Dba::fetch_row($db_results)) {
- $sql = "DESCRIBE `" . $row['0'] . "`";
- $describe_results = Dba::read($sql);
-
- // Change the tables default charset and colliation
- $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
- $alter_table = Dba::write($sql);
-
- // Itterate through the columns of the table
- while ($table = Dba::fetch_assoc($describe_results)) {
- if (
- (strpos($table['Type'], 'varchar') !== false) ||
- (strpos($table['Type'], 'enum') !== false) ||
- strpos($table['Table'],'text') !== false) {
- $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset;
- $charset_results = Dba::write($sql);
- if (!$charset_results) {
- debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3');
- } // if it fails
- } // if its a varchar
- } // end columns
-
- } // end tables
-
- self::set_version('db_version','340018');
-
- return true;
-
- } // update_340018
-
- /**
- * update_350001
- * This updates modifies the tag tables per codeunde1load's specs from his tag patch
- * it also adjusts the prefix fields so that we can use more prefixes
- */
- public static function update_350001() {
-
- $sql = "ALTER TABLE `tag_map` ADD `tag_id` INT ( 11 ) UNSIGNED NOT NULL AFTER `id`";
- $db_results = Dba::write($sql);
-
- $sql = "RENAME TABLE `tags` TO `tag`";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `tag` CHANGE `map_id` `id` INT ( 11 ) UNSIGNED NOT NULL auto_increment";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `album` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `artist` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','350001');
-
- return true;
-
- } // update_350001
-
- /**
- * update_350002
- * This update adds in the browse_cache table that we use to hold peoples cached browse results
- * rather then try to store everything in the session we split them out into one serilized array per
- * row, per person. A little slow this way when browsing, but faster when now browsing and more flexible
- */
- public static function update_350002() {
-
- $sql = "CREATE TABLE `tmp_browse` (`sid` varchar(128) NOT NULL,`data` longtext NOT NULL," .
- " UNIQUE KEY `sid` (`sid`)) ENGINE=MyISAM";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `tmp_browse` ADD INDEX ( `type` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `rating` ADD `rating` TINYINT ( 4 ) NOT NULL";
+ $db_results = Dba::write($sql);
+
+ foreach ($results as $row) {
+ $rating = Dba::escape($row['rating']);
+ $id = Dba::escape($row['id']);
+ $sql = "UPDATE `rating` SET `rating`='$rating' WHERE `id`='$id'";
+ $db_results = Dba::write($sql);
+ }
+
+ self::set_version('db_version','340015');
+
+ return true;
+
+ } // update_340015
+
+ /**
+ * update_340016
+ * This adds in the base_playlist to the democratic table... should have
+ * done this in the previous one but I screwed up... sigh
+ */
+ public static function update_340016() {
+
+ $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT ( 11 ) UNSIGNED NOT NULL";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','340016');
+
+ return true;
+
+ } // update_340016
+
+ /**
+ * update_340017
+ * This finalizes the democratic table.
+ * and fixes the charset crap
+ */
+ public static function update_340017() {
+
+ $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT( 11 ) UNSIGNED NOT NULL AFTER `name`";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `tmp_playlist` DROP `base_playlist`";
+ $db_results = Dba::write($sql);
+
+ $sql = "DELETE FROM `tmp_playlist` WHERE `session`='-1'";
+ $db_results = Dba::write($sql);
+
+ $sql = "TRUNCATE `democratic`";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','340017');
+
+ return true;
+
+ } // update_340017
+
+ /**
+ * update_340018
+ * This attempts to correct the charset on your database, it does some checking
+ * to make sure that if we do this it will actually will work. We will fail this update
+ * if it would cause problems
+ */
+ public static function update_340018() {
+
+ // MySQL translate real charset names into fancy smancy MySQL land names
+ switch (strtoupper(Config::get('site_charset'))) {
+ case 'CP1250':
+ case 'WINDOWS-1250':
+ case 'WINDOWS-1252':
+ $target_charset = 'cp1250';
+ $target_collation = 'cp1250_general_ci';
+ break;
+ case 'ISO-8859':
+ case 'ISO-8859-2':
+ $target_charset = 'latin2';
+ $target_collation = 'latin2_general_ci';
+ break;
+ case 'ISO-8859-1':
+ $target_charset = 'latin1';
+ $target_charset = 'latin1_general_ci';
+ break;
+ case 'EUC-KR':
+ $target_charset = 'euckr';
+ $target_collation = 'euckr_korean_ci';
+ break;
+ case 'CP932':
+ $target_charset = 'sjis';
+ $target_collation = 'sjis_japanese_ci';
+ break;
+ case 'KOI8-U':
+ $target_charset = 'koi8u';
+ $target_collation = 'koi8u_general_ci';
+ break;
+ case 'KOI8-R':
+ $target_charset = 'koi8r';
+ $target_collation = 'koi8r_general_ci';
+ break;
+ case 'ISO-8859':
+ $target_charset = 'latin2';
+ $target_collation = 'latin2_general_ci';
+ break;
+ default;
+ case 'UTF-8':
+ $target_charset = 'utf8';
+ $target_collation = 'utf8_unicode_ci';
+ break;
+ } // end mysql charset translation
+
+ // Alter the charset for the entire database
+ $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
+ $db_results = Dba::write($sql);
+
+ $sql = "SHOW TABLES";
+ $db_results = Dba::read($sql);
+
+ // Go through the tables!
+ while ($row = Dba::fetch_row($db_results)) {
+ $sql = "DESCRIBE `" . $row['0'] . "`";
+ $describe_results = Dba::read($sql);
+
+ // Change the tables default charset and colliation
+ $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation";
+ $alter_table = Dba::write($sql);
+
+ // Itterate through the columns of the table
+ while ($table = Dba::fetch_assoc($describe_results)) {
+ if (
+ (strpos($table['Type'], 'varchar') !== false) ||
+ (strpos($table['Type'], 'enum') !== false) ||
+ strpos($table['Table'],'text') !== false) {
+ $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset;
+ $charset_results = Dba::write($sql);
+ if (!$charset_results) {
+ debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3');
+ } // if it fails
+ } // if its a varchar
+ } // end columns
+
+ } // end tables
+
+ self::set_version('db_version','340018');
+
+ return true;
+
+ } // update_340018
+
+ /**
+ * update_350001
+ * This updates modifies the tag tables per codeunde1load's specs from his tag patch
+ * it also adjusts the prefix fields so that we can use more prefixes
+ */
+ public static function update_350001() {
+
+ $sql = "ALTER TABLE `tag_map` ADD `tag_id` INT ( 11 ) UNSIGNED NOT NULL AFTER `id`";
+ $db_results = Dba::write($sql);
+
+ $sql = "RENAME TABLE `tags` TO `tag`";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `tag` CHANGE `map_id` `id` INT ( 11 ) UNSIGNED NOT NULL auto_increment";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `album` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `artist` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','350001');
+
+ return true;
+
+ } // update_350001
+
+ /**
+ * update_350002
+ * This update adds in the browse_cache table that we use to hold peoples cached browse results
+ * rather then try to store everything in the session we split them out into one serilized array per
+ * row, per person. A little slow this way when browsing, but faster when now browsing and more flexible
+ */
+ public static function update_350002() {
+
+ $sql = "CREATE TABLE `tmp_browse` (`sid` varchar(128) NOT NULL,`data` longtext NOT NULL," .
+ " UNIQUE KEY `sid` (`sid`)) ENGINE=MyISAM";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `tmp_browse` ADD INDEX ( `type` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` DROP `genre`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` DROP `genre`";
+ $db_results = Dba::write($sql);
- $sql = "CREATE TABLE `user_catalog` (`user` INT( 11 ) UNSIGNED NOT NULL ,`catalog` INT( 11 ) UNSIGNED NOT NULL ,`level` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '5', " .
- "INDEX ( `user` )) ENGINE = MYISAM";
- $db_results = Dba::write($sql);
+ $sql = "CREATE TABLE `user_catalog` (`user` INT( 11 ) UNSIGNED NOT NULL ,`catalog` INT( 11 ) UNSIGNED NOT NULL ,`level` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '5', " .
+ "INDEX ( `user` )) ENGINE = MYISAM";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `user_catalog` ADD INDEX ( `catalog` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `user_catalog` ADD INDEX ( `catalog` )";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','350002');
+ self::set_version('db_version','350002');
- return true;
+ return true;
- } // update_350002
+ } // update_350002
- /**
- * update_350003
- * This update tweakes the tag tables a little bit more, we're going to simplify things for the first little bit and then
- * then if it all works out we will worry about making it complex again. One thing at a time people...
- */
- public static function update_350003() {
+ /**
+ * update_350003
+ * This update tweakes the tag tables a little bit more, we're going to simplify things for the first little bit and then
+ * then if it all works out we will worry about making it complex again. One thing at a time people...
+ */
+ public static function update_350003() {
- $sql = "ALTER TABLE `tag` DROP `order`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `tag` DROP `order`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `tag` DROP INDEX `order`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `tag` DROP INDEX `order`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `tag` ADD UNIQUE ( `name` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `tag` ADD UNIQUE ( `name` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `tag` CHANGE `name` `name` VARCHAR( 255 )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `tag` CHANGE `name` `name` VARCHAR( 255 )";
+ $db_results = Dba::write($sql);
- // Make sure that they don't have any of the mystrands crap left
- $sql = "DELETE FROM `preference` WHERE `name`='mystrands_user' OR `name`='mystrands_pass'";
- $db_results = Dba::write($sql);
+ // Make sure that they don't have any of the mystrands crap left
+ $sql = "DELETE FROM `preference` WHERE `name`='mystrands_user' OR `name`='mystrands_pass'";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','350003');
+ self::set_version('db_version','350003');
- return true;
+ return true;
- } // update_350003
+ } // update_350003
- /**
- * update_350004
- * This update makes some changes to the ACL table so that it can support IPv6 entries as well as some other feature
- * enhancements
- */
- public static function update_350004() {
+ /**
+ * update_350004
+ * This update makes some changes to the ACL table so that it can support IPv6 entries as well as some other feature
+ * enhancements
+ */
+ public static function update_350004() {
- $sql = "ALTER TABLE `session` CHANGE `ip` `ip` VARBINARY( 255 ) NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `session` CHANGE `ip` `ip` VARBINARY( 255 ) NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `session_stream` CHANGE `ip` `ip` VARBINARY( 255 ) NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `session_stream` CHANGE `ip` `ip` VARBINARY( 255 ) NULL";
+ $db_results = Dba::write($sql);
- // Pull all of the IP history, this could take a while
- $sql = "SELECT * FROM `ip_history`";
- $db_results = Dba::read($sql);
+ // Pull all of the IP history, this could take a while
+ $sql = "SELECT * FROM `ip_history`";
+ $db_results = Dba::read($sql);
- $ip_history = array();
+ $ip_history = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $row['ip'] = long2ip($row['ip']);
- $ip_history[] = $row;
- }
-
- // Clear the table before we make the changes
- $sql = "TRUNCATE `ip_history`";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `ip_history` CHANGE `ip` `ip` VARBINARY( 255 ) NULL";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `ip_history` ADD `agent` VARCHAR ( 255 ) NULL AFTER `date`";
- $db_results = Dba::write($sql);
-
- // Reinsert the old rows
- foreach ($ip_history as $row) {
- $ip = Dba::escape(inet_pton($row['ip']));
- $sql = "INSERT INTO `ip_history` (`user`,`ip`,`date`,`agent`) " .
- "VALUES ('" . $row['user'] . "','" . $ip . "','" . $row['date'] . "',NULL)";
- $db_results = Dba::write($sql);
- }
-
- // First pull all of their current ACL's
- $sql = "SELECT * FROM `access_list`";
- $db_results = Dba::read($sql);
-
- $acl_information = array();
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $row['ip'] = long2ip($row['ip']);
+ $ip_history[] = $row;
+ }
+
+ // Clear the table before we make the changes
+ $sql = "TRUNCATE `ip_history`";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `ip_history` CHANGE `ip` `ip` VARBINARY( 255 ) NULL";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `ip_history` ADD `agent` VARCHAR ( 255 ) NULL AFTER `date`";
+ $db_results = Dba::write($sql);
+
+ // Reinsert the old rows
+ foreach ($ip_history as $row) {
+ $ip = Dba::escape(inet_pton($row['ip']));
+ $sql = "INSERT INTO `ip_history` (`user`,`ip`,`date`,`agent`) " .
+ "VALUES ('" . $row['user'] . "','" . $ip . "','" . $row['date'] . "',NULL)";
+ $db_results = Dba::write($sql);
+ }
+
+ // First pull all of their current ACL's
+ $sql = "SELECT * FROM `access_list`";
+ $db_results = Dba::read($sql);
+
+ $acl_information = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $row['start'] = long2ip($row['start']);
- $row['end'] = long2ip($row['end']);
- $acl_information[] = $row;
- }
-
- $sql = "TRUNCATE `access_list`";
- $db_results = Dba::write($sql);
-
- // Make the changes to the database
- $sql = "ALTER TABLE `access_list` CHANGE `start` `start` VARBINARY( 255 ) NOT NULL";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `access_list` CHANGE `end` `end` VARBINARY( 255 ) NOT NULL";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `access_list` DROP `dns`";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `access_list` ADD `enabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1' AFTER `key`";
- $db_results = Dba::write($sql);
-
- // If we had nothing in there before add some base ALLOW ALL stuff as we're going
- // to start defaulting Access Control to On.
- if (!count($acl_information)) {
- $v6_start = Dba::escape(inet_pton('::'));
- $v6_end = Dba::escape(inet_pton('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'));
- $v4_start = Dba::escape(inet_pton('0.0.0.0'));
- $v4_end = Dba::escape(inet_pton('255.255.255.255'));
- $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
- "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','interface','1')";
- $db_results = Dba::write($sql);
- $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
- "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','stream','1')";
- $db_results = Dba::write($sql);
- $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
- "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','interface','1')";
- $db_results = Dba::write($sql);
- $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
- "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','stream','1')";
- $db_results = Dba::write($sql);
- } // Adding default information
-
- foreach ($acl_information as $row) {
- $row['start'] = Dba::escape(inet_pton($row['start']));
- $row['end'] = Dba::escape(inet_pton($row['end']));
- $row['key'] = Dba::escape($row['key']);
- $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
- "VALUES ('" . Dba::escape($row['name']) . "','" . intval($row['level']) .
- "','" . $row['start'] . "','" . $row['end'] . "','" . $row['key'] . "','" . intval($row['user']) . "','" .
- $row['type'] . "','1')";
- $db_results = Dba::write($sql);
- } // end foreach of existing rows
-
- self::set_version('db_version','350004');
-
- return true;
-
- } // update_350004
-
- /**
- * update_350005
- * This update adds the video table... *gasp* no you didn't <head shake>
- */
- public static function update_350005() {
-
- $sql = " CREATE TABLE `video` (" .
- "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
- "`file` VARCHAR( 255 ) NOT NULL , " .
- "`catalog` INT( 11 ) UNSIGNED NOT NULL ," .
- "`title` VARCHAR( 255 ) NOT NULL ," .
- "`video_codec` VARCHAR( 255 ) NOT NULL ," .
- "`audio_codec` VARCHAR( 255 ) NOT NULL ," .
- "`resolution_x` MEDIUMINT UNSIGNED NOT NULL ," .
- "`resolution_y` MEDIUMINT UNSIGNED NOT NULL ," .
- "`time` INT( 11 ) UNSIGNED NOT NULL ," .
- "`size` BIGINT UNSIGNED NOT NULL," .
- "`mime` VARCHAR( 255 ) NOT NULL," .
- "`enabled` TINYINT( 1) NOT NULL DEFAULT '1'" .
- ") ENGINE = MYISAM ";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `access_list` ADD INDEX ( `enabled` )";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `video` ADD INDEX ( `file` )";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `video` ADD INDEX ( `enabled` )";
- $db_results = Dba::write($sql);
-
- $sql = "ALTER TABLE `video` ADD INDEX ( `title` )";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','350005');
-
- return true;
-
- } // update_350005
-
- /**
- * update_350006
- * This update inserts the Lyrics pref table...
- */
- public static function update_350006() {
-
- $sql = "INSERT INTO `preference` VALUES (69,'show_lyrics','0','Show Lyrics',0,'boolean','interface')";
- $db_results = Dba::write($sql);
-
- $sql = "INSERT INTO `user_preference` VALUES (1,69,'0')";
- $db_results = Dba::write($sql);
-
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
-
- User::fix_preferences('-1');
-
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- } // while we're fixing the useres stuff
-
- self::set_version('db_version','350006');
-
- return true;
-
- } // update_350006
-
- /**
- * update_350007
- * This update adds in the random rules tables, and also increases the size of the blobs
- * on the album and artist data. Also add track to tmp_playlist_data
- */
- public static function update_350007() {
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $row['start'] = long2ip($row['start']);
+ $row['end'] = long2ip($row['end']);
+ $acl_information[] = $row;
+ }
+
+ $sql = "TRUNCATE `access_list`";
+ $db_results = Dba::write($sql);
+
+ // Make the changes to the database
+ $sql = "ALTER TABLE `access_list` CHANGE `start` `start` VARBINARY( 255 ) NOT NULL";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `access_list` CHANGE `end` `end` VARBINARY( 255 ) NOT NULL";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `access_list` DROP `dns`";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `access_list` ADD `enabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1' AFTER `key`";
+ $db_results = Dba::write($sql);
+
+ // If we had nothing in there before add some base ALLOW ALL stuff as we're going
+ // to start defaulting Access Control to On.
+ if (!count($acl_information)) {
+ $v6_start = Dba::escape(inet_pton('::'));
+ $v6_end = Dba::escape(inet_pton('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'));
+ $v4_start = Dba::escape(inet_pton('0.0.0.0'));
+ $v4_end = Dba::escape(inet_pton('255.255.255.255'));
+ $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
+ "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','interface','1')";
+ $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
+ "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','stream','1')";
+ $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
+ "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','interface','1')";
+ $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
+ "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','stream','1')";
+ $db_results = Dba::write($sql);
+ } // Adding default information
+
+ foreach ($acl_information as $row) {
+ $row['start'] = Dba::escape(inet_pton($row['start']));
+ $row['end'] = Dba::escape(inet_pton($row['end']));
+ $row['key'] = Dba::escape($row['key']);
+ $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " .
+ "VALUES ('" . Dba::escape($row['name']) . "','" . intval($row['level']) .
+ "','" . $row['start'] . "','" . $row['end'] . "','" . $row['key'] . "','" . intval($row['user']) . "','" .
+ $row['type'] . "','1')";
+ $db_results = Dba::write($sql);
+ } // end foreach of existing rows
+
+ self::set_version('db_version','350004');
+
+ return true;
+
+ } // update_350004
+
+ /**
+ * update_350005
+ * This update adds the video table... *gasp* no you didn't <head shake>
+ */
+ public static function update_350005() {
+
+ $sql = " CREATE TABLE `video` (" .
+ "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
+ "`file` VARCHAR( 255 ) NOT NULL , " .
+ "`catalog` INT( 11 ) UNSIGNED NOT NULL ," .
+ "`title` VARCHAR( 255 ) NOT NULL ," .
+ "`video_codec` VARCHAR( 255 ) NOT NULL ," .
+ "`audio_codec` VARCHAR( 255 ) NOT NULL ," .
+ "`resolution_x` MEDIUMINT UNSIGNED NOT NULL ," .
+ "`resolution_y` MEDIUMINT UNSIGNED NOT NULL ," .
+ "`time` INT( 11 ) UNSIGNED NOT NULL ," .
+ "`size` BIGINT UNSIGNED NOT NULL," .
+ "`mime` VARCHAR( 255 ) NOT NULL," .
+ "`enabled` TINYINT( 1) NOT NULL DEFAULT '1'" .
+ ") ENGINE = MYISAM ";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `access_list` ADD INDEX ( `enabled` )";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `video` ADD INDEX ( `file` )";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `video` ADD INDEX ( `enabled` )";
+ $db_results = Dba::write($sql);
+
+ $sql = "ALTER TABLE `video` ADD INDEX ( `title` )";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','350005');
+
+ return true;
+
+ } // update_350005
+
+ /**
+ * update_350006
+ * This update inserts the Lyrics pref table...
+ */
+ public static function update_350006() {
+
+ $sql = "INSERT INTO `preference` VALUES (69,'show_lyrics','0','Show Lyrics',0,'boolean','interface')";
+ $db_results = Dba::write($sql);
+
+ $sql = "INSERT INTO `user_preference` VALUES (1,69,'0')";
+ $db_results = Dba::write($sql);
+
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
+
+ User::fix_preferences('-1');
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ } // while we're fixing the useres stuff
+
+ self::set_version('db_version','350006');
+
+ return true;
+
+ } // update_350006
+
+ /**
+ * update_350007
+ * This update adds in the random rules tables, and also increases the size of the blobs
+ * on the album and artist data. Also add track to tmp_playlist_data
+ */
+ public static function update_350007() {
- // We need to clear the thumbs as they will need to be re-generated
- $sql = "UPDATE `album_data` SET `thumb`=NULL,`thumb_mime`=NULL";
- $db_results = Dba::write($sql);
+ // We need to clear the thumbs as they will need to be re-generated
+ $sql = "UPDATE `album_data` SET `thumb`=NULL,`thumb_mime`=NULL";
+ $db_results = Dba::write($sql);
- $sql = "UPDATE `artist_data` SET `thumb`=NULL,`thumb_mime`=NULL";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `artist_data` SET `thumb`=NULL,`thumb_mime`=NULL";
+ $db_results = Dba::write($sql);
- // Change the db thumb sizes
- $sql = "ALTER TABLE `album_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL";
- $db_results = Dba::write($sql);
+ // Change the db thumb sizes
+ $sql = "ALTER TABLE `album_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `artist_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `artist_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL";
+ $db_results = Dba::write($sql);
- // Remove dead column
- $sql = "ALTER TABLE `playlist_data` DROP `dynamic_song`";
- $db_results = Dba::write($sql);
+ // Remove dead column
+ $sql = "ALTER TABLE `playlist_data` DROP `dynamic_song`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `playlist` DROP `genre`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `playlist` DROP `genre`";
+ $db_results = Dba::write($sql);
- // Add track item to tmp_playlist_data so we can order this stuff manually
- $sql = "ALTER TABLE `tmp_playlist_data` ADD `track` INT ( 11 ) UNSIGNED NULL";
- $db_results = Dba::write($sql);
+ // Add track item to tmp_playlist_data so we can order this stuff manually
+ $sql = "ALTER TABLE `tmp_playlist_data` ADD `track` INT ( 11 ) UNSIGNED NULL";
+ $db_results = Dba::write($sql);
- $sql = "DROP TABLE `genre`";
- $db_results = Dba::write($sql);
+ $sql = "DROP TABLE `genre`";
+ $db_results = Dba::write($sql);
- // Clean up the catalog and add last_clean to it
- $sql = "ALTER TABLE `catalog` ADD `last_clean` INT ( 11 ) UNSIGNED NULL AFTER `last_update`";
- $db_results = Dba::write($sql);
+ // Clean up the catalog and add last_clean to it
+ $sql = "ALTER TABLE `catalog` ADD `last_clean` INT ( 11 ) UNSIGNED NULL AFTER `last_update`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `catalog` DROP `add_path`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `catalog` DROP `add_path`";
+ $db_results = Dba::write($sql);
- $sql = "CREATE TABLE `dynamic_playlist` (" .
- "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
- "`name` VARCHAR( 255 ) NOT NULL ," .
- "`user` INT( 11 ) NOT NULL ," .
- "`date` INT( 11 ) UNSIGNED NOT NULL ," .
- "`type` VARCHAR( 128 ) NOT NULL" .
- ") ENGINE = MYISAM ";
- $db_results = Dba::write($sql);
+ $sql = "CREATE TABLE `dynamic_playlist` (" .
+ "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
+ "`name` VARCHAR( 255 ) NOT NULL ," .
+ "`user` INT( 11 ) NOT NULL ," .
+ "`date` INT( 11 ) UNSIGNED NOT NULL ," .
+ "`type` VARCHAR( 128 ) NOT NULL" .
+ ") ENGINE = MYISAM ";
+ $db_results = Dba::write($sql);
- $sql = "CREATE TABLE `dynamic_playlist_data` (" .
- "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
- "`dynamic_id` INT( 11 ) UNSIGNED NOT NULL ," .
- "`field` VARCHAR( 255 ) NOT NULL ," .
- "`internal_operator` VARCHAR( 64 ) NOT NULL ," .
- "`external_operator` VARCHAR( 64 ) NOT NULL ," .
- "`value` VARCHAR( 255 ) NOT NULL" .
- ") ENGINE = MYISAM";
- $db_results = Dba::write($sql);
+ $sql = "CREATE TABLE `dynamic_playlist_data` (" .
+ "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," .
+ "`dynamic_id` INT( 11 ) UNSIGNED NOT NULL ," .
+ "`field` VARCHAR( 255 ) NOT NULL ," .
+ "`internal_operator` VARCHAR( 64 ) NOT NULL ," .
+ "`external_operator` VARCHAR( 64 ) NOT NULL ," .
+ "`value` VARCHAR( 255 ) NOT NULL" .
+ ") ENGINE = MYISAM";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','350007');
+ self::set_version('db_version','350007');
- return true;
+ return true;
- } // update_350007
+ } // update_350007
- /**
- * update_350008
- * Change song_id references to be object so they are a little more general
- * add a type to now playing table so that we can handle different playing information
- */
- public static function update_350008() {
+ /**
+ * update_350008
+ * Change song_id references to be object so they are a little more general
+ * add a type to now playing table so that we can handle different playing information
+ */
+ public static function update_350008() {
- $sql = "ALTER TABLE `now_playing` CHANGE `song_id` `object_id` INT( 11 ) UNSIGNED NOT NULL";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `now_playing` CHANGE `song_id` `object_id` INT( 11 ) UNSIGNED NOT NULL";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `now_playing` ADD `object_type` VARCHAR ( 255 ) NOT NULL AFTER `object_id`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `now_playing` ADD `object_type` VARCHAR ( 255 ) NOT NULL AFTER `object_id`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `now_playing` ADD INDEX ( `expire` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `now_playing` ADD INDEX ( `expire` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `video` ADD `addition_time` INT( 11 ) UNSIGNED NOT NULL AFTER `mime`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `video` ADD `addition_time` INT( 11 ) UNSIGNED NOT NULL AFTER `mime`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `video` ADD `update_time` INT( 11 ) UNSIGNED NULL AFTER `addition_time`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `video` ADD `update_time` INT( 11 ) UNSIGNED NULL AFTER `addition_time`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `video` ADD INDEX (`addition_time`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `video` ADD INDEX (`addition_time`)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `video` ADD INDEX (`update_time`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `video` ADD INDEX (`update_time`)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `artist_data` ADD INDEX ( `art_mime` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `artist_data` ADD INDEX ( `art_mime` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `album_data` ADD INDEX ( `art_mime` )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `album_data` ADD INDEX ( `art_mime` )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `tmp_browse` ADD `type` VARCHAR ( 255 ) NOT NULL AFTER `sid`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `tmp_browse` ADD `type` VARCHAR ( 255 ) NOT NULL AFTER `sid`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `tmp_browse` ADD INDEX (`type)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `tmp_browse` ADD INDEX (`type)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` DROP `hash`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` DROP `hash`";
+ $db_results = Dba::write($sql);
- self::set_version('db_version','350008');
+ self::set_version('db_version','350008');
- } // update_350008
+ } // update_350008
- /**
- * update_360001
- * This adds the MB UUIDs to the different tables as well as some additional cleanup
- */
- public static function update_360001() {
+ /**
+ * update_360001
+ * This adds the MB UUIDs to the different tables as well as some additional cleanup
+ */
+ public static function update_360001() {
- $sql = "ALTER TABLE `album` ADD `mbid` CHAR ( 36 ) AFTER `prefix`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `album` ADD `mbid` CHAR ( 36 ) AFTER `prefix`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `artist` ADD `mbid` CHAR ( 36 ) AFTER `prefix`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `artist` ADD `mbid` CHAR ( 36 ) AFTER `prefix`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` ADD `mbid` CHAR ( 36 ) AFTER `track`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` ADD `mbid` CHAR ( 36 ) AFTER `track`";
+ $db_results = Dba::write($sql);
- // Remove any RIO related information from the database as the plugin has been removed
- $sql = "DELETE FROM `update_info` WHERE `key` LIKE 'Plugin_Ri%'";
- $db_results = Dba::write($sql);
+ // Remove any RIO related information from the database as the plugin has been removed
+ $sql = "DELETE FROM `update_info` WHERE `key` LIKE 'Plugin_Ri%'";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `preference` WHERE `name` LIKE 'rio_%'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `preference` WHERE `name` LIKE 'rio_%'";
+ $db_results = Dba::write($sql);
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- } // while we're fixing the useres stuff
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ } // while we're fixing the useres stuff
- self::set_version('db_version','360001');
+ self::set_version('db_version','360001');
- } // update_360001
+ } // update_360001
- /**
- * update_360002
- * This update makes changes to the cataloging to accomodate the new method for syncing between
- * Ampache instances, could be adapted to sync with whatever for "full" catalog
- */
- public static function update_360002() {
+ /**
+ * update_360002
+ * This update makes changes to the cataloging to accomodate the new method for syncing between
+ * Ampache instances, could be adapted to sync with whatever for "full" catalog
+ */
+ public static function update_360002() {
- // Drop the key from catalog and ACL
- $sql = "ALTER TABLE `catalog` DROP `key`";
- $db_results = Dba::write($sql);
+ // Drop the key from catalog and ACL
+ $sql = "ALTER TABLE `catalog` DROP `key`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `access_list` DROP `key`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `access_list` DROP `key`";
+ $db_results = Dba::write($sql);
- // Add in Username / Password for catalog - to be used for remote catalogs
- $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`";
- $db_results = Dba::write($sql);
+ // Add in Username / Password for catalog - to be used for remote catalogs
+ $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`";
+ $db_results = Dba::write($sql);
- // Adjust the Filename field in song, make it gi-normous. If someone has anything close to
- // this file length, they seriously need to reconsider what they are doing.
- $sql = "ALTER TABLE `song` CHANGE `file` `file` VARCHAR ( 4096 )";
- $db_results = Dba::write($sql);
+ // Adjust the Filename field in song, make it gi-normous. If someone has anything close to
+ // this file length, they seriously need to reconsider what they are doing.
+ $sql = "ALTER TABLE `song` CHANGE `file` `file` VARCHAR ( 4096 )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `video` CHANGE `file` `file` VARCHAR ( 4096 )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `video` CHANGE `file` `file` VARCHAR ( 4096 )";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `live_stream` CHANGE `url` `url` VARCHAR ( 4096 )";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `live_stream` CHANGE `url` `url` VARCHAR ( 4096 )";
+ $db_results = Dba::write($sql);
- // Index the Artist, Album, and Song tables to prepare for Fulltext searches.
- $sql = "ALTER TABLE `artist` ADD FULLTEXT(`name`)";
- $db_results = Dba::write($sql);
+ // Index the Artist, Album, and Song tables to prepare for Fulltext searches.
+ $sql = "ALTER TABLE `artist` ADD FULLTEXT(`name`)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `album` ADD FULLTEXT(`name`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `album` ADD FULLTEXT(`name`)";
+ $db_results = Dba::write($sql);
- $sql = "ALTER TABLE `song` ADD FULLTEXT(`title`)";
- $db_results = Dba::write($sql);
+ $sql = "ALTER TABLE `song` ADD FULLTEXT(`title`)";
+ $db_results = Dba::write($sql);
- // Now add in the min_object_count preference and the random_method
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('bandwidth','50','Bandwidth','5','integer','interface')";
- $db_results = Dba::write($sql);
+ // Now add in the min_object_count preference and the random_method
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('bandwidth','50','Bandwidth','5','integer','interface')";
+ $db_results = Dba::write($sql);
- $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
- "VALUES ('features','50','Features','5','integer','interface')";
- $db_results = Dba::write($sql);
+ $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('features','50','Features','5','integer','interface')";
+ $db_results = Dba::write($sql);
- /* Fix every users preferences */
- $sql = "SELECT `id` FROM `user`";
- $db_results = Dba::read($sql);
+ /* Fix every users preferences */
+ $sql = "SELECT `id` FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($r = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($r['id']);
- } // while results
+ while ($r = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($r['id']);
+ } // while results
- self::set_version('db_version','360002');
-
- } // update_360002
-
- /**
- * update_360003
- * This update moves the image data to its own table.
- */
- public static function update_360003() {
- $sql = "CREATE TABLE `image` (" .
- "`id` int(11) unsigned NOT NULL auto_increment," .
- "`image` mediumblob NOT NULL," .
- "`mime` varchar(64) NOT NULL," .
- "`size` varchar(64) NOT NULL," .
- "`object_type` varchar(64) NOT NULL," .
- "`object_id` int(11) unsigned NOT NULL," .
- "PRIMARY KEY (`id`)," .
- "KEY `object_type` (`object_type`)," .
- "KEY `object_id` (`object_id`)" .
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
- $db_results = Dba::write($sql);
-
- foreach (array('album', 'artist') as $type) {
- $sql = "SELECT `" . $type . "_id` AS `object_id`, " .
- "`art`, `art_mime` FROM `" . $type .
- "_data` WHERE `art` IS NOT NULL";
- $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $sql = "INSERT INTO `image` " .
- "(`image`, `mime`, `size`, " .
- "`object_type`, `object_id`) " .
- "VALUES('" . Dba::escape($row['art']) .
- "', '" . $row['art_mime'] .
- "', 'original', '" . $type . "', '" .
- $row['object_id'] . "')";
- $db_other_results = Dba::write($sql);
- }
- $sql = "DROP TABLE `" . $type . "_data`";
- $db_results = Dba::write($sql);
- }
-
- self::set_version('db_version','360003');
-
- } // update_360003
+ self::set_version('db_version','360002');
+
+ } // update_360002
+
+ /**
+ * update_360003
+ * This update moves the image data to its own table.
+ */
+ public static function update_360003() {
+ $sql = "CREATE TABLE `image` (" .
+ "`id` int(11) unsigned NOT NULL auto_increment," .
+ "`image` mediumblob NOT NULL," .
+ "`mime` varchar(64) NOT NULL," .
+ "`size` varchar(64) NOT NULL," .
+ "`object_type` varchar(64) NOT NULL," .
+ "`object_id` int(11) unsigned NOT NULL," .
+ "PRIMARY KEY (`id`)," .
+ "KEY `object_type` (`object_type`)," .
+ "KEY `object_id` (`object_id`)" .
+ ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+ $db_results = Dba::write($sql);
+
+ foreach (array('album', 'artist') as $type) {
+ $sql = "SELECT `" . $type . "_id` AS `object_id`, " .
+ "`art`, `art_mime` FROM `" . $type .
+ "_data` WHERE `art` IS NOT NULL";
+ $db_results = Dba::read($sql);
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $sql = "INSERT INTO `image` " .
+ "(`image`, `mime`, `size`, " .
+ "`object_type`, `object_id`) " .
+ "VALUES('" . Dba::escape($row['art']) .
+ "', '" . $row['art_mime'] .
+ "', 'original', '" . $type . "', '" .
+ $row['object_id'] . "')";
+ $db_other_results = Dba::write($sql);
+ }
+ $sql = "DROP TABLE `" . $type . "_data`";
+ $db_results = Dba::write($sql);
+ }
+
+ self::set_version('db_version','360003');
+
+ } // update_360003
/**
- * update_360004
- * This update creates an index on the rating table.
- */
- public static function update_360004() {
- $sql = "CREATE UNIQUE INDEX `unique_rating` ON `rating` (`user`, `object_type`, `object_id`)";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','360004');
- } // update_360004
-
- /**
- * update_360005
- * This changes the tmp_browse table around.
- */
- public static function update_360005() {
- $sql = "DROP TABLE `tmp_browse`";
- $db_results = Dba::write($sql);
-
- $sql = "CREATE TABLE `tmp_browse` (" .
- "`id` int(13) NOT NULL auto_increment," .
- "`sid` varchar(128) character set utf8 NOT NULL default ''," .
- "`data` longtext NOT NULL," .
- "`object_data` longtext," .
- "PRIMARY KEY (`sid`,`id`)" .
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','360005');
- } // update_360005
-
- /**
- * update_360006
- * This adds the table for newsearch/dynamic playlists
- */
- public static function update_360006() {
- $sql = "CREATE TABLE `search` (
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
- `user` int(11) NOT NULL,
- `type` enum('private','public') CHARACTER SET utf8 DEFAULT NULL,
- `rules` mediumtext NOT NULL,
- `name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
- `logic_operator` varchar(3) CHARACTER SET utf8 DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','360006');
- }
-
- /**
- * update_360007
- * This fixes the session table
- */
- public static function update_360007() {
- $sql = "ALTER TABLE `session` MODIFY `type` ENUM ('mysql','ldap','http','api','xml-rpc','local') NOT NULL";
- $db_results = Dba::write($sql);
- self::set_version('db_version','360007');
- }
-
- /**
- * update_360008
- * Fix bug that caused the remote_username/password fields to not be created
- */
- public static function update_360008() {
-
- $remote_username = false;
- $remote_password = false;
-
- $sql = "DESCRIBE `catalog`";
- $db_results = Dba::read($sql);
-
- while ($row = Dba::fetch_assoc($db_results)) {
- if ($row['Field'] == 'remote_username') {
- $remote_username = true;
- }
- if ($row['Field'] == 'remote_password') {
- $remote_password = true;
- }
- } // end while
-
- if (!$remote_username) {
- // Add in Username / Password for catalog - to be used for remote catalogs
- $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`";
- $db_results = Dba::write($sql);
- }
- if (!$remote_password) {
- $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`";
- $db_results = Dba::write($sql);
- }
-
- self::set_version('db_version','360008');
-
- } // update_360008
-
-
- /**
- * update_360009
- * The main session table was already updated to use varchar(64) for the ID,
- * tmp_playlist needs the same change
- */
- public static function update_360009() {
- $sql = "ALTER TABLE `tmp_playlist` CHANGE `session` `session` VARCHAR(64)";
- $db_results = Dba::write($sql);
-
- self::set_version('db_version','360009');
- }
-
- /**
- * update_360010
- * MBz NGS means collaborations have more than one MBID (the ones
- * belonging to the underlying artists). We need a bigger column.
- */
- public static function update_360010() {
- $sql = 'ALTER TABLE `artist` CHANGE `mbid` `mbid` VARCHAR(1369)';
- $db_results = Dba::write($sql);
-
- self::set_version('db_version', '360010');
- }
-
- /**
- * update_380011
- * We need a place to store actual playlist data for downloadable
- * playlist files.
- */
- public static function update_360011() {
- $sql = 'CREATE TABLE `stream_playlist` (' .
- '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,' .
- '`sid` varchar(64) NOT NULL,' .
- '`url` text NOT NULL,' .
- '`info_url` text DEFAULT NULL,' .
- '`image_url` text DEFAULT NULL,' .
- '`title` varchar(255) DEFAULT NULL,' .
- '`author` varchar(255) DEFAULT NULL,' .
- '`album` varchar(255) DEFAULT NULL,' .
- '`type` varchar(255) DEFAULT NULL,' .
- '`time` smallint(5) DEFAULT NULL,' .
- 'PRIMARY KEY (`id`), KEY `sid` (`sid`))';
- $db_results = Dba::write($sql);
- self::set_version('db_version', '360011');
- }
+ * update_360004
+ * This update creates an index on the rating table.
+ */
+ public static function update_360004() {
+ $sql = "CREATE UNIQUE INDEX `unique_rating` ON `rating` (`user`, `object_type`, `object_id`)";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','360004');
+ } // update_360004
+
+ /**
+ * update_360005
+ * This changes the tmp_browse table around.
+ */
+ public static function update_360005() {
+ $sql = "DROP TABLE `tmp_browse`";
+ $db_results = Dba::write($sql);
+
+ $sql = "CREATE TABLE `tmp_browse` (" .
+ "`id` int(13) NOT NULL auto_increment," .
+ "`sid` varchar(128) character set utf8 NOT NULL default ''," .
+ "`data` longtext NOT NULL," .
+ "`object_data` longtext," .
+ "PRIMARY KEY (`sid`,`id`)" .
+ ") ENGINE=MyISAM DEFAULT CHARSET=utf8";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','360005');
+ } // update_360005
+
+ /**
+ * update_360006
+ * This adds the table for newsearch/dynamic playlists
+ */
+ public static function update_360006() {
+ $sql = "CREATE TABLE `search` (
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `user` int(11) NOT NULL,
+ `type` enum('private','public') CHARACTER SET utf8 DEFAULT NULL,
+ `rules` mediumtext NOT NULL,
+ `name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
+ `logic_operator` varchar(3) CHARACTER SET utf8 DEFAULT NULL,
+ PRIMARY KEY (`id`)
+ ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','360006');
+ }
+
+ /**
+ * update_360007
+ * This fixes the session table
+ */
+ public static function update_360007() {
+ $sql = "ALTER TABLE `session` MODIFY `type` ENUM ('mysql','ldap','http','api','xml-rpc','local') NOT NULL";
+ $db_results = Dba::write($sql);
+ self::set_version('db_version','360007');
+ }
+
+ /**
+ * update_360008
+ * Fix bug that caused the remote_username/password fields to not be created
+ */
+ public static function update_360008() {
+
+ $remote_username = false;
+ $remote_password = false;
+
+ $sql = "DESCRIBE `catalog`";
+ $db_results = Dba::read($sql);
+
+ while ($row = Dba::fetch_assoc($db_results)) {
+ if ($row['Field'] == 'remote_username') {
+ $remote_username = true;
+ }
+ if ($row['Field'] == 'remote_password') {
+ $remote_password = true;
+ }
+ } // end while
+
+ if (!$remote_username) {
+ // Add in Username / Password for catalog - to be used for remote catalogs
+ $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`";
+ $db_results = Dba::write($sql);
+ }
+ if (!$remote_password) {
+ $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`";
+ $db_results = Dba::write($sql);
+ }
+
+ self::set_version('db_version','360008');
+
+ } // update_360008
+
+
+ /**
+ * update_360009
+ * The main session table was already updated to use varchar(64) for the ID,
+ * tmp_playlist needs the same change
+ */
+ public static function update_360009() {
+ $sql = "ALTER TABLE `tmp_playlist` CHANGE `session` `session` VARCHAR(64)";
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version','360009');
+ }
+
+ /**
+ * update_360010
+ * MBz NGS means collaborations have more than one MBID (the ones
+ * belonging to the underlying artists). We need a bigger column.
+ */
+ public static function update_360010() {
+ $sql = 'ALTER TABLE `artist` CHANGE `mbid` `mbid` VARCHAR(1369)';
+ $db_results = Dba::write($sql);
+
+ self::set_version('db_version', '360010');
+ }
+
+ /**
+ * update_380011
+ * We need a place to store actual playlist data for downloadable
+ * playlist files.
+ */
+ public static function update_360011() {
+ $sql = 'CREATE TABLE `stream_playlist` (' .
+ '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,' .
+ '`sid` varchar(64) NOT NULL,' .
+ '`url` text NOT NULL,' .
+ '`info_url` text DEFAULT NULL,' .
+ '`image_url` text DEFAULT NULL,' .
+ '`title` varchar(255) DEFAULT NULL,' .
+ '`author` varchar(255) DEFAULT NULL,' .
+ '`album` varchar(255) DEFAULT NULL,' .
+ '`type` varchar(255) DEFAULT NULL,' .
+ '`time` smallint(5) DEFAULT NULL,' .
+ 'PRIMARY KEY (`id`), KEY `sid` (`sid`))';
+ $db_results = Dba::write($sql);
+ self::set_version('db_version', '360011');
+ }
} // end update class
?>
diff --git a/lib/class/user.class.php b/lib/class/user.class.php
index 01f709f2..edc711e9 100644
--- a/lib/class/user.class.php
+++ b/lib/class/user.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,1089 +30,1089 @@
*/
class User extends database_object {
- //Basic Componets
- public $id;
- public $username;
- public $fullname;
- public $access;
- public $disabled;
- public $email;
- public $last_seen;
- public $create_date;
- public $validation;
+ //Basic Componets
+ public $id;
+ public $username;
+ public $fullname;
+ public $access;
+ public $disabled;
+ public $email;
+ public $last_seen;
+ public $create_date;
+ public $validation;
- // Constructed variables
- public $prefs = array();
+ // Constructed variables
+ public $prefs = array();
- /**
- * Constructor
- * This function is the constructor object for the user
- * class, it currently takes a username
- */
- public function __construct($user_id=0) {
+ /**
+ * Constructor
+ * This function is the constructor object for the user
+ * class, it currently takes a username
+ */
+ public function __construct($user_id=0) {
- if (!$user_id) { return false; }
+ if (!$user_id) { return false; }
- $this->id = intval($user_id);
+ $this->id = intval($user_id);
- $info = $this->_get_info();
+ $info = $this->_get_info();
- foreach ($info as $key=>$value) {
- // Let's not save the password in this object :S
- if ($key == 'password') { continue; }
- $this->$key = $value;
- }
+ foreach ($info as $key=>$value) {
+ // Let's not save the password in this object :S
+ if ($key == 'password') { continue; }
+ $this->$key = $value;
+ }
- // Make sure the Full name is always filled
- if (strlen($this->fullname) < 1) { $this->fullname = $this->username; }
+ // Make sure the Full name is always filled
+ if (strlen($this->fullname) < 1) { $this->fullname = $this->username; }
- } // Constructor
+ } // Constructor
- /**
- * _get_info
- * This function returns the information for this object
- */
- private function _get_info() {
+ /**
+ * _get_info
+ * This function returns the information for this object
+ */
+ private function _get_info() {
- $id = intval($this->id);
+ $id = intval($this->id);
- if (parent::is_cached('user',$id)) {
- return parent::get_from_cache('user',$id);
- }
+ if (parent::is_cached('user',$id)) {
+ return parent::get_from_cache('user',$id);
+ }
- // If the ID is -1 then
- if ($id == '-1') {
- $data['username'] = 'System';
- $data['fullname'] = 'Ampache User';
- $data['access'] = '25';
- return $data;
- }
+ // If the ID is -1 then
+ if ($id == '-1') {
+ $data['username'] = 'System';
+ $data['fullname'] = 'Ampache User';
+ $data['access'] = '25';
+ return $data;
+ }
- $sql = "SELECT * FROM `user` WHERE `id`='$id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `user` WHERE `id`='$id'";
+ $db_results = Dba::read($sql);
- $data = Dba::fetch_assoc($db_results);
+ $data = Dba::fetch_assoc($db_results);
- parent::add_to_cache('user',$id,$data);
+ parent::add_to_cache('user',$id,$data);
- return $data;
+ return $data;
- } // _get_info
+ } // _get_info
- /**
- * load_playlist
- * This is called once per page load it makes sure that this session
- * has a tmp_playlist, creating it if it doesn't, then sets $this->playlist
- * as a tmp_playlist object that can be fiddled with later on
- */
- public function load_playlist() {
+ /**
+ * load_playlist
+ * This is called once per page load it makes sure that this session
+ * has a tmp_playlist, creating it if it doesn't, then sets $this->playlist
+ * as a tmp_playlist object that can be fiddled with later on
+ */
+ public function load_playlist() {
- $session_id = session_id();
+ $session_id = session_id();
- $this->playlist = Tmp_Playlist::get_from_session($session_id);
+ $this->playlist = Tmp_Playlist::get_from_session($session_id);
- } // load_playlist
+ } // load_playlist
- /**
- * get_from_username
- * This returns a built user from a username. This is a
- * static function so it doesn't require an instance
- */
- public static function get_from_username($username) {
+ /**
+ * get_from_username
+ * This returns a built user from a username. This is a
+ * static function so it doesn't require an instance
+ */
+ public static function get_from_username($username) {
- $username = Dba::escape($username);
+ $username = Dba::escape($username);
- $sql = "SELECT `id` FROM `user` WHERE `username`='$username'";
- $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $sql = "SELECT `id` FROM `user` WHERE `username`='$username'";
+ $db_results = Dba::read($sql);
+ $results = Dba::fetch_assoc($db_results);
- $user = new User($results['id']);
+ $user = new User($results['id']);
- return $user;
+ return $user;
- } // get_from_username
+ } // get_from_username
- /**
- * get_from_email
- * This returns a built user from a email. This is a
- * static function so it doesn't require an instance
- */
- public static function get_from_email($email) {
+ /**
+ * get_from_email
+ * This returns a built user from a email. This is a
+ * static function so it doesn't require an instance
+ */
+ public static function get_from_email($email) {
- $email = Dba::escape($email);
+ $email = Dba::escape($email);
- $sql = "SELECT `id` FROM `user` WHERE `email`='$email'";
- $db_results = Dba::read($sql);
- $results = Dba::fetch_assoc($db_results);
+ $sql = "SELECT `id` FROM `user` WHERE `email`='$email'";
+ $db_results = Dba::read($sql);
+ $results = Dba::fetch_assoc($db_results);
- $user = new User($results['id']);
+ $user = new User($results['id']);
- return $user;
+ return $user;
- } // get_from_username
+ } // get_from_username
- /**
- * get_catalogs
- * This returns the catalogs as an array of ids that this user is allowed to access
- */
- public function get_catalogs() {
+ /**
+ * get_catalogs
+ * This returns the catalogs as an array of ids that this user is allowed to access
+ */
+ public function get_catalogs() {
- if (parent::is_cached('user_catalog',$this->id)) {
- return parent::get_from_cache('user_catalog',$this->id);
- }
+ if (parent::is_cached('user_catalog',$this->id)) {
+ return parent::get_from_cache('user_catalog',$this->id);
+ }
- $sql = "SELECT * FROM `user_catalog` WHERE `user`='$user_id'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `user_catalog` WHERE `user`='$user_id'";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $catalogs[] = $row['catalog'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $catalogs[] = $row['catalog'];
+ }
- parent::add_to_cache('user_catalog',$this->id,$catalogs);
+ parent::add_to_cache('user_catalog',$this->id,$catalogs);
- return $catalogs;
+ return $catalogs;
- } // get_catalogs
+ } // get_catalogs
- /**
- * get_preferences
- * This is a little more complicate now that we've got many types of preferences
- * This funtions pulls all of them an arranges them into a spiffy little array
- * You can specify a type to limit it to a single type of preference
- * []['title'] = ucased type name
- * []['prefs'] = array(array('name','display','value'));
- * []['admin'] = t/f value if this is an admin only section
- */
- function get_preferences($type = 0, $system = false) {
+ /**
+ * get_preferences
+ * This is a little more complicate now that we've got many types of preferences
+ * This funtions pulls all of them an arranges them into a spiffy little array
+ * You can specify a type to limit it to a single type of preference
+ * []['title'] = ucased type name
+ * []['prefs'] = array(array('name','display','value'));
+ * []['admin'] = t/f value if this is an admin only section
+ */
+ function get_preferences($type = 0, $system = false) {
- // Fill out the user id
- $user_id = $system ? Dba::escape(-1) : Dba::escape($this->id);
+ // Fill out the user id
+ $user_id = $system ? Dba::escape(-1) : Dba::escape($this->id);
- if (!$system) {
- $user_limit = "AND preference.catagory != 'system'";
- }
-
- if ($type != '0') {
- $user_limit = "AND preference.catagory = '" . Dba::escape($type) . "'";
- }
-
-
- $sql = "SELECT preference.name, preference.description, preference.catagory, preference.level, user_preference.value " .
- "FROM preference INNER JOIN user_preference ON user_preference.preference=preference.id " .
- "WHERE user_preference.user='$user_id' " . $user_limit .
- " ORDER BY preference.catagory, preference.description";
-
- $db_results = Dba::read($sql);
-
- /* Ok this is crapy, need to clean this up or improve the code FIXME */
- while ($r = Dba::fetch_assoc($db_results)) {
- $type = $r['catagory'];
- $admin = false;
- if ($type == 'system') { $admin = true; }
- $type_array[$type][$r['name']] = array('name'=>$r['name'],'level'=>$r['level'],'description'=>$r['description'],'value'=>$r['value']);
- $results[$type] = array ('title'=>ucwords($type),'admin'=>$admin,'prefs'=>$type_array[$type]);
- } // end while
-
- return $results;
-
- } // get_preferences
-
- /**
- * set_preferences
- * sets the prefs for this specific user
- */
- public function set_preferences() {
-
- $user_id = Dba::escape($this->id);
-
- $sql = "SELECT preference.name,user_preference.value FROM preference,user_preference WHERE user_preference.user='$user_id' " .
- "AND user_preference.preference=preference.id AND preference.type != 'system'";
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $key = $r['name'];
- $this->prefs[$key] = $r['value'];
- }
- } // set_preferences
-
- /**
- * get_favorites
- * returns an array of your $type favorites
- */
- function get_favorites($type) {
-
- $web_path = Config::get('web_path');
-
- $results = Stats::get_user(Config::get('popular_threshold'),$type,$this->id,1);
-
- $items = array();
-
- foreach ($results as $r) {
- /* If its a song */
- if ($type == 'song') {
- $data = new Song($r['object_id']);
- $data->count = $r['count'];
- $data->format();
- $data->f_name = $data->f_link;
- $items[] = $data;
- }
- /* If its an album */
- elseif ($type == 'album') {
- $data = new Album($r['object_id']);
- $data->count = $r['count'];
- $data->format();
- $items[] = $data;
- }
- /* If its an artist */
- elseif ($type == 'artist') {
- $data = new Artist($r['object_id']);
- $data->count = $r['count'];
- $data->format();
- $data->f_name = $data->f_link;
- $items[] = $data;
- }
- /* If it's a genre */
- elseif ($type == 'genre') {
- $data = new Genre($r['object_id']);
- $data->count = $r['count'];
- $data->format();
- $data->f_name = $data->f_link;
- $items[] = $data;
- }
-
- } // end foreach
-
- return $items;
-
- } // 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='" . Dba::escape($type) . "' AND user='" . Dba::escape($this->id) . "'";
- $db_results = Dba::read($sql);
-
- // Incase they only have one user
- $users = array();
-
- while ($r = Dba::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='" . Dba::escape($type) . "' " .
- "AND user !='" . Dba::escape($this->id) . "' AND object_id='" . Dba::escape($r['object_id']) . "' " .
- "AND user_rating ='" . Dba::escape($r['user_rating']) . "'";
- $user_results = Dba::read($sql);
-
- while ($user_info = Dba::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
- */
- $recommendations = array();
- asort($users);
-
- foreach ($users as $user_id=>$score) {
-
- /* Find everything they've rated at 4+ */
- $sql = "SELECT object_id,user_rating FROM ratings " .
- "WHERE user='" . Dba::escape($user_id) . "' AND user_rating >='4' AND " .
- "object_type = '" . Dba::escape($type) . "' ORDER BY user_rating DESC";
- $db_results = Dba::read($sql);
-
- while ($r = Dba::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
-
- /**
- * is_logged_in
- * checks to see if $this user is logged in returns their current IP if they
- * are logged in
- */
- public function is_logged_in() {
-
- $username = Dba::escape($this->username);
-
- $sql = "SELECT `id`,`ip` FROM `session` WHERE `username`='$username'" .
- " AND `expire` > ". time();
- $db_results = Dba::read($sql);
-
- if ($row = Dba::fetch_assoc($db_results)) {
- $ip = $row['ip'] ? $row['ip'] : NULL;
- return $ip;
- }
-
- return false;
-
- } // is_logged_in
+ if (!$system) {
+ $user_limit = "AND preference.catagory != 'system'";
+ }
+
+ if ($type != '0') {
+ $user_limit = "AND preference.catagory = '" . Dba::escape($type) . "'";
+ }
+
+
+ $sql = "SELECT preference.name, preference.description, preference.catagory, preference.level, user_preference.value " .
+ "FROM preference INNER JOIN user_preference ON user_preference.preference=preference.id " .
+ "WHERE user_preference.user='$user_id' " . $user_limit .
+ " ORDER BY preference.catagory, preference.description";
+
+ $db_results = Dba::read($sql);
+
+ /* Ok this is crapy, need to clean this up or improve the code FIXME */
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $type = $r['catagory'];
+ $admin = false;
+ if ($type == 'system') { $admin = true; }
+ $type_array[$type][$r['name']] = array('name'=>$r['name'],'level'=>$r['level'],'description'=>$r['description'],'value'=>$r['value']);
+ $results[$type] = array ('title'=>ucwords($type),'admin'=>$admin,'prefs'=>$type_array[$type]);
+ } // end while
+
+ return $results;
+
+ } // get_preferences
+
+ /**
+ * set_preferences
+ * sets the prefs for this specific user
+ */
+ public function set_preferences() {
+
+ $user_id = Dba::escape($this->id);
+
+ $sql = "SELECT preference.name,user_preference.value FROM preference,user_preference WHERE user_preference.user='$user_id' " .
+ "AND user_preference.preference=preference.id AND preference.type != 'system'";
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $key = $r['name'];
+ $this->prefs[$key] = $r['value'];
+ }
+ } // set_preferences
+
+ /**
+ * get_favorites
+ * returns an array of your $type favorites
+ */
+ function get_favorites($type) {
+
+ $web_path = Config::get('web_path');
+
+ $results = Stats::get_user(Config::get('popular_threshold'),$type,$this->id,1);
+
+ $items = array();
+
+ foreach ($results as $r) {
+ /* If its a song */
+ if ($type == 'song') {
+ $data = new Song($r['object_id']);
+ $data->count = $r['count'];
+ $data->format();
+ $data->f_name = $data->f_link;
+ $items[] = $data;
+ }
+ /* If its an album */
+ elseif ($type == 'album') {
+ $data = new Album($r['object_id']);
+ $data->count = $r['count'];
+ $data->format();
+ $items[] = $data;
+ }
+ /* If its an artist */
+ elseif ($type == 'artist') {
+ $data = new Artist($r['object_id']);
+ $data->count = $r['count'];
+ $data->format();
+ $data->f_name = $data->f_link;
+ $items[] = $data;
+ }
+ /* If it's a genre */
+ elseif ($type == 'genre') {
+ $data = new Genre($r['object_id']);
+ $data->count = $r['count'];
+ $data->format();
+ $data->f_name = $data->f_link;
+ $items[] = $data;
+ }
+
+ } // end foreach
+
+ return $items;
+
+ } // 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='" . Dba::escape($type) . "' AND user='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::read($sql);
+
+ // Incase they only have one user
+ $users = array();
+
+ while ($r = Dba::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='" . Dba::escape($type) . "' " .
+ "AND user !='" . Dba::escape($this->id) . "' AND object_id='" . Dba::escape($r['object_id']) . "' " .
+ "AND user_rating ='" . Dba::escape($r['user_rating']) . "'";
+ $user_results = Dba::read($sql);
+
+ while ($user_info = Dba::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
+ */
+ $recommendations = array();
+ asort($users);
+
+ foreach ($users as $user_id=>$score) {
+
+ /* Find everything they've rated at 4+ */
+ $sql = "SELECT object_id,user_rating FROM ratings " .
+ "WHERE user='" . Dba::escape($user_id) . "' AND user_rating >='4' AND " .
+ "object_type = '" . Dba::escape($type) . "' ORDER BY user_rating DESC";
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::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
+
+ /**
+ * is_logged_in
+ * checks to see if $this user is logged in returns their current IP if they
+ * are logged in
+ */
+ public function is_logged_in() {
+
+ $username = Dba::escape($this->username);
+
+ $sql = "SELECT `id`,`ip` FROM `session` WHERE `username`='$username'" .
+ " AND `expire` > ". time();
+ $db_results = Dba::read($sql);
+
+ if ($row = Dba::fetch_assoc($db_results)) {
+ $ip = $row['ip'] ? $row['ip'] : NULL;
+ return $ip;
+ }
+
+ return false;
+
+ } // is_logged_in
- /**
- * has_access
- * this function checkes to see if this user has access
- * to the passed action (pass a level requirement)
- */
- function has_access($needed_level) {
+ /**
+ * has_access
+ * this function checkes to see if this user has access
+ * to the passed action (pass a level requirement)
+ */
+ function has_access($needed_level) {
- if (!Config::get('use_auth') || Config::get('demo_mode')) { return true; }
+ if (!Config::get('use_auth') || Config::get('demo_mode')) { return true; }
- if ($this->access >= $needed_level) { return true; }
+ if ($this->access >= $needed_level) { return true; }
- return false;
+ return false;
- } // has_access
+ } // has_access
- /**
- * update
- * This function is an all encompasing update function that
- * calls the mini ones does all the error checking and all that
- * good stuff
- */
- public function update($data) {
+ /**
+ * update
+ * This function is an all encompasing update function that
+ * calls the mini ones does all the error checking and all that
+ * good stuff
+ */
+ public function update($data) {
- if (empty($data['username'])) {
- Error::add('username', T_('Error Username Required'));
- }
+ if (empty($data['username'])) {
+ Error::add('username', T_('Error Username Required'));
+ }
- if ($data['password1'] != $data['password2'] AND !empty($data['password1'])) {
- Error::add('password', T_("Error Passwords don't match"));
- }
+ if ($data['password1'] != $data['password2'] AND !empty($data['password1'])) {
+ Error::add('password', T_("Error Passwords don't match"));
+ }
- if (Error::occurred()) {
- return false;
- }
+ if (Error::occurred()) {
+ return false;
+ }
- foreach ($data as $name=>$value) {
- switch ($name) {
- case 'password1';
- $name = 'password';
- case 'access':
- case 'email':
- case 'username':
- case 'fullname';
- if ($this->$name != $value) {
- $function = 'update_' . $name;
- $this->$function($value);
- }
- break;
- default:
- // Rien a faire
- break;
- } // end switch on field
+ foreach ($data as $name=>$value) {
+ switch ($name) {
+ case 'password1';
+ $name = 'password';
+ case 'access':
+ case 'email':
+ case 'username':
+ case 'fullname';
+ if ($this->$name != $value) {
+ $function = 'update_' . $name;
+ $this->$function($value);
+ }
+ break;
+ default:
+ // Rien a faire
+ break;
+ } // end switch on field
- } // end foreach
+ } // end foreach
- return true;
+ return true;
- } // update
+ } // update
- /**
- * update_username
- * updates their username
- */
- public function update_username($new_username) {
+ /**
+ * update_username
+ * updates their username
+ */
+ public function update_username($new_username) {
- $new_username = Dba::escape($new_username);
- $sql = "UPDATE `user` SET `username`='$new_username' WHERE `id`='$this->id'";
- $this->username = $new_username;
- $db_results = Dba::write($sql);
+ $new_username = Dba::escape($new_username);
+ $sql = "UPDATE `user` SET `username`='$new_username' WHERE `id`='$this->id'";
+ $this->username = $new_username;
+ $db_results = Dba::write($sql);
- } // update_username
+ } // update_username
- /**
- * update_validation
- * This is used by the registration mumbojumbo
- * Use this function to update the validation key
- * NOTE: crap this doesn't have update_item the humanity of it all
- */
- public function update_validation($new_validation) {
+ /**
+ * update_validation
+ * This is used by the registration mumbojumbo
+ * Use this function to update the validation key
+ * NOTE: crap this doesn't have update_item the humanity of it all
+ */
+ public function update_validation($new_validation) {
- $new_validation = Dba::escape($new_validation);
- $sql = "UPDATE `user` SET `validation`='$new_validation', `disabled`='1' WHERE `id`='" . Dba::escape($this->id) . "'";
- $db_results = Dba::write($sql);
- $this->validation = $new_validation;
+ $new_validation = Dba::escape($new_validation);
+ $sql = "UPDATE `user` SET `validation`='$new_validation', `disabled`='1' WHERE `id`='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::write($sql);
+ $this->validation = $new_validation;
- return $db_results;
+ return $db_results;
- } // update_validation
+ } // update_validation
- /**
- * update_fullname
- * updates their fullname
- */
- public function update_fullname($new_fullname) {
+ /**
+ * update_fullname
+ * updates their fullname
+ */
+ public function update_fullname($new_fullname) {
- $new_fullname = Dba::escape($new_fullname);
- $sql = "UPDATE `user` SET `fullname`='$new_fullname' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- } // update_fullname
-
- /**
- * update_email
- * updates their email address
- */
- public function update_email($new_email) {
+ $new_fullname = Dba::escape($new_fullname);
+ $sql = "UPDATE `user` SET `fullname`='$new_fullname' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ } // update_fullname
+
+ /**
+ * update_email
+ * updates their email address
+ */
+ public function update_email($new_email) {
- $new_email = Dba::escape($new_email);
- $sql = "UPDATE `user` SET `email`='$new_email' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
+ $new_email = Dba::escape($new_email);
+ $sql = "UPDATE `user` SET `email`='$new_email' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
- } // update_email
-
- /**
- * disable
- * This disables the current user
- */
- public function disable() {
-
- // Make sure we aren't disabling the last admin
- $sql = "SELECT `id` FROM `user` WHERE `disabled` = '0' AND `id` != '" . $this->id . "' AND `access`='100'";
- $db_results = Dba::read($sql);
-
- if (!Dba::num_rows($db_results)) { return false; }
-
- $sql = "UPDATE `user` SET `disabled`='1' WHERE id='" . $this->id . "'";
- $db_results = Dba::write($sql);
-
- // Delete any sessions they may have
- $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'";
- $db_results = Dba::write($sql);
-
- return true;
-
- } // disable
-
- /**
- * enable
- * this enables the current user
- */
- public function enable() {
-
- $sql = "UPDATE `user` SET `disabled`='0' WHERE id='" . $this->id . "'";
- $db_results = Dba::write($sql);
+ } // update_email
+
+ /**
+ * disable
+ * This disables the current user
+ */
+ public function disable() {
+
+ // Make sure we aren't disabling the last admin
+ $sql = "SELECT `id` FROM `user` WHERE `disabled` = '0' AND `id` != '" . $this->id . "' AND `access`='100'";
+ $db_results = Dba::read($sql);
+
+ if (!Dba::num_rows($db_results)) { return false; }
+
+ $sql = "UPDATE `user` SET `disabled`='1' WHERE id='" . $this->id . "'";
+ $db_results = Dba::write($sql);
+
+ // Delete any sessions they may have
+ $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'";
+ $db_results = Dba::write($sql);
+
+ return true;
+
+ } // disable
+
+ /**
+ * enable
+ * this enables the current user
+ */
+ public function enable() {
+
+ $sql = "UPDATE `user` SET `disabled`='0' WHERE id='" . $this->id . "'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // enable
+ } // enable
- /**
- * update_access
- * updates their access level
- */
- public function update_access($new_access) {
+ /**
+ * update_access
+ * updates their access level
+ */
+ public function update_access($new_access) {
- /* Prevent Only User accounts */
- if ($new_access < '100') {
- $sql = "SELECT `id` FROM user WHERE `access`='100' AND `id` != '$this->id'";
- $db_results = Dba::read($sql);
- if (!Dba::num_rows($db_results)) { return false; }
- }
-
- $new_access = Dba::escape($new_access);
- $sql = "UPDATE `user` SET `access`='$new_access' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- } // update_access
-
- /*!
- @function update_last_seen
- @discussion updates the last seen data for this user
- */
- function update_last_seen() {
-
- $sql = "UPDATE user SET last_seen='" . time() . "' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
+ /* Prevent Only User accounts */
+ if ($new_access < '100') {
+ $sql = "SELECT `id` FROM user WHERE `access`='100' AND `id` != '$this->id'";
+ $db_results = Dba::read($sql);
+ if (!Dba::num_rows($db_results)) { return false; }
+ }
+
+ $new_access = Dba::escape($new_access);
+ $sql = "UPDATE `user` SET `access`='$new_access' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ } // update_access
+
+ /*!
+ @function update_last_seen
+ @discussion updates the last seen data for this user
+ */
+ function update_last_seen() {
+
+ $sql = "UPDATE user SET last_seen='" . time() . "' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
- } // update_last_seen
+ } // update_last_seen
- /**
- * update_user_stats
- * updates the playcount mojo for this specific user
- */
- public function update_stats($song_id) {
+ /**
+ * update_user_stats
+ * updates the playcount mojo for this specific user
+ */
+ public function update_stats($song_id) {
- $song_info = new Song($song_id);
- $song_info->format();
- $user = $this->id;
+ $song_info = new Song($song_id);
+ $song_info->format();
+ $user = $this->id;
- if (!strlen($song_info->file)) { return false; }
+ if (!strlen($song_info->file)) { return false; }
- $this->set_preferences();
+ $this->set_preferences();
- foreach (Plugin::get_plugins('save_songplay') as $plugin_name) {
- $plugin = new Plugin($plugin_name);
- if ($plugin->load()) {
- $plugin->_plugin->save_songplay($song_info);
- }
- }
+ foreach (Plugin::get_plugins('save_songplay') as $plugin_name) {
+ $plugin = new Plugin($plugin_name);
+ if ($plugin->load()) {
+ $plugin->_plugin->save_songplay($song_info);
+ }
+ }
- // Do this last so the 'last played checks are correct'
- Stats::insert('song',$song_id,$user);
- Stats::insert('album',$song_info->album,$user);
- Stats::insert('artist',$song_info->artist,$user);
+ // Do this last so the 'last played checks are correct'
+ Stats::insert('song',$song_id,$user);
+ Stats::insert('album',$song_info->album,$user);
+ Stats::insert('artist',$song_info->artist,$user);
- return true;
+ return true;
- } // update_stats
+ } // update_stats
- /**
- * insert_ip_history
- * This inserts a row into the IP History recording this user at this
- * address at this time in this place, doing this thing.. you get the point
- */
- public function insert_ip_history() {
+ /**
+ * insert_ip_history
+ * This inserts a row into the IP History recording this user at this
+ * address at this time in this place, doing this thing.. you get the point
+ */
+ public function insert_ip_history() {
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
- $sip = $_SERVER['HTTP_X_FORWARDED_FOR'];
- debug_event('User Ip', 'Login from ip adress: ' . $sip,'3');
- }
- else {
- $sip = $_SERVER['REMOTE_ADDR'];
- debug_event('User Ip', 'Login from ip adress: ' . $sip,'3');
- }
+ if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
+ $sip = $_SERVER['HTTP_X_FORWARDED_FOR'];
+ debug_event('User Ip', 'Login from ip adress: ' . $sip,'3');
+ }
+ else {
+ $sip = $_SERVER['REMOTE_ADDR'];
+ debug_event('User Ip', 'Login from ip adress: ' . $sip,'3');
+ }
- $ip = Dba::escape(inet_pton($sip));
- $date = time();
- $user = $this->id;
- $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']);
-
- $sql = "INSERT INTO `ip_history` (`ip`,`user`,`date`,`agent`) VALUES ('$ip','$user','$date','$agent')";
- $db_results = Dba::write($sql);
-
- /* Clean up old records... sometimes */
- if (rand(1,100) > 60) {
- $date = time() - (86400*Config::get('user_ip_cardinality'));
- $sql = "DELETE FROM `ip_history` WHERE `date` < $date";
- $db_results = Dba::write($sql);
- }
-
- return true;
-
- } // insert_ip_history
-
- /**
- * create
- * inserts a new user into ampache
- */
- public static function create($username, $fullname, $email, $password, $access, $disabled = false) {
-
- /* Lets clean up the fields... */
- $username = Dba::escape($username);
- $fullname = Dba::escape($fullname);
- $email = Dba::escape($email);
- $access = Dba::escape($access);
- $password = hash('sha256', $password);
- $disabled = $disabled ? 1 : 0;
-
- /* Now Insert this new user */
- $sql = "INSERT INTO `user` (`username`, `disabled`, " .
- "`fullname`, `email`, `password`, `access`, " .
- "`create_date`)" .
- "VALUES('$username', '$disabled', '$fullname', " .
- "'$email', '$password', '$access', '" . time() ."')";
- $db_results = Dba::write($sql);
-
- if (!$db_results) { return false; }
-
- // Get the insert_id
- $insert_id = Dba::insert_id();
-
- /* Populates any missing preferences, in this case all of them */
- self::fix_preferences($insert_id);
-
- return $insert_id;
-
- } // create
-
- /**
- * update_password
- * updates a users password
- */
- public function update_password($new_password) {
-
- $new_password = hash('sha256',$new_password);
-
- $new_password = Dba::escape($new_password);
- $sql = "UPDATE `user` SET `password`='$new_password' WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Clear this (temp fix)
- if ($db_results) { unset($_SESSION['userdata']['password']); }
-
- } // update_password
-
- /**
- * format
- * This function sets up the extra variables we need when we are displaying a
- * user for an admin, these should not be normally called when creating a
- * user object
- */
- public function format() {
-
- /* If they have a last seen date */
- if (!$this->last_seen) { $this->f_last_seen = T_('Never'); }
- else { $this->f_last_seen = date("m\/d\/Y - H:i",$this->last_seen); }
-
- /* If they have a create date */
- if (!$this->create_date) { $this->f_create_date = T_('Unknown'); }
- else { $this->f_create_date = date("m\/d\/Y - H:i",$this->create_date); }
-
- // Base link
- $this->f_link = '<a href="' . Config::get('web_path') . '/stats.php?action=show_user&user_id=' . $this->id . '">' . $this->fullname . '</a>';
-
- /* Calculate their total Bandwidth Useage */
- $sql = "SELECT `song`.`size` FROM `song` LEFT JOIN `object_count` ON `song`.`id`=`object_count`.`object_id` " .
- "WHERE `object_count`.`user`='$this->id' AND `object_count`.`object_type`='song'";
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $total = $total + $r['size'];
- }
-
- $this->f_useage = UI::format_bytes($total);
-
- /* Get Users Last ip */
- if (count($data = $this->get_ip_history(1))) {
- $this->ip_history = inet_ntop($data['0']['ip']);
- }
- else {
- $this->ip_history = T_('Not Enough Data');
- }
-
- } // format_user
-
- /**
- * format_favorites
- * takes an array of objects and formats them corrrectly
- * and returns a simply array with just <a href values
- */
- public function format_favorites($items) {
-
- // The length of the longest item
- $maxlen = strlen($items[0]->count);
-
- // Go through the favs
- foreach ($items as $data) {
-
- // Make all number lengths equal
- $len = strlen($data->count);
- while ($len < $maxlen) {
- $data->count = "0" . $data->count;
- $len++;
- }
-
- $item = "[$data->count] - $data->f_name";
- $results[]->f_name_link = $item;
- } // end foreach items
-
- return $results;
-
- } // 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->link;
- break;
- case 'album':
- $object = new Album($object_id);
- $object->format_album();
- $name = $object->f_link;
- break;
- case 'song':
- $object = new Song($object_id);
- $object->format_song();
- $name = $object->f_link;
- break;
- } // end switch on type
- $results[] = "<li>$name -- " . get_rating_name($rating) . "<br />\n</li>";
-
- } // end foreach items
-
-
- return $results;
-
- } // format_recommendations
-
- /**
- * access_name_to_level
- * This takes the access name for the user and returns the level
- */
- public static function access_name_to_level($level) {
-
- switch ($level) {
- case 'admin':
- return '100';
- break;
- case 'user':
- return '25';
- break;
- case 'manager':
- return '75';
- break;
- case 'guest':
- return '5';
- break;
- default:
- return '0';
- break;
- }
-
- return false;
-
- } // access_name_to_level
-
- /**
- * fix_preferences
- * This is the new fix_preferences function, it does the following
- * Remove Duplicates from user, add in missing
- * If -1 is passed it also removes duplicates from the `preferences`
- * table.
- */
- public static function fix_preferences($user_id) {
-
- $user_id = Dba::escape($user_id);
-
- /* Get All Preferences for the current user */
- $sql = "SELECT * FROM `user_preference` WHERE `user`='$user_id'";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $pref_id = $r['preference'];
- /* Check for duplicates */
- if (isset($results[$pref_id])) {
- $r['value'] = Dba::escape($r['value']);
- $sql = "DELETE FROM `user_preference` WHERE `user`='$user_id' AND `preference`='" . $r['preference'] . "' AND" .
- " `value`='" . Dba::escape($r['value']) . "'";
- $delete_results = Dba::write($sql);
- } // if its set
- else {
- $results[$pref_id] = 1;
- }
- } // end while
-
- /* If we aren't the -1 user before we continue grab the -1 users values */
- if ($user_id != '-1') {
- $sql = "SELECT `user_preference`.`preference`,`user_preference`.`value` FROM `user_preference`,`preference` " .
- "WHERE `user_preference`.`preference` = `preference`.`id` AND `user_preference`.`user`='-1' AND `preference`.`catagory` !='system'";
- $db_results = Dba::read($sql);
- /* While through our base stuff */
- while ($r = Dba::fetch_assoc($db_results)) {
- $key = $r['preference'];
- $zero_results[$key] = $r['value'];
- }
- } // if not user -1
-
- // get me _EVERYTHING_
- $sql = "SELECT * FROM `preference`";
-
- // If not system, exclude system... *gasp*
- if ($user_id != '-1') {
- $sql .= " WHERE catagory !='system'";
- }
- $db_results = Dba::read($sql);
-
- while ($r = Dba::fetch_assoc($db_results)) {
-
- $key = $r['id'];
-
- /* Check if this preference is set */
- if (!isset($results[$key])) {
- if (isset($zero_results[$key])) {
- $r['value'] = $zero_results[$key];
- }
- $value = Dba::escape($r['value']);
- $sql = "INSERT INTO user_preference (`user`,`preference`,`value`) VALUES ('$user_id','$key','$value')";
- $insert_db = Dba::write($sql);
- }
- } // while preferences
-
- /* Let's also clean out any preferences garbage left over */
- $sql = "SELECT DISTINCT(user_preference.user) FROM user_preference " .
- "LEFT JOIN user ON user_preference.user = user.id " .
- "WHERE user_preference.user!='-1' AND user.id IS NULL";
- $db_results = Dba::read($sql);
-
- $results = array();
-
- while ($r = Dba::fetch_assoc($db_results)) {
- $results[] = $r['user'];
- }
-
- foreach ($results as $data) {
- $sql = "DELETE FROM user_preference WHERE user='$data'";
- $db_results = Dba::write($sql);
- }
-
- } // fix_preferences
-
- /**
- * delete
- * deletes this user and everything associated with it. This will affect
- * ratings and tottal stats
- */
- public function delete() {
-
- /*
- Before we do anything make sure that they aren't the last
- admin
- */
- if ($this->has_access(100)) {
- $sql = "SELECT `id` FROM `user` WHERE `access`='100' AND id !='" . Dba::escape($this->id) . "'";
- $db_results = Dba::read($sql);
- if (!Dba::num_rows($db_results)) {
- return false;
- }
- } // if this is an admin check for others
-
- // Delete their playlists
- $sql = "DELETE FROM `playlist` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Clean up the playlist data table
- $sql = "DELETE FROM `playlist_data` USING `playlist_data` " .
- "LEFT JOIN `playlist` ON `playlist`.`id`=`playlist_data`.`playlist` " .
- "WHERE `playlist`.`id` IS NULL";
- $db_results = Dba::write($sql);
-
- // Delete any stats they have
- $sql = "DELETE FROM `object_count` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Clear the IP history for this user
- $sql = "DELETE FROM `ip_history` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Nuke any access lists that are specific to this user
- $sql = "DELETE FROM `access_list` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Delete their ratings
- $sql = "DELETE FROM `rating` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Delete their tags
- $sql = "DELETE FROM `tag_map` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
-
- // Clean out the tags
- $sql = "DELETE FROM `tags` USING `tag_map` LEFT JOIN `tag_map` ON tag_map.id=tags.map_id AND tag_map.id IS NULL";
- $db_results = Dba::write($sql);
-
- // Delete their preferences
- $sql = "DELETE FROM `user_preference` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
+ $ip = Dba::escape(inet_pton($sip));
+ $date = time();
+ $user = $this->id;
+ $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']);
+
+ $sql = "INSERT INTO `ip_history` (`ip`,`user`,`date`,`agent`) VALUES ('$ip','$user','$date','$agent')";
+ $db_results = Dba::write($sql);
+
+ /* Clean up old records... sometimes */
+ if (rand(1,100) > 60) {
+ $date = time() - (86400*Config::get('user_ip_cardinality'));
+ $sql = "DELETE FROM `ip_history` WHERE `date` < $date";
+ $db_results = Dba::write($sql);
+ }
+
+ return true;
+
+ } // insert_ip_history
+
+ /**
+ * create
+ * inserts a new user into ampache
+ */
+ public static function create($username, $fullname, $email, $password, $access, $disabled = false) {
+
+ /* Lets clean up the fields... */
+ $username = Dba::escape($username);
+ $fullname = Dba::escape($fullname);
+ $email = Dba::escape($email);
+ $access = Dba::escape($access);
+ $password = hash('sha256', $password);
+ $disabled = $disabled ? 1 : 0;
+
+ /* Now Insert this new user */
+ $sql = "INSERT INTO `user` (`username`, `disabled`, " .
+ "`fullname`, `email`, `password`, `access`, " .
+ "`create_date`)" .
+ "VALUES('$username', '$disabled', '$fullname', " .
+ "'$email', '$password', '$access', '" . time() ."')";
+ $db_results = Dba::write($sql);
+
+ if (!$db_results) { return false; }
+
+ // Get the insert_id
+ $insert_id = Dba::insert_id();
+
+ /* Populates any missing preferences, in this case all of them */
+ self::fix_preferences($insert_id);
+
+ return $insert_id;
+
+ } // create
+
+ /**
+ * update_password
+ * updates a users password
+ */
+ public function update_password($new_password) {
+
+ $new_password = hash('sha256',$new_password);
+
+ $new_password = Dba::escape($new_password);
+ $sql = "UPDATE `user` SET `password`='$new_password' WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Clear this (temp fix)
+ if ($db_results) { unset($_SESSION['userdata']['password']); }
+
+ } // update_password
+
+ /**
+ * format
+ * This function sets up the extra variables we need when we are displaying a
+ * user for an admin, these should not be normally called when creating a
+ * user object
+ */
+ public function format() {
+
+ /* If they have a last seen date */
+ if (!$this->last_seen) { $this->f_last_seen = T_('Never'); }
+ else { $this->f_last_seen = date("m\/d\/Y - H:i",$this->last_seen); }
+
+ /* If they have a create date */
+ if (!$this->create_date) { $this->f_create_date = T_('Unknown'); }
+ else { $this->f_create_date = date("m\/d\/Y - H:i",$this->create_date); }
+
+ // Base link
+ $this->f_link = '<a href="' . Config::get('web_path') . '/stats.php?action=show_user&user_id=' . $this->id . '">' . $this->fullname . '</a>';
+
+ /* Calculate their total Bandwidth Useage */
+ $sql = "SELECT `song`.`size` FROM `song` LEFT JOIN `object_count` ON `song`.`id`=`object_count`.`object_id` " .
+ "WHERE `object_count`.`user`='$this->id' AND `object_count`.`object_type`='song'";
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $total = $total + $r['size'];
+ }
+
+ $this->f_useage = UI::format_bytes($total);
+
+ /* Get Users Last ip */
+ if (count($data = $this->get_ip_history(1))) {
+ $this->ip_history = inet_ntop($data['0']['ip']);
+ }
+ else {
+ $this->ip_history = T_('Not Enough Data');
+ }
+
+ } // format_user
+
+ /**
+ * format_favorites
+ * takes an array of objects and formats them corrrectly
+ * and returns a simply array with just <a href values
+ */
+ public function format_favorites($items) {
+
+ // The length of the longest item
+ $maxlen = strlen($items[0]->count);
+
+ // Go through the favs
+ foreach ($items as $data) {
+
+ // Make all number lengths equal
+ $len = strlen($data->count);
+ while ($len < $maxlen) {
+ $data->count = "0" . $data->count;
+ $len++;
+ }
+
+ $item = "[$data->count] - $data->f_name";
+ $results[]->f_name_link = $item;
+ } // end foreach items
+
+ return $results;
+
+ } // 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->link;
+ break;
+ case 'album':
+ $object = new Album($object_id);
+ $object->format_album();
+ $name = $object->f_link;
+ break;
+ case 'song':
+ $object = new Song($object_id);
+ $object->format_song();
+ $name = $object->f_link;
+ break;
+ } // end switch on type
+ $results[] = "<li>$name -- " . get_rating_name($rating) . "<br />\n</li>";
+
+ } // end foreach items
+
+
+ return $results;
+
+ } // format_recommendations
+
+ /**
+ * access_name_to_level
+ * This takes the access name for the user and returns the level
+ */
+ public static function access_name_to_level($level) {
+
+ switch ($level) {
+ case 'admin':
+ return '100';
+ break;
+ case 'user':
+ return '25';
+ break;
+ case 'manager':
+ return '75';
+ break;
+ case 'guest':
+ return '5';
+ break;
+ default:
+ return '0';
+ break;
+ }
+
+ return false;
+
+ } // access_name_to_level
+
+ /**
+ * fix_preferences
+ * This is the new fix_preferences function, it does the following
+ * Remove Duplicates from user, add in missing
+ * If -1 is passed it also removes duplicates from the `preferences`
+ * table.
+ */
+ public static function fix_preferences($user_id) {
+
+ $user_id = Dba::escape($user_id);
+
+ /* Get All Preferences for the current user */
+ $sql = "SELECT * FROM `user_preference` WHERE `user`='$user_id'";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $pref_id = $r['preference'];
+ /* Check for duplicates */
+ if (isset($results[$pref_id])) {
+ $r['value'] = Dba::escape($r['value']);
+ $sql = "DELETE FROM `user_preference` WHERE `user`='$user_id' AND `preference`='" . $r['preference'] . "' AND" .
+ " `value`='" . Dba::escape($r['value']) . "'";
+ $delete_results = Dba::write($sql);
+ } // if its set
+ else {
+ $results[$pref_id] = 1;
+ }
+ } // end while
+
+ /* If we aren't the -1 user before we continue grab the -1 users values */
+ if ($user_id != '-1') {
+ $sql = "SELECT `user_preference`.`preference`,`user_preference`.`value` FROM `user_preference`,`preference` " .
+ "WHERE `user_preference`.`preference` = `preference`.`id` AND `user_preference`.`user`='-1' AND `preference`.`catagory` !='system'";
+ $db_results = Dba::read($sql);
+ /* While through our base stuff */
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $key = $r['preference'];
+ $zero_results[$key] = $r['value'];
+ }
+ } // if not user -1
+
+ // get me _EVERYTHING_
+ $sql = "SELECT * FROM `preference`";
+
+ // If not system, exclude system... *gasp*
+ if ($user_id != '-1') {
+ $sql .= " WHERE catagory !='system'";
+ }
+ $db_results = Dba::read($sql);
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+
+ $key = $r['id'];
+
+ /* Check if this preference is set */
+ if (!isset($results[$key])) {
+ if (isset($zero_results[$key])) {
+ $r['value'] = $zero_results[$key];
+ }
+ $value = Dba::escape($r['value']);
+ $sql = "INSERT INTO user_preference (`user`,`preference`,`value`) VALUES ('$user_id','$key','$value')";
+ $insert_db = Dba::write($sql);
+ }
+ } // while preferences
+
+ /* Let's also clean out any preferences garbage left over */
+ $sql = "SELECT DISTINCT(user_preference.user) FROM user_preference " .
+ "LEFT JOIN user ON user_preference.user = user.id " .
+ "WHERE user_preference.user!='-1' AND user.id IS NULL";
+ $db_results = Dba::read($sql);
+
+ $results = array();
+
+ while ($r = Dba::fetch_assoc($db_results)) {
+ $results[] = $r['user'];
+ }
+
+ foreach ($results as $data) {
+ $sql = "DELETE FROM user_preference WHERE user='$data'";
+ $db_results = Dba::write($sql);
+ }
+
+ } // fix_preferences
+
+ /**
+ * delete
+ * deletes this user and everything associated with it. This will affect
+ * ratings and tottal stats
+ */
+ public function delete() {
+
+ /*
+ Before we do anything make sure that they aren't the last
+ admin
+ */
+ if ($this->has_access(100)) {
+ $sql = "SELECT `id` FROM `user` WHERE `access`='100' AND id !='" . Dba::escape($this->id) . "'";
+ $db_results = Dba::read($sql);
+ if (!Dba::num_rows($db_results)) {
+ return false;
+ }
+ } // if this is an admin check for others
+
+ // Delete their playlists
+ $sql = "DELETE FROM `playlist` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Clean up the playlist data table
+ $sql = "DELETE FROM `playlist_data` USING `playlist_data` " .
+ "LEFT JOIN `playlist` ON `playlist`.`id`=`playlist_data`.`playlist` " .
+ "WHERE `playlist`.`id` IS NULL";
+ $db_results = Dba::write($sql);
+
+ // Delete any stats they have
+ $sql = "DELETE FROM `object_count` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Clear the IP history for this user
+ $sql = "DELETE FROM `ip_history` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Nuke any access lists that are specific to this user
+ $sql = "DELETE FROM `access_list` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Delete their ratings
+ $sql = "DELETE FROM `rating` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Delete their tags
+ $sql = "DELETE FROM `tag_map` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
+
+ // Clean out the tags
+ $sql = "DELETE FROM `tags` USING `tag_map` LEFT JOIN `tag_map` ON tag_map.id=tags.map_id AND tag_map.id IS NULL";
+ $db_results = Dba::write($sql);
+
+ // Delete their preferences
+ $sql = "DELETE FROM `user_preference` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
- // Delete their voted stuff in democratic play
- $sql = "DELETE FROM `user_vote` WHERE `user`='$this->id'";
- $db_results = Dba::write($sql);
+ // Delete their voted stuff in democratic play
+ $sql = "DELETE FROM `user_vote` WHERE `user`='$this->id'";
+ $db_results = Dba::write($sql);
- // Delete their shoutbox posts
- $sql = "DELETE FROM `user_shout` WHERE `user='$this->id'";
- $db_results = Dba::write($sql);
+ // Delete their shoutbox posts
+ $sql = "DELETE FROM `user_shout` WHERE `user='$this->id'";
+ $db_results = Dba::write($sql);
- // Delete the user itself
- $sql = "DELETE FROM `user` WHERE `id`='$this->id'";
- $db_results = Dba::write($sql);
+ // Delete the user itself
+ $sql = "DELETE FROM `user` WHERE `id`='$this->id'";
+ $db_results = Dba::write($sql);
- $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'";
+ $db_results = Dba::write($sql);
- return true;
+ return true;
- } // delete
+ } // delete
- /**
- * is_online
- * delay how long since last_seen in seconds default of 20 min
- * calcs difference between now and last_seen
- * if less than delay, we consider them still online
- */
- public function is_online( $delay = 1200 ) {
+ /**
+ * is_online
+ * delay how long since last_seen in seconds default of 20 min
+ * calcs difference between now and last_seen
+ * if less than delay, we consider them still online
+ */
+ public function is_online( $delay = 1200 ) {
- return time() - $this->last_seen <= $delay;
+ return time() - $this->last_seen <= $delay;
- } // is_online
+ } // is_online
- /**
- * get_user_validation
- *if user exists before activation can be done.
- */
- public static function get_validation($username) {
+ /**
+ * get_user_validation
+ *if user exists before activation can be done.
+ */
+ public static function get_validation($username) {
- $usename = Dba::escape($username);
+ $usename = Dba::escape($username);
- $sql = "SELECT `validation` FROM `user` WHERE `username`='$username'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `validation` FROM `user` WHERE `username`='$username'";
+ $db_results = Dba::read($sql);
- $row = Dba::fetch_assoc($db_results);
+ $row = Dba::fetch_assoc($db_results);
- return $row['validation'];
+ return $row['validation'];
- } // get_validation
+ } // get_validation
- /**
- * get_recently_played
- * This gets the recently played items for this user respecting
- * the limit passed
- */
- public function get_recently_played($limit,$type='') {
+ /**
+ * get_recently_played
+ * This gets the recently played items for this user respecting
+ * the limit passed
+ */
+ public function get_recently_played($limit,$type='') {
- if (!$type) { $type = 'song'; }
+ if (!$type) { $type = 'song'; }
- $sql = "SELECT * FROM `object_count` WHERE `object_type`='$type' AND `user`='$this->id' " .
- "ORDER BY `date` DESC LIMIT $limit";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `object_count` WHERE `object_type`='$type' AND `user`='$this->id' " .
+ "ORDER BY `date` DESC LIMIT $limit";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row['object_id'];
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row['object_id'];
+ }
- return $results;
+ return $results;
- } // get_recently_played
+ } // get_recently_played
- /**
- * get_ip_history
- * This returns the ip_history from the
- * last Config::get('user_ip_cardinality') days
- */
- public function get_ip_history($count='',$distinct='') {
+ /**
+ * get_ip_history
+ * This returns the ip_history from the
+ * last Config::get('user_ip_cardinality') days
+ */
+ public function get_ip_history($count='',$distinct='') {
- $username = Dba::escape($this->id);
- $count = $count ? intval($count) : intval(Config::get('user_ip_cardinality'));
+ $username = Dba::escape($this->id);
+ $count = $count ? intval($count) : intval(Config::get('user_ip_cardinality'));
- // Make sure it's something
- if ($count < 1) { $count = '1'; }
- $limit_sql = "LIMIT " . intval($count);
+ // Make sure it's something
+ if ($count < 1) { $count = '1'; }
+ $limit_sql = "LIMIT " . intval($count);
- if ($distinct) { $group_sql = "GROUP BY `ip`"; }
+ if ($distinct) { $group_sql = "GROUP BY `ip`"; }
- /* Select ip history */
- $sql = "SELECT `ip`,`date` FROM `ip_history`" .
- " WHERE `user`='$username'" .
- " $group_sql ORDER BY `date` DESC $limit_sql";
- $db_results = Dba::read($sql);
+ /* Select ip history */
+ $sql = "SELECT `ip`,`date` FROM `ip_history`" .
+ " WHERE `user`='$username'" .
+ " $group_sql ORDER BY `date` DESC $limit_sql";
+ $db_results = Dba::read($sql);
- $results = array();
+ $results = array();
- while ($row = Dba::fetch_assoc($db_results)) {
- $results[] = $row;
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ $results[] = $row;
+ }
- return $results;
+ return $results;
- } // get_ip_history
+ } // get_ip_history
- /**
- * activate_user
- * the user from public_registration
- */
- public function activate_user($username) {
+ /**
+ * activate_user
+ * the user from public_registration
+ */
+ public function activate_user($username) {
- $username = Dba::escape($username);
+ $username = Dba::escape($username);
- $sql = "UPDATE `user` SET `disabled`='0' WHERE `username`='$username'";
- $db_results = Dba::write($sql);
+ $sql = "UPDATE `user` SET `disabled`='0' WHERE `username`='$username'";
+ $db_results = Dba::write($sql);
- } // activate_user
+ } // activate_user
- /**
- * is_xmlrpc
- * checks to see if this is a valid xmlrpc user
- */
- public function is_xmlrpc() {
+ /**
+ * is_xmlrpc
+ * checks to see if this is a valid xmlrpc user
+ */
+ public function is_xmlrpc() {
- /* If we aren't using XML-RPC return true */
- if (!Config::get('xml_rpc')) {
- return false;
- }
+ /* If we aren't using XML-RPC return true */
+ if (!Config::get('xml_rpc')) {
+ return false;
+ }
- //FIXME: Ok really what we will do is check the MD5 of the HTTP_REFERER
- //FIXME: combined with the song title to make sure that the REFERER
- //FIXME: is in the access list with full rights
- return true;
+ //FIXME: Ok really what we will do is check the MD5 of the HTTP_REFERER
+ //FIXME: combined with the song title to make sure that the REFERER
+ //FIXME: is in the access list with full rights
+ return true;
- } // is_xmlrpc
+ } // is_xmlrpc
- /**
- * check_username
- * This checks to make sure the username passed doesn't already
- * exist in this instance of ampache
- */
- public static function check_username($username) {
+ /**
+ * check_username
+ * This checks to make sure the username passed doesn't already
+ * exist in this instance of ampache
+ */
+ public static function check_username($username) {
- $username = Dba::escape($username);
+ $username = Dba::escape($username);
- $sql = "SELECT `id` FROM `user` WHERE `username`='$username'";
- $db_results = Dba::read($sql);
+ $sql = "SELECT `id` FROM `user` WHERE `username`='$username'";
+ $db_results = Dba::read($sql);
- if (Dba::num_rows($db_results)) {
- return false;
- }
+ if (Dba::num_rows($db_results)) {
+ return false;
+ }
- return true;
+ return true;
- } // check_username
+ } // check_username
- /**
- * rebuild_all_preferences
- * This rebuilds the user preferences for all installed users, called by the plugin functions
- */
- public static function rebuild_all_preferences() {
+ /**
+ * rebuild_all_preferences
+ * This rebuilds the user preferences for all installed users, called by the plugin functions
+ */
+ public static function rebuild_all_preferences() {
- $sql = "SELECT * FROM `user`";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `user`";
+ $db_results = Dba::read($sql);
- User::fix_preferences('-1');
+ User::fix_preferences('-1');
- while ($row = Dba::fetch_assoc($db_results)) {
- User::fix_preferences($row['id']);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ User::fix_preferences($row['id']);
+ }
- return true;
+ return true;
- } // rebuild_all_preferences
+ } // rebuild_all_preferences
} //end user class
?>
diff --git a/lib/class/vainfo.class.php b/lib/class/vainfo.class.php
index 2df7e743..b1d825bb 100644
--- a/lib/class/vainfo.class.php
+++ b/lib/class/vainfo.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -28,1061 +28,1061 @@
*/
class vainfo {
- public $encoding = '';
- public $encoding_id3v1 = '';
- public $encoding_id3v2 = '';
-
- public $filename = '';
- public $type = '';
- public $tags = array();
-
- protected $_raw = array();
- protected $_getID3 = '';
- protected $_iconv = false;
-
- protected $_file_encoding = '';
- protected $_file_pattern = '';
- protected $_dir_pattern = '';
-
- private $_pathinfo;
- private $_broken = false;
-
- /**
- * Constructor
- *
- * This function just sets up the class, it doesn't
- * actually pull the information
- *
- * @param string $file filename
- * @param string $encoding Target encode character set
- * @param string $encoding_id3v1 Default id3v1 encode character set
- * @param string $encoding_iv3v2 Default id3v2 encode character set
- * @param string $dir_pattern Directory pattern
- * @param string $file_pattern File pattern
- * @return mixed If can't analyze file, return false. default return: void
- */
- public function __construct($file, $encoding = null, $encoding_id3v1 = null, $encoding_id3v2 = null, $dir_pattern, $file_pattern) {
-
- /* Check for ICONV */
- if (function_exists('iconv') && Config::get('use_iconv') == "1") {
- $this->_iconv = true;
- }
- else {
- $this->_iconv = false;
- }
-
- $this->filename = $file;
- if ($encoding) {
- $this->encoding = $encoding;
- }
- else {
- $this->encoding = Config::get('site_charset');
- }
-
- /* These are needed for the filename mojo */
- $this->_file_pattern = $file_pattern;
- $this->_dir_pattern = $dir_pattern;
-
- if(strtoupper(substr(PHP_OS,0,3)) == 'WIN') {
- $this->_pathinfo = str_replace('%3A', ':', urlencode($this->filename));
- $this->_pathinfo = pathinfo(str_replace('%5C', '\\', $this->_pathinfo));
- }
- else {
- $this->_pathinfo = pathinfo(str_replace('%2F', '/', urlencode($this->filename)));
- }
- $this->_pathinfo['extension'] = strtolower($this->_pathinfo['extension']);
-
- // Initialize getID3 engine
- $this->_getID3 = new getID3();
-
- $this->_getID3->option_md5_data = false;
- $this->_getID3->option_md5_data_source = false;
- $this->_getID3->option_tags_html = false;
- $this->_getID3->option_extra_info = true;
- $this->_getID3->option_tag_lyrics3 = true;
- $this->_getID3->option_tags_process = true;
- $this->_getID3->encoding = $this->encoding;
-
- // get id3tag encoding (try to work around off-spec id3v1 tags)
- try {
- $this->_raw = $this->_getID3->analyze($file);
- }
- catch (Exception $error) {
- debug_event('Getid3()',"Broken file detected $file - " . $error->message,'1');
- $this->_broken = true;
- return false;
- }
-
- /* Use default mb_detect_order in php.ini or not */
- if (Config::get('mb_detect_order')) {
- $mb_order = Config::get('mb_detect_order');
- }
- elseif (function_exists('mb_detect_order')) {
- $mb_order = implode(", ", mb_detect_order());
- }
- else {
- $mb_order = "auto";
- }
-
- $test_tags = array('artist', 'album', 'genre', 'title');
-
- if ($encoding_id3v1) {
- $this->encoding_id3v1 = $encoding_id3v1;
- }
- else {
- foreach ($test_tags as $tag) {
- if ($value = $this->_raw['id3v1'][$tag]) {
- $tags[$tag] = $value;
- }
- }
-
- $this->encoding_id3v1 = self::_detect_encoding($tags, $mb_order);
- }
-
- if (Config::get('getid3_detect_id3v2_encoding')) {
- foreach ($test_tags as $tag) {
- if ($value = $this->_raw['id3v2']['comments'][$tag]) {
- $tags[$tag] = $value;
- }
- }
-
- $this->encoding_id3v2 = self::_detect_encoding($tags, $mb_order);
- $this->_getID3->encoding_id3v2 = $this->encoding_id3v2;
- }
-
- $this->_getID3->encoding_id3v1 = $this->encoding_id3v1;
-
- } // vainfo
-
- /**
- * _detect_encoding
- * Takes an array of tags and attempts to automatically detect their
- * encoding.
- */
- private static function _detect_encoding($tags, $mb_order) {
- if (function_exists('mb_detect_encoding')) {
- $encodings = array();
- $tags = array('artist', 'album', 'genre', 'title');
- foreach ($tags as $tag) {
- $encodings[mb_detect_encoding($tag, $mb_order, true)]++;
- }
-
- debug_event('vainfo', 'encoding detection: ' . json_encode($encodings), 5);
- $high = 0;
- foreach ($encodings as $key => $value) {
- if ($value > $high) {
- $encoding = $key;
- $high = $value;
- }
- }
-
- if ($encoding != 'ASCII' && $encoding != '0') {
- return $encoding;
- }
- else {
- return 'ISO-8859-1';
- }
- }
- return 'ISO-8859-1';
- }
-
-
- /**
- * get_info
- * This function runs the various steps to gathering the metadata
- */
- public function get_info() {
-
- // If this is broken, don't waste time figuring it out a second
- // time, just return their rotting carcass of a media file.
- if ($this->_broken) {
- $this->tags = $this->set_broken();
- return true;
- }
-
- /* Get the Raw file information */
- try {
- $this->_raw = $this->_getID3->analyze($this->filename);
- }
- catch (Exception $error) {
- debug_event('Getid3()',"Unable to catalog file:" . $error->message,'1');
- }
-
- /* Figure out what type of file we are dealing with */
- $this->type = $this->_get_type();
-
- $enabled_sources = (array)Config::get('metadata_order');
-
- if (in_array('filename', $enabled_sources)) {
- $this->tags['filename'] = $this->_parse_filename($this->filename);
- }
-
- if (in_array('getID3', $enabled_sources)) {
- $this->tags['getID3'] = $this->_get_tags();
- }
-
- $this->_get_plugin_tags();
-
- } // get_info
-
- /**
- * get_tag_type
- * This takes the result set and the tag_order defined in your config
- * file and tries to figure out which tag type(s) it should use. If your
- * tag_order doesn't match anything then it throws up its hands and uses
- * everything.
- */
- public static function get_tag_type($results, $config_key = 'metadata_order') {
-
- $order = (array)Config::get($config_key);
-
- /* Iterate through the defined key order adding them to an
- * ordered array as we go.
- */
-
- foreach($order as $key) {
- if ($results[$key]) {
- $returned_keys[] = $key;
- }
- }
-
- /* If we didn't find anything then default to everything.
- */
- if (!isset($returned_keys)) {
- $returned_keys = array_keys($results);
- $returned_keys = sort($returned_keys);
- }
-
- return $returned_keys;
-
- } // get_tag_type
-
- /**
- * clean_tag_info
- * This function takes the array from vainfo along with the
- * key we've decided on and the filename and returns it in a
- * sanitized format that ampache can actually use
- */
- public static function clean_tag_info($results, $keys, $filename = null) {
-
- $info = array();
-
- if ($filename) {
- $info['file'] = $filename;
- }
-
- // Iteration!
- foreach ($keys as $key) {
- $tags = $results[$key];
-
- $info['file'] = $info['file'] ?: $tags['file'];
- $info['bitrate'] = $info['bitrate'] ?: intval($tags['bitrate']);
- $info['rate'] = $info['rate'] ?: intval($tags['rate']);
- $info['mode'] = $info['mode'] ?: $tags['mode'];
- $info['size'] = $info['size'] ?: $tags['size'];
- $info['mime'] = $info['mime'] ?: $tags['mime'];
- $info['encoding'] = $info['encoding'] ?: $tags['encoding'];
- $info['rating'] = $info['rating'] ?: $tags['rating'];
- $info['time'] = $info['time'] ?: intval($tags['time']);
- $info['channels'] = $info['channels'] ?: $tags['channels'];
-
- /* These are used to generate the correct IDs later */
- $info['title'] = $info['title'] ?: stripslashes(trim($tags['title']));
-
- $info['year'] = $info['year'] ?: intval($tags['year']);
-
- $info['disk'] = $info['disk'] ?: intval($tags['disk']);
-
- $info['totaldiscs'] = $info['totaldiscs'] ?: intval($tags['totaldiscs']);
-
- $info['artist'] = $info['artist'] ?: trim($tags['artist']);
-
- $info['album'] = $info['album'] ?: trim($tags['album']);
-
- // multiple genre support
- if ((!$info['genre']) && $tags['genre']) {
- if (!is_array($tags['genre'])) {
- // not all tag formats will return an array, but we need one
- $info['genre'][] = trim($tags['genre']);
- }
- else {
- // if we trim the array we lose everything after 1st entry
- foreach ($tags['genre'] as $genre) {
- $info['genre'][] = trim($genre);
- }
- }
- }
-
- $info['mb_trackid'] = $info['mb_trackid'] ?: trim($tags['mb_trackid']);
- $info['mb_albumid'] = $info['mb_albumid'] ?: trim($tags['mb_albumid']);
- $info['mb_artistid'] = $info['mb_artistid'] ?: trim($tags['mb_artistid']);
-
- /* @TODO language doesn't import from id3tag. @momo-i */
- $info['language'] = $info['language'] ?: Dba::escape($tags['language']);
-
- $info['lyrics'] = $info['lyrics']
- ?: str_replace(
- array("\r\n","\r","\n"),
- '<br />',
- strip_tags($tags['lyrics']));
-
- $info['track'] = $info['track'] ?: intval($tags['track']);
- $info['resolution_x'] = $info['resolution_x'] ?: intval($tags['resolution_x']);
- $info['resolution_y'] = $info['resolution_y'] ?: intval($tags['resolution_y']);
- $info['audio_codec'] = $info['audio_codec'] ?: Dba::escape($tags['audio_codec']);
- $info['video_codec'] = $info['video_codec'] ?: Dba::escape($tags['video_codec']);
- }
-
- if ($info['totaldiscs'] == 1 && $info['disk'] == 1) {
- unset($info['disk']);
- unset($info['totaldiscs']);
- }
-
- return $info;
-
- } // clean_tag_info
-
- /**
- * _get_type
- * This function takes the raw information and figures out
- * what type of file we are dealing with for use by the tag
- * function
- */
- public function _get_type() {
-
- /* There are a few places that the file type can
- * come from, in the end we trust the encoding
- * type
- */
- if ($type = $this->_raw['video']['dataformat']) {
- $type = $this->_clean_type($type);
- return $type;
- }
- if ($type = $this->_raw['audio']['streams']['0']['dataformat']) {
- $type = $this->_clean_type($type);
- return $type;
- }
- if ($type = $this->_raw['audio']['dataformat']) {
- $type = $this->_clean_type($type);
- return $type;
- }
- if ($type = $this->_raw['fileformat']) {
- $type = $this->_clean_type($type);
- return $type;
- }
-
- return false;
-
- } // _get_type
-
-
- /**
- * _get_tags
- * This function takes the raw information and the type and
- * attempts to gather the tags and then normalize them into
- * ['tag_name']['var'] = value
- */
- public function _get_tags() {
-
- $results = array();
-
- /* The tags can come in many different shapes and colors
- * depending on the encoding time of day and phase of the moon.
- */
- foreach ($this->_raw['tags'] as $key => $tag_array) {
- switch ($key) {
- case 'vorbiscomment':
- debug_event('_get_tags', 'Parsing vorbis', '5');
- $results[$key] = $this->_parse_vorbiscomment($tag_array);
- break;
- case 'id3v1':
- debug_event('_get_tags', 'Parsing id3v1', '5');
- $results[$key] = $this->_parse_id3v1($tag_array);
- break;
- case 'id3v2':
- debug_event('_get_tags', 'Parsing id3v2', '5');
- $results[$key] = $this->_parse_id3v2($tag_array);
- break;
- case 'ape':
- debug_event('_get_tags', 'Parsing ape', '5');
- $results[$key] = $this->_parse_ape($tag_array);
- break;
- case 'quicktime':
- debug_event('_get_tags', 'Parsing quicktime', '5');
- $results[$key] = $this->_parse_quicktime($tag_array);
- break;
- case 'riff':
- debug_event('_get_tags', 'Parsing riff', '5');
- $results[$key] = $this->_parse_riff($tag_array);
- break;
- case 'flv':
- debug_event('_get_tags', 'Parsing flv', '5');
- $results[$key] = $this->_parse_flv($this->_raw);
- break;
- case 'mpg':
- case 'mpeg':
- debug_event('_get_tags', 'Parsing MPEG', '5');
- $results['mpeg'] = $this->_parse_mpg($this->_raw);
- break;
- case 'asf':
- case 'wmv':
- debug_event('_get_tags', 'Parsing WMV/WMA/ASF', '5');
- $results['asf'] = $this->_parse_wmv($this->_raw);
- break;
- case 'avi':
- debug_event('_get_tags', 'Parsing avi', '5');
- $results[$key] = $this->_parse_avi($this->_raw);
- break;
- case 'lyrics3':
- debug_event('_get_tags', 'Parsing lyrics3', '5');
- $results[$key] = $this->_parse_lyrics($tag_array);
- break;
- default:
- debug_event('vainfo','Error: Unable to determine tag type of ' . $key . ' for file ' . $this->filename . ' Assuming id3v2','5');
- $results[$key] = $this->_parse_id3v2($this->_raw['id3v2']['comments']);
- break;
- } // end switch
- } // end foreach
-
-
- $cleaned = self::clean_tag_info($results, self::get_tag_type($results, 'getid3_tag_order'), $this->filename);
- $cleaned = array_merge($cleaned, $this->_get_info());
- $cleaned['raw'] = $results;
-
- return $cleaned;
-
- } // _get_tags
-
- /**
- * _get_plugin_tags
- * Get additional metadata from plugins
- */
- private function _get_plugin_tags() {
- $tag_order = Config::get('metadata_order');
- if (!is_array($tag_order)) {
- $tag_order = array($tag_order);
- }
-
- $plugin_names = Plugin::get_plugins('get_metadata');
- foreach ($tag_order as $key => $tag_source) {
- if (in_array($tag_source, $plugin_names)) {
- $plugin = new Plugin($tag_source);
- if ($plugin->load()) {
- $this->tags[$tag_source] = $plugin->_plugin->get_metadata(self::clean_tag_info($this->tags, self::get_tag_type($this->tags), $this->filename));
- }
- }
- }
- } // _get_plugin_tags
-
- /**
- * _get_info
- * Gather and return the general information about a song (vbr/cbr,
- * sample rate, channels, etc.)
- */
- private function _get_info() {
-
- $array = array();
-
- /* Try to pull the information directly from
- * the audio array
- */
- if ($this->_raw['audio']['bitrate_mode']) {
- $array['mode'] = $this->_raw['audio']['bitrate_mode'];
- if ($array['mode'] == 'con') {
- $array['mode'] = 'cbr';
- }
- }
- if ($this->_raw['audio']['bitrate']) {
- $array['bitrate'] = $this->_raw['audio']['bitrate'];
- }
- if ($this->_raw['audio']['channels']) {
- $array['channels'] = intval($this->_raw['audio']['channels']);
- }
- if ($this->_raw['audio']['sample_rate']) {
- $array['rate'] = intval($this->_raw['audio']['sample_rate']);
- }
- if ($this->_raw['filesize']) {
- $array['size'] = intval($this->_raw['filesize']);
- }
- if ($this->_raw['encoding']) {
- $array['encoding'] = $this->_raw['encoding'];
- }
- if ($this->_raw['mime_type']) {
- $array['mime'] = $this->_raw['mime_type'];
- }
- if ($this->_raw['playtime_seconds']) {
- $array['time'] = $this->_raw['playtime_seconds'];
- }
-
- return $array;
-
- } // _get_info
-
- /**
- * _clean_type
- * This standardizes the type that we are given into a recognized type.
- */
- private function _clean_type($type) {
-
- switch ($type) {
- case 'mp3':
- case 'mp2':
- case 'mpeg3':
- return 'mp3';
- break;
- case 'vorbis':
- return 'ogg';
- break;
- case 'flac':
- case 'flv':
- case 'mpg':
- case 'mpeg':
- case 'asf':
- case 'wmv':
- case 'avi':
- case 'quicktime':
- return $type;
- default:
- /* Log the fact that we couldn't figure it out */
- debug_event('vainfo','Unable to determine file type from ' . $type . ' on file ' . $this->filename,'5');
- return $type;
- break;
- } // end switch on type
-
- } // _clean_type
-
- /**
- * _parse_lyrics
- * This function takes a lyrics3 from getid3()
- * nothing to do?
- */
- private function _parse_lyrics($tags) {
-
- /* Results array */
- $array = array();
-
- /* go through them all! */
- foreach ($tags as $tag => $data) {
- if ($tag == 'unsynchedlyrics' || $tag == 'unsynchronised lyric') {
- $tag = 'lyrics';
- }
- $array[$tag] = $this->_clean_tag($data['0']);
-
- } // end foreach
-
- return $array;
-
- } // _parse_lyrics
-
- /**
- * _parse_vorbiscomment
- * This function takes a vorbiscomment from getid3() and then
- * returns the elements translated using iconv if needed in a
- * pretty little format
- */
- private function _parse_vorbiscomment($tags) {
-
- /* Results array */
- $array = array();
-
- /* go through them all! */
- foreach ($tags as $tag=>$data) {
-
- /* We need to translate a few of these tags */
- switch ($tag) {
-
- case 'genre':
- // multiple genre support
- foreach($data as $foo) {
- $array['genre'][] = $this->_clean_tag($foo,'');
- }
- break;
- case 'tracknumber':
- $array['track'] = $this->_clean_tag($data['0']);
- break;
- case 'discnumber':
- $el = explode('/', $data['0']);
- $array['disk'] = $el[0];
- break;
- case 'date':
- $array['year'] = $this->_clean_tag($data['0']);
- break;
- default:
- $array[$tag] = $this->_clean_tag($data['0']);
- break;
- } // end switch
-
- } // end foreach
-
- return $array;
-
- } // _parse_vorbiscomment
-
- /**
- * _parse_id3v1
- * This function takes an id3v1 tag set from getid3() and then
- * returns the elements (translated using iconv if needed) in a
- * pretty little format.
- */
- private function _parse_id3v1($tags) {
-
- $array = array();
-
- /* Go through all the tags */
- foreach ($tags as $tag=>$data) {
-
- /* This is our baseline for naming
- * so no translation needed
- */
- $array[$tag] = $this->_clean_tag($data['0']);
-
- } // end foreach
-
- return $array;
-
- } // _parse_id3v1
-
- /**
- * _parse_id3v2
- * This function takes an id3v2 tag set from getid3() and then
- * returns the elements (translated using iconv if needed) in a
- * pretty little format.
- */
- private function _parse_id3v2($tags) {
-
- $array = array();
-
- /* Go through the tags */
- foreach ($tags as $tag=>$data) {
-
- /**
- * the new getid3 handles this differently
- * so we now need to account for it :(
- */
- switch ($tag) {
- case 'genre':
- // multiple genre support
- foreach($data as $genre) {
- $array['genre'][] = $this->_clean_tag($genre);
- }
- break;
- case 'part_of_a_set':
- $el = explode('/', $data['0']);
- $array['disk'] = $el[0];
- $array['totaldiscs'] = $el[1];
- break;
- case 'track_number':
- $array['track'] = $this->_clean_tag($data['0']);
- break;
- case 'comments':
- $array['comment'] = $this->_clean_tag($data['0']);
- break;
- default:
- $array[$tag] = $this->_clean_tag($data['0']);
- break;
- } // end switch on tag
-
- } // end foreach
-
- $id3v2 = $this->_raw['id3v2'];
-
- if(!empty($id3v2['UFID'])) {
- // Find the MBID for the track
- foreach ($id3v2['UFID'] as $ufid) {
- if ($ufid['ownerid'] == 'http://musicbrainz.org') {
- $array['mb_trackid'] = $this->_clean_tag($ufid['data']);
- }
- }
-
- // Find the MBIDs for the album and artist
- foreach ($id3v2['TXXX'] as $txxx) {
- switch ($txxx['description']) {
- case 'MusicBrainz Album Id':
- $array['mb_albumid'] = $this->_clean_tag($txxx['data']);
- break;
- case 'MusicBrainz Artist Id':
- $array['mb_artistid'] = $this->_clean_tag($txxx['data']);
- break;
- }
- }
- }
-
- // Find the rating
- if (is_array($id3v2['POPM'])) {
- foreach ($id3v2['POPM'] as $popm) {
- if (array_key_exists('email', $popm) &&
- $user = User::get_from_email($popm['email'])) {
- // Ratings are out of 255; scale it
- $array['rating'][$user->id] = $popm['rating'] / 255 * 5;
- }
- }
- }
-
- return $array;
-
- } // _parse_id3v2
-
- /**
- * _parse_ape
- * This function takes ape tags set by getid3() and then
- * returns the elements translated using iconv if needed in a
- * pretty little format
- */
- private function _parse_ape($tags) {
-
- foreach ($tags as $tag=>$data) {
- switch ($tag) {
-
- case 'genre':
- // multiple genre support
- foreach($data as $genre) {
- $array['genre'][] = $this->_clean_tag($genre);
- }
- break;
-
- default:
- $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding);
- break;
- } // end switch on tag
-
- } // end foreach tags
-
- return $array;
-
- } // _parse_ape
-
- /**
- * _parse_riff
- * this function takes the riff take information passed by getid3() and
- * then reformats it so that it matches the other formats. May require iconv
- */
- private function _parse_riff($tags) {
-
- foreach ($tags as $tag=>$data) {
-
- switch ($tag) {
- case 'product':
- $array['album'] = $this->_clean_tag($data['0'], $this->_file_encoding);
- break;
- default:
- $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding);
- break;
- } // end switch on tag
-
- } // foreach tags
-
- return $array;
-
- } // _parse_riff
-
- /**
- * _parse_quicktime
- * this function takes the quicktime tags set by getid3() and then
- * returns the elements translated using iconv if needed in a
- * pretty little format
- */
- private function _parse_quicktime($tags) {
-
- /* Results array */
- $array = array();
-
- /* go through them all! */
- foreach ($tags as $tag=>$data) {
-
- /* We need to translate a few of these tags */
- switch ($tag) {
- case 'creation_date':
- if (strlen($data['0']) > 4) {
- /* Weird Date format, attempt to normalize */
- $data['0'] = date("Y",strtotime($data['0']));
- }
- $array['year'] = $this->_clean_tag($data['0']);
- break;
- case 'MusicBrainz Track Id':
- $array['mb_trackid'] = $this->_clean_tag($data['0']);
- break;
- case 'MusicBrainz Album Id':
- $array['mb_albumid'] = $this->_clean_tag($data['0']);
- break;
- case 'MusicBrainz Artist Id':
- $array['mb_artistid'] = $this->_clean_tag($data['0']);
- break;
- } // end switch
-
- $array[$tag] = $this->_clean_tag($data['0']);
-
- } // end foreach
-
- // Also add in any video related stuff we might find
- if (strpos($this->_raw['mime_type'], 'video') !== false) {
- $info = $this->_parse_avi($this->_raw);
- $info['video_codec'] = $this->_raw['quicktime']['ftyp']['fourcc'];
- $array = array_merge($info, $array);
- }
-
- return $array;
-
- } // _parse_quicktime
-
- /**
- * _parse_avi
- * This attempts to parse our the information on an avi file and present it in some
- * kind of sane format, this is a little hard as these files don't have tags
- */
- private function _parse_avi($tags) {
-
- $array = array();
-
- $array['title'] = urldecode($this->_pathinfo['filename']);
- $array['video_codec'] = $tags['video']['fourcc'];
- $array['audio_codec'] = $tags['audio']['dataformat'];
- $array['resolution_x'] = $tags['video']['resolution_x'];
- $array['resolution_y'] = $tags['video']['resolution_y'];
- $array['mime'] = $tags['mime_type'];
- $array['comment'] = $tags['video']['codec'];
-
- return $array;
-
- } // _parse_avi
-
- /**
- * _parse_mpg
- * This attempts to parse our the information on a mpg file and present it in some
- * kind of sane format, this is a little hard as these files don't have tags
- */
- private function _parse_mpg($tags) {
-
- $array = array();
-
- $array['title'] = urldecode($this->_pathinfo['filename']);
- $array['video_codec'] = $tags['video']['codec'];
- $array['audio_codec'] = $tags['audio']['dataformat'];
- $array['resolution_x'] = $tags['video']['resolution_x'];
- $array['resolution_y'] = $tags['video']['resolution_y'];
- $array['mime'] = $tags['mime_type'];
- $array['comment'] = $tags['video']['codec'];
-
- return $array;
-
- } // _parse_mpg
-
- /**
- * _parse_wmv
- * This attempts to parse our the information on a asf/wmv file and present it in some
- * kind of sane format, this is a little hard as these files don't have tags
- */
- private function _parse_wmv($tags) {
-
- $array = array();
-
- $array['mime'] = $tags['mime_type'];
-
- switch($array['mime']) {
- default:
- case 'video/x-ms-wmv':
- if(isset($tags['tags']['asf']['title']['0'])) {
- $array['title'] = $tags['tags']['asf']['title']['0'];
- }
- else {
- $array['title'] = urldecode($this->_pathinfo['filename']);
- }
- $array['video_codec'] = $tags['video']['streams']['2']['codec'];
- $array['audio_codec'] = $tags['audio']['streams']['1']['codec'];
- $array['resolution_x'] = $tags['video']['streams']['2']['resolution_x'];
- $array['resolution_y'] = $tags['video']['streams']['2']['resolution_y'];
- $array['comment'] = $tags['tags']['asf']['title']['1'];
- break;
- }
-
- foreach($tags['tags']['asf'] as $tag => $data) {
- $array[$tag] = $this->_clean_tag($data['0']);
- }
-
- return $array;
-
- } // _parse_wmv
-
- /**
- * _parse_flv
- * This attempts to parse our the information on an flv file and present it in some
- * kind of sane format, this is a little hard as these files don't have tags
- */
- private function _parse_flv($tags) {
-
- $array = array();
-
- $array['title'] = urldecode($this->_pathinfo['filename']);
- $array['video_codec'] = $tags['video']['codec'];
- $array['audio_codec'] = $tags['audio']['dataformat'];
- $array['resolution_x'] = $tags['video']['resolution_x'];
- $array['resolution_y'] = $tags['video']['resolution_y'];
- $array['mime'] = $tags['mime_type'];
- $array['comment'] = $tags['video']['codec'];
-
- return $array;
-
- } // _parse_flv
-
- /**
- * _parse_filename
- *
- * This function uses the passed file and dir patterns
- * To pull out extra tag information and populate it into
- * its own array
- *
- * @param string $filename Filename that want to parse
- * @return array Parsed results
- */
- private function _parse_filename($filename) {
-
- $results = array();
-
- // Correctly detect the slash we need to use here
- if (strpos($filename, '/') !== false) {
- $slash_type = '/';
- }
- else {
- $slash_type = '\\';
- }
-
- // Combine the patterns
- $pattern = preg_quote($this->_dir_pattern) . $slash_type . preg_quote($this->_file_pattern);
-
- // Pull out the pattern codes into an array
- preg_match_all('/\%\w/', $pattern, $elements);
-
- // Mangle the pattern by turning the codes into regex captures
- $pattern = preg_replace('/\%[Ty]/', '([0-9]+?)', $pattern);
- $pattern = preg_replace('/\%\w/', '(.+?)', $pattern);
- $pattern = str_replace('/', '\/', $pattern);
- $pattern = str_replace(' ', '\s', $pattern);
- $pattern = '/' . $pattern . '\..+$/';
-
- // Pull out our actual matches
- preg_match($pattern, $filename, $matches);
-
- // The first element is the full match text
- $matched = array_shift($matches);
- debug_event('vainfo', $pattern . ' matched ' . $matched . ' on ' . $filename, 5);
-
- // Iterate over what we found
- foreach ($matches as $key => $value) {
- $new_key = translate_pattern_code($elements['0'][$key]);
- if ($new_key) {
- $results[$new_key] = $value;
- }
- }
-
- $results['size'] = filesize($filename);
-
- return $results;
-
- } // _parse_filename
-
- /**
- * _id3v2_tag_to_frame
- *
- * This translates the tag name to a frame, if there a many it returns the first
- * one if finds that exists in the raw
- *
- * @param string $tag_name Tag name
- * @return mixed If found id3v2 frame, return frame. If not found, return false.
- */
- private function _id3v2_tag_to_frame($tag_name) {
-
- static $map = array(
- 'comment'=>array('COM','COMM'),
- 'cd_ident'=>array('MCDI','MCI'),
- 'album'=>array('TAL','TALB'),
- 'language'=>array('TLA','TLAN'),
- 'mood'=>array('TMOO'),
- 'artist'=>array('TPE1'),
- 'year'=>array('TDRC'));
-
- foreach ($map[$tag_name] as $frame) {
- if (isset($this->_raw['id3v2'][$frame])) {
- return $frame;
- }
- }
-
- return false;
-
- } // _id3v2_tag_to_frame
-
- /**
- * _clean_tag
- *
- * This function cleans up the tag that it's passed using Iconv
- * if we've got it. It also takes an optional encoding param
- * for the cases where we know what the tags source encoding
- * is, and or if it's different then the encoding recorded
- * in the file
- *
- * @param string $tag Encoding string
- * @param string $encoding Encode charset
- * @return string Return encoded string
- */
- private function _clean_tag($tag, $encoding = null) {
-
- // Default to getID3's native encoding
- if (!$encoding) {
- $encoding = $this->_getID3->encoding;
- }
- // If we've got iconv then go ahead and clear her up
- if ($encoding == $this->encoding) {
- debug_event('vainfo', "\$encoding -> ${encoding}, \$this->encoding -> {$this->encoding}", 5);
- return $tag;
- }
- if ($this->_iconv) {
- debug_event('vainfo', 'Use iconv()',5);
-
- // Try GNU iconv //TRANSLIT extension first
- $new_encoding = $this->encoding . '//TRANSLIT';
- $clean = iconv($encoding, $new_encoding, $tag);
-
- // If that fails, do a plain conversion
- if(strcmp($clean, '') == 0) {
- $clean = iconv($encoding, $this->encoding, $tag);
- }
- }
- elseif (function_exists('mb_convert_encoding')) {
- debug_event('vainfo', 'Use mbstring',5);
- debug_event('vainfo', "Try to convert from {$this->encoding} to $encoding", 5);
- $clean = mb_convert_encoding($tag, $encoding, $this->encoding);
- }
- else {
- $clean = $tag;
- }
-
- return $clean;
-
- } // _clean_tag
-
- /**
- * set_broken
- *
- * This fills all tag types with Unknown (Broken)
- *
- * @return array Return broken title, album, artist
- */
- public function set_broken() {
-
- /* Pull In the config option */
- $order = Config::get('tag_order');
-
- if (!is_array($order)) {
- $order = array($order);
- }
-
- $key = array_shift($order);
-
- $broken[$key]['title'] = '**BROKEN** ' . $this->filename;
- $broken[$key]['album'] = 'Unknown (Broken)';
- $broken[$key]['artist'] = 'Unknown (Broken)';
-
- return $broken;
-
- } // set_broken
+ public $encoding = '';
+ public $encoding_id3v1 = '';
+ public $encoding_id3v2 = '';
+
+ public $filename = '';
+ public $type = '';
+ public $tags = array();
+
+ protected $_raw = array();
+ protected $_getID3 = '';
+ protected $_iconv = false;
+
+ protected $_file_encoding = '';
+ protected $_file_pattern = '';
+ protected $_dir_pattern = '';
+
+ private $_pathinfo;
+ private $_broken = false;
+
+ /**
+ * Constructor
+ *
+ * This function just sets up the class, it doesn't
+ * actually pull the information
+ *
+ * @param string $file filename
+ * @param string $encoding Target encode character set
+ * @param string $encoding_id3v1 Default id3v1 encode character set
+ * @param string $encoding_iv3v2 Default id3v2 encode character set
+ * @param string $dir_pattern Directory pattern
+ * @param string $file_pattern File pattern
+ * @return mixed If can't analyze file, return false. default return: void
+ */
+ public function __construct($file, $encoding = null, $encoding_id3v1 = null, $encoding_id3v2 = null, $dir_pattern, $file_pattern) {
+
+ /* Check for ICONV */
+ if (function_exists('iconv') && Config::get('use_iconv') == "1") {
+ $this->_iconv = true;
+ }
+ else {
+ $this->_iconv = false;
+ }
+
+ $this->filename = $file;
+ if ($encoding) {
+ $this->encoding = $encoding;
+ }
+ else {
+ $this->encoding = Config::get('site_charset');
+ }
+
+ /* These are needed for the filename mojo */
+ $this->_file_pattern = $file_pattern;
+ $this->_dir_pattern = $dir_pattern;
+
+ if(strtoupper(substr(PHP_OS,0,3)) == 'WIN') {
+ $this->_pathinfo = str_replace('%3A', ':', urlencode($this->filename));
+ $this->_pathinfo = pathinfo(str_replace('%5C', '\\', $this->_pathinfo));
+ }
+ else {
+ $this->_pathinfo = pathinfo(str_replace('%2F', '/', urlencode($this->filename)));
+ }
+ $this->_pathinfo['extension'] = strtolower($this->_pathinfo['extension']);
+
+ // Initialize getID3 engine
+ $this->_getID3 = new getID3();
+
+ $this->_getID3->option_md5_data = false;
+ $this->_getID3->option_md5_data_source = false;
+ $this->_getID3->option_tags_html = false;
+ $this->_getID3->option_extra_info = true;
+ $this->_getID3->option_tag_lyrics3 = true;
+ $this->_getID3->option_tags_process = true;
+ $this->_getID3->encoding = $this->encoding;
+
+ // get id3tag encoding (try to work around off-spec id3v1 tags)
+ try {
+ $this->_raw = $this->_getID3->analyze($file);
+ }
+ catch (Exception $error) {
+ debug_event('Getid3()',"Broken file detected $file - " . $error->message,'1');
+ $this->_broken = true;
+ return false;
+ }
+
+ /* Use default mb_detect_order in php.ini or not */
+ if (Config::get('mb_detect_order')) {
+ $mb_order = Config::get('mb_detect_order');
+ }
+ elseif (function_exists('mb_detect_order')) {
+ $mb_order = implode(", ", mb_detect_order());
+ }
+ else {
+ $mb_order = "auto";
+ }
+
+ $test_tags = array('artist', 'album', 'genre', 'title');
+
+ if ($encoding_id3v1) {
+ $this->encoding_id3v1 = $encoding_id3v1;
+ }
+ else {
+ foreach ($test_tags as $tag) {
+ if ($value = $this->_raw['id3v1'][$tag]) {
+ $tags[$tag] = $value;
+ }
+ }
+
+ $this->encoding_id3v1 = self::_detect_encoding($tags, $mb_order);
+ }
+
+ if (Config::get('getid3_detect_id3v2_encoding')) {
+ foreach ($test_tags as $tag) {
+ if ($value = $this->_raw['id3v2']['comments'][$tag]) {
+ $tags[$tag] = $value;
+ }
+ }
+
+ $this->encoding_id3v2 = self::_detect_encoding($tags, $mb_order);
+ $this->_getID3->encoding_id3v2 = $this->encoding_id3v2;
+ }
+
+ $this->_getID3->encoding_id3v1 = $this->encoding_id3v1;
+
+ } // vainfo
+
+ /**
+ * _detect_encoding
+ * Takes an array of tags and attempts to automatically detect their
+ * encoding.
+ */
+ private static function _detect_encoding($tags, $mb_order) {
+ if (function_exists('mb_detect_encoding')) {
+ $encodings = array();
+ $tags = array('artist', 'album', 'genre', 'title');
+ foreach ($tags as $tag) {
+ $encodings[mb_detect_encoding($tag, $mb_order, true)]++;
+ }
+
+ debug_event('vainfo', 'encoding detection: ' . json_encode($encodings), 5);
+ $high = 0;
+ foreach ($encodings as $key => $value) {
+ if ($value > $high) {
+ $encoding = $key;
+ $high = $value;
+ }
+ }
+
+ if ($encoding != 'ASCII' && $encoding != '0') {
+ return $encoding;
+ }
+ else {
+ return 'ISO-8859-1';
+ }
+ }
+ return 'ISO-8859-1';
+ }
+
+
+ /**
+ * get_info
+ * This function runs the various steps to gathering the metadata
+ */
+ public function get_info() {
+
+ // If this is broken, don't waste time figuring it out a second
+ // time, just return their rotting carcass of a media file.
+ if ($this->_broken) {
+ $this->tags = $this->set_broken();
+ return true;
+ }
+
+ /* Get the Raw file information */
+ try {
+ $this->_raw = $this->_getID3->analyze($this->filename);
+ }
+ catch (Exception $error) {
+ debug_event('Getid3()',"Unable to catalog file:" . $error->message,'1');
+ }
+
+ /* Figure out what type of file we are dealing with */
+ $this->type = $this->_get_type();
+
+ $enabled_sources = (array)Config::get('metadata_order');
+
+ if (in_array('filename', $enabled_sources)) {
+ $this->tags['filename'] = $this->_parse_filename($this->filename);
+ }
+
+ if (in_array('getID3', $enabled_sources)) {
+ $this->tags['getID3'] = $this->_get_tags();
+ }
+
+ $this->_get_plugin_tags();
+
+ } // get_info
+
+ /**
+ * get_tag_type
+ * This takes the result set and the tag_order defined in your config
+ * file and tries to figure out which tag type(s) it should use. If your
+ * tag_order doesn't match anything then it throws up its hands and uses
+ * everything.
+ */
+ public static function get_tag_type($results, $config_key = 'metadata_order') {
+
+ $order = (array)Config::get($config_key);
+
+ /* Iterate through the defined key order adding them to an
+ * ordered array as we go.
+ */
+
+ foreach($order as $key) {
+ if ($results[$key]) {
+ $returned_keys[] = $key;
+ }
+ }
+
+ /* If we didn't find anything then default to everything.
+ */
+ if (!isset($returned_keys)) {
+ $returned_keys = array_keys($results);
+ $returned_keys = sort($returned_keys);
+ }
+
+ return $returned_keys;
+
+ } // get_tag_type
+
+ /**
+ * clean_tag_info
+ * This function takes the array from vainfo along with the
+ * key we've decided on and the filename and returns it in a
+ * sanitized format that ampache can actually use
+ */
+ public static function clean_tag_info($results, $keys, $filename = null) {
+
+ $info = array();
+
+ if ($filename) {
+ $info['file'] = $filename;
+ }
+
+ // Iteration!
+ foreach ($keys as $key) {
+ $tags = $results[$key];
+
+ $info['file'] = $info['file'] ?: $tags['file'];
+ $info['bitrate'] = $info['bitrate'] ?: intval($tags['bitrate']);
+ $info['rate'] = $info['rate'] ?: intval($tags['rate']);
+ $info['mode'] = $info['mode'] ?: $tags['mode'];
+ $info['size'] = $info['size'] ?: $tags['size'];
+ $info['mime'] = $info['mime'] ?: $tags['mime'];
+ $info['encoding'] = $info['encoding'] ?: $tags['encoding'];
+ $info['rating'] = $info['rating'] ?: $tags['rating'];
+ $info['time'] = $info['time'] ?: intval($tags['time']);
+ $info['channels'] = $info['channels'] ?: $tags['channels'];
+
+ /* These are used to generate the correct IDs later */
+ $info['title'] = $info['title'] ?: stripslashes(trim($tags['title']));
+
+ $info['year'] = $info['year'] ?: intval($tags['year']);
+
+ $info['disk'] = $info['disk'] ?: intval($tags['disk']);
+
+ $info['totaldiscs'] = $info['totaldiscs'] ?: intval($tags['totaldiscs']);
+
+ $info['artist'] = $info['artist'] ?: trim($tags['artist']);
+
+ $info['album'] = $info['album'] ?: trim($tags['album']);
+
+ // multiple genre support
+ if ((!$info['genre']) && $tags['genre']) {
+ if (!is_array($tags['genre'])) {
+ // not all tag formats will return an array, but we need one
+ $info['genre'][] = trim($tags['genre']);
+ }
+ else {
+ // if we trim the array we lose everything after 1st entry
+ foreach ($tags['genre'] as $genre) {
+ $info['genre'][] = trim($genre);
+ }
+ }
+ }
+
+ $info['mb_trackid'] = $info['mb_trackid'] ?: trim($tags['mb_trackid']);
+ $info['mb_albumid'] = $info['mb_albumid'] ?: trim($tags['mb_albumid']);
+ $info['mb_artistid'] = $info['mb_artistid'] ?: trim($tags['mb_artistid']);
+
+ /* @TODO language doesn't import from id3tag. @momo-i */
+ $info['language'] = $info['language'] ?: Dba::escape($tags['language']);
+
+ $info['lyrics'] = $info['lyrics']
+ ?: str_replace(
+ array("\r\n","\r","\n"),
+ '<br />',
+ strip_tags($tags['lyrics']));
+
+ $info['track'] = $info['track'] ?: intval($tags['track']);
+ $info['resolution_x'] = $info['resolution_x'] ?: intval($tags['resolution_x']);
+ $info['resolution_y'] = $info['resolution_y'] ?: intval($tags['resolution_y']);
+ $info['audio_codec'] = $info['audio_codec'] ?: Dba::escape($tags['audio_codec']);
+ $info['video_codec'] = $info['video_codec'] ?: Dba::escape($tags['video_codec']);
+ }
+
+ if ($info['totaldiscs'] == 1 && $info['disk'] == 1) {
+ unset($info['disk']);
+ unset($info['totaldiscs']);
+ }
+
+ return $info;
+
+ } // clean_tag_info
+
+ /**
+ * _get_type
+ * This function takes the raw information and figures out
+ * what type of file we are dealing with for use by the tag
+ * function
+ */
+ public function _get_type() {
+
+ /* There are a few places that the file type can
+ * come from, in the end we trust the encoding
+ * type
+ */
+ if ($type = $this->_raw['video']['dataformat']) {
+ $type = $this->_clean_type($type);
+ return $type;
+ }
+ if ($type = $this->_raw['audio']['streams']['0']['dataformat']) {
+ $type = $this->_clean_type($type);
+ return $type;
+ }
+ if ($type = $this->_raw['audio']['dataformat']) {
+ $type = $this->_clean_type($type);
+ return $type;
+ }
+ if ($type = $this->_raw['fileformat']) {
+ $type = $this->_clean_type($type);
+ return $type;
+ }
+
+ return false;
+
+ } // _get_type
+
+
+ /**
+ * _get_tags
+ * This function takes the raw information and the type and
+ * attempts to gather the tags and then normalize them into
+ * ['tag_name']['var'] = value
+ */
+ public function _get_tags() {
+
+ $results = array();
+
+ /* The tags can come in many different shapes and colors
+ * depending on the encoding time of day and phase of the moon.
+ */
+ foreach ($this->_raw['tags'] as $key => $tag_array) {
+ switch ($key) {
+ case 'vorbiscomment':
+ debug_event('_get_tags', 'Parsing vorbis', '5');
+ $results[$key] = $this->_parse_vorbiscomment($tag_array);
+ break;
+ case 'id3v1':
+ debug_event('_get_tags', 'Parsing id3v1', '5');
+ $results[$key] = $this->_parse_id3v1($tag_array);
+ break;
+ case 'id3v2':
+ debug_event('_get_tags', 'Parsing id3v2', '5');
+ $results[$key] = $this->_parse_id3v2($tag_array);
+ break;
+ case 'ape':
+ debug_event('_get_tags', 'Parsing ape', '5');
+ $results[$key] = $this->_parse_ape($tag_array);
+ break;
+ case 'quicktime':
+ debug_event('_get_tags', 'Parsing quicktime', '5');
+ $results[$key] = $this->_parse_quicktime($tag_array);
+ break;
+ case 'riff':
+ debug_event('_get_tags', 'Parsing riff', '5');
+ $results[$key] = $this->_parse_riff($tag_array);
+ break;
+ case 'flv':
+ debug_event('_get_tags', 'Parsing flv', '5');
+ $results[$key] = $this->_parse_flv($this->_raw);
+ break;
+ case 'mpg':
+ case 'mpeg':
+ debug_event('_get_tags', 'Parsing MPEG', '5');
+ $results['mpeg'] = $this->_parse_mpg($this->_raw);
+ break;
+ case 'asf':
+ case 'wmv':
+ debug_event('_get_tags', 'Parsing WMV/WMA/ASF', '5');
+ $results['asf'] = $this->_parse_wmv($this->_raw);
+ break;
+ case 'avi':
+ debug_event('_get_tags', 'Parsing avi', '5');
+ $results[$key] = $this->_parse_avi($this->_raw);
+ break;
+ case 'lyrics3':
+ debug_event('_get_tags', 'Parsing lyrics3', '5');
+ $results[$key] = $this->_parse_lyrics($tag_array);
+ break;
+ default:
+ debug_event('vainfo','Error: Unable to determine tag type of ' . $key . ' for file ' . $this->filename . ' Assuming id3v2','5');
+ $results[$key] = $this->_parse_id3v2($this->_raw['id3v2']['comments']);
+ break;
+ } // end switch
+ } // end foreach
+
+
+ $cleaned = self::clean_tag_info($results, self::get_tag_type($results, 'getid3_tag_order'), $this->filename);
+ $cleaned = array_merge($cleaned, $this->_get_info());
+ $cleaned['raw'] = $results;
+
+ return $cleaned;
+
+ } // _get_tags
+
+ /**
+ * _get_plugin_tags
+ * Get additional metadata from plugins
+ */
+ private function _get_plugin_tags() {
+ $tag_order = Config::get('metadata_order');
+ if (!is_array($tag_order)) {
+ $tag_order = array($tag_order);
+ }
+
+ $plugin_names = Plugin::get_plugins('get_metadata');
+ foreach ($tag_order as $key => $tag_source) {
+ if (in_array($tag_source, $plugin_names)) {
+ $plugin = new Plugin($tag_source);
+ if ($plugin->load()) {
+ $this->tags[$tag_source] = $plugin->_plugin->get_metadata(self::clean_tag_info($this->tags, self::get_tag_type($this->tags), $this->filename));
+ }
+ }
+ }
+ } // _get_plugin_tags
+
+ /**
+ * _get_info
+ * Gather and return the general information about a song (vbr/cbr,
+ * sample rate, channels, etc.)
+ */
+ private function _get_info() {
+
+ $array = array();
+
+ /* Try to pull the information directly from
+ * the audio array
+ */
+ if ($this->_raw['audio']['bitrate_mode']) {
+ $array['mode'] = $this->_raw['audio']['bitrate_mode'];
+ if ($array['mode'] == 'con') {
+ $array['mode'] = 'cbr';
+ }
+ }
+ if ($this->_raw['audio']['bitrate']) {
+ $array['bitrate'] = $this->_raw['audio']['bitrate'];
+ }
+ if ($this->_raw['audio']['channels']) {
+ $array['channels'] = intval($this->_raw['audio']['channels']);
+ }
+ if ($this->_raw['audio']['sample_rate']) {
+ $array['rate'] = intval($this->_raw['audio']['sample_rate']);
+ }
+ if ($this->_raw['filesize']) {
+ $array['size'] = intval($this->_raw['filesize']);
+ }
+ if ($this->_raw['encoding']) {
+ $array['encoding'] = $this->_raw['encoding'];
+ }
+ if ($this->_raw['mime_type']) {
+ $array['mime'] = $this->_raw['mime_type'];
+ }
+ if ($this->_raw['playtime_seconds']) {
+ $array['time'] = $this->_raw['playtime_seconds'];
+ }
+
+ return $array;
+
+ } // _get_info
+
+ /**
+ * _clean_type
+ * This standardizes the type that we are given into a recognized type.
+ */
+ private function _clean_type($type) {
+
+ switch ($type) {
+ case 'mp3':
+ case 'mp2':
+ case 'mpeg3':
+ return 'mp3';
+ break;
+ case 'vorbis':
+ return 'ogg';
+ break;
+ case 'flac':
+ case 'flv':
+ case 'mpg':
+ case 'mpeg':
+ case 'asf':
+ case 'wmv':
+ case 'avi':
+ case 'quicktime':
+ return $type;
+ default:
+ /* Log the fact that we couldn't figure it out */
+ debug_event('vainfo','Unable to determine file type from ' . $type . ' on file ' . $this->filename,'5');
+ return $type;
+ break;
+ } // end switch on type
+
+ } // _clean_type
+
+ /**
+ * _parse_lyrics
+ * This function takes a lyrics3 from getid3()
+ * nothing to do?
+ */
+ private function _parse_lyrics($tags) {
+
+ /* Results array */
+ $array = array();
+
+ /* go through them all! */
+ foreach ($tags as $tag => $data) {
+ if ($tag == 'unsynchedlyrics' || $tag == 'unsynchronised lyric') {
+ $tag = 'lyrics';
+ }
+ $array[$tag] = $this->_clean_tag($data['0']);
+
+ } // end foreach
+
+ return $array;
+
+ } // _parse_lyrics
+
+ /**
+ * _parse_vorbiscomment
+ * This function takes a vorbiscomment from getid3() and then
+ * returns the elements translated using iconv if needed in a
+ * pretty little format
+ */
+ private function _parse_vorbiscomment($tags) {
+
+ /* Results array */
+ $array = array();
+
+ /* go through them all! */
+ foreach ($tags as $tag=>$data) {
+
+ /* We need to translate a few of these tags */
+ switch ($tag) {
+
+ case 'genre':
+ // multiple genre support
+ foreach($data as $foo) {
+ $array['genre'][] = $this->_clean_tag($foo,'');
+ }
+ break;
+ case 'tracknumber':
+ $array['track'] = $this->_clean_tag($data['0']);
+ break;
+ case 'discnumber':
+ $el = explode('/', $data['0']);
+ $array['disk'] = $el[0];
+ break;
+ case 'date':
+ $array['year'] = $this->_clean_tag($data['0']);
+ break;
+ default:
+ $array[$tag] = $this->_clean_tag($data['0']);
+ break;
+ } // end switch
+
+ } // end foreach
+
+ return $array;
+
+ } // _parse_vorbiscomment
+
+ /**
+ * _parse_id3v1
+ * This function takes an id3v1 tag set from getid3() and then
+ * returns the elements (translated using iconv if needed) in a
+ * pretty little format.
+ */
+ private function _parse_id3v1($tags) {
+
+ $array = array();
+
+ /* Go through all the tags */
+ foreach ($tags as $tag=>$data) {
+
+ /* This is our baseline for naming
+ * so no translation needed
+ */
+ $array[$tag] = $this->_clean_tag($data['0']);
+
+ } // end foreach
+
+ return $array;
+
+ } // _parse_id3v1
+
+ /**
+ * _parse_id3v2
+ * This function takes an id3v2 tag set from getid3() and then
+ * returns the elements (translated using iconv if needed) in a
+ * pretty little format.
+ */
+ private function _parse_id3v2($tags) {
+
+ $array = array();
+
+ /* Go through the tags */
+ foreach ($tags as $tag=>$data) {
+
+ /**
+ * the new getid3 handles this differently
+ * so we now need to account for it :(
+ */
+ switch ($tag) {
+ case 'genre':
+ // multiple genre support
+ foreach($data as $genre) {
+ $array['genre'][] = $this->_clean_tag($genre);
+ }
+ break;
+ case 'part_of_a_set':
+ $el = explode('/', $data['0']);
+ $array['disk'] = $el[0];
+ $array['totaldiscs'] = $el[1];
+ break;
+ case 'track_number':
+ $array['track'] = $this->_clean_tag($data['0']);
+ break;
+ case 'comments':
+ $array['comment'] = $this->_clean_tag($data['0']);
+ break;
+ default:
+ $array[$tag] = $this->_clean_tag($data['0']);
+ break;
+ } // end switch on tag
+
+ } // end foreach
+
+ $id3v2 = $this->_raw['id3v2'];
+
+ if(!empty($id3v2['UFID'])) {
+ // Find the MBID for the track
+ foreach ($id3v2['UFID'] as $ufid) {
+ if ($ufid['ownerid'] == 'http://musicbrainz.org') {
+ $array['mb_trackid'] = $this->_clean_tag($ufid['data']);
+ }
+ }
+
+ // Find the MBIDs for the album and artist
+ foreach ($id3v2['TXXX'] as $txxx) {
+ switch ($txxx['description']) {
+ case 'MusicBrainz Album Id':
+ $array['mb_albumid'] = $this->_clean_tag($txxx['data']);
+ break;
+ case 'MusicBrainz Artist Id':
+ $array['mb_artistid'] = $this->_clean_tag($txxx['data']);
+ break;
+ }
+ }
+ }
+
+ // Find the rating
+ if (is_array($id3v2['POPM'])) {
+ foreach ($id3v2['POPM'] as $popm) {
+ if (array_key_exists('email', $popm) &&
+ $user = User::get_from_email($popm['email'])) {
+ // Ratings are out of 255; scale it
+ $array['rating'][$user->id] = $popm['rating'] / 255 * 5;
+ }
+ }
+ }
+
+ return $array;
+
+ } // _parse_id3v2
+
+ /**
+ * _parse_ape
+ * This function takes ape tags set by getid3() and then
+ * returns the elements translated using iconv if needed in a
+ * pretty little format
+ */
+ private function _parse_ape($tags) {
+
+ foreach ($tags as $tag=>$data) {
+ switch ($tag) {
+
+ case 'genre':
+ // multiple genre support
+ foreach($data as $genre) {
+ $array['genre'][] = $this->_clean_tag($genre);
+ }
+ break;
+
+ default:
+ $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding);
+ break;
+ } // end switch on tag
+
+ } // end foreach tags
+
+ return $array;
+
+ } // _parse_ape
+
+ /**
+ * _parse_riff
+ * this function takes the riff take information passed by getid3() and
+ * then reformats it so that it matches the other formats. May require iconv
+ */
+ private function _parse_riff($tags) {
+
+ foreach ($tags as $tag=>$data) {
+
+ switch ($tag) {
+ case 'product':
+ $array['album'] = $this->_clean_tag($data['0'], $this->_file_encoding);
+ break;
+ default:
+ $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding);
+ break;
+ } // end switch on tag
+
+ } // foreach tags
+
+ return $array;
+
+ } // _parse_riff
+
+ /**
+ * _parse_quicktime
+ * this function takes the quicktime tags set by getid3() and then
+ * returns the elements translated using iconv if needed in a
+ * pretty little format
+ */
+ private function _parse_quicktime($tags) {
+
+ /* Results array */
+ $array = array();
+
+ /* go through them all! */
+ foreach ($tags as $tag=>$data) {
+
+ /* We need to translate a few of these tags */
+ switch ($tag) {
+ case 'creation_date':
+ if (strlen($data['0']) > 4) {
+ /* Weird Date format, attempt to normalize */
+ $data['0'] = date("Y",strtotime($data['0']));
+ }
+ $array['year'] = $this->_clean_tag($data['0']);
+ break;
+ case 'MusicBrainz Track Id':
+ $array['mb_trackid'] = $this->_clean_tag($data['0']);
+ break;
+ case 'MusicBrainz Album Id':
+ $array['mb_albumid'] = $this->_clean_tag($data['0']);
+ break;
+ case 'MusicBrainz Artist Id':
+ $array['mb_artistid'] = $this->_clean_tag($data['0']);
+ break;
+ } // end switch
+
+ $array[$tag] = $this->_clean_tag($data['0']);
+
+ } // end foreach
+
+ // Also add in any video related stuff we might find
+ if (strpos($this->_raw['mime_type'], 'video') !== false) {
+ $info = $this->_parse_avi($this->_raw);
+ $info['video_codec'] = $this->_raw['quicktime']['ftyp']['fourcc'];
+ $array = array_merge($info, $array);
+ }
+
+ return $array;
+
+ } // _parse_quicktime
+
+ /**
+ * _parse_avi
+ * This attempts to parse our the information on an avi file and present it in some
+ * kind of sane format, this is a little hard as these files don't have tags
+ */
+ private function _parse_avi($tags) {
+
+ $array = array();
+
+ $array['title'] = urldecode($this->_pathinfo['filename']);
+ $array['video_codec'] = $tags['video']['fourcc'];
+ $array['audio_codec'] = $tags['audio']['dataformat'];
+ $array['resolution_x'] = $tags['video']['resolution_x'];
+ $array['resolution_y'] = $tags['video']['resolution_y'];
+ $array['mime'] = $tags['mime_type'];
+ $array['comment'] = $tags['video']['codec'];
+
+ return $array;
+
+ } // _parse_avi
+
+ /**
+ * _parse_mpg
+ * This attempts to parse our the information on a mpg file and present it in some
+ * kind of sane format, this is a little hard as these files don't have tags
+ */
+ private function _parse_mpg($tags) {
+
+ $array = array();
+
+ $array['title'] = urldecode($this->_pathinfo['filename']);
+ $array['video_codec'] = $tags['video']['codec'];
+ $array['audio_codec'] = $tags['audio']['dataformat'];
+ $array['resolution_x'] = $tags['video']['resolution_x'];
+ $array['resolution_y'] = $tags['video']['resolution_y'];
+ $array['mime'] = $tags['mime_type'];
+ $array['comment'] = $tags['video']['codec'];
+
+ return $array;
+
+ } // _parse_mpg
+
+ /**
+ * _parse_wmv
+ * This attempts to parse our the information on a asf/wmv file and present it in some
+ * kind of sane format, this is a little hard as these files don't have tags
+ */
+ private function _parse_wmv($tags) {
+
+ $array = array();
+
+ $array['mime'] = $tags['mime_type'];
+
+ switch($array['mime']) {
+ default:
+ case 'video/x-ms-wmv':
+ if(isset($tags['tags']['asf']['title']['0'])) {
+ $array['title'] = $tags['tags']['asf']['title']['0'];
+ }
+ else {
+ $array['title'] = urldecode($this->_pathinfo['filename']);
+ }
+ $array['video_codec'] = $tags['video']['streams']['2']['codec'];
+ $array['audio_codec'] = $tags['audio']['streams']['1']['codec'];
+ $array['resolution_x'] = $tags['video']['streams']['2']['resolution_x'];
+ $array['resolution_y'] = $tags['video']['streams']['2']['resolution_y'];
+ $array['comment'] = $tags['tags']['asf']['title']['1'];
+ break;
+ }
+
+ foreach($tags['tags']['asf'] as $tag => $data) {
+ $array[$tag] = $this->_clean_tag($data['0']);
+ }
+
+ return $array;
+
+ } // _parse_wmv
+
+ /**
+ * _parse_flv
+ * This attempts to parse our the information on an flv file and present it in some
+ * kind of sane format, this is a little hard as these files don't have tags
+ */
+ private function _parse_flv($tags) {
+
+ $array = array();
+
+ $array['title'] = urldecode($this->_pathinfo['filename']);
+ $array['video_codec'] = $tags['video']['codec'];
+ $array['audio_codec'] = $tags['audio']['dataformat'];
+ $array['resolution_x'] = $tags['video']['resolution_x'];
+ $array['resolution_y'] = $tags['video']['resolution_y'];
+ $array['mime'] = $tags['mime_type'];
+ $array['comment'] = $tags['video']['codec'];
+
+ return $array;
+
+ } // _parse_flv
+
+ /**
+ * _parse_filename
+ *
+ * This function uses the passed file and dir patterns
+ * To pull out extra tag information and populate it into
+ * its own array
+ *
+ * @param string $filename Filename that want to parse
+ * @return array Parsed results
+ */
+ private function _parse_filename($filename) {
+
+ $results = array();
+
+ // Correctly detect the slash we need to use here
+ if (strpos($filename, '/') !== false) {
+ $slash_type = '/';
+ }
+ else {
+ $slash_type = '\\';
+ }
+
+ // Combine the patterns
+ $pattern = preg_quote($this->_dir_pattern) . $slash_type . preg_quote($this->_file_pattern);
+
+ // Pull out the pattern codes into an array
+ preg_match_all('/\%\w/', $pattern, $elements);
+
+ // Mangle the pattern by turning the codes into regex captures
+ $pattern = preg_replace('/\%[Ty]/', '([0-9]+?)', $pattern);
+ $pattern = preg_replace('/\%\w/', '(.+?)', $pattern);
+ $pattern = str_replace('/', '\/', $pattern);
+ $pattern = str_replace(' ', '\s', $pattern);
+ $pattern = '/' . $pattern . '\..+$/';
+
+ // Pull out our actual matches
+ preg_match($pattern, $filename, $matches);
+
+ // The first element is the full match text
+ $matched = array_shift($matches);
+ debug_event('vainfo', $pattern . ' matched ' . $matched . ' on ' . $filename, 5);
+
+ // Iterate over what we found
+ foreach ($matches as $key => $value) {
+ $new_key = translate_pattern_code($elements['0'][$key]);
+ if ($new_key) {
+ $results[$new_key] = $value;
+ }
+ }
+
+ $results['size'] = filesize($filename);
+
+ return $results;
+
+ } // _parse_filename
+
+ /**
+ * _id3v2_tag_to_frame
+ *
+ * This translates the tag name to a frame, if there a many it returns the first
+ * one if finds that exists in the raw
+ *
+ * @param string $tag_name Tag name
+ * @return mixed If found id3v2 frame, return frame. If not found, return false.
+ */
+ private function _id3v2_tag_to_frame($tag_name) {
+
+ static $map = array(
+ 'comment'=>array('COM','COMM'),
+ 'cd_ident'=>array('MCDI','MCI'),
+ 'album'=>array('TAL','TALB'),
+ 'language'=>array('TLA','TLAN'),
+ 'mood'=>array('TMOO'),
+ 'artist'=>array('TPE1'),
+ 'year'=>array('TDRC'));
+
+ foreach ($map[$tag_name] as $frame) {
+ if (isset($this->_raw['id3v2'][$frame])) {
+ return $frame;
+ }
+ }
+
+ return false;
+
+ } // _id3v2_tag_to_frame
+
+ /**
+ * _clean_tag
+ *
+ * This function cleans up the tag that it's passed using Iconv
+ * if we've got it. It also takes an optional encoding param
+ * for the cases where we know what the tags source encoding
+ * is, and or if it's different then the encoding recorded
+ * in the file
+ *
+ * @param string $tag Encoding string
+ * @param string $encoding Encode charset
+ * @return string Return encoded string
+ */
+ private function _clean_tag($tag, $encoding = null) {
+
+ // Default to getID3's native encoding
+ if (!$encoding) {
+ $encoding = $this->_getID3->encoding;
+ }
+ // If we've got iconv then go ahead and clear her up
+ if ($encoding == $this->encoding) {
+ debug_event('vainfo', "\$encoding -> ${encoding}, \$this->encoding -> {$this->encoding}", 5);
+ return $tag;
+ }
+ if ($this->_iconv) {
+ debug_event('vainfo', 'Use iconv()',5);
+
+ // Try GNU iconv //TRANSLIT extension first
+ $new_encoding = $this->encoding . '//TRANSLIT';
+ $clean = iconv($encoding, $new_encoding, $tag);
+
+ // If that fails, do a plain conversion
+ if(strcmp($clean, '') == 0) {
+ $clean = iconv($encoding, $this->encoding, $tag);
+ }
+ }
+ elseif (function_exists('mb_convert_encoding')) {
+ debug_event('vainfo', 'Use mbstring',5);
+ debug_event('vainfo', "Try to convert from {$this->encoding} to $encoding", 5);
+ $clean = mb_convert_encoding($tag, $encoding, $this->encoding);
+ }
+ else {
+ $clean = $tag;
+ }
+
+ return $clean;
+
+ } // _clean_tag
+
+ /**
+ * set_broken
+ *
+ * This fills all tag types with Unknown (Broken)
+ *
+ * @return array Return broken title, album, artist
+ */
+ public function set_broken() {
+
+ /* Pull In the config option */
+ $order = Config::get('tag_order');
+
+ if (!is_array($order)) {
+ $order = array($order);
+ }
+
+ $key = array_shift($order);
+
+ $broken[$key]['title'] = '**BROKEN** ' . $this->filename;
+ $broken[$key]['album'] = 'Unknown (Broken)';
+ $broken[$key]['artist'] = 'Unknown (Broken)';
+
+ return $broken;
+
+ } // set_broken
} // end class vainfo
?>
diff --git a/lib/class/vauth.class.php b/lib/class/vauth.class.php
index b978c35c..e6dcab43 100644
--- a/lib/class/vauth.class.php
+++ b/lib/class/vauth.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,691 +30,691 @@
*/
class vauth {
- /**
- * Constructor
- * This should never be called
- */
- private function __construct() {
- // Rien a faire
- } // __construct
+ /**
+ * Constructor
+ * This should never be called
+ */
+ private function __construct() {
+ // Rien a faire
+ } // __construct
- /**
- * open
- * This function is for opening a new session so we just verify that we
- * have a database connection, nothing more is needed
- */
- public static function open($save_path, $session_name) {
+ /**
+ * open
+ * This function is for opening a new session so we just verify that we
+ * have a database connection, nothing more is needed
+ */
+ public static function open($save_path, $session_name) {
- if (!is_resource(Dba::dbh())) {
- debug_event('SESSION', 'Error: no database connection session failed', '1');
- return false;
- }
+ if (!is_resource(Dba::dbh())) {
+ debug_event('SESSION', 'Error: no database connection session failed', '1');
+ return false;
+ }
- return true;
+ return true;
- } // open
+ } // open
- /**
- * close
- * This is run on the end of a session, nothing to do here for now
- */
- public static function close() {
+ /**
+ * close
+ * This is run on the end of a session, nothing to do here for now
+ */
+ public static function close() {
- return true;
+ return true;
- } // close
+ } // close
- /**
- * read
- * This takes a key and then looks in the database and returns the value
- */
- public static function read($key) {
+ /**
+ * read
+ * This takes a key and then looks in the database and returns the value
+ */
+ public static function read($key) {
- $results = self::get_session_data($key);
+ $results = self::get_session_data($key);
- if (!is_array($results)) {
- debug_event('SESSION', 'Unable to read session from key ' . $key . ' no data found', 5);
- return '';
- }
+ if (!is_array($results)) {
+ debug_event('SESSION', 'Unable to read session from key ' . $key . ' no data found', 5);
+ return '';
+ }
- return $results['value'];
+ return $results['value'];
- } // read
+ } // read
- /**
- * write
- * This saves the session information into the database
- */
- public static function write($key, $value) {
+ /**
+ * write
+ * This saves the session information into the database
+ */
+ public static function write($key, $value) {
- if (defined('NO_SESSION_UPDATE')) { return true; }
-
- $length = Config::get('session_length');
- $value = Dba::escape($value);
- $key = Dba::escape($key);
- // Check to see if remember me cookie is set, if so use remember
- // length, otherwise use the session length
- $expire
- = isset($_COOKIE[Config::get('session_name') . '_remember'])
- ? time() + Config::get('remember_length')
- : time() + Config::get('session_length');
+ if (defined('NO_SESSION_UPDATE')) { return true; }
+
+ $length = Config::get('session_length');
+ $value = Dba::escape($value);
+ $key = Dba::escape($key);
+ // Check to see if remember me cookie is set, if so use remember
+ // length, otherwise use the session length
+ $expire
+ = isset($_COOKIE[Config::get('session_name') . '_remember'])
+ ? time() + Config::get('remember_length')
+ : time() + Config::get('session_length');
- $sql = "UPDATE `session` SET `value`='$value', " .
- "`expire`='$expire' WHERE `id`='$key'";
- $db_results = Dba::read($sql);
+ $sql = "UPDATE `session` SET `value`='$value', " .
+ "`expire`='$expire' WHERE `id`='$key'";
+ $db_results = Dba::read($sql);
- debug_event('SESSION', 'Writing to ' . $key . ' with expire ' . $expire . ' ' . Dba::error(), '6');
+ debug_event('SESSION', 'Writing to ' . $key . ' with expire ' . $expire . ' ' . Dba::error(), '6');
- return $db_results;
+ return $db_results;
- } // write
+ } // write
- /**
- * destroy
- * This removes the specified session from the database
- */
- public static function destroy($key) {
+ /**
+ * destroy
+ * This removes the specified session from the database
+ */
+ public static function destroy($key) {
- $key = Dba::escape($key);
+ $key = Dba::escape($key);
- if (!strlen($key)) { return false; }
+ if (!strlen($key)) { return false; }
- // Remove anything and EVERYTHING
- $sql = "DELETE FROM `session` WHERE `id`='$key'";
- $db_results = Dba::write($sql);
+ // Remove anything and EVERYTHING
+ $sql = "DELETE FROM `session` WHERE `id`='$key'";
+ $db_results = Dba::write($sql);
- debug_event('SESSION', 'Deleting Session with key:' . $key, '6');
+ debug_event('SESSION', 'Deleting Session with key:' . $key, '6');
- // Destroy our cookie!
- setcookie(Config::get('session_name'), '', time() - 86400);
+ // Destroy our cookie!
+ setcookie(Config::get('session_name'), '', time() - 86400);
- return true;
+ return true;
- } // destroy
+ } // destroy
- /**
- * gc
- * This function is randomly called and it cleans up the spoo
- */
- public static function gc($maxlifetime) {
+ /**
+ * gc
+ * This function is randomly called and it cleans up the spoo
+ */
+ public static function gc($maxlifetime) {
- $sql = "DELETE FROM `session` WHERE `expire` < '" . time() . "'";
- $db_results = Dba::write($sql);
+ $sql = "DELETE FROM `session` WHERE `expire` < '" . time() . "'";
+ $db_results = Dba::write($sql);
- // Also clean up things that use sessions as keys
- Query::gc();
- Tmp_Playlist::gc();
+ // Also clean up things that use sessions as keys
+ Query::gc();
+ Tmp_Playlist::gc();
- return true;
+ return true;
- } // gc
+ } // gc
- /**
- * logout
- * This is called when you want to log out and nuke your session
- * This is the function used for the Ajax logouts, if no id is passed
- * it tries to find one from the session
- */
- public static function logout($key='', $relogin=true) {
+ /**
+ * logout
+ * This is called when you want to log out and nuke your session
+ * This is the function used for the Ajax logouts, if no id is passed
+ * it tries to find one from the session
+ */
+ public static function logout($key='', $relogin=true) {
- // If no key is passed try to find the session id
- $key = $key ? $key : session_id();
+ // If no key is passed try to find the session id
+ $key = $key ? $key : session_id();
- // Nuke the cookie before all else
- self::destroy($key);
- if ((! $relogin) && Config::get('logout_redirect')) {
- $target = Config::get('logout_redirect');
- }
- else {
- $target = Config::get('web_path') . '/login.php';
- }
+ // Nuke the cookie before all else
+ self::destroy($key);
+ if ((! $relogin) && Config::get('logout_redirect')) {
+ $target = Config::get('logout_redirect');
+ }
+ else {
+ $target = Config::get('web_path') . '/login.php';
+ }
- // Do a quick check to see if this is an AJAXed logout request
- // if so use the iframe to redirect
- if (defined('AJAX_INCLUDE')) {
- ob_end_clean();
- ob_start();
-
- /* Set the correct headers */
- header("Content-type: text/xml; charset=" . Config::get('site_charset'));
- header("Content-Disposition: attachment; filename=ajax.xml");
- header("Expires: Tuesday, 27 Mar 1984 05:00:00 GMT");
- header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
- header("Cache-Control: no-store, no-cache, must-revalidate");
- header("Pragma: no-cache");
-
- $results['rfc3514'] = '<script type="text/javascript">reloadRedirect("' . $target . '")</script>';
- echo xml_from_array($results);
- }
- else {
- /* Redirect them to the login page */
- header('Location: ' . $target);
- }
-
- exit;
-
- } // logout
-
- /**
- * get_session_data
- * This takes a key and returns the raw data from the database, nothing
- * to see here move along people
- */
- public static function get_session_data($key) {
-
- $key = Dba::escape($key);
-
- $sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '" . time() . "'";
- $db_results = Dba::read($sql);
-
- if ($results = Dba::fetch_assoc($db_results)) {
- return $results;
- }
-
- return false;
-
- } // get_session_data
-
- /**
- * create_cookie
- * This is separated into its own function because of some flaws in
- * specific webservers *cough* IIS *cough* which prevent us from setting
- * a cookie at the same time as a header redirect. As such on view of a
- * login a cookie is set with the proper name
- */
- public static function create_cookie() {
-
- /* Setup the cookie prefs before we throw down, this is very important */
- $cookie_life = Config::get('cookie_life');
- $cookie_path = Config::get('cookie_path');
- $cookie_domain = false;
- $cookie_secure = Config::get('cookie_secure');
-
- session_set_cookie_params($cookie_life,$cookie_path,$cookie_domain,$cookie_secure);
-
- session_name(Config::get('session_name'));
-
- /* Start the session */
- self::ungimp_ie();
- session_start();
-
- } // create_cookie, just watch out for the cookie monster
-
- /**
- * create_remember_cookie
- * This function just creates the remember me cookie, nothing special
- */
- public static function create_remember_cookie() {
-
- $remember_length = Config::get('remember_length');
- $session_name = Config::get('session_name');
-
- Config::set('cookie_life', $remember_length, true);
- setcookie($session_name . '_remember',"Rappelez-vous, rappelez-vous le 27 mars", time() + $remember_length, '/');
-
- } // create_remember_cookie
-
- /**
- * session_create
- * This is called when you want to create a new session
- * it takes care of setting the initial cookie, and inserting the first
- * chunk of data, nifty ain't it!
- */
- public static function session_create($data) {
-
- // Regenerate the session ID to prevent fixation
- switch ($data['type']) {
- case 'xml-rpc':
- case 'api':
- $key = md5(uniqid(rand(), true));
- break;
- case 'mysql':
- default:
- session_regenerate_id();
-
- // Before refresh we don't have the cookie so we
- // have to use session ID
- $key = session_id();
- break;
- } // end switch on data type
-
- $username = Dba::escape($data['username']);
- $ip = $_SERVER['REMOTE_ADDR']
- ? Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']))
- : '0';
- $type = Dba::escape($data['type']);
- $value = Dba::escape($data['value']);
- $agent = Dba::escape(substr($_SERVER['HTTP_USER_AGENT'], 0, 254));
- $expire = Dba::escape(time() + Config::get('session_length'));
-
- /* We can't have null things here people */
- if (!strlen($value)) { $value = ' '; }
-
- /* Insert the row */
- $sql = "INSERT INTO `session` (`id`,`username`,`ip`,`type`,`agent`,`value`,`expire`) " .
- " VALUES ('$key','$username','$ip','$type','$agent','$value','$expire')";
- $db_results = Dba::write($sql);
-
- if (!$db_results) {
- debug_event('SESSION', "Session Creation Failed with Query: $sql and " . Dba::error(), '1');
- return false;
- }
-
- debug_event('SESSION', 'Session Created:' . $key, '6');
-
- return $key;
-
- } // session_create
-
- /**
- * check_session
- * This checks for an existing session. If it's still valid we go ahead
- * and start it and return true.
- */
- public static function check_session() {
-
- $session_name = Config::get('session_name');
-
- // No cookie no go!
- if (!isset($_COOKIE[$session_name])) { return false; }
-
- // Check for a remember me
- if (isset($_COOKIE[$session_name . '_remember'])) {
- self::create_remember_cookie();
- }
-
- // Set up the cookie params before we start the session.
- // This is vital
- session_set_cookie_params(
- Config::get('cookie_life'),
- Config::get('cookie_path'),
- Config::get('cookie_domain'),
- Config::get('cookie_secure'));
-
- // Set name
- session_name($session_name);
-
- // Ungimp IE and go
- self::ungimp_ie();
- session_start();
-
- return true;
-
- } // check_session
-
- /**
- * session_exists
- * This checks to see if the specified session of the specified type
- * exists, it also provides an array of key'd data that may be required
- * based on the type
- */
- public static function session_exists($type, $key, $data=array()) {
-
- // Switch on the type they pass
- switch ($type) {
- case 'xml-rpc':
- case 'api':
- $key = Dba::escape($key);
- $time = time();
- $sql = "SELECT * FROM `session` WHERE " .
- "`id`='$key' AND `expire` > '$time' " .
- "AND `type`='$type'";
- $db_results = Dba::read($sql);
-
- if (Dba::num_rows($db_results)) {
- return true;
- }
- break;
- case 'interface':
- $key = Dba::escape($key);
- $time = time();
- // Build a list of enabled authentication types
- $types = Config::get('auth_methods');
- if (!Config::get('use_auth')) {
- $types[] = '';
- }
- $enabled_types = implode("','", $types);
- $sql = "SELECT * FROM `session` WHERE " .
- "`id`='$key' AND `expire` > '$time' " .
- "AND `type` IN('$enabled_types')";
- $db_results = Dba::read($sql);
-
- if (Dba::num_rows($db_results)) {
- return true;
- }
- break;
- case 'stream':
- $key = Dba::escape($key);
- $ip = Dba::escape(inet_pton($data['ip']));
- $agent = Dba::escape($data['agent']);
- $sql = "SELECT * FROM `session_stream` WHERE " .
- "`id`='$key' AND `expire` > '$time' " .
- "AND `ip`='$ip' AND `agent`='$agent'";
- $db_results = Dba::read($sql);
-
- if (Dba::num_rows($db_results)) {
- return true;
- }
-
- break;
- default:
- return false;
- break;
- } // type
-
- // Default to false
- return false;
-
- } // session_exists
-
- /**
- * session_extend
- * This should really be extend_session but hey you gotta go with the
- * flow.
- * This takes a SID and extends its expiration.
- */
- public static function session_extend($sid) {
- $time = time();
- $sid = Dba::escape($sid);
- $expire = isset($_COOKIE[Config::get('session_name') . '_remember'])
- ? $time + Config::get('remember_length')
- : $time + Config::get('session_length');
-
- $sql = "UPDATE `session` SET `expire`='$expire' WHERE `id`='$sid'";
- $db_results = Dba::write($sql);
-
- debug_event('SESSION', $sid . ' has been extended to ' . date('r', $expire) . ' extension length ' . ($expire - $time), 5);
-
- return $db_results;
- } // session_extend
-
- /**
- * _auto_init
- * This function is called when the object is included, this sets up the
- * session_save_handler
- */
- public static function _auto_init() {
-
- if (!function_exists('session_start')) {
- header("Location:" . Config::get('web_path') . "/test.php");
- exit;
- }
-
- session_set_save_handler(
- array('vauth', 'open'),
- array('vauth', 'close'),
- array('vauth', 'read'),
- array('vauth', 'write'),
- array('vauth', 'destroy'),
- array('vauth', 'gc'));
-
- } // auto init
-
- /**
- * ungimp_ie
- * This function sets the cache limiting to public if you are running
- * some flavor of IE. The detection used here is very conservative so
- * feel free to fix it. This only has to be done if we're rolling HTTPS.
- */
- public static function ungimp_ie() {
-
- // If no https, no ungimpage required
- if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'on') {
- return true;
- }
-
- // Try to detect IE
- $agent = trim($_SERVER['HTTP_USER_AGENT']);
-
- if ((strpos($agent, 'MSIE') !== false) ||
- (strpos($agent,'Internet Explorer/') !== false)) {
- session_cache_limiter('public');
- }
-
- return true;
-
- } // ungimp_ie
-
- /**
- * authenticate
- * This takes a username and password and then returns the results
- * based on what happens when we try to do the auth.
- */
- public static function authenticate($username, $password) {
-
- // Foreach the auth methods
- foreach (Config::get('auth_methods') as $method) {
-
- // Build the function name and call it
- $function_name = $method . '_auth';
-
- if (!method_exists('vauth', $function_name)) {
- continue;
- }
-
- $results = self::$function_name($username, $password);
-
- // If we achieve victory return
- if ($results['success']) { break; }
-
- } // end foreach
-
- return $results;
-
- } // authenticate
-
- /**
- * mysql_auth
- *
- * This is the core function of our built-in authentication.
- */
- private static function mysql_auth($username, $password) {
-
- $username = Dba::escape($username);
-
- if (strlen($password) && strlen($username)) {
- $sql = "SELECT `password` FROM `user` WHERE " .
- "`username`='$username'";
- $db_results = Dba::read($sql);
- if ($row = Dba::fetch_assoc($db_results)) {
-
- // Use SHA2 now... cooking with fire.
- // For backwards compatibility, we hash a couple
- // of different variations of the password.
- // Increases collision chances, but doesn't
- // break things.
- $hashed_password[] = hash('sha256', $password);
- $hashed_password[] = hash('sha256',
- Dba::escape(scrub_in($password)));
-
- // Automagically update the password if it's
- // old and busted.
- if($row['password'] == $hashed_password[1] &&
- $hashed_password[0] != $hashed_password[1]) {
- $user = User::get_from_username($username);
- $user->update_password($password);
- }
-
- if(in_array($row['password'], $hashed_password)) {
- $results['success'] = true;
- $results['type'] = 'mysql';
- $results['username'] = $username;
- return $results;
- }
- }
- }
-
- // Default to failure
- $results['success'] = false;
- $results['error'] = 'MySQL login attempt failed';
- return $results;
-
- } // mysql_auth
-
- /**
- * local_auth
- * Check to make sure the pam_auth function is implemented (module is
- * installed), then check the credentials.
- */
- private static function local_auth($username, $password) {
- if (!function_exists('pam_auth')) {
- $results['success'] = false;
- $results['error'] = 'The PAM PHP module is not installed';
- return $results;
- }
-
- $password = scrub_in($password);
-
- if (pam_auth($username, $password)) {
- $results['success'] = true;
- $results['type'] = 'local';
- $results['username'] = $username;
- }
- else {
- $results['success'] = false;
- $results['error'] = 'PAM login attempt failed';
- }
-
- return $results;
- } // local_auth
-
- /**
- * ldap_auth
- * Step one, connect to the LDAP server and perform a search for the
- * username provided.
- * Step two, attempt to bind using that username and the password
- * provided.
- * Step three, figure out if they are authorized to use ampache:
- * TODO: in config but unimplemented:
- * * require-dn "Grant access if the DN in the directive matches
- * the DN fetched from the LDAP directory"
- * * require-attribute "an attribute fetched from the LDAP
- * directory matches the given value"
- */
- private static function ldap_auth($username, $password) {
-
- $ldap_username = Config::get('ldap_username');
- $ldap_password = Config::get('ldap_password');
-
- $require_group = Config::get('ldap_require_group');
-
- // This is the DN for the users (required)
- $ldap_dn = Config::get('ldap_search_dn');
-
- // This is the server url (required)
- $ldap_url = Config::get('ldap_url');
-
- // This is the ldap filter string (required)
- $ldap_filter = Config::get('ldap_filter');
-
- //This is the ldap objectclass (required)
- $ldap_class = Config::get('ldap_objectclass');
-
- if (!($ldap_dn && $ldap_url && $ldap_filter && $ldap_class)) {
- debug_event('ldap_auth', 'Required config value missing', 1);
- $results['success'] = false;
- $results['error'] = 'Incomplete LDAP config';
- return $results;
- }
-
- $ldap_name_field = Config::get('ldap_name_field');
- $ldap_email_field = Config::get('ldap_email_field');
-
- if ($ldap_link = ldap_connect($ldap_url) ) {
-
- /* Set to Protocol 3 */
- ldap_set_option($ldap_link, LDAP_OPT_PROTOCOL_VERSION, 3);
-
- // bind using our auth if we need to for initial search
- if (!ldap_bind($ldap_link, $ldap_username, $ldap_password)) {
- $results['success'] = false;
- $results['error'] = 'Could not bind to LDAP server.';
- return $results;
- } // If bind fails
-
- $sr = ldap_search($ldap_link, $ldap_dn, "(&(objectclass=$ldap_class)($ldap_filter=$username))");
- $info = ldap_get_entries($ldap_link, $sr);
-
- if ($info["count"] == 1) {
- $user_entry = ldap_first_entry($ldap_link, $sr);
- $user_dn = ldap_get_dn($ldap_link, $user_entry);
- $password = scrub_in($password);
- // bind using the user..
- $retval = ldap_bind($ldap_link, $user_dn, $password);
-
- if ($retval) {
- // When the current user needs to be in
- // a specific group to access Ampache,
- // check whether the 'member' list of
- // the group contains the DN
- if ($require_group) {
- $group_result = ldap_read($ldap_link, $require_group, 'objectclass=*', array('member'));
- if (!$group_result) {
- debug_event('ldap_auth', "Failure reading $require_group", 1);
- $results['success'] = false;
- $results['error'] = 'The LDAP group could not be read';
- return $results;
- }
-
- $group_info = ldap_get_entries($ldap_link, $group_result);
-
- if ($group_info['count'] < 1) {
- debug_event('ldap_auth', "No members found in $require_group", 1);
- $results['success'] = false;
- $results['error'] = 'Empty LDAP group';
- return $results;
- }
-
- $group_match = preg_grep("/^$user_dn\$/i", $group_info[0]['member']);
- if (!$group_match) {
- debug_event('ldap_auth', "$user_dn is not a member of $require_group",1);
- $results['success'] = false;
- $results['error'] = 'LDAP login attempt failed';
- return $results;
- }
- }
- ldap_close($ldap_link);
- $results['success'] = true;
- $results['type'] = "ldap";
- $results['username'] = $username;
- $results['name'] = $info[0][$ldap_name_field][0];
- $results['email'] = $info[0][$ldap_email_field][0];
-
- return $results;
-
- } // if we get something good back
-
- } // if something was sent back
-
- } // if failed connect
-
- /* Default to bad news */
- $results['success'] = false;
- $results['error'] = 'LDAP login attempt failed';
-
- return $results;
-
- } // ldap_auth
-
- /**
- * http_auth
- * This auth method relies on HTTP auth from the webserver
- */
- private static function http_auth($username, $password) {
- if (($_SERVER['REMOTE_USER'] == $username) ||
- ($_SERVER['HTTP_REMOTE_USER'] == $username)) {
- $results['success'] = true;
- $results['type'] = 'http';
- $results['username'] = $username;
- $results['name'] = $username;
- $results['email'] = '';
- }
- else {
- $results['success'] = false;
- $results['error'] = 'HTTP auth login attempt failed';
- }
- return $results;
- } // http_auth
+ // Do a quick check to see if this is an AJAXed logout request
+ // if so use the iframe to redirect
+ if (defined('AJAX_INCLUDE')) {
+ ob_end_clean();
+ ob_start();
+
+ /* Set the correct headers */
+ header("Content-type: text/xml; charset=" . Config::get('site_charset'));
+ header("Content-Disposition: attachment; filename=ajax.xml");
+ header("Expires: Tuesday, 27 Mar 1984 05:00:00 GMT");
+ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+ header("Cache-Control: no-store, no-cache, must-revalidate");
+ header("Pragma: no-cache");
+
+ $results['rfc3514'] = '<script type="text/javascript">reloadRedirect("' . $target . '")</script>';
+ echo xml_from_array($results);
+ }
+ else {
+ /* Redirect them to the login page */
+ header('Location: ' . $target);
+ }
+
+ exit;
+
+ } // logout
+
+ /**
+ * get_session_data
+ * This takes a key and returns the raw data from the database, nothing
+ * to see here move along people
+ */
+ public static function get_session_data($key) {
+
+ $key = Dba::escape($key);
+
+ $sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '" . time() . "'";
+ $db_results = Dba::read($sql);
+
+ if ($results = Dba::fetch_assoc($db_results)) {
+ return $results;
+ }
+
+ return false;
+
+ } // get_session_data
+
+ /**
+ * create_cookie
+ * This is separated into its own function because of some flaws in
+ * specific webservers *cough* IIS *cough* which prevent us from setting
+ * a cookie at the same time as a header redirect. As such on view of a
+ * login a cookie is set with the proper name
+ */
+ public static function create_cookie() {
+
+ /* Setup the cookie prefs before we throw down, this is very important */
+ $cookie_life = Config::get('cookie_life');
+ $cookie_path = Config::get('cookie_path');
+ $cookie_domain = false;
+ $cookie_secure = Config::get('cookie_secure');
+
+ session_set_cookie_params($cookie_life,$cookie_path,$cookie_domain,$cookie_secure);
+
+ session_name(Config::get('session_name'));
+
+ /* Start the session */
+ self::ungimp_ie();
+ session_start();
+
+ } // create_cookie, just watch out for the cookie monster
+
+ /**
+ * create_remember_cookie
+ * This function just creates the remember me cookie, nothing special
+ */
+ public static function create_remember_cookie() {
+
+ $remember_length = Config::get('remember_length');
+ $session_name = Config::get('session_name');
+
+ Config::set('cookie_life', $remember_length, true);
+ setcookie($session_name . '_remember',"Rappelez-vous, rappelez-vous le 27 mars", time() + $remember_length, '/');
+
+ } // create_remember_cookie
+
+ /**
+ * session_create
+ * This is called when you want to create a new session
+ * it takes care of setting the initial cookie, and inserting the first
+ * chunk of data, nifty ain't it!
+ */
+ public static function session_create($data) {
+
+ // Regenerate the session ID to prevent fixation
+ switch ($data['type']) {
+ case 'xml-rpc':
+ case 'api':
+ $key = md5(uniqid(rand(), true));
+ break;
+ case 'mysql':
+ default:
+ session_regenerate_id();
+
+ // Before refresh we don't have the cookie so we
+ // have to use session ID
+ $key = session_id();
+ break;
+ } // end switch on data type
+
+ $username = Dba::escape($data['username']);
+ $ip = $_SERVER['REMOTE_ADDR']
+ ? Dba::escape(inet_pton($_SERVER['REMOTE_ADDR']))
+ : '0';
+ $type = Dba::escape($data['type']);
+ $value = Dba::escape($data['value']);
+ $agent = Dba::escape(substr($_SERVER['HTTP_USER_AGENT'], 0, 254));
+ $expire = Dba::escape(time() + Config::get('session_length'));
+
+ /* We can't have null things here people */
+ if (!strlen($value)) { $value = ' '; }
+
+ /* Insert the row */
+ $sql = "INSERT INTO `session` (`id`,`username`,`ip`,`type`,`agent`,`value`,`expire`) " .
+ " VALUES ('$key','$username','$ip','$type','$agent','$value','$expire')";
+ $db_results = Dba::write($sql);
+
+ if (!$db_results) {
+ debug_event('SESSION', "Session Creation Failed with Query: $sql and " . Dba::error(), '1');
+ return false;
+ }
+
+ debug_event('SESSION', 'Session Created:' . $key, '6');
+
+ return $key;
+
+ } // session_create
+
+ /**
+ * check_session
+ * This checks for an existing session. If it's still valid we go ahead
+ * and start it and return true.
+ */
+ public static function check_session() {
+
+ $session_name = Config::get('session_name');
+
+ // No cookie no go!
+ if (!isset($_COOKIE[$session_name])) { return false; }
+
+ // Check for a remember me
+ if (isset($_COOKIE[$session_name . '_remember'])) {
+ self::create_remember_cookie();
+ }
+
+ // Set up the cookie params before we start the session.
+ // This is vital
+ session_set_cookie_params(
+ Config::get('cookie_life'),
+ Config::get('cookie_path'),
+ Config::get('cookie_domain'),
+ Config::get('cookie_secure'));
+
+ // Set name
+ session_name($session_name);
+
+ // Ungimp IE and go
+ self::ungimp_ie();
+ session_start();
+
+ return true;
+
+ } // check_session
+
+ /**
+ * session_exists
+ * This checks to see if the specified session of the specified type
+ * exists, it also provides an array of key'd data that may be required
+ * based on the type
+ */
+ public static function session_exists($type, $key, $data=array()) {
+
+ // Switch on the type they pass
+ switch ($type) {
+ case 'xml-rpc':
+ case 'api':
+ $key = Dba::escape($key);
+ $time = time();
+ $sql = "SELECT * FROM `session` WHERE " .
+ "`id`='$key' AND `expire` > '$time' " .
+ "AND `type`='$type'";
+ $db_results = Dba::read($sql);
+
+ if (Dba::num_rows($db_results)) {
+ return true;
+ }
+ break;
+ case 'interface':
+ $key = Dba::escape($key);
+ $time = time();
+ // Build a list of enabled authentication types
+ $types = Config::get('auth_methods');
+ if (!Config::get('use_auth')) {
+ $types[] = '';
+ }
+ $enabled_types = implode("','", $types);
+ $sql = "SELECT * FROM `session` WHERE " .
+ "`id`='$key' AND `expire` > '$time' " .
+ "AND `type` IN('$enabled_types')";
+ $db_results = Dba::read($sql);
+
+ if (Dba::num_rows($db_results)) {
+ return true;
+ }
+ break;
+ case 'stream':
+ $key = Dba::escape($key);
+ $ip = Dba::escape(inet_pton($data['ip']));
+ $agent = Dba::escape($data['agent']);
+ $sql = "SELECT * FROM `session_stream` WHERE " .
+ "`id`='$key' AND `expire` > '$time' " .
+ "AND `ip`='$ip' AND `agent`='$agent'";
+ $db_results = Dba::read($sql);
+
+ if (Dba::num_rows($db_results)) {
+ return true;
+ }
+
+ break;
+ default:
+ return false;
+ break;
+ } // type
+
+ // Default to false
+ return false;
+
+ } // session_exists
+
+ /**
+ * session_extend
+ * This should really be extend_session but hey you gotta go with the
+ * flow.
+ * This takes a SID and extends its expiration.
+ */
+ public static function session_extend($sid) {
+ $time = time();
+ $sid = Dba::escape($sid);
+ $expire = isset($_COOKIE[Config::get('session_name') . '_remember'])
+ ? $time + Config::get('remember_length')
+ : $time + Config::get('session_length');
+
+ $sql = "UPDATE `session` SET `expire`='$expire' WHERE `id`='$sid'";
+ $db_results = Dba::write($sql);
+
+ debug_event('SESSION', $sid . ' has been extended to ' . date('r', $expire) . ' extension length ' . ($expire - $time), 5);
+
+ return $db_results;
+ } // session_extend
+
+ /**
+ * _auto_init
+ * This function is called when the object is included, this sets up the
+ * session_save_handler
+ */
+ public static function _auto_init() {
+
+ if (!function_exists('session_start')) {
+ header("Location:" . Config::get('web_path') . "/test.php");
+ exit;
+ }
+
+ session_set_save_handler(
+ array('vauth', 'open'),
+ array('vauth', 'close'),
+ array('vauth', 'read'),
+ array('vauth', 'write'),
+ array('vauth', 'destroy'),
+ array('vauth', 'gc'));
+
+ } // auto init
+
+ /**
+ * ungimp_ie
+ * This function sets the cache limiting to public if you are running
+ * some flavor of IE. The detection used here is very conservative so
+ * feel free to fix it. This only has to be done if we're rolling HTTPS.
+ */
+ public static function ungimp_ie() {
+
+ // If no https, no ungimpage required
+ if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'on') {
+ return true;
+ }
+
+ // Try to detect IE
+ $agent = trim($_SERVER['HTTP_USER_AGENT']);
+
+ if ((strpos($agent, 'MSIE') !== false) ||
+ (strpos($agent,'Internet Explorer/') !== false)) {
+ session_cache_limiter('public');
+ }
+
+ return true;
+
+ } // ungimp_ie
+
+ /**
+ * authenticate
+ * This takes a username and password and then returns the results
+ * based on what happens when we try to do the auth.
+ */
+ public static function authenticate($username, $password) {
+
+ // Foreach the auth methods
+ foreach (Config::get('auth_methods') as $method) {
+
+ // Build the function name and call it
+ $function_name = $method . '_auth';
+
+ if (!method_exists('vauth', $function_name)) {
+ continue;
+ }
+
+ $results = self::$function_name($username, $password);
+
+ // If we achieve victory return
+ if ($results['success']) { break; }
+
+ } // end foreach
+
+ return $results;
+
+ } // authenticate
+
+ /**
+ * mysql_auth
+ *
+ * This is the core function of our built-in authentication.
+ */
+ private static function mysql_auth($username, $password) {
+
+ $username = Dba::escape($username);
+
+ if (strlen($password) && strlen($username)) {
+ $sql = "SELECT `password` FROM `user` WHERE " .
+ "`username`='$username'";
+ $db_results = Dba::read($sql);
+ if ($row = Dba::fetch_assoc($db_results)) {
+
+ // Use SHA2 now... cooking with fire.
+ // For backwards compatibility, we hash a couple
+ // of different variations of the password.
+ // Increases collision chances, but doesn't
+ // break things.
+ $hashed_password[] = hash('sha256', $password);
+ $hashed_password[] = hash('sha256',
+ Dba::escape(scrub_in($password)));
+
+ // Automagically update the password if it's
+ // old and busted.
+ if($row['password'] == $hashed_password[1] &&
+ $hashed_password[0] != $hashed_password[1]) {
+ $user = User::get_from_username($username);
+ $user->update_password($password);
+ }
+
+ if(in_array($row['password'], $hashed_password)) {
+ $results['success'] = true;
+ $results['type'] = 'mysql';
+ $results['username'] = $username;
+ return $results;
+ }
+ }
+ }
+
+ // Default to failure
+ $results['success'] = false;
+ $results['error'] = 'MySQL login attempt failed';
+ return $results;
+
+ } // mysql_auth
+
+ /**
+ * local_auth
+ * Check to make sure the pam_auth function is implemented (module is
+ * installed), then check the credentials.
+ */
+ private static function local_auth($username, $password) {
+ if (!function_exists('pam_auth')) {
+ $results['success'] = false;
+ $results['error'] = 'The PAM PHP module is not installed';
+ return $results;
+ }
+
+ $password = scrub_in($password);
+
+ if (pam_auth($username, $password)) {
+ $results['success'] = true;
+ $results['type'] = 'local';
+ $results['username'] = $username;
+ }
+ else {
+ $results['success'] = false;
+ $results['error'] = 'PAM login attempt failed';
+ }
+
+ return $results;
+ } // local_auth
+
+ /**
+ * ldap_auth
+ * Step one, connect to the LDAP server and perform a search for the
+ * username provided.
+ * Step two, attempt to bind using that username and the password
+ * provided.
+ * Step three, figure out if they are authorized to use ampache:
+ * TODO: in config but unimplemented:
+ * * require-dn "Grant access if the DN in the directive matches
+ * the DN fetched from the LDAP directory"
+ * * require-attribute "an attribute fetched from the LDAP
+ * directory matches the given value"
+ */
+ private static function ldap_auth($username, $password) {
+
+ $ldap_username = Config::get('ldap_username');
+ $ldap_password = Config::get('ldap_password');
+
+ $require_group = Config::get('ldap_require_group');
+
+ // This is the DN for the users (required)
+ $ldap_dn = Config::get('ldap_search_dn');
+
+ // This is the server url (required)
+ $ldap_url = Config::get('ldap_url');
+
+ // This is the ldap filter string (required)
+ $ldap_filter = Config::get('ldap_filter');
+
+ //This is the ldap objectclass (required)
+ $ldap_class = Config::get('ldap_objectclass');
+
+ if (!($ldap_dn && $ldap_url && $ldap_filter && $ldap_class)) {
+ debug_event('ldap_auth', 'Required config value missing', 1);
+ $results['success'] = false;
+ $results['error'] = 'Incomplete LDAP config';
+ return $results;
+ }
+
+ $ldap_name_field = Config::get('ldap_name_field');
+ $ldap_email_field = Config::get('ldap_email_field');
+
+ if ($ldap_link = ldap_connect($ldap_url) ) {
+
+ /* Set to Protocol 3 */
+ ldap_set_option($ldap_link, LDAP_OPT_PROTOCOL_VERSION, 3);
+
+ // bind using our auth if we need to for initial search
+ if (!ldap_bind($ldap_link, $ldap_username, $ldap_password)) {
+ $results['success'] = false;
+ $results['error'] = 'Could not bind to LDAP server.';
+ return $results;
+ } // If bind fails
+
+ $sr = ldap_search($ldap_link, $ldap_dn, "(&(objectclass=$ldap_class)($ldap_filter=$username))");
+ $info = ldap_get_entries($ldap_link, $sr);
+
+ if ($info["count"] == 1) {
+ $user_entry = ldap_first_entry($ldap_link, $sr);
+ $user_dn = ldap_get_dn($ldap_link, $user_entry);
+ $password = scrub_in($password);
+ // bind using the user..
+ $retval = ldap_bind($ldap_link, $user_dn, $password);
+
+ if ($retval) {
+ // When the current user needs to be in
+ // a specific group to access Ampache,
+ // check whether the 'member' list of
+ // the group contains the DN
+ if ($require_group) {
+ $group_result = ldap_read($ldap_link, $require_group, 'objectclass=*', array('member'));
+ if (!$group_result) {
+ debug_event('ldap_auth', "Failure reading $require_group", 1);
+ $results['success'] = false;
+ $results['error'] = 'The LDAP group could not be read';
+ return $results;
+ }
+
+ $group_info = ldap_get_entries($ldap_link, $group_result);
+
+ if ($group_info['count'] < 1) {
+ debug_event('ldap_auth', "No members found in $require_group", 1);
+ $results['success'] = false;
+ $results['error'] = 'Empty LDAP group';
+ return $results;
+ }
+
+ $group_match = preg_grep("/^$user_dn\$/i", $group_info[0]['member']);
+ if (!$group_match) {
+ debug_event('ldap_auth', "$user_dn is not a member of $require_group",1);
+ $results['success'] = false;
+ $results['error'] = 'LDAP login attempt failed';
+ return $results;
+ }
+ }
+ ldap_close($ldap_link);
+ $results['success'] = true;
+ $results['type'] = "ldap";
+ $results['username'] = $username;
+ $results['name'] = $info[0][$ldap_name_field][0];
+ $results['email'] = $info[0][$ldap_email_field][0];
+
+ return $results;
+
+ } // if we get something good back
+
+ } // if something was sent back
+
+ } // if failed connect
+
+ /* Default to bad news */
+ $results['success'] = false;
+ $results['error'] = 'LDAP login attempt failed';
+
+ return $results;
+
+ } // ldap_auth
+
+ /**
+ * http_auth
+ * This auth method relies on HTTP auth from the webserver
+ */
+ private static function http_auth($username, $password) {
+ if (($_SERVER['REMOTE_USER'] == $username) ||
+ ($_SERVER['HTTP_REMOTE_USER'] == $username)) {
+ $results['success'] = true;
+ $results['type'] = 'http';
+ $results['username'] = $username;
+ $results['name'] = $username;
+ $results['email'] = '';
+ }
+ else {
+ $results['success'] = false;
+ $results['error'] = 'HTTP auth login attempt failed';
+ }
+ return $results;
+ } // http_auth
} // end of vauth class
diff --git a/lib/class/video.class.php b/lib/class/video.class.php
index 5a758aae..8299cf8d 100644
--- a/lib/class/video.class.php
+++ b/lib/class/video.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -22,107 +22,107 @@
class Video extends database_object implements media {
- public $id;
- public $title;
- public $enabled;
- public $file;
- public $size;
+ public $id;
+ public $title;
+ public $enabled;
+ public $file;
+ public $size;
- /**
- * Constructor
- * This pulls the shoutbox information from the database and returns
- * a constructed object, uses user_shout table
- */
- public function __construct($id) {
+ /**
+ * Constructor
+ * This pulls the shoutbox information from the database and returns
+ * a constructed object, uses user_shout table
+ */
+ public function __construct($id) {
- // Load the data from the database
- $info = $this->get_info($id);
- foreach ($info as $key=>$value) {
- $this->$key = $value;
- }
+ // Load the data from the database
+ $info = $this->get_info($id);
+ foreach ($info as $key=>$value) {
+ $this->$key = $value;
+ }
- return true;
+ return true;
- } // Constructor
+ } // Constructor
- /**
- * build_cache
- * Build a cache based on the array of ids passed, saves lots of little queries
- */
- public static function build_cache($ids=array()) {
+ /**
+ * build_cache
+ * Build a cache based on the array of ids passed, saves lots of little queries
+ */
+ public static function build_cache($ids=array()) {
- if (!is_array($ids) OR !count($ids)) { return false; }
+ if (!is_array($ids) OR !count($ids)) { return false; }
- $idlist = '(' . implode(',',$ids) . ')';
+ $idlist = '(' . implode(',',$ids) . ')';
- $sql = "SELECT * FROM `video` WHERE `video`.`id` IN $idlist";
- $db_results = Dba::read($sql);
+ $sql = "SELECT * FROM `video` WHERE `video`.`id` IN $idlist";
+ $db_results = Dba::read($sql);
- while ($row = Dba::fetch_assoc($db_results)) {
- parent::add_to_cache('video',$row['id'],$row);
- }
+ while ($row = Dba::fetch_assoc($db_results)) {
+ parent::add_to_cache('video',$row['id'],$row);
+ }
- } // build_cache
+ } // build_cache
- /**
- * format
- * This formats a video object so that it is human readable
- */
- public function format() {
+ /**
+ * format
+ * This formats a video object so that it is human readable
+ */
+ public function format() {
- $this->f_title = scrub_out($this->title);
- $this->f_link = scrub_out($this->title);
- $this->f_codec = $this->video_codec . ' / ' . $this->audio_codec;
- $this->f_resolution = $this->resolution_x . 'x' . $this->resolution_y;
- $this->f_tags = '';
- $this->f_length = floor($this->time/60) . ' ' . T_('minutes');
+ $this->f_title = scrub_out($this->title);
+ $this->f_link = scrub_out($this->title);
+ $this->f_codec = $this->video_codec . ' / ' . $this->audio_codec;
+ $this->f_resolution = $this->resolution_x . 'x' . $this->resolution_y;
+ $this->f_tags = '';
+ $this->f_length = floor($this->time/60) . ' ' . T_('minutes');
- } // format
+ } // format
- public function get_stream_types() {
+ public function get_stream_types() {
- return array('native');
+ return array('native');
- } // native_stream
+ } // native_stream
- /**
- * play_url
- * This returns a "PLAY" url for the video in question here, this currently feels a little
- * like a hack, might need to adjust it in the future
- */
- public static function play_url($oid,$sid='',$force_http='') {
+ /**
+ * play_url
+ * This returns a "PLAY" url for the video in question here, this currently feels a little
+ * like a hack, might need to adjust it in the future
+ */
+ public static function play_url($oid,$sid='',$force_http='') {
- $video = new Video($oid);
+ $video = new Video($oid);
- if (!$video->id) { return false; }
+ if (!$video->id) { return false; }
- $uid = intval($GLOBALS['user']->id);
- $oid = intval($video->id);
+ $uid = intval($GLOBALS['user']->id);
+ $oid = intval($video->id);
- $url = Stream::get_base_url() . "video=true&uid=$uid&oid=$oid";
+ $url = Stream::get_base_url() . "video=true&uid=$uid&oid=$oid";
- return $url;
+ return $url;
- } // play_url
+ } // play_url
- /**
- * get_transcode_settings
- *
- * FIXME: Video transcoding is not implemented
- */
- public function get_transcode_settings($target = null) {
- return false;
- }
+ /**
+ * get_transcode_settings
+ *
+ * FIXME: Video transcoding is not implemented
+ */
+ public function get_transcode_settings($target = null) {
+ return false;
+ }
- /**
- * has_flag
- * returns true if the video has been flagged and we shouldn't try to re-read
- * the meta data
- */
- public function has_flag() {
+ /**
+ * has_flag
+ * returns true if the video has been flagged and we shouldn't try to re-read
+ * the meta data
+ */
+ public function has_flag() {
- } // has_flag
+ } // has_flag
} // end Video class
diff --git a/lib/class/xml_data.class.php b/lib/class/xml_data.class.php
index da3c98c2..8c7884c9 100644
--- a/lib/class/xml_data.class.php
+++ b/lib/class/xml_data.class.php
@@ -1,5 +1,5 @@
<?php
-/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
/**
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
@@ -30,629 +30,629 @@
*/
class XML_Data {
- // This is added so that we don't pop any webservers
- private static $limit = '5000';
- private static $offset = '0';
- private static $type = '';
-
- /**
- * constructor
- *
- * We don't use this, as its really a static class
- */
- private function __construct() {
-
- // Rien a faire
-
- } // constructor
-
- /**
- * set_offset
- *
- * This takes an int and changes the offset
- *
- * @param integer $offset (description here...)
- * @return void
- */
- public static function set_offset($offset) {
-
- $offset = intval($offset);
- self::$offset = $offset;
-
- } // set_offset
-
- /**
- * set_limit
- *
- * This sets the limit for any ampache transactions
- *
- * @param integer $limit (description here...)
- * @return void
- */
- public static function set_limit($limit) {
-
- if (!$limit) { return false; }
-
- $limit = intval($limit);
- self::$limit = $limit;
-
- } // set_limit
-
- /**
- * set_type
- *
- * This sets the type of XML_Data we are working on
- *
- * @param string $type XML_Data type
- * @return void
- */
- public static function set_type($type) {
-
- if (!in_array($type,array('rss','xspf','itunes'))) { return false; }
-
- self::$type = $type;
-
- } // set_type
-
- /**
- * error
- *
- * This generates a standard XML Error message
- * nothing fancy here...
- *
- * @param integer $code Error code
- * @param string $string Error message
- * @return string return error message xml
- */
- public static function error($code,$string) {
-
- $string = self::_header() . "\t<error code=\"$code\"><![CDATA[$string]]></error>" . self::_footer();
- return $string;
-
- } // error
-
- /**
- * single_string
- *
- * This takes two values, first the key second the string
- *
- * @param string $key (description here...)
- * @param string $string xml data
- * @return string return xml
- */
- public static function single_string($key,$string) {
-
- $final = self::_header() . "\t<$key><![CDATA[$string]]></$key>" . self::_footer();
-
- return $final;
-
- } // single_string
-
- /**
- * header
- *
- * This returns the header
- *
- * @see _header()
- * @return string return xml
- */
- public static function header() {
-
- return self::_header();
-
- } // header
-
- /**
- * footer
- *
- * This returns the footer
- *
- * @see _footer()
- * @return string return xml
- */
- public static function footer() {
-
- return self::_footer();
-
- } // footer
-
- /**
- * tags_string
- *
- * This returns the formatted 'tags' string for an xml document
- *
- */
- private static function tags_string($tags) {
-
- $string = '';
-
- if (is_array($tags)) {
-
- foreach ($tags as $tag_id => $data) {
- $tag = new Tag($tag_id);
- $string .= "\t<tag id=\"" . $tag->id .
- '" count="' . count($data['users']) .
- '"><![CDATA[' . $tag->name . "]]></tag>\n";
- }
- }
-
- return $string;
-
- } // tags_string
-
- /**
- * keyed_array
- *
- * This will build an xml document from a key'd array,
- *
- * @param array $array (description here...)
- * @param boolean $callback (description here...)
- * @return string return xml
- */
- public static function keyed_array($array,$callback='') {
-
- $string = '';
-
- // Foreach it
- foreach ($array as $key=>$value) {
- $attribute = '';
- // See if the key has attributes
- if (is_array($value) AND isset($value['<attributes>'])) {
- $attribute = ' ' . $value['<attributes>'];
- $key = $value['value'];
- }
-
- // If it's an array, run again
- if (is_array($value)) {
- $value = self::keyed_array($value,1);
- $string .= "<$key$attribute>\n$value\n</$key>\n";
- }
- else {
- $string .= "\t<$key$attribute><![CDATA[$value]]></$key>\n";
- }
-
- } // end foreach
-
- if (!$callback) {
- $string = self::_header() . $string . self::_footer();
- }
-
- return $string;
-
- } // keyed_array
-
- /**
- * tags
- *
- * This returns tags to the user, in a pretty xml document with the information
- *
- * @param array $tags (description here...)
- * @return string return xml
- */
- public static function tags($tags) {
-
- if (count($tags) > self::$limit OR self::$offset > 0) {
- $tags = array_splice($tags,self::$offset,self::$limit);
- }
-
- $string = '';
-
- foreach ($tags as $tag_id) {
- $tag = new Tag($tag_id);
- $counts = $tag->count();
- $string .= "<tag id=\"$tag_id\">\n" .
- "\t<name><![CDATA[$tag->name]]></name>\n" .
- "\t<albums>" . intval($counts['album']) . "</albums>\n" .
- "\t<artists>" . intval($counts['artist']) . "</artists>\n" .
- "\t<songs>" . intval($counts['song']) . "</songs>\n" .
- "\t<videos>" . intval($counts['video']) . "</videos>\n" .
- "\t<playlists>" . intval($count['playlist']) . "</playlists>\n" .
- "\t<stream>" . intval($count['live_stream']) . "</stream>\n" .
- "</tag>\n";
- } // end foreach
-
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // tags
-
- /**
- * artists
- *
- * This takes an array of artists and then returns a pretty xml document with the information
- * we want
- *
- * @param array $artists (description here...)
- * @return string return xml
- */
- public static function artists($artists) {
-
- if (count($artists) > self::$limit OR self::$offset > 0) {
- $artists = array_splice($artists,self::$offset,self::$limit);
- }
-
- $string = '';
-
- Rating::build_cache('artist',$artists);
-
- foreach ($artists as $artist_id) {
- $artist = new Artist($artist_id);
- $artist->format();
-
- $rating = new Rating($artist_id,'artist');
- $tag_string = self::tags_string($artist->tags);
-
- $string .= "<artist id=\"$artist->id\">\n" .
- "\t<name><![CDATA[$artist->f_full_name]]></name>\n" .
- $tag_string .
- "\t<albums>$artist->albums</albums>\n" .
- "\t<songs>$artist->songs</songs>\n" .
- "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
- "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
- "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
- "</artist>\n";
- } // end foreach artists
-
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // artists
-
- /**
- * albums
- *
- * This echos out a standard albums XML document, it pays attention to the limit
- *
- * @param array $albums (description here...)
- * @return string return xml
- */
- public static function albums($albums) {
-
- if (count($albums) > self::$limit OR self::$offset > 0) {
- $albums = array_splice($albums,self::$offset,self::$limit);
- }
-
- Rating::build_cache('album',$albums);
-
- foreach ($albums as $album_id) {
- $album = new Album($album_id);
- $album->format();
-
- $rating = new Rating($album_id,'album');
-
- // Build the Art URL, include session
- $art_url = Config::get('web_path') . '/image.php?id=' . $album->id . '&auth=' . scrub_out($_REQUEST['auth']);
-
- $string .= "<album id=\"$album->id\">\n" .
- "\t<name><![CDATA[$album->name]]></name>\n";
-
- // Do a little check for artist stuff
- if ($album->artist_count != 1) {
- $string .= "\t<artist id=\"0\"><![CDATA[Various]]></artist>\n";
- }
- else {
- $string .= "\t<artist id=\"$album->artist_id\"><![CDATA[$album->artist_name]]></artist>\n";
- }
-
- $string .= "\t<year>$album->year</year>\n" .
- "\t<tracks>$album->song_count</tracks>\n" .
- "\t<disk>$album->disk</disk>\n" .
- self::tags_string($album->tags) .
- "\t<art><![CDATA[$art_url]]></art>\n" .
- "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
- "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
- "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
- "</album>\n";
- } // end foreach
-
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // albums
-
- /**
- * playlists
- *
- * This takes an array of playlist ids and then returns a nice pretty XML document
- *
- * @param array $playlists (description here...)
- * @return string return xml
- */
- public static function playlists($playlists) {
-
- if (count($playlists) > self::$limit OR self::$offset > 0) {
- $playlists = array_slice($playlists,self::$offset,self::$limit);
- }
-
- $string = '';
-
- // Foreach the playlist ids
- foreach ($playlists as $playlist_id) {
- $playlist = new Playlist($playlist_id);
- $playlist->format();
- $item_total = $playlist->get_song_count();
-
- // Build this element
- $string .= "<playlist id=\"$playlist->id\">\n" .
- "\t<name><![CDATA[$playlist->name]]></name>\n" .
- "\t<owner><![CDATA[$playlist->f_user]]></owner>\n" .
- "\t<items>$item_total</items>\n" .
- "\t<type>$playlist->type</type>\n" .
- "</playlist>\n";
-
-
- } // end foreach
-
- // Build the final and then send her off
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // playlists
-
- /**
- * songs
- *
- * This returns an xml document from an array of song ids.
- * (Spiffy isn't it!)
- */
- public static function songs($songs) {
-
- if (count($songs) > self::$limit OR self::$offset > 0) {
- $songs = array_slice($songs, self::$offset, self::$limit);
- }
-
- Song::build_cache($songs);
- Stream::set_session($_REQUEST['auth']);
-
- // Foreach the ids!
- foreach ($songs as $song_id) {
- $song = new Song($song_id);
-
- // If the song id is invalid/null
- if (!$song->id) { continue; }
-
- $tag_string = self::tags_string(Tag::get_top_tags('song', $song_id));
- $rating = new Rating($song_id, 'song');
- $art_url = Art::url($song->album, 'album', $_REQUEST['auth']);
-
- $string .= "<song id=\"$song->id\">\n" .
- "\t<title><![CDATA[$song->title]]></title>\n" .
- "\t<artist id=\"" . $song->artist .
- '"><![CDATA[' . $song->get_artist_name() .
- "]]></artist>\n" .
- "\t<album id=\"" . $song->album .
- '"><![CDATA[' . $song->get_album_name().
- "]]></album>\n" .
- $tag_string .
- "\t<track>$song->track</track>\n" .
- "\t<time>$song->time</time>\n" .
- "\t<year>$song->year</year>\n" .
- "\t<bitrate>$song->bitrate</bitrate>\n".
- "\t<mode>$song->mode</mode>\n".
- "\t<mime>$song->mime</mime>\n" .
- "\t<url><![CDATA[" . Song::play_url($song->id) . "]]></url>\n" .
- "\t<size>$song->size</size>\n".
- "\t<mbid>$song->mbid</mbid>\n".
- "\t<album_mbid>$song->album_mbid</album_mbid>\n".
- "\t<artist_mbid>$song->artist_mbid</artist_mbid>\n".
- "\t<art><![CDATA[" . $art_url . "]]></art>\n" .
- "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
- "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
- "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
- "</song>\n";
-
- } // end foreach
-
- return self::_header() . $string . self::_footer();
-
- } // songs
-
- /**
- * videos
- *
- * This builds the xml document for displaying video objects
- *
- * @param array $videos (description here...)
- * @return string return xml
- */
- public static function videos($videos) {
-
- if (count($videos) > self::$limit OR self::$offset > 0) {
- $videos = array_slice($videos,self::$offset,self::$limit);
- }
-
- $string = '';
-
- foreach ($videos as $video_id) {
- $video = new Video($video_id);
- $video->format();
-
- $string .= "<video id=\"$video->id\">\n" .
- "\t<title><![CDATA[$video->title]]></title>\n" .
- "\t<mime><![CDATA[$video->mime]]></mime>\n" .
- "\t<resolution>$video->f_resolution</resolution>\n" .
- "\t<size>$video->size</size>\n" .
- self::tags_string($video->tags) .
- "\t<url><![CDATA[" . Video::play_url($video->id) . "]]></url>\n" .
- "</video>\n";
-
- } // end foreach
-
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // videos
-
- /**
- * democratic
- *
- * This handles creating an xml document for democratic items, this can be a little complicated
- * due to the votes and all of that
- *
- * @param array $object_ids Object IDs
- * @return string return xml
- */
- public static function democratic($object_ids=array()) {
-
- if (!is_array($object_ids)) { $object_ids = array(); }
-
- $democratic = Democratic::get_current_playlist();
-
- $string = '';
-
- foreach ($object_ids as $row_id=>$data) {
- $song = new $data['object_type']($data['object_id']);
- $song->format();
-
- //FIXME: This is duplicate code and so wrong, functions need to be improved
- $tag_string = '';
-
- $tag = new Tag($song->tags['0']);
- $song->genre = $tag->id;
- $song->f_genre = $tag->name;
-
- $tag_string = self::tags_string($song->tags);
-
- $rating = new Rating($song_id,'song');
-
- $art_url = Art::url($song->album, 'album', $_REQUEST['auth']);
-
- $string .= "<song id=\"$song->id\">\n" .
- "\t<title><![CDATA[$song->title]]></title>\n" .
- "\t<artist id=\"$song->artist\"><![CDATA[$song->f_artist_full]]></artist>\n" .
- "\t<album id=\"$song->album\"><![CDATA[$song->f_album_full]]></album>\n" .
- "\t<genre id=\"$song->genre\"><![CDATA[$song->f_genre]]></genre>\n" .
- $tag_string .
- "\t<track>$song->track</track>\n" .
- "\t<time>$song->time</time>\n" .
- "\t<mime>$song->mime</mime>\n" .
- "\t<url><![CDATA[" . Song::play_url($song->id) . "]]></url>\n" .
- "\t<size>$song->size</size>\n" .
- "\t<art><![CDATA[" . $art_url . "]]></art>\n" .
- "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
- "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
- "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
- "\t<vote>" . $democratic->get_vote($row_id) . "</vote>\n" .
- "</song>\n";
-
- } // end foreach
-
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // democratic
-
- /**
- * rss_feed
- *
- * (description here...)
- *
- * @param array $data (descriptiong here...)
- * @param string $title RSS feed title
- * @param string $description (not use yet?)
- * @param string $date publish date
- * @return string RSS feed xml
- */
- public static function rss_feed($data,$title,$description,$date) {
-
- $string = "\t<title>$title</title>\n\t<link>" . Config::get('web_path') . "</link>\n\t" .
- "<pubDate>" . date("r",$date) . "</pubDate>\n";
-
- // Pass it to the keyed array xml function
- foreach ($data as $item) {
- // We need to enclose it in an item tag
- $string .= self::keyed_array(array('item'=>$item),1);
- }
-
- $final = self::_header() . $string . self::_footer();
-
- return $final;
-
- } // rss_feed
-
- /**
- * _header
- *
- * this returns a standard header, there are a few types
- * so we allow them to pass a type if they want to
- *
- * @return string Header xml tag.
- */
- private static function _header() {
-
- switch (self::$type) {
- case 'xspf':
- $header = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" .
- "<playlist version = \"1\" xmlns=\"http://xspf.org/ns/0/\">\n " .
- "<title>Ampache XSPF Playlist</title>\n" .
- "<creator>" . scrub_out(Config::get('site_title')) . "</creator>\n" .
- "<annotation>" . scrub_out(Config::get('site_title')) . "</annotation>\n" .
- "<info>". Config::get('web_path') ."</info>\n" .
- "<trackList>\n";
- break;
- case 'itunes':
- $header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
- "<!-- XML Generated by Ampache v." . Config::get('version') . " -->\n";
- "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" .
- "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" .
- "<plist version=\"1.0\">\n" .
- "<dict>\n" .
- " <key>Major Version</key><integer>1</integer>\n" .
- " <key>Minor Version</key><integer>1</integer>\n" .
- " <key>Application Version</key><string>7.0.2</string>\n" .
- " <key>Features</key><integer>1</integer>\n" .
- " <key>Show Content Ratings</key><true/>\n" .
- " <key>Tracks</key>\n" .
- " <dict>\n";
- break;
- case 'rss':
- $header = "<?xml version=\"1.0\" encoding=\"" . Config::get('site_charset') . "\" ?>\n " .
- "<!-- RSS Generated by Ampache v." . Config::get('version') . " on " . date("r",time()) . "-->\n" .
- "<rss version=\"2.0\">\n<channel>\n";
- break;
- default:
- $header = "<?xml version=\"1.0\" encoding=\"" . Config::get('site_charset') . "\" ?>\n<root>\n";
- break;
- } // end switch
-
- return $header;
-
- } // _header
-
- /**
- * _footer
- *
- * this returns the footer for this document, these are pretty boring
- *
- * @return string Footer xml tag.
- */
- private static function _footer() {
-
- switch (self::$type) {
- case 'itunes':
- $footer = "\t\t</dict>\t\n</dict>\n</plist>\n";
- break;
- case 'xspf':
- $footer = "</trackList>\n</playlist>\n";
- break;
- case 'rss':
- $footer = "\n</channel>\n</rss>\n";
- break;
- default:
- $footer = "\n</root>\n";
- break;
- } // end switch on type
-
-
- return $footer;
-
- } // _footer
+ // This is added so that we don't pop any webservers
+ private static $limit = '5000';
+ private static $offset = '0';
+ private static $type = '';
+
+ /**
+ * constructor
+ *
+ * We don't use this, as its really a static class
+ */
+ private function __construct() {
+
+ // Rien a faire
+
+ } // constructor
+
+ /**
+ * set_offset
+ *
+ * This takes an int and changes the offset
+ *
+ * @param integer $offset (description here...)
+ * @return void
+ */
+ public static function set_offset($offset) {
+
+ $offset = intval($offset);
+ self::$offset = $offset;
+
+ } // set_offset
+
+ /**
+ * set_limit
+ *
+ * This sets the limit for any ampache transactions
+ *
+ * @param integer $limit (description here...)
+ * @return void
+ */
+ public static function set_limit($limit) {
+
+ if (!$limit) { return false; }
+
+ $limit = intval($limit);
+ self::$limit = $limit;
+
+ } // set_limit
+
+ /**
+ * set_type
+ *
+ * This sets the type of XML_Data we are working on
+ *
+ * @param string $type XML_Data type
+ * @return void
+ */
+ public static function set_type($type) {
+
+ if (!in_array($type,array('rss','xspf','itunes'))) { return false; }
+
+ self::$type = $type;
+
+ } // set_type
+
+ /**
+ * error
+ *
+ * This generates a standard XML Error message
+ * nothing fancy here...
+ *
+ * @param integer $code Error code
+ * @param string $string Error message
+ * @return string return error message xml
+ */
+ public static function error($code,$string) {
+
+ $string = self::_header() . "\t<error code=\"$code\"><![CDATA[$string]]></error>" . self::_footer();
+ return $string;
+
+ } // error
+
+ /**
+ * single_string
+ *
+ * This takes two values, first the key second the string
+ *
+ * @param string $key (description here...)
+ * @param string $string xml data
+ * @return string return xml
+ */
+ public static function single_string($key,$string) {
+
+ $final = self::_header() . "\t<$key><![CDATA[$string]]></$key>" . self::_footer();
+
+ return $final;
+
+ } // single_string
+
+ /**
+ * header
+ *
+ * This returns the header
+ *
+ * @see _header()
+ * @return string return xml
+ */
+ public static function header() {
+
+ return self::_header();
+
+ } // header
+
+ /**
+ * footer
+ *
+ * This returns the footer
+ *
+ * @see _footer()
+ * @return string return xml
+ */
+ public static function footer() {
+
+ return self::_footer();
+
+ } // footer
+
+ /**
+ * tags_string
+ *
+ * This returns the formatted 'tags' string for an xml document
+ *
+ */
+ private static function tags_string($tags) {
+
+ $string = '';
+
+ if (is_array($tags)) {
+
+ foreach ($tags as $tag_id => $data) {
+ $tag = new Tag($tag_id);
+ $string .= "\t<tag id=\"" . $tag->id .
+ '" count="' . count($data['users']) .
+ '"><![CDATA[' . $tag->name . "]]></tag>\n";
+ }
+ }
+
+ return $string;
+
+ } // tags_string
+
+ /**
+ * keyed_array
+ *
+ * This will build an xml document from a key'd array,
+ *
+ * @param array $array (description here...)
+ * @param boolean $callback (description here...)
+ * @return string return xml
+ */
+ public static function keyed_array($array,$callback='') {
+
+ $string = '';
+
+ // Foreach it
+ foreach ($array as $key=>$value) {
+ $attribute = '';
+ // See if the key has attributes
+ if (is_array($value) AND isset($value['<attributes>'])) {
+ $attribute = ' ' . $value['<attributes>'];
+ $key = $value['value'];
+ }
+
+ // If it's an array, run again
+ if (is_array($value)) {
+ $value = self::keyed_array($value,1);
+ $string .= "<$key$attribute>\n$value\n</$key>\n";
+ }
+ else {
+ $string .= "\t<$key$attribute><![CDATA[$value]]></$key>\n";
+ }
+
+ } // end foreach
+
+ if (!$callback) {
+ $string = self::_header() . $string . self::_footer();
+ }
+
+ return $string;
+
+ } // keyed_array
+
+ /**
+ * tags
+ *
+ * This returns tags to the user, in a pretty xml document with the information
+ *
+ * @param array $tags (description here...)
+ * @return string return xml
+ */
+ public static function tags($tags) {
+
+ if (count($tags) > self::$limit OR self::$offset > 0) {
+ $tags = array_splice($tags,self::$offset,self::$limit);
+ }
+
+ $string = '';
+
+ foreach ($tags as $tag_id) {
+ $tag = new Tag($tag_id);
+ $counts = $tag->count();
+ $string .= "<tag id=\"$tag_id\">\n" .
+ "\t<name><![CDATA[$tag->name]]></name>\n" .
+ "\t<albums>" . intval($counts['album']) . "</albums>\n" .
+ "\t<artists>" . intval($counts['artist']) . "</artists>\n" .
+ "\t<songs>" . intval($counts['song']) . "</songs>\n" .
+ "\t<videos>" . intval($counts['video']) . "</videos>\n" .
+ "\t<playlists>" . intval($count['playlist']) . "</playlists>\n" .
+ "\t<stream>" . intval($count['live_stream']) . "</stream>\n" .
+ "</tag>\n";
+ } // end foreach
+
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // tags
+
+ /**
+ * artists
+ *
+ * This takes an array of artists and then returns a pretty xml document with the information
+ * we want
+ *
+ * @param array $artists (description here...)
+ * @return string return xml
+ */
+ public static function artists($artists) {
+
+ if (count($artists) > self::$limit OR self::$offset > 0) {
+ $artists = array_splice($artists,self::$offset,self::$limit);
+ }
+
+ $string = '';
+
+ Rating::build_cache('artist',$artists);
+
+ foreach ($artists as $artist_id) {
+ $artist = new Artist($artist_id);
+ $artist->format();
+
+ $rating = new Rating($artist_id,'artist');
+ $tag_string = self::tags_string($artist->tags);
+
+ $string .= "<artist id=\"$artist->id\">\n" .
+ "\t<name><![CDATA[$artist->f_full_name]]></name>\n" .
+ $tag_string .
+ "\t<albums>$artist->albums</albums>\n" .
+ "\t<songs>$artist->songs</songs>\n" .
+ "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
+ "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
+ "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
+ "</artist>\n";
+ } // end foreach artists
+
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // artists
+
+ /**
+ * albums
+ *
+ * This echos out a standard albums XML document, it pays attention to the limit
+ *
+ * @param array $albums (description here...)
+ * @return string return xml
+ */
+ public static function albums($albums) {
+
+ if (count($albums) > self::$limit OR self::$offset > 0) {
+ $albums = array_splice($albums,self::$offset,self::$limit);
+ }
+
+ Rating::build_cache('album',$albums);
+
+ foreach ($albums as $album_id) {
+ $album = new Album($album_id);
+ $album->format();
+
+ $rating = new Rating($album_id,'album');
+
+ // Build the Art URL, include session
+ $art_url = Config::get('web_path') . '/image.php?id=' . $album->id . '&auth=' . scrub_out($_REQUEST['auth']);
+
+ $string .= "<album id=\"$album->id\">\n" .
+ "\t<name><![CDATA[$album->name]]></name>\n";
+
+ // Do a little check for artist stuff
+ if ($album->artist_count != 1) {
+ $string .= "\t<artist id=\"0\"><![CDATA[Various]]></artist>\n";
+ }
+ else {
+ $string .= "\t<artist id=\"$album->artist_id\"><![CDATA[$album->artist_name]]></artist>\n";
+ }
+
+ $string .= "\t<year>$album->year</year>\n" .
+ "\t<tracks>$album->song_count</tracks>\n" .
+ "\t<disk>$album->disk</disk>\n" .
+ self::tags_string($album->tags) .
+ "\t<art><![CDATA[$art_url]]></art>\n" .
+ "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
+ "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
+ "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
+ "</album>\n";
+ } // end foreach
+
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // albums
+
+ /**
+ * playlists
+ *
+ * This takes an array of playlist ids and then returns a nice pretty XML document
+ *
+ * @param array $playlists (description here...)
+ * @return string return xml
+ */
+ public static function playlists($playlists) {
+
+ if (count($playlists) > self::$limit OR self::$offset > 0) {
+ $playlists = array_slice($playlists,self::$offset,self::$limit);
+ }
+
+ $string = '';
+
+ // Foreach the playlist ids
+ foreach ($playlists as $playlist_id) {
+ $playlist = new Playlist($playlist_id);
+ $playlist->format();
+ $item_total = $playlist->get_song_count();
+
+ // Build this element
+ $string .= "<playlist id=\"$playlist->id\">\n" .
+ "\t<name><![CDATA[$playlist->name]]></name>\n" .
+ "\t<owner><![CDATA[$playlist->f_user]]></owner>\n" .
+ "\t<items>$item_total</items>\n" .
+ "\t<type>$playlist->type</type>\n" .
+ "</playlist>\n";
+
+
+ } // end foreach
+
+ // Build the final and then send her off
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // playlists
+
+ /**
+ * songs
+ *
+ * This returns an xml document from an array of song ids.
+ * (Spiffy isn't it!)
+ */
+ public static function songs($songs) {
+
+ if (count($songs) > self::$limit OR self::$offset > 0) {
+ $songs = array_slice($songs, self::$offset, self::$limit);
+ }
+
+ Song::build_cache($songs);
+ Stream::set_session($_REQUEST['auth']);
+
+ // Foreach the ids!
+ foreach ($songs as $song_id) {
+ $song = new Song($song_id);
+
+ // If the song id is invalid/null
+ if (!$song->id) { continue; }
+
+ $tag_string = self::tags_string(Tag::get_top_tags('song', $song_id));
+ $rating = new Rating($song_id, 'song');
+ $art_url = Art::url($song->album, 'album', $_REQUEST['auth']);
+
+ $string .= "<song id=\"$song->id\">\n" .
+ "\t<title><![CDATA[$song->title]]></title>\n" .
+ "\t<artist id=\"" . $song->artist .
+ '"><![CDATA[' . $song->get_artist_name() .
+ "]]></artist>\n" .
+ "\t<album id=\"" . $song->album .
+ '"><![CDATA[' . $song->get_album_name().
+ "]]></album>\n" .
+ $tag_string .
+ "\t<track>$song->track</track>\n" .
+ "\t<time>$song->time</time>\n" .
+ "\t<year>$song->year</year>\n" .
+ "\t<bitrate>$song->bitrate</bitrate>\n".
+ "\t<mode>$song->mode</mode>\n".
+ "\t<mime>$song->mime</mime>\n" .
+ "\t<url><![CDATA[" . Song::play_url($song->id) . "]]></url>\n" .
+ "\t<size>$song->size</size>\n".
+ "\t<mbid>$song->mbid</mbid>\n".
+ "\t<album_mbid>$song->album_mbid</album_mbid>\n".
+ "\t<artist_mbid>$song->artist_mbid</artist_mbid>\n".
+ "\t<art><![CDATA[" . $art_url . "]]></art>\n" .
+ "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
+ "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
+ "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
+ "</song>\n";
+
+ } // end foreach
+
+ return self::_header() . $string . self::_footer();
+
+ } // songs
+
+ /**
+ * videos
+ *
+ * This builds the xml document for displaying video objects
+ *
+ * @param array $videos (description here...)
+ * @return string return xml
+ */
+ public static function videos($videos) {
+
+ if (count($videos) > self::$limit OR self::$offset > 0) {
+ $videos = array_slice($videos,self::$offset,self::$limit);
+ }
+
+ $string = '';
+
+ foreach ($videos as $video_id) {
+ $video = new Video($video_id);
+ $video->format();
+
+ $string .= "<video id=\"$video->id\">\n" .
+ "\t<title><![CDATA[$video->title]]></title>\n" .
+ "\t<mime><![CDATA[$video->mime]]></mime>\n" .
+ "\t<resolution>$video->f_resolution</resolution>\n" .
+ "\t<size>$video->size</size>\n" .
+ self::tags_string($video->tags) .
+ "\t<url><![CDATA[" . Video::play_url($video->id) . "]]></url>\n" .
+ "</video>\n";
+
+ } // end foreach
+
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // videos
+
+ /**
+ * democratic
+ *
+ * This handles creating an xml document for democratic items, this can be a little complicated
+ * due to the votes and all of that
+ *
+ * @param array $object_ids Object IDs
+ * @return string return xml
+ */
+ public static function democratic($object_ids=array()) {
+
+ if (!is_array($object_ids)) { $object_ids = array(); }
+
+ $democratic = Democratic::get_current_playlist();
+
+ $string = '';
+
+ foreach ($object_ids as $row_id=>$data) {
+ $song = new $data['object_type']($data['object_id']);
+ $song->format();
+
+ //FIXME: This is duplicate code and so wrong, functions need to be improved
+ $tag_string = '';
+
+ $tag = new Tag($song->tags['0']);
+ $song->genre = $tag->id;
+ $song->f_genre = $tag->name;
+
+ $tag_string = self::tags_string($song->tags);
+
+ $rating = new Rating($song_id,'song');
+
+ $art_url = Art::url($song->album, 'album', $_REQUEST['auth']);
+
+ $string .= "<song id=\"$song->id\">\n" .
+ "\t<title><![CDATA[$song->title]]></title>\n" .
+ "\t<artist id=\"$song->artist\"><![CDATA[$song->f_artist_full]]></artist>\n" .
+ "\t<album id=\"$song->album\"><![CDATA[$song->f_album_full]]></album>\n" .
+ "\t<genre id=\"$song->genre\"><![CDATA[$song->f_genre]]></genre>\n" .
+ $tag_string .
+ "\t<track>$song->track</track>\n" .
+ "\t<time>$song->time</time>\n" .
+ "\t<mime>$song->mime</mime>\n" .
+ "\t<url><![CDATA[" . Song::play_url($song->id) . "]]></url>\n" .
+ "\t<size>$song->size</size>\n" .
+ "\t<art><![CDATA[" . $art_url . "]]></art>\n" .
+ "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" .
+ "\t<rating>" . $rating->get_user_rating() . "</rating>\n" .
+ "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" .
+ "\t<vote>" . $democratic->get_vote($row_id) . "</vote>\n" .
+ "</song>\n";
+
+ } // end foreach
+
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // democratic
+
+ /**
+ * rss_feed
+ *
+ * (description here...)
+ *
+ * @param array $data (descriptiong here...)
+ * @param string $title RSS feed title
+ * @param string $description (not use yet?)
+ * @param string $date publish date
+ * @return string RSS feed xml
+ */
+ public static function rss_feed($data,$title,$description,$date) {
+
+ $string = "\t<title>$title</title>\n\t<link>" . Config::get('web_path') . "</link>\n\t" .
+ "<pubDate>" . date("r",$date) . "</pubDate>\n";
+
+ // Pass it to the keyed array xml function
+ foreach ($data as $item) {
+ // We need to enclose it in an item tag
+ $string .= self::keyed_array(array('item'=>$item),1);
+ }
+
+ $final = self::_header() . $string . self::_footer();
+
+ return $final;
+
+ } // rss_feed
+
+ /**
+ * _header
+ *
+ * this returns a standard header, there are a few types
+ * so we allow them to pass a type if they want to
+ *
+ * @return string Header xml tag.
+ */
+ private static function _header() {
+
+ switch (self::$type) {
+ case 'xspf':
+ $header = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" .
+ "<playlist version = \"1\" xmlns=\"http://xspf.org/ns/0/\">\n " .
+ "<title>Ampache XSPF Playlist</title>\n" .
+ "<creator>" . scrub_out(Config::get('site_title')) . "</creator>\n" .
+ "<annotation>" . scrub_out(Config::get('site_title')) . "</annotation>\n" .
+ "<info>". Config::get('web_path') ."</info>\n" .
+ "<trackList>\n";
+ break;
+ case 'itunes':
+ $header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
+ "<!-- XML Generated by Ampache v." . Config::get('version') . " -->\n";
+ "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" .
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" .
+ "<plist version=\"1.0\">\n" .
+ "<dict>\n" .
+ " <key>Major Version</key><integer>1</integer>\n" .
+ " <key>Minor Version</key><integer>1</integer>\n" .
+ " <key>Application Version</key><string>7.0.2</string>\n" .
+ " <key>Features</key><integer>1</integer>\n" .
+ " <key>Show Content Ratings</key><true/>\n" .
+ " <key>Tracks</key>\n" .
+ " <dict>\n";
+ break;
+ case 'rss':
+ $header = "<?xml version=\"1.0\" encoding=\"" . Config::get('site_charset') . "\" ?>\n " .
+ "<!-- RSS Generated by Ampache v." . Config::get('version') . " on " . date("r",time()) . "-->\n" .
+ "<rss version=\"2.0\">\n<channel>\n";
+ break;
+ default:
+ $header = "<?xml version=\"1.0\" encoding=\"" . Config::get('site_charset') . "\" ?>\n<root>\n";
+ break;
+ } // end switch
+
+ return $header;
+
+ } // _header
+
+ /**
+ * _footer
+ *
+ * this returns the footer for this document, these are pretty boring
+ *
+ * @return string Footer xml tag.
+ */
+ private static function _footer() {
+
+ switch (self::$type) {
+ case 'itunes':
+ $footer = "\t\t</dict>\t\n</dict>\n</plist>\n";
+ break;
+ case 'xspf':
+ $footer = "</trackList>\n</playlist>\n";
+ break;
+ case 'rss':
+ $footer = "\n</channel>\n</rss>\n";
+ break;
+ default:
+ $footer = "\n</root>\n";
+ break;
+ } // end switch on type
+
+
+ return $footer;
+
+ } // _footer
} // XML_Data