| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: station_playlist.module,v 1.27 2010/11/06 21:11:01 timplunkett Exp $ 3 4 /** 5 * Implementation of hook_help(). 6 */ 7 function station_playlist_help($path, $arg) { 8 switch ($path) { 9 case 'admin/settings/station/playlist': 10 return t("These settings allow you to configure the playlist node."); 11 } 12 } 13 14 /** 15 * Implementation of hook_menu(). 16 */ 17 function station_playlist_menu() { 18 $items['admin/settings/station/playlist'] = array( 19 'title' => 'Playlist', 20 'page callback' => 'drupal_get_form', 21 'page arguments' => array('station_playlist_admin_settings'), 22 'access arguments' => array('administer site configuration'), 23 'file' => 'station_playlist.admin.inc', 24 'type' => MENU_LOCAL_TASK 25 ); 26 27 $items['station/autocomplete/playlist'] = array( 28 'title' => 'Playlist Autocomplete', 29 'page callback' => 'station_playlist_autocomplete', 30 'access arguments' => array('access content'), 31 'type' => MENU_CALLBACK, 32 ); 33 34 $items['station/ahah/playlist'] = array( 35 'page callback' => 'station_playlist_ahah', 36 'page arguments' => array(), 37 'access arguments' => array('access content'), 38 'type' => MENU_CALLBACK, 39 ); 40 return $items; 41 } 42 43 /** 44 * Implementation of hook_theme(). 45 */ 46 function station_playlist_theme() { 47 return array( 48 'station_playlist_track_form' => array( 49 'arguments' => array('form' => NULL), 50 ), 51 ); 52 } 53 54 /** 55 * Implementation of hook_node_info(). 56 */ 57 function station_playlist_node_info() { 58 return array( 59 'station_playlist' => array( 60 'name' => t('Program Playlist'), 61 'module' => 'station_playlist', 62 'description' => t("A playlist lets your listeners see a list of all the music played during a program. It also allows the music director to easily chart what's being played."), 63 'has_title' => TRUE, 64 'title_label' => t('Title'), 65 'has_body' => TRUE, 66 'body_label' => t('Description'), 67 ) 68 ); 69 } 70 71 /** 72 * Implementation of hook_perm(). 73 */ 74 function station_playlist_perm() { 75 return array( 76 'administer station playlists', 77 'view station playlist content', 78 'create station playlist content', 79 'edit any station playlist content', 80 'edit own station playlist content', 81 'delete any station playlist content', 82 'delete own station playlist content', 83 ); 84 } 85 86 /** 87 * Implementation of hook_link(). 88 * 89 * This is implemented so that an edit link is displayed for users who have 90 * the rights to edit a node. 91 */ 92 function station_playlist_link($type, $object, $teaser = FALSE) { 93 if ($type == 'node') { 94 switch ($object->type) { 95 case 'station_program': 96 $links = array(); 97 98 $field = content_fields('field_station_program', 'station_playlist'); 99 $db_info = content_database_info($field); 100 $col = $db_info['columns']['nid']['column']; 101 $result = db_query(db_rewrite_sql("SELECT COUNT(n.nid) FROM {node} n INNER JOIN {{$db_info['table']}} sp ON n.nid = sp.$col WHERE sp.$col = %d AND n.status = 1"), $object->nid); 102 if (db_result($result)) { 103 $links['station_station_playlist_view'] = array( 104 'title' => t('View all playlists'), 105 'href' => 'station/playlists/'. $object->nid, 106 ); 107 } 108 109 if (!$teaser) { 110 if (node_access('update', $object)) { 111 $links['station_station_playlist_add'] = array( 112 'title' => t('Add new playlist'), 113 'href' => 'node/add/station-playlist/'. $object->nid, 114 ); 115 } 116 } 117 return $links; 118 119 case 'station_playlist': 120 if (!empty($object->field_station_program[0]['nid'])) { 121 return array('station_program_program_view' => array( 122 'title' => t('View program'), 123 'href' => 'node/'. $object->field_station_program[0]['nid'], 124 )); 125 } 126 } 127 } 128 return array(); 129 } 130 131 /** 132 * Implementation of hook_access(). 133 */ 134 function station_playlist_access($op, $node, $account) { 135 if (user_access('administer station playlists', $account)) { 136 return TRUE; 137 } 138 139 switch ($op) { 140 case 'view': 141 return user_access('view station playlist content', $account); 142 143 case 'create': 144 return user_access('create station playlist content', $account); 145 146 case 'update': 147 if (user_access('edit own station playlist content', $account) && ($account->uid == $node->uid)) { 148 return TRUE; 149 } 150 return user_access('edit any station playlist content', $account); 151 152 case 'delete': 153 if (user_access('delete own station playlist content', $account) && ($account->uid == $node->uid)) { 154 return TRUE; 155 } 156 return user_access('delete any station playlist content', $account); 157 } 158 } 159 160 /** 161 * Does this track have all the required fields be saved? 162 * 163 * Tracks need to have an artist or title to be saved to the database. 164 * 165 * @param $track 166 * Array with track information. 167 * @return 168 * The track has some values filled in but is missing an artist or title. 169 * @see station_playlist_track_is_incomplete() 170 */ 171 function station_playlist_track_is_saveable($track) { 172 return ($track['artist'] || $track['title']); 173 } 174 175 /** 176 * Does an unsavable track have other values set? 177 * 178 * @param $track 179 * Array with track information. 180 * @return 181 * The track has some values filled in but is missing an artist or title. 182 * @see station_playlist_track_is_empty() 183 */ 184 function station_playlist_track_is_incomplete($track) { 185 return ($track['album'] || $track['label'] || $track['link']) && !($track['artist'] || $track['title']); 186 } 187 188 /** 189 * Helper function to build an empty track row. 190 */ 191 function station_playlist_get_empty_track() { 192 static $track; 193 194 if (!isset($track)) { 195 $track = array( 196 'artist' => '', 197 'album' => '', 198 'title' => '', 199 'label' => '', 200 'link' => '', 201 'weight' => 9999, 202 ); 203 drupal_alter('station_playlist_empty_track', $track); 204 } 205 return $track; 206 } 207 208 /** 209 * Implementation of hook_form(). 210 * 211 * Build a form for playlist nodes. 212 */ 213 function station_playlist_form(&$node, $form_state) { 214 // if this is a new node (with no nid) and we've got a numeric argument, 215 // assume that's the program we should attach to. 216 if (empty($node->nid) && is_numeric(arg(3))) { 217 $node->field_station_program[0]['nid'] = (int) arg(3); 218 } 219 220 // Figure out how many empty rows we have and decide if we need to add some 221 // more. 222 if (isset($node->tracks)) { 223 $num_empty_tracks = 5; 224 foreach ($node->tracks as $track) { 225 if (!station_playlist_track_is_saveable($track)) { 226 $num_empty_tracks--; 227 } 228 } 229 } 230 else { 231 // New playlists get 10 blank tracks. 232 $num_empty_tracks = 10; 233 $node->tracks = array(); 234 } 235 $empty_track = station_playlist_get_empty_track(); 236 for ($i = 0; $i < $num_empty_tracks; $i++) { 237 $node->tracks[] = $empty_track; 238 } 239 240 $form['body_filter']['body'] = array( 241 '#type' => 'textarea', 242 '#title' => t('Description'), 243 '#default_value' => $node->body, 244 '#rows' => 5, 245 ); 246 $form['body_filter']['format'] = filter_form($node->format); 247 248 // Wrapper to hold all the tracks elements. 249 $form['tracks_wrapper'] = array( 250 '#value' => '<label>'. t('Tracks') .':</label>', 251 '#prefix' => '<div class="clear-block form-item" id="station-playlist-tracks-wrapper">', 252 '#suffix' => '</div>', 253 '#theme' => 'station_playlist_track_form', 254 '#description' => t('Enter the tracks played on the show, the artist and title are required. If you provide a link, it needs to begin with <code>http://</code> or you will get a link to a page on this site.'), 255 '#tree' => FALSE, 256 ); 257 // Container to display existing tracks. 258 $form['tracks_wrapper']['tracks'] = array( 259 '#prefix' => '<div id="station-playlist-tracks">', 260 '#suffix' => '</div>', 261 '#tree' => TRUE, 262 ); 263 264 foreach ($node->tracks as $weight => $track) { 265 $form['tracks_wrapper']['tracks'][$weight]['artist'] = array( 266 '#type' => 'textfield', 267 '#size' => 20, 268 '#maxlength' => 255, 269 '#default_value' => isset($track['artist']) ? $track['artist'] : '', 270 '#autocomplete_path' => 'station/autocomplete/playlist/artist', 271 ); 272 $form['tracks_wrapper']['tracks'][$weight]['album'] = array( 273 '#type' => 'textfield', 274 '#size' => 20, 275 '#maxlength' => 255, 276 '#default_value' => isset($track['album']) ? $track['album'] : '', 277 '#autocomplete_path' => 'station/autocomplete/playlist/album', 278 ); 279 $form['tracks_wrapper']['tracks'][$weight]['title'] = array( 280 '#type' => 'textfield', 281 '#size' => 20, 282 '#maxlength' => 255, 283 '#default_value' => isset($track['title']) ? $track['title'] : '', 284 ); 285 $form['tracks_wrapper']['tracks'][$weight]['label'] = array( 286 '#type' => 'textfield', 287 '#size' => 20, 288 '#maxlength' => 255, 289 '#default_value' => isset($track['label']) ? $track['label'] : '', 290 '#autocomplete_path' => 'station/autocomplete/playlist/label', 291 ); 292 $form['tracks_wrapper']['tracks'][$weight]['link'] = array( 293 '#type' => 'textfield', 294 '#size' => 20, 295 '#maxlength' => 255, 296 '#default_value' => isset($track['link']) ? $track['link'] : '', 297 ); 298 $form['tracks_wrapper']['tracks'][$weight]['weight'] = array( 299 '#type' => 'weight', 300 '#default_value' => $weight, 301 '#delta' => 100, 302 ); 303 // Remove button. 304 $form['tracks_wrapper']['tracks'][$weight]['remove'] = array( 305 '#type' => 'submit', 306 '#name' => 'remove_' . $weight, 307 '#value' => t('Remove'), 308 '#submit' => array('station_playlist_form_ahah_track_submit'), 309 '#ahah' => array( 310 'path' => 'station/ahah/playlist', 311 'wrapper' => 'station-playlist-tracks-wrapper', 312 'method' => 'replace', 313 'effect' => 'fade', 314 ), 315 ); 316 } 317 318 // We name our button 'add_more' to avoid conflicts with other modules using 319 // AHAH-enabled buttons with the id 'more'. 320 $form['tracks_wrapper']['add_more'] = array( 321 '#type' => 'submit', 322 '#value' => t('Add more'), 323 '#weight' => 1, 324 '#submit' => array('station_playlist_form_ahah_track_submit'), 325 '#ahah' => array( 326 'path' => 'station/ahah/playlist', 327 'wrapper' => 'station-playlist-tracks-wrapper', 328 'method' => 'replace', 329 'effect' => 'fade', 330 ), 331 ); 332 $form['#validate'][] = 'station_playlist_node_form_validate'; 333 $form['#submit'][] = 'station_playlist_node_form_submit'; 334 return $form; 335 } 336 337 /** 338 * A do nothing submit function to prevent the form from saving. 339 */ 340 function station_playlist_form_ahah_track_submit($form, &$form_state) { 341 // Set the form to rebuild and run submit handlers. 342 node_form_submit_build_node($form, $form_state); 343 } 344 345 function theme_station_playlist_track_form($form) { 346 // To have the drag and drop not totally wack out the formatting we need 347 // the first column in the table with no form element. 348 $header = array('', t('Artist'), t('Title'), t('Album'), t('Label'), t('Link'), t('Weight'), ''); 349 350 $rows = array(); 351 foreach (element_children($form['tracks']) as $key) { 352 $form['tracks'][$key]['weight']['#attributes']['class'] = 'track-weight'; 353 $row = array( 354 '', 355 drupal_render($form['tracks'][$key]['artist']), 356 drupal_render($form['tracks'][$key]['title']), 357 drupal_render($form['tracks'][$key]['album']), 358 drupal_render($form['tracks'][$key]['label']), 359 drupal_render($form['tracks'][$key]['link']), 360 drupal_render($form['tracks'][$key]['weight']), 361 drupal_render($form['tracks'][$key]['remove']), 362 ); 363 $rows[] = array('data' => $row, 'class' => 'draggable'); 364 } 365 366 $output = ''; 367 if (count($rows)) { 368 drupal_add_tabledrag('station-playlist-tracks-table', 'order', 'sibling', 'track-weight'); 369 $output .= theme('table', $header, $rows, array('id' => 'station-playlist-tracks-table')); 370 } 371 372 return $output . drupal_render($form); 373 } 374 375 function station_playlist_node_form_validate($form, &$form_state) { 376 $tracks = $form_state['values']['tracks']; 377 378 // Check if a track should be removed. 379 if (isset($form_state['clicked_button']['#parents'][2]) && $form_state['clicked_button']['#parents'][2] == 'remove') { 380 $delta = $form_state['clicked_button']['#parents'][1]; 381 unset($tracks[$delta]); 382 } 383 384 // Sort the table by weight (which might have changed with a tablesort) 385 // then reset the keys. 386 usort($tracks, '_station_playlist_sort_tracks'); 387 $tracks = array_values($tracks); 388 // Now strip the previous weights which may not be adjacent and update the 389 // track's weights. 390 foreach ($tracks as $key => $track) { 391 $track['weight'] = $key; 392 } 393 394 // Check if they've requested a new track. 395 if (isset($form_state['clicked_button']['#parents'][0]) && $form_state['clicked_button']['#parents'][0] == 'add_more') { 396 // Add the new row to the tracks list. 397 $track = station_playlist_get_empty_track(); 398 for ($i = 0; $i < 5; $i++) { 399 $tracks[] = $track; 400 } 401 } 402 403 form_set_value($form['tracks_wrapper']['tracks'], $tracks, $form_state); 404 } 405 406 /** 407 * Helper function to sort tracks by weight. 408 */ 409 function _station_playlist_sort_tracks($a, $b) { 410 if ((int) $a['weight'] == (int) $b['weight']) { 411 return 0; 412 } 413 return ((int) $a['weight'] < (int) $b['weight']) ? -1 : 1; 414 } 415 416 /** 417 * Implementation of hook_validate(). 418 * 419 * Use this hook to convert form elements to node values. 420 */ 421 function station_playlist_validate(&$node, &$form) { 422 // Check for missing track information. 423 foreach ($node->tracks as $track) { 424 if (station_playlist_track_is_incomplete($track)) { 425 form_set_error('tracks]['. $track['weight'] .'][artist', t("You must provide either an artist or a title.")); 426 form_set_error('tracks]['. $track['weight'] .'][title', ' '); 427 } 428 } 429 } 430 431 function station_playlist_ahah() { 432 // The form is generated in an include file which we need to include manually. 433 include_once 'modules/node/node.pages.inc'; 434 435 $form = station_ajax_form_handler(); 436 437 // Render the new output. 438 $sub_form = $form['tracks_wrapper']; 439 // Prevent duplicate wrappers. 440 unset($sub_form['#prefix'], $sub_form['#suffix']); 441 442 $output = theme('status_messages') . drupal_render($sub_form); 443 444 // AHAH is not being nice to us and doesn't know about the "Remove" button. 445 // This causes it not to attach AHAH behaviours to it after modifying the form. 446 // So we need to tell it first. 447 $javascript = drupal_add_js(NULL, NULL); 448 if (isset($javascript['setting'])) { 449 $output .= '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>'; 450 } 451 452 // Final rendering callback. 453 drupal_json(array('status' => TRUE, 'data' => $output)); 454 } 455 456 /** 457 * Form submit handler to set the node's title(). 458 */ 459 function station_playlist_node_form_submit($form, &$form_state) { 460 // Compute the title. 461 $form_state['values']['title'] = t('!program-title playlist for !date', array( 462 '!program-title' => _nodereference_titles($form_state['values']['field_station_program'][0]['nid']), 463 '!date' => format_date($form_state['values']['field_station_playlist_date'][0]['value'], 'custom', variable_get('station_playlist_title_dateformat', 'm/d/Y')), 464 )); 465 } 466 467 468 /** 469 * Implementation of hook_load(). 470 */ 471 function station_playlist_load($node) { 472 // Tracks 473 $extras = new stdClass(); 474 $extras->tracks = array(); 475 $result = db_query('SELECT * FROM {station_playlist_track} WHERE nid = %d ORDER BY weight', $node->nid); 476 while ($track = db_fetch_array($result)) { 477 $extras->tracks[] = $track; 478 } 479 480 return $extras; 481 } 482 483 /** 484 * Insert a new playlist 485 */ 486 function station_playlist_insert($node) { 487 foreach ($node->tracks as $track) { 488 if (station_playlist_track_is_saveable($track)) { 489 $record = array_merge($track, array('nid' => $node->nid, 'vid' => $node->vid)); 490 drupal_write_record('station_playlist_track', $record); 491 } 492 } 493 } 494 495 /** 496 * Delete a playlist. 497 */ 498 function station_playlist_delete($node) { 499 db_query('DELETE FROM {station_playlist_track} WHERE nid = %d', $node->nid); 500 } 501 502 /** 503 * Update a playlist. 504 */ 505 function station_playlist_update($node) { 506 // delete and re-add tracks 507 db_query('DELETE FROM {station_playlist_track} WHERE nid = %d', $node->nid); 508 foreach ($node->tracks as $track) { 509 if (station_playlist_track_is_saveable($track)) { 510 $record = array_merge($track, array('nid' => $node->nid, 'vid' => $node->vid)); 511 drupal_write_record('station_playlist_track', $record); 512 } 513 } 514 } 515 516 /** 517 * Get a playlist ready for viewing. 518 */ 519 function station_playlist_view(&$node, $teaser = false, $page = false) { 520 $node = node_prepare($node, $teaser); 521 522 if ($page) { 523 $program_nid = $node->field_station_program[0]['nid']; 524 $breadcrumb = drupal_get_breadcrumb(); 525 $breadcrumb[] = l(t('Station'), 'station'); 526 $breadcrumb[] = l(t('Programs'), 'station/programs'); 527 $breadcrumb[] = l(_nodereference_titles($program_nid), 'node/'. $program_nid); 528 drupal_set_breadcrumb($breadcrumb); 529 } 530 531 if (!$teaser && isset($node->nid)) { 532 if ($view = views_get_view('station_playlist_tracks')) { 533 $display_id = 'default'; 534 if ($view->access($display_id)) { 535 if ($output = $view->preview($display_id, array($node->nid))) { 536 $node->content['tracks'] = array( 537 '#value' => $output, 538 '#title' => 'Tracks', 539 '#weight' => 0, 540 ); 541 } 542 } 543 $view->destroy(); 544 } 545 } 546 return $node; 547 } 548 549 /** 550 * Implementation of hook_nodeapi(). 551 * 552 * We inject our past and future playlists onto program nodes here. 553 */ 554 function station_playlist_nodeapi(&$node, $op, $teaser, $page) { 555 if ($node->type == 'station_program' && $op == 'view') { 556 $block_content_mapping = array( 557 'block_1' => 'playlists_future', 558 'block_2' => 'playlists_past', 559 ); 560 foreach ($block_content_mapping as $display_id => $content_key) { 561 if ($view = views_get_view('station_program_playlists')) { 562 if ($view->access($display_id)) { 563 $block = $view->execute_display($display_id); 564 if (isset($block)) { 565 $node->content[$content_key]['#type'] = 'item'; 566 $node->content[$content_key]['#title'] = $block['subject']; 567 $node->content[$content_key]['#value'] = $block['content']; 568 } 569 } 570 $view->destroy(); 571 } 572 } 573 } 574 } 575 576 /** 577 * Retrieve a list of autocomplete suggestions for playlist items. 578 * 579 * @param $field 580 * The name of the field to match: 'artist', 'album', 'label' 581 * @param $string 582 * The value to search for. 583 */ 584 function station_playlist_autocomplete($field = '', $string = '') { 585 $matches = array(); 586 if (in_array($field, array('artist', 'album', 'label'))) { 587 $sql = NULL; 588 $catalog_sql = 'SELECT DISTINCT %s AS val FROM {station_catalog} WHERE LOWER(%s) LIKE LOWER("%s%%")'; 589 $playlist_sql = 'SELECT DISTINCT %s AS val FROM {station_playlist_track} WHERE LOWER(%s) LIKE LOWER("%s%%")'; 590 $args = array($field, $field, $string); 591 switch (variable_get('station_playlist_track_autocomplete_source', 'playlists')) { 592 case 'playlists': 593 $sql = $playlist_sql; 594 break; 595 596 case 'catalog': 597 $sql = $catalog_sql; 598 break; 599 600 case 'both': 601 $sql = $catalog_sql . ' UNION ' . $playlist_sql; 602 $args = array_merge($args, $args); 603 break; 604 } 605 606 if ($sql) { 607 $result = db_query_range($sql . ' ORDER BY val', $args, 0, 10); 608 while ($item = db_fetch_object($result)) { 609 $matches[$item->val] = check_plain($item->val); 610 } 611 } 612 } 613 614 print drupal_to_js($matches); 615 exit(); 616 } 617 618 /** 619 * Implementation of hook_content_extra_fields. 620 * 621 * Let CCK know about the playlist stuff we're putting on nodes. 622 */ 623 function station_playlist_content_extra_fields($type_name) { 624 switch ($type_name) { 625 case 'station_playlist': 626 return array( 627 'tracks' => array( 628 'label' => t('Tracks'), 629 'description' => t('Station Playlist module form.'), 630 'weight' => 0, 631 ), 632 ); 633 634 case 'station_program': 635 return array( 636 'playlists_future' => array( 637 'label' => t('Upcoming shows'), 638 'description' => t('Station Playlist module form.'), 639 'weight' => 1, 640 ), 641 'playlists_past' => array( 642 'label' => t('Previous shows'), 643 'description' => t('Station Playlist module form.'), 644 'weight' => 2, 645 ), 646 ); 647 } 648 } 649 650 /** 651 * Implementation of hook_view_api(). 652 */ 653 function station_playlist_views_api() { 654 return array( 655 'api' => 2.0, 656 'path' => drupal_get_path('module', 'station_playlist'), 657 ); 658 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |