| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: station_schedule.module,v 1.97 2010/09/13 18:54:05 timplunkett Exp $ 3 4 /** 5 * Implementation of hook_help(). 6 */ 7 function station_schedule_help($path, $arg) { 8 switch ($path) { 9 case 'node/%/schedule': 10 return t('Use this page to make changes to the schedule. You can select which programs air at what time.'); 11 12 case 'admin/settings/station/schedule': 13 return t("These settings allow you to configure the station's schedule."); 14 15 case 'node/%/view/%': 16 $output = ''; 17 if (station_has_archive()) { 18 $output .= t('The !listen_img listen link will take you to the list of archived copies of a show. The !rss_img link will take you to an RSS feed of the archived copies suitable for podcasting.', 19 array( 20 '!listen_img' => theme('image', drupal_get_path('module', 'station_schedule') .'/images/listen_tiny.gif', 'listen'), 21 '!rss_img' => theme('image', drupal_get_path('module', 'station_schedule') .'/images/rss_tiny.gif', 'podcast'), 22 ) 23 ); 24 } 25 return $output; 26 } 27 } 28 29 /** 30 * Implementation of hook_menu(). 31 */ 32 function station_schedule_menu() { 33 $items['admin/settings/station/schedule'] = array( 34 'title' => 'Schedule', 35 'page callback' => 'drupal_get_form', 36 'page arguments' => array('station_schedule_admin_settings'), 37 'access arguments' => array('administer site configuration'), 38 'file' => 'station_schedule.admin.inc', 39 'type' => MENU_LOCAL_TASK 40 ); 41 42 if (variable_get('station_schedule_redirect_old_urls', 0)) { 43 $items['schedule'] = array( 44 'page callback' => 'station_schedule_redirect_old', 45 'access arguments' => array('access content'), 46 'type' => MENU_CALLBACK, 47 ); 48 $items['station/schedule'] = array( 49 'page callback' => 'station_schedule_redirect_old', 50 'access arguments' => array('access content'), 51 'type' => MENU_CALLBACK, 52 ); 53 } 54 55 $items['node/%node/view/week'] = array( 56 'title' => 'Week', 57 'page callback' => 'node_page_view', 58 'page arguments' => array(1), 59 'access callback' => 'station_schedule_node_view_access', 60 'access arguments' => array(1), 61 'type' => MENU_DEFAULT_LOCAL_TASK, 62 'weight' => -10, 63 ); 64 $items['node/%node/view/today'] = array( 65 'title' => 'Today', 66 'page callback' => 'station_schedule_goto_today', 67 'page arguments' => array(1), 68 'access callback' => 'station_schedule_node_view_access', 69 'access arguments' => array(1), 70 'file' => 'station_schedule.pages.inc', 71 'type' => MENU_CALLBACK, 72 ); 73 // Use a separate variable to set the weights since station_day_name() 74 // may return index values that are not sorted. 75 $weight = 0; 76 foreach (station_day_name() as $day => $dayname) { 77 $items['node/%node/view/'. drupal_strtolower($dayname)] = array( 78 'title' => substr($dayname, 0, 3), 79 'page callback' => 'station_schedule_day_page', 80 'page arguments' => array(1, $dayname), 81 'access callback' => 'station_schedule_node_view_access', 82 'access arguments' => array(1), 83 'file' => 'station_schedule.pages.inc', 84 'type' => MENU_LOCAL_TASK, 85 'weight' => $weight++, 86 ); 87 } 88 $items['node/%node/schedule'] = array( 89 'title' => 'Alter schedule', 90 'page callback' => 'station_schedule_item_list', 91 'page arguments' => array(1), 92 'access callback' => 'station_schedule_node_update_access', 93 'access arguments' => array(1), 94 'file' => 'station_schedule.edit.inc', 95 'type' => MENU_LOCAL_TASK, 96 ); 97 $items['node/%node/schedule/list'] = array( 98 'title' => 'View', 99 'type' => MENU_DEFAULT_LOCAL_TASK, 100 'weight' => -10, 101 ); 102 $items['node/%node/schedule/add'] = array( 103 'title' => 'Add item', 104 'page callback' => 'station_schedule_item_add', 105 'page arguments' => array(1), 106 'access callback' => 'station_schedule_node_update_access', 107 'access arguments' => array(1), 108 'file' => 'station_schedule.edit.inc', 109 'type' => MENU_LOCAL_TASK, 110 ); 111 $items['node/%node/schedule/%station_schedule_item/edit'] = array( 112 'title' => 'Edit item', 113 'page callback' => 'station_schedule_item_edit', 114 'page arguments' => array(1, 3), 115 'access callback' => 'station_schedule_node_update_access', 116 'access arguments' => array(1), 117 'file' => 'station_schedule.edit.inc', 118 'type' => MENU_CALLBACK 119 ); 120 $items['node/%node/schedule/%station_schedule_item/remove'] = array( 121 'title' => 'Remove item', 122 'page callback' => 'drupal_get_form', 123 'page arguments' => array('station_schedule_item_remove_form', 1, 3), 124 'access callback' => 'station_schedule_node_update_access', 125 'access arguments' => array(1), 126 'file' => 'station_schedule.edit.inc', 127 'type' => MENU_CALLBACK 128 ); 129 130 return $items; 131 } 132 133 function station_schedule_node_view_access($node) { 134 return ($node->type == 'station_schedule' && node_access('view', $node)); 135 } 136 137 function station_schedule_node_update_access($node) { 138 return ($node->type == 'station_schedule' && node_access('update', $node)); 139 } 140 141 142 /** 143 * Implementation of hook_elements(). 144 */ 145 function station_schedule_elements() { 146 $type['station_schedule_daytime'] = array( 147 '#input' => TRUE, 148 '#process' => array('expand_station_schedule_daytime'), 149 '#increment' => 60, 150 '#roll_midnight_back' => FALSE, 151 ); 152 $type['station_schedule_daytime_range'] = array( 153 '#input' => TRUE, 154 '#process' => array('expand_station_schedule_daytime_range'), 155 '#default_value' => array('start' => 0, 'finish' => 0), 156 '#increment' => 60, 157 ); 158 return $type; 159 } 160 161 /** 162 * Implementation of hook_theme(). 163 */ 164 function station_schedule_theme() { 165 return array( 166 'station_schedule_daytime' => array( 167 'arguments' => array('element' => NULL), 168 ), 169 'station_schedule_daytime_range' => array( 170 'arguments' => array('element' => NULL), 171 ), 172 'station_schedule_admin_item' => array( 173 'arguments' => array('node' => NULL, 'item' => NULL), 174 'file' => 'station_schedule.edit.inc', 175 ), 176 'station_schedule_admin_nonitem' => array( 177 'arguments' => array('node' => NULL, 'start' => NULL, 'finish' => NULL), 178 'file' => 'station_schedule.edit.inc', 179 ), 180 'station_schedule_form_streams' => array( 181 'arguments' => array('form' => NULL), 182 ), 183 'station_schedule_hour' => array( 184 'arguments' => array('hour' => NULL), 185 'file' => 'station_schedule.pages.inc', 186 ), 187 'station_schedule_item' => array( 188 'arguments' => array('start' => NULL, 'finish' => NULL, 'program' => NULL), 189 'file' => 'station_schedule.pages.inc', 190 ), 191 'station_schedule_spacer' => array( 192 'arguments' => array('start' => NULL, 'finish' => NULL), 193 'file' => 'station_schedule.pages.inc', 194 ), 195 ); 196 } 197 198 /** 199 * Implementation of hook_perm(). 200 */ 201 function station_schedule_perm() { 202 return array( 203 'administer station schedule', 204 'view station schedule content', 205 'create station schedule content', 206 'edit any station schedule content', 207 'edit own station schedule content', 208 'delete any station schedule content', 209 ); 210 } 211 212 /** 213 * Implementation of hook_node_info(). 214 */ 215 function station_schedule_node_info() { 216 return array( 217 'station_schedule' => array( 218 'name' => t('Schedule'), 219 'module' => 'station_schedule', 220 'title_label' => t('Name'), 221 'description' => t('A station schedule.'), 222 ) 223 ); 224 } 225 226 /** 227 * Implementation of hook_access(). 228 */ 229 function station_schedule_access($op, $node, $account) { 230 if (user_access('administer station schedule', $account)) { 231 return TRUE; 232 } 233 234 switch ($op) { 235 case 'view': 236 return user_access('view station schedule content', $account); 237 238 case 'create': 239 return user_access('create station schedule content', $account); 240 241 case 'update': 242 if (user_access('edit own station schedule content', $account) && ($account->uid == $node->uid)) { 243 return TRUE; 244 } 245 return user_access('edit any station schedule content', $account); 246 247 case 'delete': 248 return user_access('delete any station schedule content', $account); 249 } 250 } 251 252 /** 253 * Implementation of hook_form(). 254 */ 255 function station_schedule_form($node) { 256 $type = node_get_types('type', $node); 257 258 $form['title'] = array( 259 '#type' => 'textfield', 260 '#title' => check_plain($type->title_label), 261 '#default_value' => $node->title, 262 '#required' => TRUE, 263 '#maxlength' => 128, 264 '#description' => t("The name of the schedule, e.g. 'AM', 'FM', callsign."), 265 ); 266 267 $form['settings']['#tree'] = TRUE; 268 $form['settings']['increment'] = array( 269 '#type' => 'select', 270 '#title' => t('Time increment'), 271 '#default_value' => isset($node->settings['increment']) ? $node->settings['increment'] : 60, 272 '#options' => array(1 => t('1 Minute'), 5 => t('5 Minutes'), 15 => t('15 Minutes'), 30 => t('30 Minutes'), 60 => t('1 Hour'), 120 => t('2 Hours')), 273 '#description' => t("This is the minimum increment that programs can be scheduled in. <strong>Caution:</strong> Increasing this value on an existing schedule will probably cause weirdness."), 274 ); 275 $form['settings']['start_hour'] = array( 276 '#type' => 'select', 277 '#title' => t('Programming start time'), 278 '#default_value' => isset($node->settings['start_hour']) ? $node->settings['start_hour'] : 0, 279 '#options' => station_schedule_hour_options('start'), 280 '#required' => TRUE, 281 '#description' => t("This is the time of day when your programming starts."), 282 ); 283 $form['settings']['end_hour'] = array( 284 '#type' => 'select', 285 '#title' => t('Programming end time'), 286 '#default_value' => isset($node->settings['end_hour']) ? $node->settings['end_hour'] : 24, 287 '#options' => station_schedule_hour_options('end'), 288 '#required' => TRUE, 289 '#description' => t("This is the time of day when your programming ends. It allows for programming ending as late as noon the next day."), 290 ); 291 $form['settings']['unscheduled_message'] = array( 292 '#type' => 'textfield', 293 '#title' => t('No scheduled programming message'), 294 '#size' => 60, 295 '#maxlength' => 255, 296 '#default_value' => isset($node->settings['unscheduled_message']) ? $node->settings['unscheduled_message'] : t("We're on autopilot."), 297 '#required' => TRUE, 298 '#description' => t('This string will appear when no program is currently scheduled.'), 299 ); 300 $form['settings']['streams'] = array( 301 '#type' => 'fieldset', 302 '#title' => t('Web streams'), 303 '#theme' => 'station_schedule_form_streams', 304 '#collapsible' => TRUE, 305 '#description' => t("If your station has webstreams enter them below."), 306 ); 307 if (!isset($node->settings['streams']['new'])) { 308 $node->settings['streams']['new'] = array( 309 'name' => '', 310 'description' => '', 311 'urls' => array(), 312 ); 313 } 314 foreach ($node->settings['streams'] as $key => $stream) { 315 $form['settings']['streams'][$key]['name'] = array( 316 '#type' => 'textfield', 317 '#size' => 10, 318 '#default_value' => $stream['name'], 319 ); 320 $form['settings']['streams'][$key]['description'] = array( 321 '#type' => 'textfield', 322 '#size' => 20, 323 '#default_value' => $stream['description'], 324 ); 325 $form['settings']['streams'][$key]['urls'] = array( 326 '#type' => 'textarea', 327 '#rows' => 2, 328 '#cols' => 20, 329 '#default_value' => empty($stream['urls']) ? '' : implode("\n", $stream['urls']), 330 ); 331 } 332 333 if ($type->has_body) { 334 $form['body_filter']['body'] = array( 335 '#type' => 'textarea', 336 '#title' => check_plain($type->body_label), 337 '#default_value' => $node->body, 338 '#rows' => 10, 339 '#required' => ($type->min_word_count > 0), 340 '#description' => t("Description of the schedule."), 341 ); 342 $form['body_filter']['format'] = filter_form($node->format); 343 } 344 345 // Stick in out submit handler to put the stream URLs back into an array. 346 $form['#submit'] = array('station_schedule_form_submit'); 347 348 return $form; 349 } 350 351 /** 352 * Returns an array of possible programming start and end times. 353 */ 354 function station_schedule_hour_options($type) { 355 // If type is "start", we'll provide 12am-11pm. If type is "end", we'll provide 1am through noon the next day. 356 switch ($type) { 357 case 'start': 358 $earliest = 0; 359 $latest = 24; 360 break; 361 362 case 'end': 363 $earliest = 1; 364 $latest = 36; 365 break; 366 367 default: 368 return; 369 } 370 $hour_options = array(); 371 for ($i = $earliest; $i < $latest; $i++) { 372 if ($i == 0 || $i == 24) { 373 $hour = '12'; 374 $suffix = 'am'; 375 } 376 elseif ($i == 12) { 377 $hour = '12'; 378 $suffix = 'pm'; 379 } 380 elseif ($i > 12) { 381 if ($i > 24) { 382 // This is during the morning of the next day, so subtract 24 and attach the suffix 'tomorrow'. 383 $hour = $i - 24; 384 $suffix = 'am ' . t('the next day'); 385 } 386 else { 387 // This is after noon on the current day, so subtract 12. 388 $hour = $i - 12; 389 $suffix = 'pm'; 390 } 391 } 392 else { 393 // This is during the morning of the current day. 394 $hour = $i; 395 $suffix = 'am'; 396 } 397 $hour_options[$i] = $hour . ':00' . $suffix; 398 } 399 return $hour_options; 400 } 401 402 function theme_station_schedule_form_streams($form) { 403 $header = array(t('Name'), t('Description'), t('URLs')); 404 foreach (element_children($form) as $key) { 405 $row = array(); 406 $row[] = drupal_render($form[$key]['name']); 407 $row[] = drupal_render($form[$key]['description']); 408 $row[] = drupal_render($form[$key]['urls']); 409 $rows[] = $row; 410 } 411 return theme('table', $header, $rows) . drupal_render($form); 412 } 413 414 /** 415 * Implementation of hook_validate(). 416 */ 417 function station_schedule_validate(&$node) { 418 # Make sure the selected programming start time is earlier than the selected end time. 419 if ($node->settings['start_hour'] > $node->settings['end_hour']) { 420 form_set_error("settings][start_hour", t('The start time must be earlier than the end time.')); 421 } 422 423 foreach ($node->settings['streams'] as $key => $stream) { 424 // Must have both a name and URL. 425 if (empty($stream['name']) xor empty($stream['urls'])) { 426 if (empty($stream['name'])) { 427 form_set_error("settings][streams][$key][name", t('You must provide a name for the webstream.')); 428 } 429 else { 430 form_set_error("settings][streams][$key][urls", t('You must provide a URL for the webstream.')); 431 } 432 } 433 434 $urls = is_array($stream['urls']) ? $stream['urls'] : explode("\n", $stream['urls']); 435 foreach ($urls as $url) { 436 $url = trim($url); 437 if (!empty($url) && !valid_url($url, TRUE)) { 438 form_set_error("settings][streams][$key][urls", t('An invalid webstream URL was provided: %url', array('%url' => $url))); 439 } 440 } 441 } 442 } 443 444 /** 445 * Implementation of hook_submit(). 446 */ 447 function station_schedule_form_submit($form, &$form_state) { 448 $streams = array(); 449 foreach ((array) $form_state['values']['settings']['streams'] as $key => $stream) { 450 // Skip empty rows. 451 if (!empty($stream['name'])) { 452 if (!is_array($stream['urls'])) { 453 // Convert URLs into an array and remove adjacent white space. 454 $stream['urls'] = array_map('trim', explode("\n", $stream['urls'])); 455 } 456 // Create a new key that's the name with non-alphanumeric characters 457 // converted to underscores. 458 $new_key = preg_replace('/[^-\w]+/', '_', $stream['name']); 459 $streams[$new_key] = $stream; 460 } 461 } 462 $form_state['values']['settings']['streams'] = $streams; 463 } 464 465 /** 466 * Implementation of hook_load(). 467 */ 468 function station_schedule_load($node) { 469 $schedule = array(); 470 471 // Load the settings. 472 $settings = db_fetch_array(db_query('SELECT increment, streams, unscheduled_message, start_hour, end_hour FROM {station_schedule} WHERE nid = %d', $node->nid)); 473 474 // Use station_day_name() for the day ordering in case Sunday isn't the 475 // first day of the week. 476 foreach (station_day_name() as $day => $name) { 477 $schedule[$day] = array(); 478 479 $start_hour = $settings['start_hour'] * 60; 480 $start = $day * MINUTES_IN_DAY + $start_hour; 481 $end_hour = $settings['end_hour'] * 60; 482 $finish = $day * MINUTES_IN_DAY + $end_hour; 483 484 $result = db_query('SELECT * FROM {station_schedule_item} i WHERE i.schedule_nid = %d AND i.finish > %d AND i.start < %d ORDER BY i.start', $node->nid, $start, $finish); 485 while ($s = db_fetch_object($result)) { 486 // If a show spans a day, limit its start and finish times to be with-in 487 // the day. 488 if ($s->start < $start) { 489 $s->start = $start; 490 } 491 if ($s->finish > $finish) { 492 $s->finish = $finish; 493 } 494 $schedule[$day][] = $s; 495 } 496 } 497 498 if (isset($settings['streams']) && $streams = unserialize($settings['streams'])) { 499 $settings['streams'] = array(); 500 foreach ($streams as $key => $stream) { 501 // Add in the M3U URL. 502 $stream['m3u_url'] = file_create_url('station/'. $node->nid .'-'. $key .'.m3u'); 503 $settings['streams'][$key] = $stream; 504 } 505 } 506 else { 507 $settings['streams'] = array(); 508 } 509 510 return array( 511 'settings' => $settings, 512 'schedule' => $schedule, 513 ); 514 } 515 516 /** 517 * Implementation of hook_insert(). 518 */ 519 function station_schedule_insert($node) { 520 $record = array_merge($node->settings, array('nid' => $node->nid, 'vid' => $node->vid)); 521 drupal_write_record('station_schedule', $record); 522 523 station_schedule_write_m3u($node); 524 } 525 526 /** 527 * Implementation of hook_delete(). 528 */ 529 function station_schedule_delete($node) { 530 // Remove any old streams files for this node. 531 file_scan_directory(file_create_path('station'), $node->nid .'-.*\.m3u', array('.', '..', 'CVS'), 'file_delete', FALSE); 532 533 db_query("DELETE FROM {station_schedule_item} WHERE schedule_nid = %d", $node->nid); 534 db_query("DELETE FROM {station_schedule} WHERE nid = %d", $node->nid); 535 } 536 537 /** 538 * Implementation of hook_update(). 539 */ 540 function station_schedule_update($node) { 541 db_query("DELETE FROM {station_schedule} WHERE nid = %d", $node->nid); 542 $record = array_merge($node->settings, array('nid' => $node->nid, 'vid' => $node->vid)); 543 drupal_write_record('station_schedule', $record); 544 545 station_schedule_write_m3u($node); 546 } 547 548 /** 549 * Implementation of hook_link(). 550 * 551 * This is implemented so that an edit link is displayed for users who have 552 * the rights to edit a node. 553 */ 554 function station_schedule_link($type, $node = NULL, $teaser = FALSE) { 555 if ($type == 'node') { 556 switch ($node->type) { 557 case 'station_program': 558 return station_schedule_archive_links($node->nid); 559 case 'station_playlist': 560 if (!$teaser && !empty($node->field_station_program[0]['nid'])) { 561 return station_schedule_archive_links(!empty($node->field_station_program[0]['nid'])); 562 } 563 } 564 } 565 return array(); 566 } 567 568 /** 569 * Load listen links for a program. 570 * @param $program_nid Node id of the program. 571 * @param $short bool true for short version of links 572 */ 573 function station_schedule_archive_links($program_nid, $short = FALSE) { 574 $archive_url = station_get_archive_url(); 575 $may_archive = db_result(db_query('SELECT COUNT(*) FROM {station_schedule_item} s WHERE s.program_nid = %d AND s.may_archive = 1', $program_nid)); 576 577 if ($archive_url && $may_archive ) { 578 $listen_url = $archive_url . $program_nid; 579 $rss_url = $archive_url . $program_nid .'/feed'; 580 581 $listen_img = drupal_get_path('module', 'station_schedule') .'/images/listen_tiny.gif'; 582 $rss_img = drupal_get_path('module', 'station_schedule') .'/images/rss_tiny.gif'; 583 584 return array( 585 'station_archive_listen' => array( 586 'href' => $listen_url, 587 'title' => theme('image', $listen_img, t('Listen')) . (($short) ? '' : ' '. t('Listen to previous')), 588 'attributes' => array('title' => t('Listen to previous broadcasts of this show')), 589 'html' => TRUE, 590 ), 591 'station_archive_rss' => array( 592 'href' => $rss_url, 593 'title' => theme('image', $rss_img, t('Podcast')) . (($short) ? '' : ' '. t('Subscribe to podcast')), 594 'attributes' => array('title' => t('Grab this show with your podcast software')), 595 'html' => TRUE, 596 ), 597 ); 598 } 599 return array(); 600 } 601 602 /** 603 * Implements hook_user() to associate programs with the users. 604 */ 605 function station_schedule_user($op, &$edit, &$account, $category = NULL) { 606 switch ($op) { 607 case 'load': 608 $field = content_fields('field_station_program_dj', 'station_program'); 609 $db_info = content_database_info($field); 610 $result = db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n INNER JOIN {". $db_info['table'] ."} f ON n.vid = f.vid WHERE f.". $db_info['columns']['uid']['column'] ."=". $account->uid ." AND n.status = 1")); 611 $account->programs = array(); 612 while ($program = db_fetch_object($result)) { 613 $account->programs[$program->nid] = $program->title; 614 } 615 break; 616 617 case 'view': 618 if (count($account->programs)) { 619 $account->content['station'] = array( 620 '#type' => 'user_profile_category', 621 '#attributes' => array('class' => 'user-member'), 622 '#title' => t('Programs'), 623 '#weight' => 10, 624 ); 625 foreach ((array) $account->programs as $nid => $title) { 626 $node = node_load($nid); 627 $node = node_build_content($node, TRUE, FALSE); 628 $account->content['station'][] = array( 629 '#type' => 'user_profile_item', 630 '#attributes' => array('class' => 'user-member'), 631 '#title' => l($title, 'node/'. $nid), 632 '#value' => $node->field_station_program_genre[0]['safe'] . $node->content['station_schedule_times']['#value'], 633 ); 634 } 635 } 636 break; 637 638 case 'delete': 639 $field = content_fields('field_station_program_dj', 'station_program'); 640 $db_info = content_database_info($field); 641 db_query("DELETE FROM {". $db_info['table'] ."} WHERE ". $db_info['columns']['uid']['column'] ."=". $account->uid); 642 foreach ((array) $account->programs as $nid => $title) { 643 _station_send_notice('dj', 'remove', array('program_nid' => $nid, 'uid' => $account->uid)); 644 } 645 break; 646 } 647 } 648 649 /** 650 * Implementation of hook_nodeapi(). 651 */ 652 function station_schedule_nodeapi(&$node, $op, $teaser, $page) { 653 if ($node->type == 'station_program') { 654 switch ($op) { 655 // case 'insert': 656 // // dj additions 657 // foreach ($node->djs as $uid => $username) { 658 // db_query('INSERT INTO {station_dj} (uid, program_nid) VALUES (%d, %d)', $uid, $node->nid); 659 // _station_send_notice('dj', 'add', array('program_nid' => $node->nid, 'uid' => $uid)); 660 // } 661 // break; 662 663 // case 'update': 664 // // only schedule admins should be able to add or remove djs 665 // if (user_access('administer schedule')) { 666 // $current_djs = _station_schedule_program_load_djs($node->nid); 667 // 668 // // dj removals 669 // $removals = array_diff_assoc($current_djs, $node->djs); 670 // foreach ($removals as $uid => $username) { 671 // db_query('DELETE FROM {station_dj} WHERE uid = %d AND program_nid = %d', $uid, $node->nid); 672 // _station_send_notice('dj', 'remove', array('program_nid' => $node->nid, 'uid' => $uid)); 673 // } 674 // 675 // // dj additions 676 // $additions = array_diff_assoc($node->djs, $current_djs); 677 // foreach ($additions as $uid => $username) { 678 // db_query('INSERT INTO {station_dj} (uid, program_nid) VALUES (%d, %d)', $uid, $node->nid); 679 // _station_send_notice('dj', 'add', array('program_nid' => $node->nid, 'uid' => $uid)); 680 // } 681 // } 682 // break; 683 684 case 'delete': 685 // Remove the schedule item. 686 db_query('DELETE FROM {station_schedule_item} WHERE program_nid = %d', $node->nid); 687 break; 688 689 case 'load': 690 $node->times = array(); 691 // Load the schedule items in order of start time while taking into 692 // account Drupal's first day of the week setting. 693 $result = db_query('SELECT * FROM {station_schedule_item} s INNER JOIN {node} n on n.nid = s.schedule_nid WHERE s.program_nid = %d AND n.status = 1 ORDER BY s.schedule_nid, ((s.start + %d) %% %d)', $node->nid, MINUTES_IN_DAY * (7 - variable_get('date_first_day', 0)), MINUTES_IN_WEEK); 694 while ($item = db_fetch_array($result)) { 695 $node->times[$item['schedule_nid']][] = $item; 696 } 697 698 break; 699 700 case 'view': 701 if ($page) { 702 $breadcrumb = drupal_get_breadcrumb(); 703 $breadcrumb[] = l(t('Station'), 'station'); 704 $breadcrumb[] = l(t('Programs'), 'station/programs'); 705 drupal_set_breadcrumb($breadcrumb); 706 } 707 708 $djs = station_schedule_program_get_themed_djs($node); 709 $schedules = station_get_schedules(); 710 $times_by_schedule = station_schedule_program_get_themed_times($node); 711 712 if ($teaser) { 713 $scheduled = array(); 714 foreach ($times_by_schedule as $schedule_nid => $times) { 715 $scheduled[] = t('@title @times', array('@title' => $schedules[$schedule_nid]['title'], '@times' => station_anded_list($times))); 716 } 717 $node->content['station_schedule_times'] = array( 718 '#value' => count($scheduled) ? t(' on @scheduling.', array('@scheduling' => station_anded_list($scheduled))) : t(' is not currently scheduled.'), 719 '#weight' => 0, 720 ); 721 } 722 else { 723 $node->content['station_schedule_times']['#weight'] = -4; 724 foreach ($times_by_schedule as $schedule_nid => $times) { 725 $node->content['station_schedule_times'][$schedule_nid] = array( 726 '#type' => 'item', 727 '#title' => t('Listen on <a href="!link">@title</a> at', array('@title' => $schedules[$schedule_nid]['title'], '!link' => url('node/'. $schedule_nid))), 728 '#value' => $times ? theme('item_list', $times) : t('This program is currently unscheduled.'), 729 ); 730 } 731 } 732 break; 733 } 734 } 735 } 736 737 738 /** 739 * Implementation of hook_form_alter(). 740 */ 741 function station_schedule_form_alter(&$form, $form_state, $form_id) { 742 // We only alter station_program node edit forms 743 if ($form_id == 'station_program_node_form') { 744 $node = $form['#node']; 745 // @TODO: figure out how to handle the permissions here. 746 if (user_access('administer station schedule')) { 747 748 $form['schedule'] = array( 749 '#type' => 'fieldset', 750 '#title' => t('Station Schedule'), 751 '#weight' => 1, 752 '#tree' => TRUE, 753 '#description' => t('The program must be saved before it can be added to the schedule.'), 754 '#collapsible' => TRUE, 755 ); 756 757 // if it's a saved display the scheduled times. 758 if (!empty($node->nid)) { 759 $schedules = station_get_schedules(); 760 761 $form['schedule']['#description'] = count($schedules) ? '' : t("There are no schedules on this site."); 762 763 foreach ($schedules as $schedule_nid => $schedule) { 764 $links = array(); 765 $form['schedule'][$schedule_nid] = array( 766 '#type' => 'fieldset', 767 '#title' => $schedule['title'], 768 '#description' => t("These are the times this program is currently scheduled:"), 769 ); 770 if (!isset($node->times[$schedule_nid])) { 771 $form['schedule'][$schedule_nid]['#description'] = t('This program is not on this schedule.'); 772 } 773 else { 774 foreach ($node->times[$schedule_nid] as $time) { 775 $links[] = l(theme('station_dayhour_range', $time['start'], $time['finish']), "node/{$schedule_nid}/schedule/{$time['iid']}/edit", array('query' => array('destination' => "node/{$node->nid}/edit"))); 776 } 777 } 778 // Don't encourage adding unpublished stuff to the schedule. 779 if ($node->status != 0) { 780 $links[] = l(t('Add this program to the @name schedule', array('@name' => $schedule['title'])), "node/{$schedule_nid}/schedule/add/{$node->nid}", array('query' => array('destination' => "node/{$node->nid}/edit"))); 781 } 782 $form['schedule'][$schedule_nid]['links'] = array( 783 '#type' => 'item', 784 '#value' => theme('item_list', $links), 785 ); 786 } 787 } 788 } 789 } 790 } 791 792 /** 793 * Returns an array of themed DJs. 794 */ 795 function station_schedule_program_get_themed_djs($program_node) { 796 // make djs into links 797 $djs = array(); 798 if (!empty($program_node->field_station_program_dj)) { 799 foreach ($program_node->field_station_program_dj as $entry) { 800 $user = user_load($entry); 801 $djs[] = theme('username', $user); 802 } 803 } 804 return $djs; 805 } 806 807 /** 808 * Returns a themed array of the times a program is scheduled. 809 */ 810 function station_schedule_program_get_themed_times($program_node) { 811 $ret = array(); 812 if (!empty($program_node->times)) { 813 foreach ($program_node->times as $schedule_nid => $times) { 814 foreach ($times as $time) { 815 $ret[$schedule_nid][] = theme('station_dayhour_range', $time['start'], $time['finish']); 816 } 817 } 818 } 819 return $ret; 820 } 821 822 /** 823 * Implementation of hook_xmlrpc(). 824 */ 825 function station_schedule_xmlrpc() { 826 return array( 827 array( 828 'station.program.get.at', 829 'station_schedule_program_get_at', 830 array('array', 'int', 'int'), 831 t('Fetch info on the program playing at a day/hour of a given timestamp.') 832 ), 833 array( 834 'station.schedule.get.list', 835 'station_schedule_get_list', 836 array('array'), 837 t('Fetch a list of schedules on this site.') 838 ), 839 array( 840 'station.program.get.list', 841 'station_schedule_get_program_list', 842 array('array'), 843 t('Fetch a list of programs on this site.') 844 ), 845 ); 846 } 847 848 /** 849 * Function to redirect old /schedule/* links and /station/schedule/* 850 * node/$default/*. 851 */ 852 function station_schedule_redirect_old($day = '', $hour = '') { 853 $nid = variable_get('station_schedule_default', 0); 854 $path = "node/$nid/view"; 855 if ($day) { 856 $path .= "/$day"; 857 if ($hour) { 858 $path .= "/$hour"; 859 } 860 } 861 drupal_goto($path); 862 } 863 864 /** 865 * Return a list of schedules on this site. 866 * 867 * @return 868 * Array of schedules. 869 */ 870 function station_schedule_get_list() { 871 global $base_url; 872 873 $schedules = array(); 874 $result = db_query("SELECT n.nid, n.title, ss.increment, ss.streams, ss.unscheduled_message FROM {node} n INNER JOIN {station_schedule} ss ON n.nid = ss.nid WHERE n.type = 'station_schedule' AND n.status = 1"); 875 while ($schedule = db_fetch_array($result)) { 876 $schedule['base_url'] = $base_url; 877 if (isset($schedule['streams']) && $streams = unserialize($schedule['streams'])) { 878 $schedule['streams'] = array(); 879 foreach ($streams as $key => $stream) { 880 // Add in the M3U URL. 881 $stream['m3u_url'] = file_create_url('station/'. $schedule['nid'] .'-'. $key .'.m3u'); 882 $schedule['streams'][$key] = $stream; 883 } 884 } 885 else { 886 $schedule['streams'] = array(); 887 } 888 $schedules[$schedule['nid']] = $schedule; 889 } 890 891 return $schedules; 892 } 893 894 /** 895 * Return a list of schedules on this site. 896 * 897 * @return 898 * Array of schedules. 899 */ 900 function station_schedule_get_program_list() { 901 static $schedules; 902 903 if (!isset($schedules)) { 904 $schedules = array(); 905 $result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = 'station_program'"); 906 while ($o = db_fetch_array($result)) { 907 $schedules[$o['nid']] = $o; 908 } 909 } 910 911 return $schedules; 912 } 913 /** 914 * Get the program playing at a certain time. If no time is provide, use the 915 * current time. 916 * 917 * @param $gmt_timestamp 918 * a timestamp used to determine the day of the week an hour. 919 * @param $schedule_nid 920 * Schedule node id. 921 * @return 922 * program node object if one is scheduled, an empty object if nothing is 923 * scheduled. 924 */ 925 function station_schedule_program_get_at($gmt_timestamp, $schedule_nid) { 926 // Load the schedule item based on the time. 927 $minute = station_minute_from_local_ts(station_local_ts($gmt_timestamp)); 928 929 $schedule_item = db_fetch_object(db_query('SELECT * FROM {station_schedule_item} s WHERE s.schedule_nid = %d AND s.start <= %d AND s.finish > %d', $schedule_nid, $minute, $minute)); 930 931 // If there's an associated program, load it 932 if (isset($schedule_item->program_nid)) { 933 if ($node = node_load($schedule_item->program_nid)) { 934 // set this so that if the show is scheduled for multiple times the caller 935 // can easily figure out which one. 936 $node->may_archive = $schedule_item->may_archive; 937 // put this in so they can use a pretty url 938 $node->node_url = url('node/'. $node->nid, array('absolute' => TRUE)); 939 return $node; 940 } 941 } 942 return new stdClass(); 943 } 944 945 /** 946 * Load the schedule item by its id. 947 * 948 * This function also serves as a menu item loader. 949 * 950 * @param $iid schedule item id 951 * @return schedule item object 952 */ 953 function station_schedule_item_load($iid) { 954 $result = db_query('SELECT * FROM {station_schedule_item} i WHERE i.iid = %d', $iid); 955 if ($o = db_fetch_object($result)) { 956 return $o; 957 } 958 return FALSE; 959 } 960 961 /** 962 * Implementation of hook_view(). 963 * 964 * Display a weekly view for the schedule. 965 */ 966 function station_schedule_view($node, $teaser = FALSE, $page = FALSE) { 967 drupal_add_css(drupal_get_path('module', 'station_schedule') .'/station_schedule.css'); 968 969 if ($page) { 970 $breadcrumb = drupal_get_breadcrumb(); 971 $breadcrumb[] = l(t('Station'), 'station'); 972 $breadcrumb[] = l(t('Schedules'), 'station/schedules'); 973 drupal_set_breadcrumb($breadcrumb); 974 } 975 976 $node = node_prepare($node, $teaser); 977 if ($teaser) { 978 $node->content['streams'] = array( 979 '#title' => t('Webstreams'), 980 '#value' => theme('station_streams', $node->settings['streams']), 981 '#weight' => -5, 982 ); 983 } 984 else { 985 $node->content['weekly_schedule'] = array( 986 '#value' => station_schedule_week_page($node), 987 '#weight' => 1, 988 ); 989 } 990 return $node; 991 } 992 993 994 // TODO CONVERT THIS INTO A PREPROCESS FUNCTION WITH A THEME 995 /** 996 * Print a weekly schedule page. 997 */ 998 function station_schedule_week_page($node) { 999 $header[0] = array('data' => t('Time')); 1000 $row = array(); 1001 1002 // First column is hours. 1003 $row[0] = array('id' => 'station-sch-hours', 'data' => ''); 1004 // Load the settings. 1005 $settings = db_fetch_array(db_query('SELECT increment, streams, unscheduled_message, start_hour, end_hour FROM {station_schedule} WHERE nid = %d', $node->nid)); 1006 for ($hour = $settings['start_hour']; $hour < $settings['end_hour']; $hour++) { 1007 $row[0]['data'] .= theme('station_schedule_hour', $hour); 1008 } 1009 1010 // Then a column for each day of the week. 1011 foreach ((array) $node->schedule as $day => $items) { 1012 $header[$day + 1]['data'] = station_day_name($day); 1013 $row[$day + 1]['data'] = ''; 1014 1015 // The last finish pointer starts at the beginning of the day. 1016 $last_finish = $day * MINUTES_IN_DAY + ($settings['start_hour'] * 60); 1017 $day_finish = (($day) * MINUTES_IN_DAY) + ($settings['end_hour'] * 60); 1018 foreach ($items as $item) { 1019 // Display blocks for unscheduled time periods 1020 if ($last_finish != $item->start) { 1021 $row[$day + 1]['data'] .= theme('station_schedule_spacer', $last_finish, $item->start); 1022 } 1023 $last_finish = $item->finish; 1024 1025 // Display the schedule item. 1026 $program = node_load($item->program_nid); 1027 $row[$day + 1]['data'] .= theme('station_schedule_item', $item->start, $item->finish, $program); 1028 } 1029 // Display a block for any remaining time during the day. 1030 if ($last_finish < $day_finish) { 1031 $row[$day + 1]['data'] .= theme('station_schedule_spacer', $last_finish, $day_finish); 1032 } 1033 } 1034 1035 // Add a class to indicate what day it is. 1036 $today = station_today(); 1037 $header[$today + 1]['class'] = 'station-sch-now-day'; 1038 $row[$today + 1]['class'] = 'station-sch-now-day'; 1039 1040 return theme('table', $header, array($row), array('id' => 'station-sch')); 1041 } 1042 1043 /** 1044 * Write an M3U file to the files/station directory for each of the node's 1045 * webstrem links. 1046 * 1047 * @param $node A station_schedule node. 1048 */ 1049 function station_schedule_write_m3u($node) { 1050 // Create the files/station subdirectory. 1051 $station_path = file_create_path('station'); 1052 file_check_directory($station_path, FILE_CREATE_DIRECTORY); 1053 1054 // Remove any old streams files for this node. 1055 file_scan_directory($station_path, $node->nid .'-.*\.m3u', array('.', '..', 'CVS'), 'file_delete', FALSE); 1056 1057 // Write out new files. 1058 foreach ($node->settings['streams'] as $key => $stream) { 1059 $content = implode("\n", $stream['urls']); 1060 file_save_data($content, "{$station_path}/{$node->nid}-{$key}.m3u", FILE_EXISTS_REPLACE); 1061 } 1062 } 1063 1064 /** 1065 * Implementation of hook_file_download(). 1066 */ 1067 function station_schedule_file_download($filepath) { 1068 if (preg_match('|^station/.*\.m3u$|', $filepath)) { 1069 return array('Content-type: audio/x-mpegurl'); 1070 } 1071 return NULL; 1072 } 1073 1074 1075 1076 1077 function expand_station_schedule_daytime_range($element) { 1078 if (is_array($element['#value'])) { 1079 $value = $element['#value']; 1080 } 1081 $element['start'] = array( 1082 '#type' => 'station_schedule_daytime', 1083 '#title' => t('Starts'), 1084 '#increment' => $element['#increment'], 1085 '#roll_midnight_back' => FALSE, 1086 '#default_value' => $value['start'], 1087 ); 1088 $element['finish'] = array( 1089 '#type' => 'station_schedule_daytime', 1090 '#title' => t('Ends'), 1091 '#increment' => $element['#increment'], 1092 '#roll_midnight_back' => TRUE, 1093 '#default_value' => $value['finish'], 1094 ); 1095 $element['#tree'] = TRUE; 1096 $element['#element_validate'] = array('station_schedule_daytime_range_validate'); 1097 1098 return $element; 1099 } 1100 1101 function form_type_station_schedule_daytime_range_value(&$form) { 1102 if (isset($form['#default_value'])) { 1103 $form['#value'] = $form['#default_value']; 1104 } 1105 else { 1106 $form['#value'] = array('start' => 0, 'finish' => 0); 1107 } 1108 } 1109 1110 function station_schedule_daytime_range_validate($form, &$form_state) { 1111 $start = ($form['start']['#value']['day'] * MINUTES_IN_DAY) + $form['start']['#value']['minute']; 1112 $finish = ($form['finish']['#value']['day'] * MINUTES_IN_DAY) + $form['finish']['#value']['minute']; 1113 1114 form_set_value($form, array('start' => $start, 'finish' => $finish), $form_state); 1115 1116 if ($start >= $finish) { 1117 form_error($form['finish'], t("The end time must be after the start time.")); 1118 } 1119 return $form; 1120 } 1121 1122 1123 1124 1125 function theme_station_schedule_daytime_range($element) { 1126 return theme('form_element', $element, $element['#children'] ); 1127 } 1128 1129 function expand_station_schedule_daytime($element, $edit, &$form_state) { 1130 $value = array('day' => 0, 'minute' => 0); 1131 if (!empty($element['#value'])) { 1132 if (is_array($element['#value'])) { 1133 $value = $element['#value']; 1134 } 1135 else { 1136 $value = array( 1137 'day' => station_day_from_minute($element['#value']), 1138 'minute' => $element['#value'] % MINUTES_IN_DAY, 1139 ); 1140 } 1141 } 1142 1143 // Make sure a range that ends on midnight of one day gets pushed back 1144 // to the previous day. 1145 if ($element['#roll_midnight_back'] && $value['minute'] == 0) { 1146 $value['day']--; 1147 $value['minute'] = MINUTES_IN_DAY; 1148 } 1149 1150 // Make sure the increment will advance the counter. 1151 $increment = $element['#increment']; 1152 if (empty($increment) || $increment < 1) { 1153 $increment = 1; 1154 } 1155 1156 $minute_options = array(); 1157 for ($minute = 0; $minute <= 24 * 60; $minute += $increment) { 1158 $time = station_time_from_minute($minute); 1159 $minute_options[$minute] = $time['time'] . $time['a']; 1160 } 1161 $element['#tree'] = TRUE; 1162 $element['#element_validate'] = array('station_schedule_daytime_validate'); 1163 $element['day'] = array( 1164 '#type' => 'select', 1165 '#default_value' => $value['day'], 1166 '#options' => station_day_name(), 1167 ); 1168 $element['minute'] = array( 1169 '#type' => 'select', 1170 '#default_value' => $value['minute'], 1171 '#options' => $minute_options, 1172 ); 1173 1174 return $element; 1175 } 1176 1177 function form_type_station_schedule_daytime_value($form, $edit = FALSE) { 1178 if ($edit === FALSE) { 1179 $form += array('#default_value' => 0); 1180 return array( 1181 'day' => station_day_from_minute($form['#default_value']), 1182 'minute' => $form['#default_value'] % MINUTES_IN_DAY, 1183 ); 1184 } 1185 } 1186 1187 /** 1188 * Validate the station_schedule_daytime element and store the value back into 1189 * the root element. 1190 */ 1191 function station_schedule_daytime_validate($form, &$form_state) { 1192 $time = ($form['#value']['day'] * MINUTES_IN_DAY) + $form['#value']['minute']; 1193 // Since we don't want an array back we need to null out the children and 1194 // store the computed value. 1195 form_set_value($form['day'], NULL, $form_state); 1196 form_set_value($form['minute'], NULL, $form_state); 1197 form_set_value($form, $time, $form_state); 1198 1199 return $form; 1200 } 1201 1202 function theme_station_schedule_daytime($element) { 1203 return theme('form_element', $element, '<div class="container-inline">'. $element['#children'] .'</div>'); 1204 } 1205 1206 1207 /** 1208 * Implementation of hook_content_extra_fields(). 1209 * 1210 * Let CCK know about the playlist stuff we're putting on nodes. 1211 */ 1212 function station_schedule_content_extra_fields($type_name) { 1213 switch ($type_name) { 1214 case 'station_program': 1215 return array( 1216 'schedule' => array( 1217 'label' => t('Schedule'), 1218 'description' => t('Station Program module form.'), 1219 'weight' => -4, 1220 ), 1221 ); 1222 } 1223 } 1224 1225 /** 1226 * Implementation of hook_view_api(). 1227 */ 1228 function station_schedule_views_api() { 1229 return array( 1230 'api' => 2.0, 1231 'path' => drupal_get_path('module', 'station_schedule') . '/views', 1232 ); 1233 }
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 |