Example #1
0
 /**
  * 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();
     $group = array();
     $having = array();
     $join['tag'] = array();
     foreach ($this->rules as $rule) {
         $type = $this->name_to_basetype($rule[0]);
         $operator = array();
         foreach ($this->basetypes[$type] as $op) {
             if ($op['name'] == $rule[1]) {
                 $operator = $op;
                 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_data`.`label` {$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 'album_tag':
                 $key = md5($input . $sql_match_operator);
                 $where[] = "`realtag_{$key}`.`match` > 0";
                 $join['album_tag'][$key] = "{$sql_match_operator} '{$input}'";
                 $join['album'] = true;
                 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 'composer':
                 $where[] = "`song`.`composer` {$sql_match_operator} '{$input}'";
                 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 'label':
                 $where[] = "`song_data`.`label` {$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':
                 if ($this->type != "public") {
                     $where[] = "COALESCE(`rating`.`rating`,0) {$sql_match_operator} '{$input}'";
                 } else {
                     $group[] = "`song`.`id`";
                     $having[] = "ROUND(AVG(IFNULL(`rating`.`rating`,0))) {$sql_match_operator} '{$input}'";
                 }
                 $join['rating'] = true;
                 break;
             case 'played_times':
                 $where[] = "`song`.`id` IN (SELECT `object_count`.`object_id` FROM `object_count` " . "WHERE `object_count`.`object_type` = 'song' AND `object_count`.`count_type` = 'stream' " . "GROUP BY `object_count`.`object_id` HAVING COUNT(*) {$sql_match_operator} '{$input}')";
                 break;
             case 'catalog':
                 $where[] = "`song`.`catalog` {$sql_match_operator} '{$input}'";
                 break;
             case 'playlist_name':
                 $join['playlist'] = true;
                 $join['playlist_data'] = true;
                 $where[] = "`playlist`.`name` {$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($input, 'song');
                 $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 'license':
                 $where[] = "`song`.`license` {$sql_match_operator} '{$input}'";
                 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}";
                 break;
             case 'metadata':
                 // Need to create a join for every field so we can create and / or queries with only one table
                 $tableAlias = 'metadata' . uniqid();
                 $field = (int) $rule[3];
                 $join[$tableAlias] = true;
                 $parsedInput = is_numeric($input) ? $input : '"' . $input . '"';
                 $where[] = "(`{$tableAlias}`.`field` = {$field} AND `{$tableAlias}`.`data` {$sql_match_operator} {$parsedInput})";
                 $table[$tableAlias] = 'LEFT JOIN `metadata` AS ' . $tableAlias . ' ON `song`.`id` = `' . $tableAlias . '`.`object_id`';
                 break;
             default:
                 // NOSSINK!
                 break;
         }
         // switch on type
     }
     // foreach over rules
     $join['catalog'] = AmpConfig::get('catalog_disable');
     $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`";
     }
     foreach ($join['album_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['rating']) {
         $userid = $GLOBALS['user']->id;
         $table['rating'] = "LEFT JOIN `rating` ON `rating`.`object_type`='song' AND ";
         if ($this->type != "public") {
             $table['rating'] .= "`rating`.`user`='{$userid}' AND ";
         }
         $table['rating'] .= "`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'";
         if ($join['playlist']) {
             $table['playlist'] = "LEFT JOIN `playlist` ON `playlist_data`.`playlist`=`playlist`.`id`";
         }
     }
     if ($join['catalog']) {
         $table['catalog'] = "LEFT JOIN `catalog` AS `catalog_se` ON `catalog_se`.`id`=`song`.`catalog`";
         $where_sql .= " AND `catalog_se`.`enabled` = '1'";
     }
     $table_sql = implode(' ', $table);
     $group_sql = implode(', ', $group);
     $having_sql = implode(" {$sql_logic_operator} ", $having);
     return array('base' => 'SELECT DISTINCT(`song`.`id`) FROM `song`', 'join' => $join, 'where' => $where, 'where_sql' => $where_sql, 'table' => $table, 'table_sql' => $table_sql, 'group_sql' => $group_sql, 'having_sql' => $having_sql);
 }
Example #2
0
 /**
  * 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 */
     $limit_sql = "";
     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(null, $type);
         $search->parse_rules($search_data);
         $search_info = $search->to_sql();
     }
     $sql = "";
     switch ($type) {
         case 'song':
             $sql = "SELECT `song`.`id`, `size`, `time` " . "FROM `song` ";
             if ($search_info) {
                 $sql .= $search_info['table_sql'];
             }
             if (AmpConfig::get('catalog_disable')) {
                 $sql .= " LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
                 $sql .= " WHERE `catalog`.`enabled` = '1'";
             }
             if ($search_info) {
                 if (AmpConfig::get('catalog_disable')) {
                     $sql .= ' AND ' . $search_info['where_sql'];
                 } else {
                     $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'];
             }
             if (AmpConfig::get('catalog_disable')) {
                 $sql .= " LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
                 $sql .= " WHERE `catalog`.`enabled` = '1'";
             }
             if ($search_info) {
                 if (AmpConfig::get('catalog_disable')) {
                     $sql .= ' AND ' . $search_info['where_sql'];
                 } else {
                     $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'];
             }
             if (AmpConfig::get('catalog_disable')) {
                 $sql .= " LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
                 $sql .= " WHERE `catalog`.`enabled` = '1'";
             }
             if ($search_info) {
                 if (AmpConfig::get('catalog_disable')) {
                     $sql .= ' AND ' . $search_info['where_sql'];
                 } else {
                     $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();
     $size_total = 0;
     $fuzzy_size = 0;
     $time_total = 0;
     $fuzzy_time = 0;
     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;
         case 'album':
             $songs = array();
             foreach ($results as $result) {
                 $album = new Album($result);
                 $songs = array_merge($songs, $album->get_songs());
             }
             return $songs;
         case 'artist':
             $songs = array();
             foreach ($results as $result) {
                 $artist = new Artist($result);
                 $songs = array_merge($songs, $artist->get_songs());
             }
             return $songs;
         default:
             return false;
     }
 }
Example #3
0
 /**
  * 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]);
         $operator = array();
         foreach ($this->basetypes[$type] as $op) {
             if ($op['name'] == $rule[1]) {
                 $operator = $op;
                 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 'played_times':
                 $where[] = "`song`.`id` IN (SELECT `object_count`.`object_id` FROM `object_count` " . "WHERE `object_count`.`object_type` = 'song'" . "GROUP BY `object_count`.`object_id` HAVING COUNT(*) {$sql_match_operator} '{$input}')";
                 break;
             case 'catalog':
                 $where[] = "`song`.`catalog` {$sql_match_operator} '{$input}'";
                 break;
             case 'playlist_name':
                 $join['playlist'] = true;
                 $join['playlist_data'] = true;
                 $where[] = "`playlist`.`name` {$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;
         }
         // switch on type
     }
     // foreach over rules
     $join['catalog'] = AmpConfig::get('catalog_disable');
     $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'";
         if ($join['playlist']) {
             $table['playlist'] = "LEFT JOIN `playlist` ON `playlist_data`.`playlist`=`playlist`.`id`";
         }
     }
     if ($join['catalog']) {
         $table['catalog'] = "LEFT JOIN `catalog` AS `catalog_se` ON `catalog_se`.`id`=`song`.`catalog`";
         $where_sql .= " AND `catalog_se`.`enabled` = '1'";
     }
     $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);
 }
Example #4
0
set_time_limit(0);
$media_ids = array();
$name = "Unknown.zip";
switch ($_REQUEST['action']) {
    case 'tmp_playlist':
        $media_ids = $GLOBALS['user']->playlist->get_items();
        $name = $GLOBALS['user']->username . ' - Playlist';
        break;
    case 'playlist':
        $playlist = new Playlist($_REQUEST['id']);
        $media_ids = $playlist->get_songs();
        $name = $playlist->name;
        break;
    case 'smartplaylist':
        $search = new Search('song', $_REQUEST['id']);
        $sql = $search->to_sql();
        $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . $sql['where_sql'];
        $db_results = Dba::read($sql);
        while ($row = Dba::fetch_assoc($db_results)) {
            $media_ids[] = $row['id'];
        }
        $name = $search->name;
        break;
    case 'album':
        foreach ($_REQUEST['id'] as $a) {
            $album = new Album($a);
            if (empty($name)) {
                $name = $album->name;
            }
            $asongs = $album->get_songs();
            foreach ($asongs as $song_id) {