ParserIcalCreator.inc in iCal feed parser 7.2
Basic classes.
File
includes/ParserIcalCreator.incView source
<?php
/**
* @file
* Basic classes.
*/
class ParserIcalCreator extends ParserIcalFeeds {
/**
* Output sources this parser offers.
*
* Includes additional field for the handler for output.
*
* @see ParserIcalCreator::getMappingSources().
* @see ParserIcalCreator::getSourceElement().
*/
protected static $sources = array(
'summary' => array(
'name' => 'Summary',
'description' => 'A short summary or subject for the calendar component.',
'parser_ical_handler' => 'formatText',
),
'description' => array(
'name' => 'Description',
'description' => 'A more complete description calendar component than that provided by the "summary" property.',
'parser_ical_handler' => 'formatText',
),
'dtstart' => array(
'name' => 'Date start',
'description' => 'Start time for the feed item.',
'parser_ical_handler' => 'formatDateTime',
),
'dtend' => array(
'name' => 'Date end',
'description' => 'End time for the feed item.',
'parser_ical_handler' => 'formatDateTime',
),
'uid' => array(
'name' => 'UID',
'description' => 'UID of feed item',
'parser_ical_handler' => 'formatText',
),
'url' => array(
'name' => 'URL',
'description' => 'URL for the feed item.',
'parser_ical_handler' => 'formatText',
),
'location' => array(
'name' => 'Location text',
'description' => 'Text of location property of feed item.',
'parser_ical_handler' => 'formatText',
),
'location:altrep' => array(
'name' => 'Location alternate representation',
'description' => 'Additional location information, usually a URL to additional location information file',
'parser_ical_handler' => 'formatParamText',
),
'categories' => array(
'name' => 'Categories',
'description' => 'Catagories of the feed item.',
'parser_ical_handler' => 'formatCategories',
),
);
/**
* Load and run parser implementation of FeedsParser::parse().
*
* @params - change these to generic required paramters.
*/
public function parse(FeedsSource $source, FeedsFetcherResult $fetcher_result) {
self::loadLibrary();
// get the temporary file path
$filename = $fetcher_result
->getFilePath();
//
// create the parser and load results
//
$config = array(
'unique_id' => '',
// do we need one for incoming parsing?
'url' => $filename,
);
$parser = new vcalendar($config);
if (!$parser
->parse()) {
throw new ParserIcalParseException(t('Error parsing %source iCal file %file', array(
'%source' => 'todo',
'%file' => $filename,
)));
}
//
// Set a result object.
//
$result = new ParserIcalResult();
// FeedsResult properties
$xprop = $parser
->getProperty('X-WR-CALNAME');
$result->title = !empty($xprop) ? $xprop[1] : '';
$xprop = $parser
->getProperty('X-WR-CALDESC');
$result->description = !empty($xprop) ? $xprop[1] : '';
$result->link = NULL;
// additional ParserIcalResult() properties
$xprop = $parser
->getProperty('X-WR-TIMEZONE');
if (!empty($xprop)) {
try {
$tz = new DateTimeZone($xprop[1]);
$result->timezone = $tz;
} catch (Exception $e) {
$source
->log('parse', 'Invalid X-WR-TIMEZONE: %error', array(
'%error' => $e
->getMessage(),
), WATCHDOG_NOTICE);
}
}
$components = array();
while ($component = $parser
->getComponent('TIMEZONE')) {
$components[$component
->getProperty('tzid')] = new ParserIcalCreatorComponent($component);
}
$result->timezones = $components;
// feed items themselves
$components = array();
$component_types = array(
'vevent',
'vtodo',
'vjournal',
'vfreebusy',
'valarm',
);
// @todo: admin per feed configurable; check each makes sense.
foreach ($component_types as $component_type) {
while ($component = $parser
->getComponent($component_type)) {
$components[] = new ParserIcalCreatorComponent($component);
}
}
$result->items = $components;
return $result;
}
/******
* Source output formatters.
*
* Could be in a class of their own?
**/
/**
* Format text fields.
*
* @todo is \n \N handling correct?
*/
public function formatText($property_key, $property, ParserIcalComponentInterface $item, FeedsParserResult $result, FeedsSource $source) {
$text = $property['value'];
$text = str_replace(array(
"\\n",
"\\N",
), "\n", $text);
return $text;
}
/**
* Format Text Parameter
*
* @return string.
*/
public function formatParamText($property_key, $property, ParserIcalComponentInterface $item, ParserIcalResult $result, FeedsSource $source) {
$position = strpos($property_key, ':');
$key = substr($property_key, 0, $position);
$attribute = strtoupper(substr($property_key, ++$position));
$text = $property['params'][$attribute];
return $text;
}
/**
* Format date fields.
*
* @return FeedsDateTime
*/
public function formatDateTime($property_key, $property, ParserIcalComponentInterface $item, ParserIcalResult $result, FeedsSource $source) {
$d = $property['value'];
if (isset($property['params']['VALUE']) && $property['params']['VALUE'] == 'DATE') {
/**
* DATE are 'anniversary type' day events, no time set.
* This can span over multiple days.
* FeedsDateTime sets the granularity correctly.
* However the granularity is not used yet.
* All Day events handling is not finalized at the time of writing.
* Multiple day all day events are not handled at this point.
* http://drupal.org/node/874322 To Date & All Day Date Handling
*/
if ($property_key == 'dtend') {
$s = $item
->getProperty('dtstart');
$s = $s['value'];
if ($s['year'] == $d['year'] && $s['month'] == $d['month'] && $s['day'] == $d['day'] - 1) {
// Single day, all day event.
// iCal DATE has start on day, end on next day.
// Presently handled date.module by having same start and end dates.
// See notes about timezone handling in issue above however.
$d = $s;
}
}
// order matters here dtstart has to come before dtend
if ($property_key == 'dtstart') {
if ($duration = $item
->getProperty('duration')) {
// @todo there is handling in the iCalcreator Utils
}
elseif (!$item
->getProperty('dtend')) {
// For cases where a "VEVENT"+... calendar component
// specifies a "DTSTART" property with a DATE value type but no
// "DTEND" nor "DURATION" property, the event's duration is taken to
// be one day.
$item
->setProperty('dtend', $property);
}
}
$feeds_object = new FeedsDateTime($d['year'] . '-' . $d['month'] . '-' . $d['day']);
}
else {
// Date with time.
$date_string = iCalUtilityFunctions::_format_date_time($d);
// If there was no timezone on the date string itself,
// add one if we have one.
if (empty($d['tz'])) {
if (!empty($property['params']['TZID'])) {
// timezone on the iCal DATETIME
try {
$tz = new DateTimeZone($property['params']['TZID']);
// note: these should relate to the ParserIcalResult::$timezones
// but see comment on property
} catch (Exception $e) {
$source
->log('parse', 'DATE-TIME TZID not in PHP timezonedb: %error', array(
'%error' => $e
->getMessage(),
), WATCHDOG_NOTICE);
}
}
elseif (!empty($result->timezone)) {
// feed wide timezone
$tz = $result->timezone;
}
}
if (!(isset($tz) && is_a($tz, 'DateTimeZone'))) {
$tz = NULL;
}
$feeds_object = new FeedsDateTime($date_string, $tz);
}
return $feeds_object;
}
/**
* Format Categories
*
* @return array of free tags strings.
*/
public function formatCategories($property_key, $property, ParserIcalComponentInterface $item, ParserIcalResult $result, FeedsSource $source) {
if (!empty($property['value'])) {
if (is_array($property['value'])) {
return $property['value'];
}
else {
return array(
$property['value'],
);
}
}
}
/**
* Load external iCalcreator class from libary.
*/
public static function loadLibrary() {
$creator_path = libraries_get_path('iCalcreator');
require_once $creator_path . '/iCalcreator.class.php';
}
}
class ParserIcalResult extends FeedsParserResult {
// Feed extension timezone (X-WR-TIMEZONE)
public $timezone;
// Feed RFC 5545 timezones; we can't use these at
// present, only PHP timezonedb tz will be actually recognized.
// So this is more here as reminder/explanation.
public $timezones;
}
/**
* A wrapper on iCalcreator component class.
*/
class ParserIcalCreatorComponent implements ParserIcalComponentInterface {
protected $component;
private $_serialized_component;
/**
* Constructor.
*
* @param
* vcalendar object configured, but not parsed.
*/
public function __construct($component) {
$this->component = $component;
}
/**
* Serialization helper.
*/
public function __sleep() {
$this->_serialized_component = serialize($this->component);
return array(
'_serialized_component',
);
}
/**
* Unserialization helper.
*/
public function __wakeup() {
ParserIcalCreator::loadLibrary();
$this->component = unserialize($this->_serialized_component);
}
public function getComponentType() {
return $this
->getProperty('objName');
}
public function setComponentType($type) {
return $this
->setProperty('objName', $type);
}
public function getProperty($name) {
return $this->component
->getProperty($name, FALSE, TRUE);
}
public function setProperty($name, $value) {
return $this->component
->setProperty($name, $value);
}
}
Classes
Name | Description |
---|---|
ParserIcalCreator | @file Basic classes. |
ParserIcalCreatorComponent | A wrapper on iCalcreator component class. |
ParserIcalResult |