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