'. t('The playlist module allows users to arrange content into personal playlists. This module empowers users to become organizers of content as they re-order content from the site and create lists of their favorite content items. Once users have selected their favorite nodes and re-ordered them, others can share their RSS feeds, XSPF playlists, M3U playlists, or PLS playlists. For instance, users could make podcasts of their favorite audio on a site, or custom playlists of favorite songs, similar to iTunes playlists.', array('%elink-en-wikipedia-org' => 'http://en.wikipedia.org/wiki/Podcasts', '%elink-gonze-com' => 'http://gonze.com/playlists/playlist-format-survey.html#PLS')) .'

'; $output .= '

'. t('An RSS feed of the playlist is automatically generated of the personal playlist based on the time that it was added to the playlist (not based on order!). The XSPF, M3U, and PLS format can be used to export an XML feed of the playlist based on playlist order, which is useful for sharing playlists.') .'

'; $output .= t('

You can:

', array('%node-add-playlist' => url('node/add/playlist'))); $output .= '

'. t('For more information please read the configuration and customization handbook Playlist page.', array('%playlist' => 'http://www.drupal.org/handbook/modules/playlist/')) .'

'; return $output; case 'admin/modules#description': return t('Enables the creation of playlists, which contain audio tracks.'); case 'node/add#playlist': return t('Lets you group and order audio files into an playlist.'); } } /** * Implementation of hook_perm(). */ function playlist_perm() { return array('create playlists', 'edit own playlists', 'view playlists', 'administer playlists'); } /** * Implementation of hook_node_name(). */ function playlist_node_name($node) { return t('playlist'); } /** * Implementation of hook_access(). */ function playlist_access($op, $node = null) { global $user; if ($op == 'view'){ return user_access('view playlists'); } if ($op == 'create') { return user_access('create playlists'); } if ($op == 'update' || $op == 'delete') { if ((user_access('edit own playlists') && ($user->uid == $node->uid)) || user_access('administer playlists')) { return TRUE; } } } /** * Implementation of hook_menu(). */ function playlist_menu($may_cache) { global $user; $items = array(); if ($may_cache) { //add a new playlist... $items[] = array( 'path' => 'node/add/playlist', 'title' => t('playlist'), 'access' => playlist_access('create', NULL)); //TODO: should we ditch the 'user' prefix here?... //show 'my' playlists... $items[] = array( 'path' => 'playlist/user/'. $user->uid, 'title' => t('my playlists'), 'access' => playlist_access('create', NULL), 'type' => MENU_DYNAMIC_ITEM); $items[] = array( 'path' => 'playlist/user', 'access' => user_access('access content'), 'title' => t('playlists'), 'callback' => 'playlist_page_user', 'type' => MENU_CALLBACK); //add a new playlist item... $items[] = array( 'path' => 'playlist/additem', 'title' => t('select playlist(s)'), 'callback' => 'playlist_choose', 'access' => playlist_access('create', NULL), 'type' => MENU_CALLBACK); $items[] = array( 'path' => 'playlist', 'title' => t('Playlists'), 'access' => user_access('access content'), 'type' => MENU_SUGGESTED_ITEM, 'callback' => 'playlist_page'); //------------------------------- // AJAX Callbacks.... //------------------------------- $items[] = array( 'path' => 'playlist/ajax/order', 'title' => t('audio album'), 'type' => MENU_CALLBACK, 'callback' => 'playlist_order', 'access' => playlist_access('create', NULL)); $items[] = array( 'path' => 'playlist/ajax/additem', 'title' => t('playlist add item'), 'type' => MENU_CALLBACK, 'callback' => 'playlist_additem', 'access' => playlist_access('create', NULL)); } else if (arg(0) == 'node' && is_numeric(arg(1))) { if (db_result(db_query(db_rewrite_sql("SELECT COUNT(n.nid) FROM {node} n WHERE n.nid = %d AND n.type = 'playlist'"), arg(1))) > 0) { $items[] = array( 'path' => 'node/'. arg(1) .'/manage', 'callback' => 'playlist_manage_files', 'title' => t('manage playlist files'), 'type' => MENU_LOCAL_TASK, 'weight' => 2, 'access' => playlist_access('update', node_load(array('nid' => arg(1)), NULL, NULL))); $items[] = array( 'path' => 'node/'. arg(1) .'/playlist', 'title' => t('stream playlist'), 'type' => MENU_CALLBACK, 'callback' => 'playlist_formats'); $items[] = array( 'path' => 'node/'. arg(1) .'/feed', 'title' => t('feed playlist'), 'type' => MENU_CALLBACK, 'callback' => 'playlist_feed'); } } return $items; } /** * Menu callback * creates dynamically generated playlists * node/123/playlist/m3u * node/123/playlist/pls * node/123/playlist/XSPF //TODO * * TODO: dependency on audio.node! */ function playlist_formats() { //reject call if a playlist format is not specified... if (!arg(3)) drupal_not_found(); $nid = arg(1); $node = node_load(array('nid' => $nid)); $playlist_type = arg(3); $result = db_query('SELECT f.filepath, f.nid, a.playtime_seconds, a.artist, a.title, a.album FROM files AS f, audio_node_metadata AS a, playlist_relate AS ar, node AS n WHERE ar.parent_id=%d AND ar.child_id=n.nid AND f.nid=n.nid AND a.fid=f.fid ORDER BY ar.weight ASC', $nid); $files = array(); while ($data = db_fetch_array($result)){ $data['url'] = file_create_url($data['filepath']); //add the url for easier processing... $files[] = $data; } if (is_array($files)){ switch($playlist_type){ //------------------------------------------ //Generate M3U... //------------------------------------------ case 'm3u': $text = "#EXTM3U\r\n"; foreach ($files as $file) { $file_path = url('audio/download/'.$file['nid'], null, null, true); $text .= "#EXTINF:".$file['playtime_seconds'].",".$file['artist']."-" .$file['title']."\r\n"; $text .= $file_path."\r\n"; } header("Pragma: no-cache"); // HTTP/1.0 header("Cache-Control: private"); // HTTP/1.1 header("Content-Type: audio/x-mpegurl", TRUE); header("Content-Length: ".strlen($text)."", TRUE); header("Content-Disposition: attachment; filename=\"".$node->title.".m3u\"", TRUE); print $text; exit(); break; //------------------------------------------ //Generate PLS... //------------------------------------------ case 'pls': $text = "[playlist]\r\n"; for($i = 1; $i <= count($files); $i++) { $file = $files[$i-1]; $file_path = url('audio/download/'.$file['nid'], null, null, true); $text .= "File$i=".$file_path."\r\n"; $text .= "Title$i=".$file['artist']."-" .$file['title']."\r\n"; $text .= "Length$i=".$file['playtime_seconds']."\r\n"; } //grab the last one... but set length to '-1' $text .= "NumberOfEntries=".count($files)."\r\nVersion=2\r\n"; header("Pragma: no-cache"); // HTTP/1.0 header("Cache-Control: private"); // HTTP/1.1 header("Content-Type: x-mpegurl", TRUE); header("Content-Length: ".strlen($text)."", TRUE); header("Content-Disposition: attachment; filename=\"".$node->title.".pls\"", TRUE); print $text; exit(); break; //------------------------------------------ //Generate XSPF... //------------------------------------------ case 'xspf': $text .= ' '.$node->title.' '.url('node/'.$nid, null,null,true).' '; foreach ($files as $file) { $file_path = url('audio/download/'.$file['nid'], null, null, true); $time = $file['playtime_seconds']*1000; //in milliseconds?!... $text .= ' '.$file_path.' '.$file['artist'].' '.$file['title'].' - '.$file['artist'].' '.$file['title'].' '.$file['album'].' '.$time.' '; //TODO: add extra fields... // // http://images.amazon.com/images/P/B000002J0B.01.MZZZZZZZ.jpg } $text .= ''; $text .= ''; break; } //application/xspf+xml drupal_set_header('Content-Type: text/xml; charset=utf-8'); print $text; exit(); } //TODO: return an appropriate error message that there are no files in this album!... drupal_not_found(); } /** * adds an audio file to this album node in the node_relate table... */ function playlist_add_item($parent_id, $child_id){ //do some error checking.. if (!is_numeric($parent_id) || !is_numeric($child_id)) drupal_not_found(); //otherwise... //make sure this isn't already in this album! $exist = db_result(db_query("SELECT child_id FROM {playlist_relate} WHERE child_id=%d and parent_id=%d limit 1", $child_id, $parent_id)); if (!$exist){ //find highest id db_query("INSERT INTO {playlist_relate} (rid, parent_id, child_id, weight) VALUES (%d, %d, '%d','%d')", '', $parent_id, $child_id, _playlist_next_weight_int($parent_id)); drupal_set_message("The file has been added to the album."); return 1; } //drupal_set_message("It appears that this file has already been added to this album.", 'error'); } /** * Find the next weight to insert into the table */ function _playlist_next_weight_int($parent_id){ $max = db_result(db_query("SELECT MAX(weight) FROM {playlist_relate} WHERE parent_id=%d limit 1", $parent_id)); return (is_null($max)) ? 0 : ++$max; } /** * removes an audio file to this album node in the node_relate table... */ function playlist_remove_item($parent_id, $child_id){ //do some error checking.. if (!is_numeric($parent_id) || !is_numeric($child_id)) drupal_not_found(); //delete from album db_query("DELETE FROM {playlist_relate} WHERE parent_id=%d and child_id=%d", $parent_id, $child_id); //set message drupal_set_message("The file has been removed from this album."); } /** * removes an audio file from all album nodes in the node_relate table... */ function _playlist_remove_all_parents($nid){ if (!is_numeric($nid)) drupal_not_found(); //delete from album db_query("DELETE FROM {playlist_relate} WHERE child_id=%d", $nid); } /** * Saves the order of the audio files. * Called via AJAX */ function playlist_order($parent_id){ $audio_files = $_REQUEST['list']; foreach ($audio_files as $child_id) { db_query("UPDATE {playlist_relate} SET weight = '%d' WHERE child_id=%d AND parent_id=%d", $i++, $child_id, $parent_id); } drupal_set_message("The album order has been saved."); print theme('status_messages'); } /** * Form split over two pages for better UI... */ function playlist_manage_files(){ //grab the parameters from the query... $parent_id = arg(1); //the nid of the playlist node... $action = arg(3); //options are either add or remove $child_id = arg(4); //keep in mind here that $child_id is actually an audio node id... //is this an 'add'? if ($action == "add") playlist_add_item($parent_id, $child_id); //is this a 'remove'? if ($action == "remove") playlist_remove_item($parent_id, $child_id); //add extra css and javascript for the form... //add style sheet... //This is pretty brutal to add AJAX stuff like this into my module!... Yikes! drupal_set_html_head(' '); //grab a list of all the audio files that are in this album... $output .= form_group("Audio files in this playlist.", _playlist_get_list($parent_id), "You can reorder the tracks by clicking and dragging the item to its desired position."); //woot! there it is... $output .= ""; $output .= form_group("Available audio files", _playlist_table(), "Use this table to select the audio files that you would like to add to this album. You can also add audio files to this album by clicking on the edit tab for the actual audio file as well."); print theme('page', $output); } /** * TODO: Dependency on the audio module?... */ function _playlist_get_list($parent_id){ $result = db_query("SELECT child_id FROM {playlist_relate} WHERE parent_id = %d ORDER BY weight ASC", $parent_id); $output = ''; $output .= '

'; return $output; } /** * Displays a list of playlists of a given user */ function playlist_page_user(){ global $user; if (arg(3) == 'feed'){ playlist_feed_user(); return; } $uid = arg(2); //are we viewing our own playlists? $is_owner = ($uid == $user->uid) ? true : false ; $account = user_load(array((is_numeric($uid) ? 'uid' : 'name') => $uid, 'status' => 1)); if ($account->uid) { drupal_set_title($title = t("%name's playlists", array('%name' => $account->name))); if (($is_owner) && playlist_access('create')) { $output = ''; } $result = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE type = 'playlist' AND n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid); while ($node = db_fetch_object($result)) { $output .= node_view(node_load(array('nid' => $node->nid)), 1); } $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); $output .= theme('xml_icon', url("playlist/user/$account->uid/feed")); drupal_add_link( array( 'rel' => 'alternate', 'type' => 'application/rss+xml', 'title' => t('RSS - %title', array('%title' => $title)), 'href' => url("playlist/user/$account->uid/feed"))); print theme('page', $output); } else { drupal_not_found(); } } /** * Show feed for the last playlists of this user... */ function playlist_feed_user() { global $user; $uid = arg(2); $account = user_load(array((is_numeric($uid) ? 'uid' : 'name') => $uid, 'status' => 1)); $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'playlist' AND u.uid = %d AND n.status = 1 ORDER BY n.created DESC"), $account->uid, 0, 15); $channel['title'] = $account->name ."'s playlists"; $channel['link'] = url("playlist/user/$uid", NULL, NULL, TRUE); $channel['description'] = $term->description; node_feed($result, $channel); } /** * Displays a Drupal page containing all albums added. */ function playlist_page() { $output = ''; if (arg(1) == 'feed'){ playlist_feed_page(); return 1; } $result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'playlist' AND n.status = 1 ORDER BY n.created DESC"), variable_get('default_nodes_main', 10)); while ($node = db_fetch_object($result)) { $output .= node_view(node_load(array('nid' => $node->nid)), 1); } $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); $output .= theme('xml_icon', url("playlist/feed")); drupal_add_link( array( 'rel' => 'alternate', 'type' => 'application/rss+xml', 'title' => t('RSS - %title', array('%title' => $title)), 'href' => url("playlist/feed"))); print theme('page', $output); } /** * Feed the last playlist nodes added to site.. */ function playlist_feed_page() { $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'playlist' AND n.status = 1 ORDER BY n.created DESC"), 0, 15); $channel['title'] = variable_get('site_name', 'drupal') .' playlists'; $channel['link'] = url('playlist', NULL, NULL, TRUE); $channel['description'] = $term->description; node_feed($result, $channel); } //feed an individual playlist node function playlist_feed() { $nid = arg(1); $result = db_query('SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM files AS f, audio_node_metadata AS a, playlist_relate AS ar, node AS n, users AS u WHERE ar.parent_id=%d AND ar.child_id=n.nid AND f.nid=n.nid AND u.uid = n.uid AND a.fid=f.fid ORDER BY ar.weight ASC', $nid); $channel['title'] = variable_get('site_name', 'drupal') .' playlist files'; $channel['link'] = url("noode/$nid", NULL, NULL, TRUE); $channel['description'] = "Playlist $nid audio files"; node_feed($result, $channel); } /** * Display the track listing in a box (that is dragged around)... */ function _playlist_track($audio_node){ //TODO: Ajaxify 'remove function!... //TODO: themeable.. $remove_from_album_link = l(theme_image(drupal_get_path('module', 'playlist').'/images/watchdog-error.png', "Remove track from album", "Remove track from album"), 'node/'. arg(1) .'/manage/remove/'.$audio_node->nid, null, null, null, false, true); $text .= $remove_from_album_link . ' '.$audio_node->audio['artist'].' - ' . $audio_node->audio['title']; return $text; } /** * Implementation of hook_form(). */ function playlist_form(&$node) { if (function_exists('taxonomy_node_form')) { $output .= implode('', taxonomy_node_form('playlist', $node)); } $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); $output .= filter_form('format', $node->format); return $output; } /** * Renders the audio table on the media page */ function _playlist_table() { //try and provide some filters here... //TODO: Make work! $names['all'] = t('all messages'); $queries['all'] = ''; $col_names = array( 'artist' => 'Artist', 'filename' => 'File Name', ); //TODO: Arggg!!! if (empty($_SESSION['playlist_filter'])) { $_SESSION['playlist_filter'] = 'all'; } $op = $_POST['op']; if ($op == t('Filter') && isset($_POST['edit']['filter'])) { $_SESSION['playlist_filter'] = $_POST['edit']['filter']; } $form = form_select(t('Filter audio files where'), 'type', $_SESSION['playlist_filter_type'], $col_names); $form .= form_textfield(t(' is '), 'value', $_SESSION['playlist_filter_value'], 30, 50); //form_textfield($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) $form .= form_submit(t('Go')); //clean up the html with this ugly hack so all form elements are on one line... //TODO: Find out how to do this properly! $form = ereg_replace('*.
','',$form); $form = str_replace('
','',$form); //remove any br, if they exist... $form = str_replace(':','',$form); //remove the ':'s, if they exist... $form = ereg_replace('
','',$form); //remove the closing div tag $form = str_replace('','',$form); //and add it at the end... $output .= form($form); $keys = ($_POST['keys']) ? $_POST['keys'] : $_GET['keys']; $keys = mysql_escape_string($keys); $search_clause = ($keys) ? sprintf(" AND (f.filename LIKE '%%%s%%' OR name LIKE '%%%s%%' OR artist LIKE '%%%s%%' OR title LIKE '%%%s%%' OR album LIKE '%%%s%%' OR year LIKE '%%%s%%' OR genre LIKE '%%%s%%' OR fileformat LIKE '%%%s%%') ", $keys, $keys, $keys, $keys, $keys, $keys, $keys, $keys) : '' ; //TODO: make more robust! $media_type_clause = "(LEFT(filemime,5) = 'audio' OR RIGHT(f.filename,3) = 'ogg')"; $table_attributes = array (); $sortable_columns['File name'] = array ('data' => 'File name', 'field' => 'filename', 'sort' => 'asc'); $sortable_columns['Submitted by'] = array ('data' => 'Submitted by', 'field' => 'name'); $sortable_columns['Artist'] = array ('data' => 'Artist', 'field' => 'artist'); $sortable_columns['Title'] = array ('data' => 'Title', 'field' => 'title'); $sortable_columns['Album'] = array ('data' => 'Album', 'field' => 'album'); $sortable_columns['Year'] = array ('data' => 'Year', 'field' => 'year'); $sortable_columns['Genre']= array ('data' =>'Genre', 'field' => 'genre'); $sortable_columns['File format'] = array ('data' => 'File format', 'field' => 'fileformat'); $header = array ('Actions', $sortable_columns['File name'], $sortable_columns['Submitted by'], $sortable_columns['Artist'], $sortable_columns['Title'], $sortable_columns['Album'], $sortable_columns['Year'],$sortable_columns['Genre'], $sortable_columns['File format']); $rows = array (array ()); $result = pager_query("SELECT f.fid, f.filename, f.filepath, name, a.artist, a.title, a.album, a.year, a.genre, a.track, a.comment, a.fileformat, n.nid AS audio_nid FROM {audio_node_metadata} AS a,{node} AS n,{users} AS u,{files} AS f". " WHERE $media_type_clause $search_clause AND (a.fid = f.fid AND f.nid = n.nid AND n.uid = u.uid)".tablesort_sql($header)); while ($data_row = db_fetch_array($result)) { $add_to_album_link = l(theme_image(drupal_get_path('module', 'playlist').'/images/icon_add.png', "Add track to album", "Add track to album"), 'node/'. arg(1) .'/manage/add/'.$data_row['audio_nid'], null, null, null, false, true); $rows[] = array ($add_to_album_link, $data_row['filename'], $data_row['name'], $data_row['artist'], $data_row['title'], $data_row['album'], $data_row['year'], $data_row['genre'], $data_row['fileformat']); } $output .= theme('table', $header, $rows, $table_attributes); return $output; } /** * Implementation of hook_link. */ function playlist_link($type, $node, $main = 0) { $links = array(); if ($type == 'node' && $node->type == 'playlist') { $links = array( 'Stream album: '.l(t('m3u'), 'node/'.$node->nid.'/playlist/m3u', NULL)." ". l(t('pls'), 'node/'.$node->nid.'/playlist/pls', NULL)." ". l(t('xspf'), 'node/'.$node->nid.'/playlist/xspf', NULL) ); } if ($type == 'node' && $node->type == 'audio' && user_access('edit own playlists')) { $links[] .= l(t('add to playlist'), "playlist/additem/$node->nid", array('title' => t('Add this item to your personal playlist.'))); } return $links; } /** * Implementation of hook_delete(). * * When a node is deleted, we need to clean up related tables. */ function playlist_delete($node) { //remove all rows that reference this node... db_query('DELETE FROM {playlist_relate} WHERE parent_id = %d', $node->nid); } /** * Implementation of hook_load(). * * Now that we've defined how to manage the node data in the database, we * need to tell Drupal how to get the node back out. This hook is called * every time a node is loaded, and allows us to do some loading of our own. */ function playlist_load(&$node) { //grab all the audio node id's from the playlist_relate table... $result = db_query("SELECT child_id FROM {playlist_relate} WHERE parent_id = %d ORDER BY weight ASC", $node->nid); $audio_node = array(); while ($row = db_fetch_array($result)) { $audio_nodes[] = node_load(array('nid' => $row['child_id'])); } //set the list of audio files in the current node... $node->audio_nodes = $audio_nodes; } /** * Implementation of hook_view(). * */ function playlist_view(&$node, $teaser = FALSE, $page = FALSE) { $node = node_prepare($node, $main); //$node->teaser = theme('playlist_display_teaser', $node); $node->body = $node->body . theme('playlist_display', $node); } function theme_playlist_display(&$node){ $audio_nodes = $node->audio_nodes; if (!is_array($audio_nodes)) return; //nothing to see here... move along.. $output = "

Track Listing

"; $output .= '
    '; foreach ($audio_nodes as $audio_node) { //a link to download audio file directly /*$output .= '
  1. '.l($audio_node->audio['title'],'audio/download/'. $audio_node->nid, array('title' => "Click to download file.")). " " . $audio_node->audio['player'] ."
  2. "; */ //This line below creates a link to the actual audio node instead of downloading the file... $output .= '
  3. '.l($audio_node->audio['title'],"node/".$audio_node->nid). " " . $audio_node->audio['player'] . l(t('download'), 'audio/download/' .$audio_node->nid, NULL)."
  4. "; } $output .= '
'; $output .= theme('xml_icon', url('node/'.$node->nid.'/feed')); return $output; } /** * Implementation of hook_nodeapi */ function playlist_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { //if this is a page were viewing, add some css and rss stuff to the header... if ($page) { drupal_set_html_head(''); //add style sheet... _playlist_add_link( array( 'rel' => 'alternate', 'type' => 'application/rss+xml', 'title' => t('RSS - Audio'), 'href' => url("node/".$node->nid."/feed"))); } switch ($op) { case 'settings': return form_radios(t('Allow node to be added to audio album'), 'playlist_item_'. $node->type, variable_get('playlist_item_'. $node->type, 0), array(t('Disabled'), t('Enabled'))); break; case 'form post': if (variable_get('playlist_item_' . $node->type, 0) == 1 && user_access('edit own playlists')) { return playlist_select_form($node); //so we can show a list of available albums in the dropdown list... } break; case 'insert': case 'update': //add the node being submitted to the audio album relations table... if (variable_get('playlist_item_' . $node->type, 0) == 1 && user_access('edit audio album')) { _playlist_remove_all_parents($node->nid); if(!in_array('-1', $_REQUEST['edit']['playlist_select'])) foreach($_REQUEST['edit']['playlist_select'] as $parent_id) { if (is_numeric($parent_id)) playlist_add_item($parent_id, $node->nid); } } break; } } /** * The drop down menu that is displayed on audio pages to let a user add a * new track to an album. */ function playlist_select_form($node){ $result = db_query("SELECT title, nid FROM {node} WHERE type='%s' ORDER BY title ASC", 'playlist'); //form_select($title, $name, $value, $options, $description = NULL, $extra = 0, $multiple = FALSE, $required = FALSE) $items = array('-1' => ''); while($item = db_fetch_object($result)){ $items[$item->nid] .= $item->title; } //grab the selected albums... $result = db_query("SELECT nid FROM {playlist_relate} WHERE child_id = %d", $node->nid); //'child_id' is the node id of the audio node... $selected = array(); while($item = db_fetch_object($result)) { $selected[] .= $item->nid; } $selected = (empty($selected)) ? '-1' : $selected; $dropdown .= form_select(t('Add to playlist'), "playlist_select", $selected, $items, "You can add this item to one of these Playlists. You can always change this later.", 0, TRUE, FALSE); //grab a list of all the audio files that are in this album... $output .= form_group("Playlists", $dropdown); return $output; } /** * Implementation of function playlist_additem() * Handles the intermediary form used to add an item to a playlist. * */ function playlist_choose() { global $user; $uid = $user->uid; $child_id = arg(2); //_print_rp($_POST); if($_POST['edit'] and ($_POST['op'] == "update")){ foreach ($_POST['edit'] as $parent_id => $value) { if ($value) { playlist_add_item($parent_id, $child_id); } else { playlist_remove_item($parent_id, $child_id); } } drupal_goto($_REQUEST["REFERRER"]); } $output = ''; // get the playlist IDs where this node is already added $result = db_query("SELECT parent_id FROM {playlist_relate} WHERE child_id = %d", $child_id); while($playlist = db_fetch_object($result)) { //_print_rp($playlist); $selected_array[] = $playlist->parent_id; } //display a list of user's playlists with checkboxes $result = db_query("SELECT title, nid, uid FROM {node} WHERE type='%s' AND uid = %d ORDER BY title ASC", 'playlist', $uid); while($playlist = db_fetch_object($result)) { $title = $playlist->title; $parent_id = $playlist->nid; $checked = FALSE; // check to see if the item is already in a given playlist if($selected_array) { foreach($selected_array as $value) { if($value == $parent_id) { $checked = TRUE; } } } $form .= form_checkbox($title, $parent_id, $value = 1, $checked, $description = NULL, $attributes = NULL, $required = FALSE); } //output everything to the browser $form .= form_submit(t('update')); $output .= form($form, 'post', NULL, NULL); print theme('page', $output); } //----------------------------------------------------------------------------------- // U t i l i t i e s A n d H e l p e r s //----------------------------------------------------------------------------------- function _playlist_add_link($attributes) { drupal_set_html_head('\n"); }