Révision 599a39cd
Ajouté par Assos Assos il y a environ 3 ans
drupal7/sites/all/modules/date/date_api/date_api_ical.inc | ||
---|---|---|
10 | 10 |
/** |
11 | 11 |
* Return an array of iCalendar information from an iCalendar file. |
12 | 12 |
* |
13 |
* No timezone adjustment is performed in the import since the timezone
|
|
14 |
* conversion needed will vary depending on whether the value is being
|
|
15 |
* imported into the database (when it needs to be converted to UTC), is being
|
|
16 |
* viewed on a site that has user-configurable timezones (when it needs to be
|
|
17 |
* converted to the user's timezone), if it needs to be converted to the
|
|
18 |
* site timezone, or if it is a date without a timezone which should not have
|
|
19 |
* any timezone conversion applied.
|
|
13 |
* No timezone adjustment is performed in the import since the timezone |
|
14 |
* conversion needed will vary depending on whether the value is being |
|
15 |
* imported into the database (when it needs to be converted to UTC), is being |
|
16 |
* viewed on a site that has user-configurable timezones (when it needs to be |
|
17 |
* converted to the user's timezone), if it needs to be converted to the site
|
|
18 |
* timezone, or if it is a date without a timezone which should not have any
|
|
19 |
* timezone conversion applied. |
|
20 | 20 |
* |
21 |
* Properties that have dates and times are converted to sub-arrays like:
|
|
22 |
* 'datetime' => date in YYYY-MM-DD HH:MM format, not timezone adjusted
|
|
23 |
* 'all_day' => whether this is an all-day event
|
|
24 |
* 'tz' => the timezone of the date, could be blank for absolute
|
|
25 |
* times that should get no timezone conversion.
|
|
21 |
* Properties that have dates and times are converted to sub-arrays like: |
|
22 |
* 'datetime' => Date in YYYY-MM-DD HH:MM format, not timezone adjusted.
|
|
23 |
* 'all_day' => Whether this is an all-day event.
|
|
24 |
* 'tz' => The timezone of the date, could be blank for absolute times
|
|
25 |
* that should get no timezone conversion. |
|
26 | 26 |
* |
27 |
* Exception dates can have muliple values and are returned as arrays
|
|
28 |
* like the above for each exception date.
|
|
27 |
* Exception dates can have muliple values and are returned as arrayslike the
|
|
28 |
* above for each exception date. |
|
29 | 29 |
* |
30 |
* Most other properties are returned as PROPERTY => VALUE.
|
|
30 |
* Most other properties are returned as PROPERTY => VALUE. |
|
31 | 31 |
* |
32 |
* Each item in the VCALENDAR will return an array like: |
|
33 |
* [0] => Array ( |
|
34 |
* [TYPE] => VEVENT |
|
35 |
* [UID] => 104 |
|
36 |
* [SUMMARY] => An example event |
|
37 |
* [URL] => http://example.com/node/1 |
|
38 |
* [DTSTART] => Array ( |
|
39 |
* [datetime] => 1997-09-07 09:00:00 |
|
32 |
* Each item in the VCALENDAR will return an array like: |
|
33 |
* [0] => Array ( |
|
34 |
* [TYPE] => VEVENT |
|
35 |
* [UID] => 104 |
|
36 |
* [SUMMARY] => An example event |
|
37 |
* [URL] => http://example.com/node/1 |
|
38 |
* [DTSTART] => Array ( |
|
39 |
* [datetime] => 1997-09-07 09:00:00 |
|
40 |
* [all_day] => 0 |
|
41 |
* [tz] => US/Eastern |
|
42 |
* ) |
|
43 |
* [DTEND] => Array ( |
|
44 |
* [datetime] => 1997-09-07 11:00:00 |
|
45 |
* [all_day] => 0 |
|
46 |
* [tz] => US/Eastern |
|
47 |
* ) |
|
48 |
* [RRULE] => Array ( |
|
49 |
* [FREQ] => Array ( |
|
50 |
* [0] => MONTHLY |
|
51 |
* ) |
|
52 |
* [BYDAY] => Array ( |
|
53 |
* [0] => 1SU |
|
54 |
* [1] => -1SU |
|
55 |
* ) |
|
56 |
* ) |
|
57 |
* [EXDATE] => Array ( |
|
58 |
* [0] = Array ( |
|
59 |
* [datetime] => 1997-09-21 09:00:00 |
|
40 | 60 |
* [all_day] => 0 |
41 | 61 |
* [tz] => US/Eastern |
42 | 62 |
* ) |
43 |
* [DTEND] => Array (
|
|
44 |
* [datetime] => 1997-09-07 11:00:00
|
|
63 |
* [1] = Array (
|
|
64 |
* [datetime] => 1997-10-05 09:00:00
|
|
45 | 65 |
* [all_day] => 0 |
46 | 66 |
* [tz] => US/Eastern |
47 | 67 |
* ) |
48 |
* [RRULE] => Array ( |
|
49 |
* [FREQ] => Array ( |
|
50 |
* [0] => MONTHLY |
|
51 |
* ) |
|
52 |
* [BYDAY] => Array ( |
|
53 |
* [0] => 1SU |
|
54 |
* [1] => -1SU |
|
55 |
* ) |
|
56 |
* ) |
|
57 |
* [EXDATE] => Array ( |
|
58 |
* [0] = Array ( |
|
59 |
* [datetime] => 1997-09-21 09:00:00 |
|
60 |
* [all_day] => 0 |
|
61 |
* [tz] => US/Eastern |
|
62 |
* ) |
|
63 |
* [1] = Array ( |
|
64 |
* [datetime] => 1997-10-05 09:00:00 |
|
65 |
* [all_day] => 0 |
|
66 |
* [tz] => US/Eastern |
|
67 |
* ) |
|
68 |
* ) |
|
69 |
* [RDATE] => Array ( |
|
70 |
* [0] = Array ( |
|
71 |
* [datetime] => 1997-09-21 09:00:00 |
|
72 |
* [all_day] => 0 |
|
73 |
* [tz] => US/Eastern |
|
68 | 74 |
* ) |
69 |
* [RDATE] => Array ( |
|
70 |
* [0] = Array ( |
|
71 |
* [datetime] => 1997-09-21 09:00:00 |
|
72 |
* [all_day] => 0 |
|
73 |
* [tz] => US/Eastern |
|
74 |
* ) |
|
75 |
* [1] = Array ( |
|
76 |
* [datetime] => 1997-10-05 09:00:00 |
|
77 |
* [all_day] => 0 |
|
78 |
* [tz] => US/Eastern |
|
79 |
* ) |
|
75 |
* [1] = Array ( |
|
76 |
* [datetime] => 1997-10-05 09:00:00 |
|
77 |
* [all_day] => 0 |
|
78 |
* [tz] => US/Eastern |
|
80 | 79 |
* ) |
81 | 80 |
* ) |
81 |
* ) |
|
82 | 82 |
* |
83 | 83 |
* @todo |
84 | 84 |
* figure out how to handle this if subgroups are nested, |
... | ... | |
130 | 130 |
* @return array |
131 | 131 |
* An array with all the elements from the ical. |
132 | 132 |
*/ |
133 |
function date_ical_parse($icaldatafolded = array()) { |
|
133 |
function date_ical_parse(array $icaldatafolded = array()) {
|
|
134 | 134 |
$items = array(); |
135 | 135 |
|
136 | 136 |
// Verify this is iCal data. |
... | ... | |
249 | 249 |
|
250 | 250 |
array_pop($subgroups); |
251 | 251 |
array_pop($parents); |
252 |
break; |
|
253 | 252 |
} |
254 | 253 |
} |
255 | 254 |
} |
... | ... | |
325 | 324 |
// be given special treatment. |
326 | 325 |
default: |
327 | 326 |
$parse_result = $data; |
328 |
break; |
|
329 | 327 |
} |
330 | 328 |
|
331 | 329 |
// Store the result of our parsing. |
... | ... | |
339 | 337 |
* Parses a ical date element. |
340 | 338 |
* |
341 | 339 |
* Possible formats to parse include: |
342 |
* PROPERTY:YYYYMMDD[T][HH][MM][SS][Z]
|
|
343 |
* PROPERTY;VALUE=DATE:YYYYMMDD[T][HH][MM][SS][Z]
|
|
344 |
* PROPERTY;VALUE=DATE-TIME:YYYYMMDD[T][HH][MM][SS][Z]
|
|
345 |
* PROPERTY;TZID=XXXXXXXX;VALUE=DATE:YYYYMMDD[T][HH][MM][SS]
|
|
346 |
* PROPERTY;TZID=XXXXXXXX:YYYYMMDD[T][HH][MM][SS]
|
|
340 |
* - PROPERTY:YYYYMMDD[T][HH][MM][SS][Z]
|
|
341 |
* - PROPERTY;VALUE=DATE:YYYYMMDD[T][HH][MM][SS][Z]
|
|
342 |
* - PROPERTY;VALUE=DATE-TIME:YYYYMMDD[T][HH][MM][SS][Z]
|
|
343 |
* - PROPERTY;TZID=XXXXXXXX;VALUE=DATE:YYYYMMDD[T][HH][MM][SS]
|
|
344 |
* - PROPERTY;TZID=XXXXXXXX:YYYYMMDD[T][HH][MM][SS]
|
|
347 | 345 |
* |
348 |
* The property and the colon before the date are removed in the import
|
|
349 |
* process above and we are left with $field and $data.
|
|
346 |
* The property and the colon before the date are removed in the import |
|
347 |
* process above and we are left with $field and $data. |
|
350 | 348 |
* |
351 | 349 |
* @param string $field |
352 | 350 |
* The text before the colon and the date, i.e. |
... | ... | |
356 | 354 |
* 'Z', if supplied, means the date is in UTC. |
357 | 355 |
* |
358 | 356 |
* @return array |
359 |
* $items array, consisting of: |
|
360 |
* 'datetime' => date in YYYY-MM-DD HH:MM format, not timezone adjusted |
|
361 |
* 'all_day' => whether this is an all-day event with no time |
|
362 |
* 'tz' => the timezone of the date, could be blank if the ical |
|
363 |
* has no timezone; the ical specs say no timezone |
|
364 |
* conversion should be done if no timezone info is |
|
365 |
* supplied |
|
366 |
* @todo |
|
367 |
* Another option for dates is the format PROPERTY;VALUE=PERIOD:XXXX. The |
|
357 |
* Consisting of: |
|
358 |
* 'datetime' => Date in YYYY-MM-DD HH:MM format, not timezone adjusted. |
|
359 |
* 'all_day' => Whether this is an all-day event with no time. |
|
360 |
* 'tz' => The timezone of the date, could be blank if the iCal has no |
|
361 |
* timezone; the ical specs say no timezone conversion should be |
|
362 |
* done if no timezone info is supplied. |
|
363 |
* |
|
364 |
* @todo Another option for dates is the format PROPERTY;VALUE=PERIOD:XXXX. The |
|
368 | 365 |
* period may include a duration, or a date and a duration, or two dates, so |
369 | 366 |
* would have to be split into parts and run through date_ical_parse_date() |
370 | 367 |
* and date_ical_parse_duration(). This is not commonly used, so ignored for |
371 | 368 |
* now. It will take more work to figure how to support that. |
372 | 369 |
*/ |
373 | 370 |
function date_ical_parse_date($field, $data) { |
374 |
|
|
375 | 371 |
$items = array('datetime' => '', 'all_day' => '', 'tz' => ''); |
376 | 372 |
if (empty($data)) { |
377 | 373 |
return $items; |
... | ... | |
415 | 411 |
break; |
416 | 412 |
} |
417 | 413 |
} |
414 |
|
|
418 | 415 |
// If no format is specified, attempt a loose match. |
419 | 416 |
else { |
420 | 417 |
preg_match(DATE_REGEX_LOOSE, $data, $regs); |
... | ... | |
462 | 459 |
* Parse an ical repeat rule. |
463 | 460 |
* |
464 | 461 |
* @return array |
465 |
* Array in the form of PROPERTY => array(VALUES) |
|
466 |
* PROPERTIES include FREQ, INTERVAL, COUNT, BYDAY, BYMONTH, BYYEAR, UNTIL |
|
462 |
* A nested array in the form of 'PROPERTY' => array(VALUES) where |
|
463 |
* 'PROPERTIES' includes 'FREQ', 'INTERVAL', 'COUNT', 'BYDAY', 'BYMONTH', |
|
464 |
* 'BYYEAR', 'UNTIL'. |
|
467 | 465 |
*/ |
468 | 466 |
function date_ical_parse_rrule($field, $data) { |
469 | 467 |
$data = preg_replace("/RRULE.*:/", '', $data); |
... | ... | |
496 | 494 |
* Parse exception dates (can be multiple values). |
497 | 495 |
* |
498 | 496 |
* @return array |
499 |
* an array of date value arrays.
|
|
497 |
* An array of date value arrays.
|
|
500 | 498 |
*/ |
501 | 499 |
function date_ical_parse_exceptions($field, $data) { |
502 | 500 |
$data = str_replace($field . ':', '', $data); |
... | ... | |
512 | 510 |
* Parses the duration of the event. |
513 | 511 |
* |
514 | 512 |
* Example: |
515 |
* DURATION:PT1H30M
|
|
516 |
* DURATION:P1Y2M
|
|
513 |
* DURATION:PT1H30M |
|
514 |
* DURATION:P1Y2M.
|
|
517 | 515 |
* |
518 | 516 |
* @param array $subgroup |
519 | 517 |
* Array of other values in the vevent so we can check for DTSTART. |
518 |
* @param string $value_name |
|
519 |
* The name of the value to process; defaults to 'DURATION'. |
|
520 | 520 |
*/ |
521 |
function date_ical_parse_duration(&$subgroup, $field = 'DURATION') {
|
|
522 |
$items = $subgroup[$field];
|
|
523 |
$data = $items['DATA'];
|
|
521 |
function date_ical_parse_duration(array &$subgroup, $value_name = 'DURATION') {
|
|
522 |
$items = $subgroup[$value_name];
|
|
523 |
$data = $items['DATA']; |
|
524 | 524 |
preg_match('/^P(\d{1,4}[Y])?(\d{1,2}[M])?(\d{1,2}[W])?(\d{1,2}[D])?([T]{0,1})?(\d{1,2}[H])?(\d{1,2}[M])?(\d{1,2}[S])?/', $data, $duration); |
525 | 525 |
$items['year'] = isset($duration[1]) ? str_replace('Y', '', $duration[1]) : ''; |
526 | 526 |
$items['month'] = isset($duration[2]) ? str_replace('M', '', $duration[2]) : ''; |
... | ... | |
535 | 535 |
$timezone = 'UTC'; |
536 | 536 |
} |
537 | 537 |
$date = new DateObject($start_date, $timezone); |
538 |
$date2 = clone($date);
|
|
538 |
$date2 = clone $date;
|
|
539 | 539 |
foreach ($items as $item => $count) { |
540 | 540 |
if ($count > 0) { |
541 | 541 |
date_modify($date2, '+' . $count . ' ' . $item); |
... | ... | |
573 | 573 |
* Catch situations like the upcoming.org feed that uses |
574 | 574 |
* LOCATION;VENUE-UID="http://upcoming.yahoo.com/venue/104/":111 First Street... |
575 | 575 |
* or more normal LOCATION;UID=123:111 First Street... |
576 |
* Upcoming feed would have been improperly broken on the ':' in http:// |
|
577 |
* so we paste the $field and $data back together first.
|
|
576 |
* Upcoming feed would have been improperly broken on the ':' in http:// so we
|
|
577 |
* paste the $field and $data back together first. |
|
578 | 578 |
* |
579 | 579 |
* Use non-greedy check for ':' in case there are more of them in the address. |
580 | 580 |
*/ |
... | ... | |
603 | 603 |
* @return object |
604 | 604 |
* A timezone-adjusted date object. |
605 | 605 |
*/ |
606 |
function date_ical_date($ical_date, $to_tz = FALSE) { |
|
607 |
|
|
606 |
function date_ical_date(array $ical_date, $to_tz = FALSE) { |
|
608 | 607 |
// If the ical date has no timezone, must assume it is stateless |
609 | 608 |
// so treat it as a local date. |
610 | 609 |
if (empty($ical_date['datetime'])) { |
... | ... | |
621 | 620 |
} |
622 | 621 |
$date = new DateObject($ical_date['datetime'], new DateTimeZone($from_tz)); |
623 | 622 |
|
624 |
if ($to_tz && $ical_date['tz'] != '' && $to_tz != $ical_date['tz']) {
|
|
623 |
if ($to_tz && !empty($ical_date['tz']) && $to_tz != $ical_date['tz']) {
|
|
625 | 624 |
date_timezone_set($date, timezone_open($to_tz)); |
626 | 625 |
} |
627 | 626 |
return $date; |
... | ... | |
631 | 630 |
* Escape #text elements for safe iCal use. |
632 | 631 |
* |
633 | 632 |
* @param string $text |
634 |
* Text to escape |
|
633 |
* Text to escape.
|
|
635 | 634 |
* |
636 | 635 |
* @return string |
637 | 636 |
* Escaped text |
... | ... | |
639 | 638 |
function date_ical_escape_text($text) { |
640 | 639 |
$text = drupal_html_to_text($text); |
641 | 640 |
$text = trim($text); |
642 |
// TODO Per #38130 the iCal specs don't want : and " escaped
|
|
643 |
// but there was some reason for adding this in. Need to watch
|
|
644 |
// this and see if anything breaks.
|
|
641 |
// @todo Per #38130 the iCal specs don't want : and " escaped but there was
|
|
642 |
// some reason for adding this in. Need to watch this and see if anything
|
|
643 |
// breaks. |
|
645 | 644 |
// $text = str_replace('"', '\"', $text); |
646 | 645 |
// $text = str_replace(":", "\:", $text); |
647 | 646 |
$text = preg_replace("/\\\b/", "\\\\", $text); |
... | ... | |
695 | 694 |
* ) |
696 | 695 |
* ) |
697 | 696 |
*/ |
698 |
function date_api_ical_build_rrule($form_values) { |
|
697 |
function date_api_ical_build_rrule(array $form_values) {
|
|
699 | 698 |
$rrule = ''; |
700 | 699 |
if (empty($form_values) || !is_array($form_values)) { |
701 | 700 |
return $rrule; |
... | ... | |
725 | 724 |
if (array_key_exists('BYMONTHDAY', $form_values) && is_array($form_values['BYMONTHDAY']) && $bymonthday = implode(",", $form_values['BYMONTHDAY'])) { |
726 | 725 |
$rrule .= ';BYMONTHDAY=' . $bymonthday; |
727 | 726 |
} |
728 |
// The UNTIL date is supposed to always be expressed in UTC. |
|
729 |
// The input date values may already have been converted to a date object on a
|
|
730 |
// previous pass, so check for that.
|
|
727 |
// The UNTIL date is supposed to always be expressed in UTC. The input date
|
|
728 |
// values may already have been converted to a date object on a previous
|
|
729 |
// pass, so check for that. |
|
731 | 730 |
if (array_key_exists('UNTIL', $form_values) && array_key_exists('datetime', $form_values['UNTIL']) && !empty($form_values['UNTIL']['datetime'])) { |
732 | 731 |
// We only collect a date for UNTIL, but we need it to be inclusive, so |
733 | 732 |
// force it to a full datetime element at the last second of the day. |
... | ... | |
754 | 753 |
} |
755 | 754 |
$rrule .= ';UNTIL=' . date_format($until, DATE_FORMAT_ICAL) . 'Z'; |
756 | 755 |
} |
757 |
// Our form doesn't allow a value for COUNT, but it may be needed by |
|
758 |
// modules using the API, so add it to the rule.
|
|
756 |
// Our form doesn't allow a value for COUNT, but it may be needed by modules
|
|
757 |
// using the API, so add it to the rule. |
|
759 | 758 |
if (array_key_exists('COUNT', $form_values)) { |
760 | 759 |
$rrule .= ';COUNT=' . $form_values['COUNT']; |
761 | 760 |
} |
... | ... | |
769 | 768 |
$rrule .= ';WKST=' . date_repeat_dow2day(variable_get('date_first_day', 0)); |
770 | 769 |
} |
771 | 770 |
|
772 |
// Exceptions dates go last, on their own line. |
|
773 |
// The input date values may already have been converted to a date
|
|
774 |
// object on a previous pass, so check for that.
|
|
771 |
// Exceptions dates go last, on their own line. The input date values may
|
|
772 |
// already have been converted to a date object on a previous pass, so check
|
|
773 |
// for that. |
|
775 | 774 |
if (isset($form_values['EXDATE']) && is_array($form_values['EXDATE'])) { |
776 | 775 |
$ex_dates = array(); |
777 | 776 |
foreach ($form_values['EXDATE'] as $value) { |
Formats disponibles : Unified diff
Weekly update of contrib modules