| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
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 }
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 |