public function ParserVcalendar::parseDateTimeProperty in Date iCal 7.3
Handler that parses DATE-TIME and DATE fields.
Return value
FeedsDateTime The parsed datetime object.
File
- libraries/
ParserVcalendar.inc, line 292 - Defines a class that parses iCalcreator vcalendar objects into Feeds-compatible data arrays.
Class
- ParserVcalendar
- @file Defines a class that parses iCalcreator vcalendar objects into Feeds-compatible data arrays.
Code
public function parseDateTimeProperty($property_key, $vcalendar_component) {
$property = $vcalendar_component
->getProperty($property_key, FALSE, TRUE);
// Gather all the other date properties, so we can work with them later.
$duration = $vcalendar_component
->getProperty('DURATION', FALSE, TRUE);
$dtstart = $vcalendar_component
->getProperty('DTSTART', FALSE, TRUE);
$uid = $vcalendar_component
->getProperty('UID');
// DATE-type properties are treated as All Day events which can span over
// multiple days.
// The Date module's All Day event handling was never finalized
// (http://drupal.org/node/874322), which requires us to do some some
// special coddling later.
$is_all_day = isset($property['params']['VALUE']) && $property['params']['VALUE'] == 'DATE';
// Cover various conditions in which either DTSTART or DTEND are not set.
if ($property === FALSE) {
// When DTEND isn't defined, we may need to emulate it.
if ($property_key == 'DTEND') {
// Unset DTENDs need to emulate the DATE type from DTSTART.
$is_all_day = isset($dtstart['params']['VALUE']) && $dtstart['params']['VALUE'] == 'DATE';
if ($duration !== FALSE) {
// If a DURATION is defined, emulate DTEND as DTSTART + DURATION.
$property = array(
'value' => iCalUtilityFunctions::_duration2date($dtstart['value'], $duration['value']),
'params' => $dtstart['params'],
);
}
elseif ($is_all_day) {
// If this is an all-day event with no end or duration, treat this
// as a single-day event by emulating DTEND as 1 day after DTSTART.
$property = $dtstart;
$property['value'] = iCalUtilityFunctions::_duration2date($property['value'], array(
'day' => 1,
));
}
else {
// This event has no end date.
return NULL;
}
}
elseif ($property_key == 'DTSTART') {
// DTSTART can only be legally unset in non-VEVENT components.
if ($vcalendar_component->objName == 'vevent') {
throw new DateIcalParseException(t('Feed import failed! The VEVENT with UID %uid is invalid: it has no DTSTART.', array(
'%uid' => $uid,
)));
}
else {
return NULL;
}
}
}
// When iCalcreator parses a UTC date (one that ends with Z) from an iCal
// feed, it stores that 'Z' into the $property['value']['tz'] value.
if (isset($property['value']['tz'])) {
$property['params']['TZID'] = 'UTC';
}
if ($is_all_day) {
if ($property_key == 'DTEND') {
if ($dtstart === FALSE) {
// This will almost certainly never happen, but the error message
// would be incomprehensible without this check.
throw new DateIcalParseException(t('Feed import failed! The event with UID %uid is invalid: it has a DTEND but no DTSTART!', array(
'%uid' => $uid,
)));
}
if (module_exists('date_all_day')) {
// If the Date All Day module is installed, we need to rewind the
// DTEND by one day, because of the problem with FeedsDateTime
// mentioned below.
$prev_day = iCalUtilityFunctions::_duration2date($property['value'], array(
'day' => -1,
));
$property['value'] = $prev_day;
}
}
// FeedsDateTime->setTimezone() ignores timezone changes made to dates
// with no time element, which means we can't compensate for the Date
// module's automatic timezone conversion when it writes to the DB. To
// get around that, we must add 00:00:00 explicitly, even though this
// causes other problems (see above and below).
$date_string = sprintf('%d-%d-%d 00:00:00', $property['value']['year'], $property['value']['month'], $property['value']['day']);
// Use the server's timezone rather than letting it default to UTC.
// This will help ensure that the date value doesn't get messed up when
// Date converts its timezone as the value is read from the database.
// This is *essential* for All Day events, because Date stores them as
// '2013-10-03 00:00:00' in the database, rather than doing the sensible
// thing and storing them as '2013-10-03'.
// NOTE TO MAINTAINERS:
// This will not work properly if the site is configured to allow users
// to set their own timezone. Unfortunately, there isn't anything that
// Date iCal can do about that, as far as I can tell.
$datetimezone = new DateTimeZone(date_default_timezone_get());
}
else {
// This is a DATE-TIME property.
$date_string = iCalUtilityFunctions::_format_date_time($property['value']);
// Allow modules to alter the timezone string. This also allows for
// setting a TZID when one was not originally set for this property.
$tzid = isset($property['params']['TZID']) ? $property['params']['TZID'] : NULL;
$context = array(
'property_key' => $property_key,
'calendar_component' => $vcalendar_component,
'calendar' => $this->calendar,
'feeeds_source' => $this->source,
'feeds_fetcher_result' => $this->fetcherResult,
);
drupal_alter('date_ical_import_timezone', $tzid, $context);
if (isset($tzid)) {
$datetimezone = $this
->_tzid_to_datetimezone($tzid);
}
elseif (isset($this->xtimezone)) {
// No timezone was set on the parsed date property, so if a timezone
// was detected for the entire iCal feed, use it.
$datetimezone = $this->xtimezone;
}
else {
$msg = t("No timezone was detected for one or more of the events in this feed, forcing Date iCal to use this server's timezone as a fallback.<br>\n To make timezone-less events use a different timezone, implement hook_date_ical_import_timezone_alter() in a custom module.");
drupal_set_message($msg, 'status', FALSE);
$this->source
->log('parse', $msg, array(), WATCHDOG_NOTICE);
$datetimezone = new DateTimeZone(date_default_timezone_get());
}
}
$datetime = new FeedsDateTime($date_string, $datetimezone);
return $datetime;
}