Version 4.1.19
This commit is contained in:
1 parent
28bd025b35
commit
2bd5025018
2674 files changed
+233518
-77766
No files matched your search
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief iCalendar ICS Parser
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @package IPS Community Suite
|
||||
* @subpackage Calendar
|
||||
* @since 19 Dec 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
@@ -298,15 +298,16 @@ class _ICSParser
|
||||
{
|
||||
$this->_parsedIcsData = $this->_convertToGmt( $this->_parsedIcsData );
|
||||
}
|
||||
|
||||
|
||||
/* Now loop over the results in order to insert */
|
||||
$_imported = 0;
|
||||
$_skipped = 0;
|
||||
$_newEvents = 0;
|
||||
|
||||
// Leave this here - useful for debugging
|
||||
// print_r($this->_parsedIcsData);exit;
|
||||
|
||||
if ( count( $this->_parsedIcsData ) )
|
||||
if ( count( $this->_parsedIcsData ) and isset( $this->_parsedIcsData['events'] ) )
|
||||
{
|
||||
/* Loop over the events */
|
||||
foreach( $this->_parsedIcsData['events'] as $event )
|
||||
@@ -316,7 +317,7 @@ class _ICSParser
|
||||
{
|
||||
try
|
||||
{
|
||||
$rrule = self::parseRrule( $event['recurr'] );
|
||||
$rrule = static::parseRrule( $event['recurr'] );
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
{
|
||||
@@ -327,24 +328,24 @@ class _ICSParser
|
||||
$event['uid'] = $event['uid'] ? $event['uid'] : md5( implode( ',', $event['start'] ) . implode( ',', $event['end'] ) );
|
||||
|
||||
/* Figure out some times */
|
||||
$event_unix_from = $event['start']['gmt_ts'];
|
||||
$event_unix_to = isset( $event['end'] ) ? $event['end']['gmt_ts'] : NULL;
|
||||
$event_all_day = ( $event['start']['type'] == 'DATE' ) ? 1 : 0;
|
||||
$event_unix_from = $event['start']['utc_time'];
|
||||
$event_unix_to = isset( $event['end'] ) ? $event['end']['utc_time'] : NULL;
|
||||
$event_all_day = ( $event['start']['type'] == 'DATE' ) ? TRUE : FALSE;
|
||||
|
||||
/* End dates in iCalendar format are "exclusive", meaning they are actually the day ahead. */
|
||||
/* @link http://microformats.org/wiki/dtend-issue */
|
||||
/* Only adjust end date if end date is not equal too the start date already. */
|
||||
/* @see Ticket 876817 */
|
||||
|
||||
if( $event_unix_to AND $event['end']['type'] == 'DATE' AND ( $event_unix_from != $event_unix_to ) )
|
||||
if( $event_unix_to AND $event['end']['type'] == 'DATE' AND ( $event_unix_from->getTimestamp() != $event_unix_to->getTimestamp() ) )
|
||||
{
|
||||
$event_unix_to -= 86400;
|
||||
$event_unix_to = $event_unix_to->sub( new \DateInterval( 'P1D' ) );
|
||||
}
|
||||
|
||||
/* It is a single day event if end date is equal to start date */
|
||||
if( $event_unix_from == $event_unix_to )
|
||||
{
|
||||
$event_unix_to = 0;
|
||||
$event_unix_to = NULL;
|
||||
}
|
||||
|
||||
/* If there is a duration, calculate the end date again */
|
||||
@@ -359,14 +360,14 @@ class _ICSParser
|
||||
preg_match( "#(\d+?)S#is", $event['duration'], $match );
|
||||
$second = $match[1] ? $match[1] : 0;
|
||||
|
||||
$event_unix_to = $event_unix_from + ( $hour * 3600 ) + ( $minute * 60 ) + $second;
|
||||
$event_unix_to = $event_unix_from->add( new \DateIntveral( 'PT' . ( $hour * 3600 ) . 'H' . ( $minute * 60 ) . 'M' . $second . 'S' ) );
|
||||
}
|
||||
|
||||
/* If this is an all day event, adjust the timestamps */
|
||||
if( $event_all_day )
|
||||
{
|
||||
$event_unix_from = gmmktime( 0, 0, 0, gmstrftime( '%m', $event_unix_from ), gmstrftime( '%d', $event_unix_from ), gmstrftime( '%Y', $event_unix_from ) );
|
||||
$event_unix_to = $event_unix_to ? gmmktime( 0, 0, 0, gmstrftime( '%m', $event_unix_to ), gmstrftime( '%d', $event_unix_to ), gmstrftime( '%Y', $event_unix_to ) ) : 0;
|
||||
$event_unix_from = $event_unix_from->setTime( 0, 0, 0 );
|
||||
$event_unix_to = $event_unix_to ? $event_unix_to->setTime( 0, 0, 0 ) : NULL;
|
||||
}
|
||||
|
||||
/* If we are missing crucial data, skip this event */
|
||||
@@ -378,11 +379,19 @@ class _ICSParser
|
||||
|
||||
/* Update previously imported events, if possible */
|
||||
$eventId = NULL;
|
||||
$_new = FALSE;
|
||||
|
||||
if( $event['uid'] )
|
||||
{
|
||||
try
|
||||
{
|
||||
/* If we are importing an ICS file, feed here will be null. */
|
||||
if ( is_null( $this->feed ) )
|
||||
{
|
||||
/* Bubble up so we can create a new event */
|
||||
throw new \UnderflowException;
|
||||
}
|
||||
|
||||
$eventId = \IPS\Db::i()->select( 'import_event_id', 'calendar_import_map', array( array( 'import_guid=? and import_feed_id=?', $event['uid'], $this->feed->id ) ) )->first();
|
||||
|
||||
try
|
||||
@@ -401,6 +410,7 @@ class _ICSParser
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$newEvent = new \IPS\calendar\Event;
|
||||
$_new = TRUE;
|
||||
|
||||
/* Basics */
|
||||
$newEvent->post_key = md5( uniqid() );
|
||||
@@ -425,8 +435,8 @@ class _ICSParser
|
||||
$newEvent->lastupdated = ( isset( $event['last_modified'] ) AND $event['last_modified'] AND $event['last_modified'] < time() ) ? $event['last_modified'] : ( ( isset( $event['created'] ) AND $event['created'] AND $event['created'] < time() ) ? $event['created'] : time() );
|
||||
$newEvent->all_day = $event_all_day;
|
||||
$newEvent->recurring = ( isset( $event['recurr'] ) ) ? $event['recurr'] : NULL;
|
||||
$newEvent->start_date = gmstrftime( "%Y-%m-%d %H:%M:00", $event_unix_from );
|
||||
$newEvent->end_date = $event_unix_to ? gmstrftime( "%Y-%m-%d %H:%M:00", $event_unix_to ) : NULL;
|
||||
$newEvent->start_date = $event_unix_from->setTimezone( new \DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' );
|
||||
$newEvent->end_date = $event_unix_to ? $event_unix_to->setTimezone( new \DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' ) : NULL;
|
||||
|
||||
/* Geolocation? */
|
||||
if( isset( $event['geo'] ) AND is_array( $event['geo'] ) AND count( $event['geo'] ) )
|
||||
@@ -444,6 +454,12 @@ class _ICSParser
|
||||
/* Increment counter */
|
||||
$_imported++;
|
||||
|
||||
/* Increment only if this is a new event */
|
||||
if( $_new )
|
||||
{
|
||||
$_newEvents++;
|
||||
}
|
||||
|
||||
/* Add to index */
|
||||
\IPS\Content\Search\Index::i()->index( $newEvent );
|
||||
|
||||
@@ -481,9 +497,12 @@ class _ICSParser
|
||||
}
|
||||
|
||||
/* Increment post counts */
|
||||
$this->member->member_posts = $this->member->member_posts + $_imported;
|
||||
$this->member->member_last_post = time();
|
||||
$this->member->save();
|
||||
if( $_newEvents )
|
||||
{
|
||||
$this->member->member_posts = $this->member->member_posts + $_newEvents;
|
||||
$this->member->member_last_post = time();
|
||||
$this->member->save();
|
||||
}
|
||||
|
||||
/* Return the data */
|
||||
return array( 'skipped' => $_skipped, 'imported' => $_imported );
|
||||
@@ -630,12 +649,13 @@ class _ICSParser
|
||||
/**
|
||||
* Return a UID for iCalendar
|
||||
*
|
||||
* @param array $params Parameters to use to generate UID
|
||||
* @param \IPS\calendar\Event $event Event
|
||||
* @param string
|
||||
*/
|
||||
protected function _buildUid( $params )
|
||||
protected static function _buildUid( $event )
|
||||
{
|
||||
return md5( implode( '.', $params ) ) . '@' . $_SERVER['SERVER_ADDR'];
|
||||
$baseUrl = \IPS\Http\Url::internal('');
|
||||
return $event->id . '-' . $event->calendar_id . '-' . md5( (string) $baseUrl ) . '@' . $baseUrl->data['host'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -658,7 +678,7 @@ class _ICSParser
|
||||
$output .= "SUMMARY:" . $this->_encodeSpecialCharacters( $event->title ) . "\r\n";
|
||||
$output .= "DTSTAMP:" . \IPS\calendar\Date::ts( $event->saved )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "SEQUENCE:" . $event->sequence . "\r\n";
|
||||
$output .= "UID:" . $this->_buildUid( array( $event->saved, $event->id ) ) . "\r\n";
|
||||
$output .= "UID:" . static::_buildUid( $event ) . "\r\n";
|
||||
$output .= $this->_foldLines( "ORGANIZER;CN=\"" . $this->_encodeSpecialCharacters( $event->author()->name, false ) . '":' . \IPS\Settings::i()->email_out ) . "\r\n";
|
||||
|
||||
/* Attachments */
|
||||
@@ -696,8 +716,8 @@ class _ICSParser
|
||||
}
|
||||
else
|
||||
{
|
||||
$output .= "DTSTART;" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTEND;" . $event->_end_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTART:" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTEND:" . $event->_end_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -708,7 +728,7 @@ class _ICSParser
|
||||
}
|
||||
else
|
||||
{
|
||||
$output .= "DTSTART;" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTART:" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,16 +850,6 @@ class _ICSParser
|
||||
* @brief Raw iCalendar data before parsing
|
||||
*/
|
||||
protected $_rawIcsData = array();
|
||||
|
||||
/**
|
||||
* @brief Temp: Current timezone ID we are parsing
|
||||
*/
|
||||
protected $_tzId = '';
|
||||
|
||||
/**
|
||||
* @brief Temp: Current timezone ID we are beginning to parse
|
||||
*/
|
||||
protected $_tzBegin = '';
|
||||
|
||||
/**
|
||||
* @brief Earliest timestamp from feed
|
||||
@@ -931,32 +941,28 @@ class _ICSParser
|
||||
$_tmp = array();
|
||||
$_key = array();
|
||||
$tmp = explode( ':', $string );
|
||||
$tmp[0] = 'DATETIME';
|
||||
|
||||
/* The date string may be in the format of "DTSTART;20160219T140000Z" (for example) */
|
||||
if ( !isset( $tmp[1] ) )
|
||||
{
|
||||
if ( mb_strpos( $string, ';' ) !== false )
|
||||
{
|
||||
$tmp = explode( ';', $string );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tzid = '';
|
||||
|
||||
/* Got a TZID? */
|
||||
if ( count( $_key ) AND $_key[1] == 'TZID' )
|
||||
{
|
||||
$tzid = $tmp[0];
|
||||
}
|
||||
$tzid = ( count( $_key ) AND $_key[1] == 'TZID' ) ? $tmp[0] : '';
|
||||
|
||||
/* Is it a date? */
|
||||
if ( $tmp[0] == 'DATE' )
|
||||
{
|
||||
$timestamp = strtotime( $tmp[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$timestamp = '?';
|
||||
}
|
||||
/* If the value is a date without a time, then type should be reset to date */
|
||||
$type = ( mb_strlen( $tmp[1] ) === 8 ) ? 'DATE' : 'DATETIME';
|
||||
|
||||
/* Format return array */
|
||||
$return = array(
|
||||
'type' => $tmp[0],
|
||||
'type' => $type,
|
||||
'raw' => $tmp[1],
|
||||
'raw_ts' => strtotime( $tmp[1] ),
|
||||
'ts' => $timestamp,
|
||||
'tzid' => str_replace( '"', '', $tzid ),
|
||||
);
|
||||
|
||||
@@ -990,26 +996,14 @@ class _ICSParser
|
||||
$this->_begin = 'VCALENDAR';
|
||||
$this->_processVcalendarObject( $start + 1 );
|
||||
break;
|
||||
|
||||
case 'VTIMEZONE':
|
||||
$this->_begin = 'VTIMEZONE';
|
||||
$this->_processTimezoneObject( $start + 1 );
|
||||
break;
|
||||
|
||||
|
||||
case 'STANDARD':
|
||||
if ( $this->_begin == 'VTIMEZONE' )
|
||||
{
|
||||
$this->_processTimezoneTypeObject( $start + 1, 'STANDARD' );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DAYLIGHT':
|
||||
if ( $this->_begin == 'VTIMEZONE' )
|
||||
{
|
||||
$this->_processTimezoneTypeObject( $start + 1, 'DAYLIGHT' );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'VEVENT':
|
||||
$this->_begin = 'VEVENT';
|
||||
$this->_processEventObject( $start + 1 );
|
||||
@@ -1249,106 +1243,6 @@ class _ICSParser
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a timezone object in an ical feed
|
||||
*
|
||||
* @param int $start Line number
|
||||
* @param string $type Type of time zone object to parse
|
||||
* @return void
|
||||
*/
|
||||
protected function _processTimezoneTypeObject( $start, $type )
|
||||
{
|
||||
/* Init */
|
||||
$type = mb_strtolower( $type );
|
||||
$break = FALSE;
|
||||
|
||||
/* Loop over the lines */
|
||||
for( $i = $start, $j = count( $this->_rawIcsData ); $i < $j; $i++ )
|
||||
{
|
||||
/* Unparse and get the data */
|
||||
$tmp = $this->_unparseContent( $this->_rawIcsData[$i], $i );
|
||||
|
||||
if ( !$tmp )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$_type = $tmp['type'];
|
||||
$_data = $tmp['data'];
|
||||
|
||||
switch( $_type )
|
||||
{
|
||||
case 'DTSTART':
|
||||
$this->_parsedIcsData['timezones'][ $this->_tzId ][ $type ]['start'] = strtotime( $_data );
|
||||
break;
|
||||
|
||||
case 'TZOFFSETTO':
|
||||
$this->_parsedIcsData['timezones'][ $this->_tzId ][ $type ]['tz_offset_to'] = $_data;
|
||||
break;
|
||||
|
||||
case 'TZOFFSETFROM':
|
||||
$this->_parsedIcsData['timezones'][ $this->_tzId ][ $type ]['tz_offset_from'] = $_data;
|
||||
break;
|
||||
|
||||
case 'TZNAME':
|
||||
$this->_parsedIcsData['timezones'][ $this->_tzId ][ $type ]['tz_name'] = $_data;
|
||||
break;
|
||||
|
||||
case 'END':
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a timezone object in an ical feed
|
||||
*
|
||||
* @param int $start Line number
|
||||
* @return void
|
||||
*/
|
||||
protected function _processTimezoneObject( $start )
|
||||
{
|
||||
/* Loop over the lines */
|
||||
for( $i = $start, $j = count( $this->_rawIcsData ); $i < $j; $i++ )
|
||||
{
|
||||
/* Unparse and get the data */
|
||||
$tmp = $this->_unparseContent( $this->_rawIcsData[$i], $i );
|
||||
|
||||
if( !$tmp )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$_type = $tmp['type'];
|
||||
$_data = $tmp['data'];
|
||||
|
||||
switch( $_type )
|
||||
{
|
||||
case 'TZID':
|
||||
$this->_tzId = $_data;
|
||||
$this->_parsedIcsData['timezones'][ $_data ] = array();
|
||||
break;
|
||||
|
||||
case 'LAST-MODIFIED':
|
||||
$this->_parsedIcsData['timezones'][ $this->_tzId ]['last_modified'] = $_data;
|
||||
break;
|
||||
|
||||
case 'BEGIN':
|
||||
$this->_tzBegin = $_data;
|
||||
$this->_parseBeginBlock( $_data, $i );
|
||||
break;
|
||||
|
||||
case 'END':
|
||||
if ( $this->_tzBegin == $_data )
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unformat content from incoming ical feed
|
||||
*
|
||||
@@ -1384,17 +1278,6 @@ class _ICSParser
|
||||
*/
|
||||
protected function _convertToGmt( $data )
|
||||
{
|
||||
/* Get timezones */
|
||||
$timezones = array();
|
||||
|
||||
if ( isset( $data['timezones'] ) AND is_array( $data['timezones'] ) AND count( $data['timezones'] ) )
|
||||
{
|
||||
foreach( $data['timezones'] as $type => $_data )
|
||||
{
|
||||
$timezones[ $type ] = $_data;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix events */
|
||||
if ( is_array( $data['events'] ) AND count( $data['events'] ) )
|
||||
{
|
||||
@@ -1402,43 +1285,14 @@ class _ICSParser
|
||||
{
|
||||
foreach( array( 'start', 'end' ) as $method )
|
||||
{
|
||||
/* Set up constraints */
|
||||
if ( isset( $event[ $method ]['tzid'] ) AND isset( $timezones[ $event[ $method ]['tzid'] ] ) AND is_array( $timezones[ $event[ $method ]['tzid'] ] ) )
|
||||
/* Is a timezone specified? */
|
||||
if ( isset( $event[ $method ]['tzid'] ) AND $event[ $method ]['tzid'] )
|
||||
{
|
||||
$_standard = ( isset($timezones[ $event[ $method ]['tzid'] ]['standard']['start'] ) ) ? intval( $timezones[ $event[ $method ]['tzid'] ]['standard']['start'] ) : 0;
|
||||
$_daylight = ( isset($timezones[ $event[ $method ]['tzid'] ]['daylight']['start'] ) ) ? intval( $timezones[ $event[ $method ]['tzid'] ]['daylight']['start'] ) : 0;
|
||||
$_offset = 0;
|
||||
|
||||
if ( isset( $event[ $method ]['tzid'] ) AND $event[ $method ]['raw_ts'] )
|
||||
{
|
||||
//if ( $event[ $method ]['raw_ts'] < $_daylight )
|
||||
//{
|
||||
// $_offset = $timezones[ $event[ $method ]['tzid'] ]['standard']['tz_offset_to'];
|
||||
//}
|
||||
//else if ( $event[ $method ]['raw_ts'] > $_standard )
|
||||
//{
|
||||
// $_offset = $timezones[ $event[ $method ]['tzid'] ]['standard']['tz_offset_to'];
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// $_offset = $timezones[ $event[ $method ]['tzid'] ]['daylight']['tz_offset_to'];
|
||||
//}
|
||||
|
||||
$_offset = $timezones[ $event[ $method ]['tzid'] ]['standard']['tz_offset_to'];
|
||||
|
||||
$event[ $method ]['gmt_ts'] = $event[ $method ]['raw_ts'] - ( $_offset / 100 * 3600 );
|
||||
$event[ $method ]['offset'] = $_offset;
|
||||
$event[ $method ]['gmt_rfc'] = gmdate( 'r', $event[ $method ]['gmt_ts'] );
|
||||
}
|
||||
$event[ $method ]['utc_time'] = new \IPS\DateTime( $event[ $method ]['raw'], new \DateTimeZone( $event[ $method ]['tzid'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isset( $event[ $method ]['raw_ts'] ) )
|
||||
{
|
||||
$event[ $method ]['gmt_ts'] = $event[ $method ]['raw_ts'];
|
||||
$event[ $method ]['offset'] = 0;
|
||||
$event[ $method ]['gmt_rfc'] = gmdate( 'r', $event[ $method ]['gmt_ts'] );
|
||||
}
|
||||
$event[ $method ]['utc_time'] = new \IPS\DateTime( $event[ $method ]['raw'] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user