[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/station/schedule/ -> station_schedule.module (source)

   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  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7