Commit 11f49c89 authored by Robert Rollins's avatar Robert Rollins
Browse files

Initial commit of Date iCal 3.0!

This new version is still in a state of partial completeness. You may need to do
some manual fixing to get it working, due to a change I made in the classes
offered by this module. Try 'drush cc registry' if 'drush cc all' fails.

Please note that ALL of the hooks exposed by Date iCal have changed. They do
essentially the same things they used to do, but they're named differently.

The big change is that the Feeds plugin has been completely re-written to
conform to the Feeds APIs. It's now much more resilient and powerful. Feeds
Tamper will now work, and is in fact the prescribed way to alter data, since I
removed several alter hooks.
parent 3073af84
<?php <?php
/** /**
* Alter the HTML of an event's Summary and Description, before it gets converted * @file
* to plaintext for output in an iCal feed. This hook is only used by the * Documentation for the hooks provided by Date iCal.
* iCal Entity views row plugin.
*
* @param $data
* A reference to an associative array with the following keys and values:
* - 'description': The rendered HTML of the iCal view mode of the entity.
* - 'summary': The title of the entity.
* @param $view
* The view object that is being executed to render the iCal feed.
* @param $context
* An associative array of context, with the following keys and values:
* - 'entity_type': The type of entity being rendered, 'node', 'user' etc.
* - 'entity': The fully loaded entity being rendered.
* - 'language': The language code that indicates which translation of field
* data should be used.
*/ */
function hook_date_ical_html_alter(&$data, $view, $context) {
} /******************************************************************************
* ALTER HOOKS FOR EXPORTED ICAL FEEDS
*****************************************************************************/
/** /**
* Alter the HTML of an event's text fields, before it gets converted * Alter the HTML from an event's text fields before they get exported.
* to plaintext for output in an iCal feed. This hook is only used by the *
* iCal Fields views row plugin. * Because HTML must be converted to plaintext for iCal spec compliance, this
* hook exists to allow users to alter the original HTML to ensure that it
* gets converted into pretty plaintext.
* *
* @param $text_fields * ONLY <p> tags will be converted to newlines by the plaintext conversion.
*
* @param array $text_fields
* A reference to an associative array with the following keys and values: * A reference to an associative array with the following keys and values:
* - 'description': The description field string. * - 'description': The description field string.
* - 'summary': The title field string * - 'summary': The title field string
* - 'location': The location field string. * - 'location': The location field string.
* @param $view * @param object $view
* The view object that is being executed to render the iCal feed. * The view object that is being executed to render the iCal feed.
* @param $context * @param array $context
* An associative array of context, with the following keys and values: * Depending on whether this event is being constructed using the Fields or
* - 'row': The single query result row that is being converted into an iCal VEVENT. * Entity plugins, this context array will have different keys and values.
* - 'row_index': The index into the full query results for this row. *
* Entity Plugin:
* - 'entity_type': The type of entity being rendered (e.g. 'node').
* - 'entity': The fully loaded entity being rendered.
* - 'language': The language code that indicates which translation of field * - 'language': The language code that indicates which translation of field
* data should be used. * data should be used.
*
* Fields Plugin:
* - 'row': The full Views row object being converted to an event.
* - 'row_index': The index into the query results for this view.
* - 'language': The language code that indicates which translation of field
* data should be used.
* - 'options': The Fields plugin options.
*/ */
function hook_date_ical_fields_html_alter(&$text_fields, $view, $context) { function hook_date_ical_export_html_alter(&$text_fields, $view, $context) {
} }
/** /**
* Modify a structured event before it is rendered to iCal format. * Modify an event's raw data.
* *
* This hook is invoked after the Date iCal module has generated its * This hook is invoked after Date iCal has gathered all the data it will use
* representation of the event and allows you to modify or add to the * to build an event object. Use this hook to set values of iCal fields which
* representation. Use this hook to set values of iCal fields that are supported * Date iCal doesn't directly support.
* but have no values mapped into them by default.
* *
* @param $event * @param array $event
* An associative array representation of the iCal event. This will be used by * A reference to an associative array containing the event's raw data.
* the Date iCal rendering system to create an entry in an iCal feed. * @param object $view
* @param $view
* The view object that is being executed to render the iCal feed. * The view object that is being executed to render the iCal feed.
* @param $context * @param array $context
* An associative array of context, with the following keys and values: * Depending on whether this event is being constructed using the Fields or
* - 'entity_type': The type of entity being rendered, 'node', 'user' etc. * Entity plugins, this context array will have different keys and values.
*
* Entity Plugin:
* - 'entity_type': The type of entity being rendered (e.g. 'node').
* - 'entity': The fully loaded entity being rendered. * - 'entity': The fully loaded entity being rendered.
* - 'language': The language code that indicates which translation of field * - 'language': The language code that indicates which translation of field
* data should be used. * data should be used.
*
* Fields Plugin:
* - 'row': The full Views row object being converted to an event.
* - 'row_index': The index into the query results for this view.
* - 'language': The language code that indicates which translation of field
* data should be used.
* - 'options': The Fields plugin options.
*/ */
function hook_date_ical_feed_event_render_alter(&$event, $view, $context) { function hook_date_ical_export_raw_event_alter(&$event, $view, $context) {
// Simple example adding the location to a rendered event from a simple // Example: adding a comment to an event from a simple
// textfield called 'field_location'. // textfield called 'field_comment' (using the Entity plugin).
$entity_type = $context['entity_type']; if ($comments = field_get_items($context['entity_type'], $context['entity'], 'field_comment', $context['language'])) {
$entity = $context['entity']; foreach ($comments as $comment) {
$language = $context['language']; $event['comment'] = check_plain($comment['value']);
if ($locations = field_get_items($entity_type, $entity, 'field_location', $language)) {
foreach ($locations as $location) {
$event['location'] = check_plain($location['value']);
} }
} }
// Example: Retrieving information from additional fields in the View (using
// the Fields plugin).
$event['comment'] = $view->style_plugin->get_field($context['row_index'], 'field_comment');
} }
/** /**
* Alter an iCal representation of an event. * Alter an iCal representation of an event.
* *
* This hook allows you to modify the event that is being added to the * This hook allows you to modify an event as it is added to the iCal calendar.
* iCal calendar. If Date iCal doesn't support an iCal property that you * If Date iCal doesn't support an iCal property that you need to use, then you
* need to use, then you can add it to the event in the iCal feed here. * can add it to the event here.
* *
* @param $vevent * @param object $vevent
* The iCalcreator vevent object that is being added to the iCal feed. See the * A reference to an iCalcreator vevent which will be exported in this feed.
* iCalcreator library for documentation on how to use this object correctly. * @param object $view
* @param $view
* The view object that is being executed to render the iCal feed. * The view object that is being executed to render the iCal feed.
* @param $event_array * @param object $event_array
* The array representation of the event that's been rendered to the $vevent. * The array representation of the event that's been rendered to the $vevent.
*/ */
function hook_date_ical_feed_ical_vevent_render_alter($vevent, $view, $event_array) { function hook_date_ical_export_vevent_alter(&$vevent, $view, $event_array) {
} }
/** /**
* Alter the iCalcreator vcalendar object that will be rendered into an iCal * Alter the iCalcreator vcalendar object before it's exported as an iCal feed.
* feed View. *
* * You can use this hook to add sections to the generated iCal feed which Date
* This hook allows you to modify the iCal calendar that will be rendered into * iCal might not support.
* an iCal feed. You can use this hook to add sections to the generated iCal *
* feeds that the Date iCal module doesn't support, etc. * @param object $vcalendar
* * A reference to the iCalcreator vcalendar object representing this feed.
* @param $vcalendar * @param object $view
* The iCalcreator vcalendar object that will be rendered to generate the iCal
* feed. See the iCalcreator library for documentation on how to use this
* object correctly.
* @param $view
* The view object that is being executed to render the iCal feed. * The view object that is being executed to render the iCal feed.
*/ */
function hook_date_ical_feed_ical_vcalendar_render_alter(&$vcalendar, $view) { function hook_date_ical_export_vcalendar_alter(&$vcalendar, $view) {
} }
/** /**
* Alter the final rendered text of an iCal feed before it gets sent to Views. * Alter the final rendered text of an iCal feed before it gets exported.
* *
* @param $rendered_calendar * This is a last resort hook, allowing you to alter the output of the feed
* The rendered string of iCal text created from an iCalcreator vcalendar object. * in case nothing else works.
* @param $view *
* The view object that is being executed to render the iCal feed. * @param string $rendered_calendar
* A reference to the string containing the rendered the iCal feed.
* @param object $view
* The view that is being executed to render this iCal feed.
*/ */
function hook_date_ical_post_render_alter(&$rendered_calendar, $view) { function hook_date_ical_export_post_render_alter(&$rendered_calendar, $view) {
} }
/******************************************************************************
* ALTER HOOKS FOR IMPORTED ICAL FEEDS
*****************************************************************************/
/** /**
* Alter the iCalcreator vcalendar object that was parsed from an imported * Alter the vcalendar object created from an imported iCal feed.
* iCal feed.
* *
* @param $calendar * @param object $calendar
* The iCalcreator vcalendar object that was created by parsing the iCal * An instance of the iCalcreator library's vcalendar class.
* feed. See the iCalcreator library for documentation on this object. * @param array $context
* @param $context
* An associative array of context, with the following keys and values: * An associative array of context, with the following keys and values:
* - 'source' FeedsSource object associated with this Feed. * - 'source' FeedsSource object for this Feed.
* - 'fetcher_result': The FeedsFetcherResult object associated with this Feed. * - 'fetcher_result': The FeedsFetcherResult object for this Feed.
*/ */
function hook_date_ical_icalcreator_calendar_alter(&$calendar, &$context) { function hook_date_ical_import_calendar_alter(&$calendar, $context) {
} }
/** /**
* Alter an individual DateIcalIcalcreatorComponent (vevent, valarm, vtodo, etc.) * Alter a calendar component created from an imported iCal feed.
* that was parsed from an iCal feed.
* *
* @param $component * @param object $component
* A DateIcalIcalcreatorComponent. See the definition of this class in * This will usually be an iCalcreator vevent object, but Date iCal also
* includes/DateIcalIcalcreatorParser.inc for more information. * experimentally supports vtodo, vjournal, vfreebusy, and valarm.
* @param $context * @param array $context
* An associative array of context, with the following keys and values: * An associative array of context, with the following keys and values:
* - 'calendar': The iCalcreator vcalendar object from which this * - 'calendar': The iCalcreator vcalendar parent object of this component.
* DateIcalIcalcreatorComponent originates. * - 'source': FeedsSource object for this Feed.
* - 'parser_result': The DateIcalParserResult object which contains the parsed * - 'fetcher_result': The FeedsFetcherResult object for this Feed.
* values from the vcalendar object.
* - 'source': FeedsSource object associated with this Feed.
* - 'fetcher_result': The FeedsFetcherResult object associated with this Feed.
*/ */
function hook_date_ical_icalcreator_component_alter(&$component, $context) { function hook_date_ical_import_component_alter(&$component, $context) {
// Example of what might be done with this alter hook // Example of what might be done with this alter hook
if ($component->getComponentType() == 'vevent') { if ($component->objName == 'vevent') {
// Do something for vevents ... // Do something for vevents ...
} }
if ($component->getComponentType() == 'vtimezone') { else if ($component->objName == 'valarm') {
// Do something different for vtimezones ... // Do something different for valarms ...
} }
} }
/** /**
* Alter the post-parse data for a single field from an iCal feed. * Alter the timezone string from an imported iCal Feed.
* *
* @param $value
* A string or object representing one parsed property of an iCal component.
* @param $context
* An associative array of context, with the following keys and values:
* - 'property_key': Inernal, parser-specific identifier for this property.
* - 'property': "RAW" value of this property.
* - 'item': The DateIcalComponentInterface object that holds the unparsed component.
* - 'parser_result': The parsed result of the whole Calendar.
* - 'feeds_source': Contains all the metadata about the configuration of this Feed.
*/
function hook_date_ical_feeds_object_alter(&$value, $context) {
// Example of what might be done with this alter hook
if ($context['property_key'] == 'dtstart') {
// Tweak the parsed FeedsDateTime object created from the start time.
// ...
}
}
/**
* Alter the timezone string before it gets converted into a DateTimeZone object.
* This is useful for when an iCal feed you're trying to import uses deprecated * This is useful for when an iCal feed you're trying to import uses deprecated
* timezone names, like "Eastern Standard Time", rather than "America/New_York". * timezone names, like "Eastern Standard Time" rather than "America/New_York".
* *
* @param $tz_string * @param string $tzid
* The timezone sting to be altered (e.g. "America/Los_Angeles"). * The timezone id sting to be altered (e.g. "America/Los_Angeles").
* @param $context * @param array $context
* An associative array of context, with the following keys and values: * An associative array of context, with the following keys and values:
* - 'property_key': Inernal, parser-specific identifier for this property. * - 'property_key': The name of the property (e.g. DTSTART). Can be NULL.
* - 'property': "RAW" value of this property. * - 'calendar_component': The iCalcreator object (e.g VEVENT). Can be NULL.
* - 'item': The DateIcalComponentInterface object that holds the unparsed component. * - 'calendar': The iCalcreater vcalendar object created from the feed.
* - 'parser_result': The parsed result of the whole Calendar. * - 'feeds_source': A FeedsSource object with this feed's metadata.
* - 'feeds_source': Contains all the metadata about the configuration of this Feed. * - 'feeds_detcher_result': The FeedsFeatcherResult for this import.
*
* If property_key and calendar_component are NULL, this is the X-WR-TIMEZONE
* string for the entire feed.
*/ */
function hook_date_ical_timezone_alter(&$tz_string, $context) { function hook_date_ical_import_timezone_alter(&$tzid, $context) {
// Example of what might be done with this alter hook: // Example of what might be done with this alter hook:
if ($tz_string == 'Eastern Standard Time') { if ($tzid == 'Eastern Standard Time') {
// "Eastern Standard Time" is a deprecated timezone string, which PHP doesn't // "Eastern Standard Time" is a deprecated tzid, which PHP doesn't accept.
// recognize. It's (essentially) equivalent to "America/New_York", though, // However, it's equivalent to "America/New_York", which PHP is fine with.
// which PHP is fine with. $tzid = 'America/New_York';
$tz_string = 'America/New_York';
} }
} }
name = Date iCal name = Date iCal
description = Allows creation of iCal feeds using Views, and provides a Feeds plugin for parsing iCal feeds. description = Enables users to export iCal feeds using Views, and import iCal feeds using Feeds.
package = Date/Time package = Date/Time
php = 5.3 php = 5.3
core = 7.x core = 7.x
...@@ -10,21 +10,15 @@ dependencies[] = libraries (>=7.x-2.0) ...@@ -10,21 +10,15 @@ dependencies[] = libraries (>=7.x-2.0)
dependencies[] = date dependencies[] = date
dependencies[] = date_api dependencies[] = date_api
; Date iCal doesn't actually depend on Feeds, but it's iCal import functionality won't work without it. ; Date iCal doesn't actually depend on Feeds, but it's iCal import functionality won't be usable without it.
;dependencies[] = feeds ;dependencies[] = feeds
; Includes ; Includes for iCal feed export using Views
files[] = includes/date_ical_plugin_row_ical_entity.inc files[] = includes/date_ical_plugin_row_ical_entity.inc
files[] = includes/date_ical_plugin_row_ical_fields.inc files[] = includes/date_ical_plugin_row_ical_fields.inc
files[] = includes/date_ical_plugin_style_ical_feed.inc files[] = includes/date_ical_plugin_style_ical_feed.inc
; Includes for iCal feed import using Feeds
files[] = includes/DateIcalFeedsParser.inc files[] = includes/DateIcalFeedsParser.inc
files[] = includes/DateIcalFeedsParserOld.inc
files[] = includes/DateIcalIcalcreatorParser.inc files[] = includes/DateIcalIcalcreatorParser.inc
files[] = includes/DateIcalDateModuleParser.inc
; Tests
files[] = tests/date_ical_parser.test
files[] = tests/date_ical_parser_text.test
files[] = tests/date_ical_parser_link.test
files[] = tests/date_ical_parser_date.test
files[] = tests/date_ical_parser_location.test
files[] = tests/date_ical_parser_categories.test
...@@ -3,21 +3,37 @@ ...@@ -3,21 +3,37 @@
/** /**
* @file * @file
* Adds ical functionality to Views, and an iCal parser to Feeds. * Adds ical functionality to Views, and an iCal parser to Feeds.
*
* TODO Figure out how to incorporate VVENUE information into the parser.
*/ */
/** /**
* The version number of the current release. This is inserted into the PRODID * The version number of the current release. This is inserted into the PRODID
* value of the iCal feeds created by Date iCal. * value of the iCal feeds created by Date iCal.
*/ */
define('DATE_ICAL_VERSION', '2.13-dev'); define('DATE_ICAL_VERSION', '3.0-dev');
/** /**
* Exception for when the date field for a row in the ical_fields row plugin is blank. * Exception for when the date field for a row in the ical_fields row plugin is blank.
*/ */
class BlankDateFieldException extends Exception { } class BlankDateFieldException extends Exception { }
/**
* Generic DateIcalFeedsParser exceptions.
*/
class DateIcalException extends Exception {}
/**
* DateIcalFeedsParser failed to parse some part of iCal.
*/
class DateIcalParseException extends DateIcalException {}
/**
* Implements hook_hook_info().
*/
function date_ical_hook_info() {
// TODO: Finish this.
// Use two "groups": date_ical_parse and date_ical_output.
}
/** /**
* Implements hook_views_api(). * Implements hook_views_api().
*/ */
...@@ -134,7 +150,7 @@ function date_ical_libraries_info() { ...@@ -134,7 +150,7 @@ function date_ical_libraries_info() {
} }
/** /**
* Implementation of hook_ctools_plugin_api(). * Implements hook_ctools_plugin_api().
*/ */
function date_ical_ctools_plugin_api($owner, $api) { function date_ical_ctools_plugin_api($owner, $api) {
if ($owner == 'feeds' && $api == 'plugins') { if ($owner == 'feeds' && $api == 'plugins') {
...@@ -143,32 +159,41 @@ function date_ical_ctools_plugin_api($owner, $api) { ...@@ -143,32 +159,41 @@ function date_ical_ctools_plugin_api($owner, $api) {
} }
/** /**
* Implementation of ctools plugin for feeds hook_feeds_plugins(). * Implements hook_feeds_plugins().
*/ */
function date_ical_feeds_plugins() { function date_ical_feeds_plugins() {
$path = drupal_get_path('module', 'date_ical') . '/includes'; $path = drupal_get_path('module', 'date_ical') . '/includes';
$info = array(); $info = array();
$info['DateIcalFeedsParser'] = array( $info['DateIcalFeedsParserOld'] = array(
'hidden' => TRUE, 'hidden' => TRUE,
'handler' => array( 'handler' => array(
'parent' => 'FeedsParser', 'parent' => 'FeedsParser',
'class' => 'DateIcalFeedsParser', 'class' => 'DateIcalFeedsParserOld',
'file' => 'DateIcalFeedsParser.inc', 'file' => 'DateIcalFeedsParserOld.inc',
'path' => $path, 'path' => $path,
), ),
); );
$info['DateIcalIcalcreatorParser'] = array( $info['DateIcalIcalcreatorParser'] = array(
'name' => 'iCal parser', 'name' => 'iCal parser (old)',
'description' => t('Use the iCalcreator library to parse iCal feeds.'), 'description' => t('Use the iCalcreator library to parse iCal feeds.'),
'help' => 'Parse iCal feeds.', 'help' => 'Parse iCal feeds.',
'handler' => array( 'handler' => array(
'parent' => 'DateIcalFeedsParser', 'parent' => 'DateIcalFeedsParserOld',
'class' => 'DateIcalIcalcreatorParser', 'class' => 'DateIcalIcalcreatorParser',
'file' => 'DateIcalIcalcreatorParser.inc', 'file' => 'DateIcalIcalcreatorParser.inc',
'path' => $path, 'path' => $path,
), ),
); );
$info['DateiCalFeedsParser'] = array(
'name' => 'iCal parser',
'description' => t('Parse iCal feeds.'),
'handler' => array(
'parent' => 'FeedsParser',
'class' => 'DateiCalFeedsParser',
'file' => 'DateiCalFeedsParser.inc',
'path' => $path,
),
);
return $info; return $info;
} }
......
This diff is collapsed.
<?php
/**
* @file
* Basic classes.
*/
/**
* Parent class for Feeds integration.
*/
abstract class DateIcalFeedsParserOld extends FeedsParser {
/**
* The output sources the parser offers.
*
* array(
* 'feeds_output_key' => array(
* 'name' => 'Human readable name of output source.',
* 'description' => 'Longer description of source.',
* 'date_ical_parse_handler' => 'Method callback for parsing source before handing to feeds.',
* ),
* );
*/
static protected $sources;
/**
* Implementation of FeedsParser::getMappingSources().
*/
public function getMappingSources() {
// Quirky work around.
// Want to have the sources as a property of the class,
// but can't declare them with t().
$sources = $this::$sources;
foreach ($sources as &$source) {
foreach ($source as $key => &$value) {
if ($key == 'name' || $key == 'description') {
$value = t($value);
}
}
}
// Call parent::getMappingSources() to trigger additional target creation.
return $sources + parent::getMappingSources();
}
/**
* Override FeedsParser::getSourceElement().
*/
public function getSourceElement(FeedsSource $source, FeedsParserResult $result, $property_key) {
// Allow parent method to handle any mappings based on the parent node.
if (substr($property_key, 0, 7) == 'parent:') {
return parent::getSourceElement($source, $result, $property_key);
}
// Otherwise retrieve the current DateIcalComponent from the DateIcalParserResult.
if ($item = $result->currentItem()) {
if ($position = strpos($property_key, ':')) {
$key = substr($property_key, 0, $position);
$attribute = substr($property_key, ++$position);
}
else {
$key = $property_key;
}
// and use listed handler to get source output
$handler = $this::$sources[$property_key]['date_ical_parse_handler'];
$property = $item->getProperty($key);
if (empty($property)) {
// $property will be empty if the mapping is set up to parse optional source
// components (e.g. RRULE), and this particular VEVENT doesn't have one.
return '';