[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/date/date_repeat/ -> date_repeat_form.inc (source)

   1  <?php
   2  // $Id: date_repeat_form.inc,v 1.15.4.19 2010/10/30 10:42:51 karens Exp $
   3  /**
   4   * @file
   5   * Code to add a date repeat selection form to a date field and create
   6   * an iCal RRULE from the chosen selections.
   7   *
   8   * Moved to a separate file since it is not used on most pages
   9   * so the code is not parsed unless needed.
  10   *
  11   * Currently implemented:
  12   * INTERVAL, UNTIL, EXDATE, RDATE, BYDAY, BYMONTHDAY, BYMONTH,
  13   * YEARLY, MONTHLY, WEEKLY, DAILY
  14   *
  15   * Currently not implemented:
  16   *
  17   * BYYEARDAY, MINUTELY, HOURLY, SECONDLY, BYMINUTE, BYHOUR, BYSECOND
  18   *   These could be implemented in the future.
  19   *
  20   * COUNT
  21   *   The goal of this module is to create a way we can parse an iCal
  22   *   RRULE and pull out just dates for a specified date range, for
  23   *   instance with a date that repeats daily for several years, we might
  24   *   want to only be able to pull out the dates for the current year.
  25   *
  26   *   Adding COUNT to the rules we create makes it impossible to do that
  27   *   without parsing and computing the whole range of dates that the rule
  28   *   will create. COUNT is left off of the user form completely for this
  29   *   reason.
  30   *
  31   * BYSETPOS
  32   *   Seldom used anywhere, so no reason to complicated the code.
  33   */
  34  /**
  35   * Generate the repeat setting form.
  36   */
  37  function _date_repeat_rrule_process($element, $edit, $form_state, $form) {
  38    require_once('./'. drupal_get_path('module', 'date_api') .'/date_api_ical.inc');
  39    
  40    if (empty($element['#date_repeat_widget'])) {
  41      $element['#date_repeat_widget'] = module_exists('date_popup') ? 'date_popup' : 'date_select';
  42    }
  43    if (is_array($element['#value'])) {
  44      $element['#value'] = date_repeat_merge($element['#value'], $element);
  45      $rrule = date_api_ical_build_rrule($element['#value']);
  46    }
  47    else {
  48      $rrule = $element['#value'];
  49    }
  50    // Empty the original string value of the RRULE so we can create
  51    // an array of values for the form from the RRULE's contents.
  52    $element['#value'] = '';
  53  
  54    $parts = date_repeat_split_rrule($rrule);
  55    $rrule = $parts[0];
  56    $exceptions = $parts[1];
  57    $additions = $parts[2];
  58    
  59    $timezone = !empty($element['#date_timezone']) ? $element['#date_timezone'] : date_default_timezone_name();
  60    $merged_values = date_repeat_merge($rrule, $element);
  61    
  62    $UNTIL = '';
  63    if (!empty($merged_values['UNTIL']['datetime'])) {
  64      $until_date = date_make_date($merged_values['UNTIL']['datetime'], $merged_values['UNTIL']['tz']);
  65      date_timezone_set($until_date, timezone_open($timezone));
  66      $UNTIL = date_format($until_date, DATE_FORMAT_DATETIME);
  67    }
  68    $parent_collapsed = !empty($rrule['INTERVAL']) || !empty($rrule['FREQ']) ? 0 : (!empty($element['#date_repeat_collapsed']) ? $element['#date_repeat_collapsed'] : 0);
  69    $element['#type'] = 'fieldset';
  70    $element['#title'] = t('Repeat');
  71    $element['#description'] = theme('advanced_help_topic', 'date_api', 'date-repeat-form') . t('Choose a frequency and period to repeat this date. If nothing is selected, the date will not repeat.');
  72    $element['#collapsible'] = TRUE;
  73    $element['#collapsed'] = $parent_collapsed;
  74    
  75    // Make sure we don't get floating parts where we don't want them.
  76    $element['#prefix'] = '<div class="date-clear">';
  77    $element['#suffix'] = '</div>';
  78    
  79    $element['INTERVAL'] = array(
  80      '#type' => 'select',
  81      //'#title' => t('Interval'),
  82      '#default_value' => (!empty($rrule['INTERVAL']) ? $rrule['INTERVAL'] : 0),
  83      '#options' => INTERVAL_options(),
  84      '#prefix' => '<div class="date-repeat-input">',
  85      '#suffix' => '</div>',
  86    );
  87  
  88    $element['FREQ'] = array(
  89      '#type' => 'select',
  90      //'#title' => t('Frequency'),
  91      '#default_value' => !empty($rrule['FREQ']) ? $rrule['FREQ'] : 'NONE',
  92      '#options' => FREQ_options(),
  93      '#prefix' => '<div class="date-repeat-input">',
  94      '#suffix' => '</div>',
  95    );
  96  
  97    $element['UNTIL'] = array(
  98      '#tree' => TRUE,
  99      '#prefix' => '<div class="date-clear">',
 100      '#suffix' => '</div>',
 101      'datetime' => array(
 102        '#type' => $element['#date_repeat_widget'],
 103        '#title' => t('Until'),
 104        '#description' => t('Date to stop repeating this item.'),
 105        '#default_value' => $UNTIL,
 106        '#date_timezone' => $timezone,
 107        '#date_format' => !empty($element['#date_format']) ? date_limit_format($element['#date_format'], array('year', 'month', 'day')) : 'Y-m-d',
 108        '#date_text_parts'  => !empty($element['#date_text_parts']) ? $element['#date_text_parts'] : array(),
 109        '#date_year_range'  => !empty($element['#date_year_range']) ? $element['#date_year_range'] : '-3:+3',
 110        '#date_label_position' => !empty($element['#date_label_position']) ? $element['#date_label_position'] : 'within',
 111        ),
 112      'tz' => array('#type' => 'hidden', '#value' => $element['#date_timezone']),
 113      'all_day' => array('#type' => 'hidden', '#value' => 1),
 114      'granularity' => array('#type' => 'hidden', '#value' => serialize(array('year', 'month', 'day'))),
 115      );
 116    
 117    $collapsed = TRUE;
 118    if (!empty($merged_values['BYDAY']) || !empty($merged_values['BYMONTH'])) {
 119      $collapsed = FALSE;
 120    }
 121      // start the advanced fieldset
 122    $element['advanced'] = array(
 123      '#type' => 'fieldset',
 124      '#title' => t('Advanced'),
 125      '#collapsible' => TRUE,
 126      '#collapsed' => $collapsed,
 127      '#description' => t("If no advanced options are selected, the date will repeat on the day of week of the start date for weekly repeats, otherwise on the month and day of the start date. Use the options below to override that behavior to select specific months and days to repeat on. Use the 'Except' box to input dates that should be omitted from the results.") .' ',
 128      '#prefix' => '<div class="date-clear">',
 129      '#suffix' => '</div>',
 130      );
 131  
 132    $element['advanced']['BYMONTH'] = array(
 133      '#type' => 'select',
 134      '#title' => date_t('Month', 'datetime'),
 135      '#default_value' => !empty($rrule['BYMONTH']) ? $rrule['BYMONTH'] : '',
 136      '#options' => array('' => t('-- Any')) + date_month_names(TRUE),
 137      '#multiple' => TRUE,
 138      '#size' => 10,
 139      '#prefix' => '<div class="date-repeat-input">',
 140      '#suffix' => '</div>',
 141    );
 142  
 143    $element['advanced']['BYMONTHDAY'] = array(
 144      '#type' => 'select',
 145      '#title' => t('Day of Month'),
 146      '#default_value' => !empty($rrule['BYMONTHDAY']) ? $rrule['BYMONTHDAY'] : '',
 147      '#options' => array('' => t('-- Any')) + drupal_map_assoc(range(1, 31)) + drupal_map_assoc(range(-1, -31)),
 148      '#multiple' => TRUE,
 149      '#size' => 10,
 150      '#prefix' => '<div class="date-repeat-input">',
 151      '#suffix' => '</div>',
 152    );
 153  
 154    $element['advanced']['BYDAY'] = array(
 155      '#type' => 'select',
 156      '#title' => t('Day of Week'),
 157      '#default_value' => !empty($rrule['BYDAY']) ? $rrule['BYDAY'] : '',
 158      '#options' => array('' => t('-- Any')) + date_repeat_dow_options(),
 159      //'#attributes' => array('size' => '5'),
 160      '#multiple' => TRUE,
 161      '#size' => 10,
 162      '#prefix' => '<div class="date-repeat-input">',
 163      '#suffix' => '</div>',
 164    );
 165  
 166    $element['exceptions'] = array(
 167      '#type' => 'fieldset',
 168      '#collapsible' => TRUE,
 169      '#collapsed' => empty($exceptions) ? TRUE : FALSE,
 170      '#title' => t('Except'),
 171      '#description' => t('Dates to omit from the list of repeating dates.'),
 172      '#prefix' => '<div id="date-repeat-exceptions" class="date-repeat">',
 173      '#suffix' => '</div>',
 174      );
 175    $max = !empty($exceptions) ? sizeof($exceptions) : 0;
 176    for ($i = 0; $i <= $max; $i++) {
 177      $EXCEPT = '';
 178      if (!empty($exceptions[$i]['datetime'])) {
 179        $EXCEPT = $exceptions[$i]['datetime'];
 180      }
 181      $element['exceptions']['EXDATE'][$i] = array(
 182        '#tree' => TRUE,
 183        'datetime' => array(
 184          '#type' => $element['#date_repeat_widget'],
 185          '#default_value' => $EXCEPT,
 186          '#date_timezone' => !empty($element['#date_timezone']) ? $element['#date_timezone'] : date_default_timezone_name(),
 187          '#date_format' => !empty($element['#date_format']) ? date_limit_format($element['#date_format'], array('year', 'month', 'day')) : 'Y-m-d',
 188          '#date_text_parts'  => !empty($element['#date_text_parts']) ? $element['#date_text_parts'] : array(),
 189          '#date_year_range'  => !empty($element['#date_year_range']) ? $element['#date_year_range'] : '-3:+3',
 190          '#date_label_position' => !empty($element['#date_label_position']) ? $element['#date_label_position'] : 'within',
 191          ),
 192        'tz' => array('#type' => 'hidden', '#value' => $element['#date_timezone']),
 193        'all_day' => array('#type' => 'hidden', '#value' => 1),
 194        'granularity' => array('#type' => 'hidden', '#value' => serialize(array('year', 'month', 'day'))),
 195        );
 196    }
 197    
 198    // collect additions in the same way as exceptions - implements RDATE.
 199    $element['additions'] = array(
 200      '#type' => 'fieldset',
 201      '#collapsible' => TRUE,
 202      '#collapsed' => empty($additions) ? TRUE : FALSE,
 203      '#title' => t('Additional'),
 204      '#description' => t('Dates to add to the list of repeating dates.'),
 205      '#prefix' => '<div id="date-repeat-additions" class="date-repeat">',
 206      '#suffix' => '</div>',
 207      );
 208    $max = !empty($additions) ? sizeof($additions) : 0;
 209    for ($i = 0; $i <= $max; $i++) {
 210      $RDATE = '';
 211      if (!empty($additions[$i]['datetime'])) {
 212        $RDATE = $additions[$i]['datetime'];
 213      }
 214      $element['additions']['RDATE'][$i] = array(
 215        '#tree' => TRUE,
 216        'datetime' => array(
 217          '#type' => $element['#date_repeat_widget'],
 218          '#default_value' => $RDATE,
 219          '#date_timezone' => !empty($element['#date_timezone']) ? $element['#date_timezone'] : date_default_timezone_name(),
 220          '#date_format' => !empty($element['#date_format']) ? date_limit_format($element['#date_format'], array('year', 'month', 'day')) : 'Y-m-d',
 221          '#date_text_parts'  => !empty($element['#date_text_parts']) ? $element['#date_text_parts'] : array(),
 222          '#date_year_range'  => !empty($element['#date_year_range']) ? $element['#date_year_range'] : '-3:+3',
 223          '#date_label_position' => !empty($element['#date_label_position']) ? $element['#date_label_position'] : 'within',
 224          ),
 225        'tz' => array('#type' => 'hidden', '#value' => $element['#date_timezone']),
 226        'all_day' => array('#type' => 'hidden', '#value' => 1),
 227        'granularity' => array('#type' => 'hidden', '#value' => serialize(array('year', 'month', 'day'))),
 228        );
 229    }
 230  
 231    // Create an "Add another" button for the exceptions.
 232    $field_name = $element['#parents'][0];
 233    $element['exceptions']['exceptions_addmore'] = array(
 234      '#type' => 'button',
 235      '#value' => t('Add more exceptions'),
 236      '#ahah' => array(
 237        'event' => 'click',
 238        'path' => 'date_repeat_get_exception_form_ajax/exceptions/' . $field_name,
 239        'wrapper' => 'date-repeat-exceptions',
 240        'method' => 'replace',
 241        'effect' => 'fade'
 242      )
 243    );
 244    // Create an "Add another" button for the additions.
 245    $field_name = $element['#parents'][0];
 246    $element['additions']['additions_addmore'] = array(
 247      '#type' => 'button',
 248      '#value' => t('Add more additions'),
 249      '#ahah' => array(
 250        'event' => 'click',
 251        'path' => 'date_repeat_get_exception_form_ajax/additions/' . $field_name,
 252        'wrapper' => 'date-repeat-additions',
 253        'method' => 'replace',
 254        'effect' => 'fade'
 255      )
 256    );
 257    
 258    return $element;
 259  }
 260  
 261  /**
 262   * Ajax callback to get the exceptions form.  This is needed to
 263   * implement the "Add another" button for the date repeat exceptions.
 264   * 
 265   * @param $type - 'exceptions' or 'additions'.
 266   * @param $field_name - The name of the date field.
 267   */
 268  function date_repeat_get_exception_form_ajax($type, $field_name) {
 269    // Get the cached form.  
 270    $form_state = array('storage' => NULL, 'submitted' => FALSE);
 271    if( !($form = form_get_cache($_POST['form_build_id'], $form_state)) ) {
 272      drupal_json(array('status' => FALSE, 'data' => ''));
 273      exit();
 274    }
 275  
 276    // Set the form state values.
 277    $form_state = array_merge($form_state, array('values' => $_POST));
 278  
 279    // Set the new form rrule value.
 280    $form[$field_name]['rrule']['#value'] = $form_state['values'][$field_name]['rrule'];
 281  
 282    // Cache the new form state.
 283    form_set_cache($_POST['form_build_id'], $form, $form_state);
 284  
 285    // Rebuild the form.
 286    $form_state = array();
 287    $form['#post'] = array();
 288    $form = form_builder($form['form_id']['#value'] , $form, $form_state);
 289  
 290    // Force a rebuild of the Drupal.settings javascript object.
 291    //   - Borrowed from content.node_form.inc, content_add_more_js function
 292    $javascript = drupal_add_js(NULL, NULL);
 293    $output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>' : '';
 294  
 295    // Create our output.
 296    $output = drupal_render($form[$field_name]['rrule'][$type]) . $output_js;
 297  
 298    // Set the new exceptions form.
 299    drupal_json(array('status' => TRUE, 'data' => $output));
 300    exit();
 301  }
 302  
 303  /**
 304   * Regroup values back into a consistant array, no matter what state it is in.
 305   */
 306  function date_repeat_merge($form_values, $element) {
 307    if (empty($form_values) || !is_array($form_values)) {
 308      return $form_values;
 309    }
 310    if (array_key_exists('advanced', $form_values) || array_key_exists('exceptions', $form_values) || array_key_exists('additions', $form_values)) {
 311      if (!array_key_exists('advanced', $form_values)) $form_values['advanced'] = array();
 312      if (!array_key_exists('exceptions', $form_values)) $form_values['exceptions'] = array();
 313      if (!array_key_exists('additions', $form_values)) $form_values['additions'] = array();
 314      $form_values = array_merge($form_values, (array) $form_values['advanced'], (array) $form_values['exceptions'], (array) $form_values['additions']);
 315      unset($form_values['advanced']);
 316      unset($form_values['exceptions']);
 317      unset($form_values['additions']);
 318    }
 319    if (array_key_exists('BYDAY', $form_values)) unset($form_values['BYDAY']['']);
 320    if (array_key_exists('BYMONTH', $form_values)) unset($form_values['BYMONTH']['']);
 321    if (array_key_exists('BYMONTHDAY', $form_values)) unset($form_values['BYMONTHDAY']['']);
 322        
 323    if (array_key_exists('UNTIL', $form_values) && is_array($form_values['UNTIL']['datetime'])) {
 324      $function = $element['#date_repeat_widget'] .'_input_value';
 325      $until_element = $element;
 326      $until_element['#value'] = $form_values['UNTIL']['datetime'];
 327      $until_element['#date_format'] = date_limit_format($element['#date_format'], array('year', 'month', 'day'));
 328      $form_values['UNTIL']['datetime'] = $function($until_element);
 329    }
 330    if (array_key_exists('EXDATE', $form_values) && is_array($form_values['EXDATE'])) {
 331      $function = $element['#date_repeat_widget'] .'_input_value';
 332      $exdate_element = $element;
 333      foreach ($form_values['EXDATE'] as $delta => $value) {
 334        if (is_array($value['datetime'])) {
 335          $exdate_element['#value'] = $form_values['EXDATE'][$delta]['datetime'];
 336          $exdate_element['#date_format'] = date_limit_format($element['#date_format'], array('year', 'month', 'day'));
 337          $form_values['EXDATE'][$delta]['datetime'] = $function($exdate_element);
 338        }
 339      }
 340    }
 341    if (array_key_exists('RDATE', $form_values) && is_array($form_values['RDATE'])) {
 342      $function = $element['#date_repeat_widget'] .'_input_value';
 343      $rdate_element = $element;
 344      foreach ($form_values['RDATE'] as $delta => $value) {
 345        if (is_array($value['datetime'])) {
 346          $rdate_element['#value'] = $form_values['RDATE'][$delta]['datetime'];
 347          $rdate_element['#date_format'] = date_limit_format($element['#date_format'], array('year', 'month', 'day'));
 348          $form_values['RDATE'][$delta]['datetime'] = $function($rdate_element);
 349        }
 350      }
 351    }
 352    return $form_values;
 353  }
 354  
 355  /**
 356   * Build a RRULE out of the form values.
 357   */
 358  function date_repeat_rrule_validate($element, &$form_state) {
 359    require_once('./'. drupal_get_path('module', 'date_api') .'/date_api_ical.inc');
 360    $form_values = $form_state['values'];
 361    $field_name = $element['#parents'][0];
 362    $item = $form_values[$field_name]['rrule'];
 363    $item = date_repeat_merge($item, $element);
 364    if (!empty($item['UNTIL']['datetime'])) {
 365      $date = date_make_date($item['UNTIL']['datetime'], $element['#date_timezone']);
 366      date_time_set($date, 23, 59, 59);
 367      date_timezone_set($date, timezone_open('UTC'));
 368      $item['UNTIL']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
 369    }
 370    $rrule = date_api_ical_build_rrule($item);
 371    form_set_value($element, $rrule, $form_state);
 372  }
 373  
 374  /**
 375   * Theme the exception list as a table so the buttons line up
 376   */
 377  function theme_date_repeat_current_exceptions($rows = array()) {
 378    $rows_info = array();
 379    foreach ($rows as $key => $value) {
 380      if (substr($key, 0, 1) != '#') {
 381        $rows_info[] = array(drupal_render($value['action']), drupal_render($value['display']));
 382      }
 383    }
 384    return theme('table', array(t('Delete'), t('Current exceptions')), $rows_info);
 385  }
 386  
 387  /**
 388   * Theme the exception list as a table so the buttons line up
 389   */
 390  function theme_date_repeat_current_additions($rows = array()) {
 391    $rows_info = array();
 392    foreach ($rows as $key => $value) {
 393      if (substr($key, 0, 1) != '#') {
 394        $rows_info[] = array(drupal_render($value['action']), drupal_render($value['display']));
 395      }
 396    }
 397    return theme('table', array(t('Delete'), t('Current additions')), $rows_info);
 398  }
 399  
 400  /**
 401   * Themes the date repeat element.
 402   */
 403  function theme_date_repeat($element) {
 404    return theme('form_element', $element, '<div class="container-inline">'. drupal_render($element). '</div>');
 405  }


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