Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -12,9 +12,45 @@
|
||||
namespace IPS\calendar\Icalendar;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use BadFunctionCallException;
|
||||
use BadMethodCallException;
|
||||
use DateInterval;
|
||||
use DateTimeZone;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use IPS\Api\Webhook;
|
||||
use IPS\Application;
|
||||
use IPS\calendar\Calendar;
|
||||
use IPS\calendar\Date;
|
||||
use IPS\calendar\Event;
|
||||
use IPS\calendar\Icalendar;
|
||||
use IPS\Content\Search\Index;
|
||||
use IPS\DateTime;
|
||||
use IPS\Db;
|
||||
use IPS\File;
|
||||
use IPS\GeoLocation;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\Settings;
|
||||
use IPS\Text\Parser;
|
||||
use OutOfRangeException;
|
||||
use UnderflowException;
|
||||
use UnexpectedValueException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function get_class;
|
||||
use function in_array;
|
||||
use function intval;
|
||||
use function is_array;
|
||||
use function is_null;
|
||||
use function stripos;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -22,23 +58,23 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
* iCalendar ICS Parser
|
||||
* @todo [Future] Tags we do not support but may want to look into supporting: EXDATE, EXRULE, RDATE
|
||||
*/
|
||||
class _ICSParser
|
||||
class ICSParser
|
||||
{
|
||||
/**
|
||||
* Parse an RRULE into an array of recurrence data we can use
|
||||
*
|
||||
* @param string $rrule The ICS RRULE value
|
||||
* @param string $timezone Timezone to treat recurring end date as
|
||||
* @param NULL|\IPS\calendar\Date $startDate If supplied, we can use the start date to help convert certain repeat rules to make them simpler
|
||||
* @param string $rrule The ICS RRULE value
|
||||
* @param string|null $timezone Timezone to treat recurring end date as
|
||||
* @param Date|null $startDate If supplied, we can use the start date to help convert certain repeat rules to make them simpler
|
||||
* @return array
|
||||
* @todo [Future] We do not support HOURLY, MINUTELY or SECONDLY "FREQ" values
|
||||
* @todo [Future] We do not support the properties BYSETPOS, BYYEARDAY, BYMONTH, BYHOUR, BYMINUTE, BYSECOND, BYWEEKNO, WKST
|
||||
* @throws InvalidArgumentException
|
||||
* @note Some implementations separate with : and some with ; so we have to support both
|
||||
*@todo [Future] We do not support the properties BYSETPOS, BYYEARDAY, BYMONTH, BYHOUR, BYMINUTE, BYSECOND, BYWEEKNO, WKST
|
||||
* @todo [Future] We do not support complex BYDAY values, such as 1TU or -1FR
|
||||
* @todo [Future] We do not support multiple values for BYMONTHDAY, nor do we support negative values
|
||||
* @throws \InvalidArgumentException
|
||||
* @note Some implementations separate with : and some with ; so we have to support both
|
||||
* @todo [Future] We do not support HOURLY, MINUTELY or SECONDLY "FREQ" values
|
||||
*/
|
||||
public static function parseRrule( $rrule, $timezone=NULL, $startDate = NULL )
|
||||
public static function parseRrule( string $rrule, string $timezone=NULL, Date $startDate = NULL ): array
|
||||
{
|
||||
$rule = array_map( 'trim', explode( ';', str_replace( ':', ';', $rrule ) ) );
|
||||
$dayNames = array();
|
||||
@@ -50,7 +86,7 @@ class _ICSParser
|
||||
'repeat_end_date' => NULL, /* Ends on x date (which is separate from the event end date - e.g. jan 9 2014 3pm to jan 10 2014 3pm, repeat annually until jan 9 2019) */
|
||||
);
|
||||
|
||||
foreach( \IPS\calendar\Date::getDayNames() as $day )
|
||||
foreach( Date::getDayNames() as $day )
|
||||
{
|
||||
$repeatData['repeat_freq_on_' . $day['ical'] ] = NULL; /* If repeating weekly, this is the days of the week as checkboxes (e.g. repeat every wed, fri and sat) */
|
||||
$dayNames[] = $day['ical'];
|
||||
@@ -63,21 +99,20 @@ class _ICSParser
|
||||
switch( $_ruleData[0] )
|
||||
{
|
||||
default:
|
||||
throw new \InvalidArgumentException( $_ruleData[0] );
|
||||
break;
|
||||
throw new InvalidArgumentException( $_ruleData[0] );
|
||||
|
||||
case 'WKST':
|
||||
/* We can safely ignore this when it is set to the default value of MO. We can't make assumptions in other cases. */
|
||||
if( mb_strtolower( $_ruleData[1] ) != 'mo' )
|
||||
{
|
||||
throw new \InvalidArgumentException( $_ruleData[0] );
|
||||
throw new InvalidArgumentException( $_ruleData[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'FREQ':
|
||||
$frequency = mb_strtolower( $_ruleData[1] );
|
||||
|
||||
if( \in_array( $frequency, array( 'daily', 'weekly', 'monthly', 'yearly' ) ) )
|
||||
if( in_array( $frequency, array( 'daily', 'weekly', 'monthly', 'yearly' ) ) )
|
||||
{
|
||||
$repeatData['event_repeats'] = $frequency;
|
||||
$repeatData['event_repeat'] = TRUE;
|
||||
@@ -85,7 +120,7 @@ class _ICSParser
|
||||
else
|
||||
{
|
||||
/* We don't support less than daily*/
|
||||
throw new \InvalidArgumentException( 'FREQ' );
|
||||
throw new InvalidArgumentException( 'FREQ' );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -96,14 +131,14 @@ class _ICSParser
|
||||
{
|
||||
foreach( $dayNames as $dayName )
|
||||
{
|
||||
$dayPos = \stripos( $day, $dayName );
|
||||
$dayPos = stripos( $day, $dayName );
|
||||
|
||||
if( $dayPos !== FALSE )
|
||||
{
|
||||
/* We only support basic day recurrence values, not the negative/positive numbers */
|
||||
if( $dayPos > 0 )
|
||||
{
|
||||
throw new \InvalidArgumentException( 'BYDAY' );
|
||||
throw new InvalidArgumentException( 'BYDAY' );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -119,9 +154,9 @@ class _ICSParser
|
||||
case 'BYMONTHDAY':
|
||||
$values = array_map( 'trim', explode( ',', $_ruleData[1] ) );
|
||||
|
||||
if( \count( $values ) > 1 OR \stripos( $values[0], '-' ) !== FALSE )
|
||||
if( count( $values ) > 1 OR stripos( $values[0], '-' ) !== FALSE )
|
||||
{
|
||||
throw new \InvalidArgumentException( 'BYMONTHDAY' );
|
||||
throw new InvalidArgumentException( 'BYMONTHDAY' );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -134,7 +169,7 @@ class _ICSParser
|
||||
break;
|
||||
|
||||
case 'UNTIL':
|
||||
$repeatData['repeat_end_date'] = new \IPS\calendar\Date( $_ruleData[1], $timezone ? new \DateTimeZone( $timezone ) : NULL );
|
||||
$repeatData['repeat_end_date'] = new Date( $_ruleData[1], $timezone ? new DateTimeZone( $timezone ) : NULL );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -158,15 +193,15 @@ class _ICSParser
|
||||
{
|
||||
$_repeatDays = array();
|
||||
|
||||
foreach( \IPS\calendar\Date::getDayNames() as $day )
|
||||
foreach( Date::getDayNames() as $day )
|
||||
{
|
||||
if( $repeatData['repeat_freq_on_' . $day['ical'] ] == TRUE )
|
||||
if( $repeatData['repeat_freq_on_' . $day['ical']] )
|
||||
{
|
||||
$_repeatDays[] = $day['english'];
|
||||
}
|
||||
}
|
||||
|
||||
if( ( \count( $_repeatDays ) == 1 AND $startDate->weekday == $_repeatDays[0] ) OR \count( $_repeatDays ) == 7 )
|
||||
if( ( count( $_repeatDays ) == 1 AND $startDate->weekday == $_repeatDays[0] ) OR count( $_repeatDays ) == 7 )
|
||||
{
|
||||
foreach( $dayNames as $day )
|
||||
{
|
||||
@@ -182,11 +217,11 @@ class _ICSParser
|
||||
* Create an RRULE value from an array of data
|
||||
*
|
||||
* @note This is basically the opposite of parseRrule
|
||||
* @see self::parseRrule()
|
||||
* @param array $repeat The event repeat data
|
||||
* @return string|NULL
|
||||
*@see self::parseRrule()
|
||||
*/
|
||||
public static function buildRrule( $repeat )
|
||||
public static function buildRrule( array $repeat ): ?string
|
||||
{
|
||||
/* If checkbox was not checked, just return */
|
||||
if( !isset( $repeat['event_repeat'] ) OR !$repeat['event_repeat'] )
|
||||
@@ -208,13 +243,13 @@ class _ICSParser
|
||||
|
||||
if( isset( $repeat['repeat_end_date'] ) AND $repeat['repeat_end_date'] )
|
||||
{
|
||||
$rrule[] = 'UNTIL=' . \IPS\calendar\Date::createFromForm( $repeat['repeat_end_date'], NULL, 'UTC' )->modifiedIso8601();
|
||||
$rrule[] = 'UNTIL=' . Date::createFromForm( $repeat['repeat_end_date'], '', 'UTC' )->modifiedIso8601();
|
||||
}
|
||||
|
||||
/* By-day rule */
|
||||
$days = array();
|
||||
|
||||
foreach( \IPS\calendar\Date::getDayNames() as $day )
|
||||
foreach( Date::getDayNames() as $day )
|
||||
{
|
||||
if( isset( $repeat['repeat_freq_on_' . $day['ical'] ] ) AND $repeat['repeat_freq_on_' . $day['ical'] ] )
|
||||
{
|
||||
@@ -222,7 +257,7 @@ class _ICSParser
|
||||
}
|
||||
}
|
||||
|
||||
if( \count( $days ) )
|
||||
if( count( $days ) )
|
||||
{
|
||||
$rrule[] = 'BYDAY=' . implode( ',', $days );
|
||||
}
|
||||
@@ -233,45 +268,45 @@ class _ICSParser
|
||||
/**
|
||||
* @brief Calendar we are importing to
|
||||
*/
|
||||
protected $calendar = NULL;
|
||||
protected ?Calendar $calendar = NULL;
|
||||
|
||||
/**
|
||||
* @brief Member we are importing as
|
||||
*/
|
||||
protected $member = NULL;
|
||||
protected ?Member $member = NULL;
|
||||
|
||||
/**
|
||||
* @brief Feed we are importing from
|
||||
*/
|
||||
protected $feed = NULL;
|
||||
protected ?Icalendar $feed = NULL;
|
||||
|
||||
/**
|
||||
* Perform some basic error checking
|
||||
*
|
||||
* @param string $content The ICS contents
|
||||
* @param string $content The ICS contents
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws UnexpectedValueException
|
||||
* @note This is abstracted as a static method so we can perform error checking prior to saving the feed
|
||||
*/
|
||||
public static function isValid( $content )
|
||||
public static function isValid( string $content ): bool
|
||||
{
|
||||
/* Perform some basic error checking */
|
||||
if( !$content )
|
||||
{
|
||||
throw new \UnexpectedValueException( "NO_CONTENT" );
|
||||
throw new UnexpectedValueException( "NO_CONTENT" );
|
||||
}
|
||||
|
||||
$_raw = preg_replace( "#(\n\r|\r|\n){1,}#", "\n", $content );
|
||||
$_raw = explode( "\n", $_raw );
|
||||
|
||||
if( !\count($_raw) )
|
||||
if( !count($_raw) )
|
||||
{
|
||||
throw new \UnexpectedValueException( "NO_CONTENT" );
|
||||
throw new UnexpectedValueException( "NO_CONTENT" );
|
||||
}
|
||||
|
||||
if( $_raw[0] != 'BEGIN:VCALENDAR' )
|
||||
{
|
||||
throw new \UnexpectedValueException( "BAD_CONTENT" );
|
||||
throw new UnexpectedValueException( "BAD_CONTENT" );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -280,26 +315,26 @@ class _ICSParser
|
||||
/**
|
||||
* Parse the supplied contents (which may come from a URL or an uploaded file) and import events
|
||||
*
|
||||
* @param string $content The ICS contents
|
||||
* @param int|\IPS\calendar\Calendar $calendar The calendar to import to
|
||||
* @param int|\IPS\Member $member The member the imported events should be 'from'
|
||||
* @param int $feed The feed we are importing (used to detect and prevent duplicate imports)
|
||||
* @param int $venue The venue if provided
|
||||
* @param string $content The ICS contents
|
||||
* @param int|Calendar $calendar The calendar to import to
|
||||
* @param int|Member $member The member the imported events should be 'from'
|
||||
* @param int|null $feed The feed we are importing (used to detect and prevent duplicate imports)
|
||||
* @param int|null $venue The venue if provided
|
||||
* @return array Number of events imported and skipped
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws UnexpectedValueException
|
||||
*/
|
||||
public function parse( $content, $calendar, $member, $feed=NULL, $venue=NULL )
|
||||
public function parse( string $content, Calendar|int $calendar, int|Member $member, int $feed=NULL, int $venue=NULL ): array
|
||||
{
|
||||
/* Load the calendar */
|
||||
$this->calendar = ( $calendar instanceof \IPS\calendar\Calendar ) ? $calendar : \IPS\calendar\Calendar::load( $calendar );
|
||||
$this->calendar = ( $calendar instanceof Calendar ) ? $calendar : Calendar::load( $calendar );
|
||||
|
||||
/* And the member */
|
||||
$this->member = ( $member instanceof \IPS\Member ) ? $member : \IPS\Member::load( $member );
|
||||
$this->member = ( $member instanceof Member ) ? $member : Member::load( $member );
|
||||
|
||||
/* And the feed */
|
||||
if( $feed !== NULL )
|
||||
{
|
||||
$this->feed = \IPS\calendar\Icalendar::load( $feed );
|
||||
$this->feed = Icalendar::load( $feed );
|
||||
}
|
||||
|
||||
/* Perform some basic error checking */
|
||||
@@ -333,7 +368,7 @@ class _ICSParser
|
||||
}
|
||||
|
||||
/* Convert the raw ICS data to GMT now */
|
||||
if( \count($this->_parsedIcsData) )
|
||||
if( count($this->_parsedIcsData) )
|
||||
{
|
||||
$this->_parsedIcsData = $this->_convertToGmt( $this->_parsedIcsData );
|
||||
}
|
||||
@@ -347,7 +382,7 @@ class _ICSParser
|
||||
// Leave this here - useful for debugging
|
||||
// print_r($this->_parsedIcsData);exit;
|
||||
|
||||
if ( \count( $this->_parsedIcsData ) and isset( $this->_parsedIcsData['events'] ) )
|
||||
if ( count( $this->_parsedIcsData ) and isset( $this->_parsedIcsData['events'] ) )
|
||||
{
|
||||
usort( $this->_parsedIcsData['events'], function( $a, $b ) {
|
||||
if ( $a['start']['raw_ts'] == $b['start']['raw_ts'] )
|
||||
@@ -373,18 +408,18 @@ class _ICSParser
|
||||
{
|
||||
$rrule = static::parseRrule( $event['recurr'] );
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
catch( InvalidArgumentException $e )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$event['uid'] = $event['uid'] ? $event['uid'] : md5( implode( ',', $event['start'] ) . implode( ',', $event['end'] ) );
|
||||
$event['uid'] = $event['uid'] ?: md5( implode( ',', $event['start'] ) . implode( ',', $event['end'] ) );
|
||||
|
||||
/* Figure out some times */
|
||||
$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;
|
||||
$event_all_day = $event['start']['type'] == 'DATE';
|
||||
|
||||
/* End dates in iCalendar format are "exclusive", meaning they are actually the day ahead. */
|
||||
/* @link http://microformats.org/wiki/dtend-issue */
|
||||
@@ -393,7 +428,7 @@ class _ICSParser
|
||||
|
||||
if( $event_unix_to AND $event['end']['type'] == 'DATE' AND ( $event_unix_from->getTimestamp() != $event_unix_to->getTimestamp() ) )
|
||||
{
|
||||
$event_unix_to = $event_unix_to->sub( new \DateInterval( 'P1D' ) );
|
||||
$event_unix_to = $event_unix_to->sub( new DateInterval( 'P1D' ) );
|
||||
}
|
||||
|
||||
/* It is a single day event if end date is equal to start date */
|
||||
@@ -406,15 +441,15 @@ class _ICSParser
|
||||
if ( ! $event_unix_to AND isset( $event['duration'] ) AND $event['duration'] )
|
||||
{
|
||||
preg_match( "#(\d+?)H#is", $event['duration'], $match );
|
||||
$hour = isset( $match[1] ) ? $match[1] : 0;
|
||||
$hour = $match[1] ?? 0;
|
||||
|
||||
preg_match( "#(\d+?)M#is", $event['duration'], $match );
|
||||
$minute = isset( $match[1] ) ? $match[1] : 0;
|
||||
$minute = $match[1] ?? 0;
|
||||
|
||||
preg_match( "#(\d+?)S#is", $event['duration'], $match );
|
||||
$second = isset( $match[1] ) ? $match[1] : 0;
|
||||
$second = $match[1] ?? 0;
|
||||
|
||||
$event_unix_to = $event_unix_from->add( new \DateInterval( 'PT' . ( $hour * 3600 ) . 'H' . ( $minute * 60 ) . 'M' . $second . 'S' ) );
|
||||
$event_unix_to = $event_unix_from->add( new DateInterval( 'PT' . ( $hour * 3600 ) . 'H' . ( $minute * 60 ) . 'M' . $second . 'S' ) );
|
||||
}
|
||||
|
||||
/* If this is an all day event, adjust the timestamps */
|
||||
@@ -440,19 +475,19 @@ class _ICSParser
|
||||
try
|
||||
{
|
||||
/* If we are importing an ICS file, feed here will be null. */
|
||||
if ( \is_null( $this->feed ) )
|
||||
if ( is_null( $this->feed ) )
|
||||
{
|
||||
/* Bubble up so we can create a new event */
|
||||
throw new \UnderflowException;
|
||||
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();
|
||||
$eventId = Db::i()->select( 'import_event_id', 'calendar_import_map', array( array( 'import_guid=? and import_feed_id=?', $event['uid'], $this->feed->id ) ) )->first();
|
||||
|
||||
try
|
||||
{
|
||||
$newEvent = \IPS\calendar\Event::load( $eventId );
|
||||
$newEvent = Event::load( $eventId );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException $e )
|
||||
{
|
||||
/* This event seems to have been deleted - skip it. */
|
||||
$_skipped++;
|
||||
@@ -461,9 +496,9 @@ class _ICSParser
|
||||
|
||||
$_skipped++;
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
catch( UnderflowException $e )
|
||||
{
|
||||
$newEvent = new \IPS\calendar\Event;
|
||||
$newEvent = new Event;
|
||||
$_new = TRUE;
|
||||
|
||||
/* Basics */
|
||||
@@ -490,16 +525,16 @@ class _ICSParser
|
||||
/* Basics */
|
||||
$newEvent->title = ( isset( $event['summary'] ) AND $event['summary'] ) ? $event['summary'] : mb_substr( strip_tags( $event['description'] ), 0, 100 );
|
||||
$content = ( isset( $event['description'] ) AND $event['description'] ) ? nl2br( $event['description'] ) : $event['summary'] . ( isset( $event['location'] ) ? '<br>' . $event['location'] : '' );
|
||||
$newEvent->content = \IPS\Text\Parser::parseStatic( $content, TRUE, NULL, $this->member );
|
||||
$newEvent->sequence = ( isset( $event['sequence'] ) ? \intval( $event['sequence'] ) : 0 );
|
||||
$newEvent->content = Parser::parseStatic( $content, NULL, $this->member );
|
||||
$newEvent->sequence = ( isset( $event['sequence'] ) ? intval( $event['sequence'] ) : 0 );
|
||||
|
||||
$newEvent->all_day = $event_all_day;
|
||||
$newEvent->recurring = ( isset( $event['recurr'] ) ) ? $event['recurr'] : 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;
|
||||
$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'] ) )
|
||||
if( isset( $event['geo'] ) AND is_array( $event['geo'] ) AND count( $event['geo'] ) )
|
||||
{
|
||||
/* If we are updating an event, don't pull geo data if we already have it and it hasn't changed */
|
||||
$update = TRUE;
|
||||
@@ -518,22 +553,22 @@ class _ICSParser
|
||||
{
|
||||
try
|
||||
{
|
||||
$newEvent->location = json_encode( \IPS\GeoLocation::getByLatLong( $event['geo']['lat'], $event['geo']['long'] ) );
|
||||
$newEvent->location = json_encode( GeoLocation::getByLatLong( $event['geo']['lat'], $event['geo']['long'] ) );
|
||||
}
|
||||
catch( \BadFunctionCallException $e ){}
|
||||
catch( BadFunctionCallException $e ){}
|
||||
}
|
||||
}
|
||||
elseif( isset( $event['location'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$location = new \IPS\GeoLocation;
|
||||
$location = new GeoLocation;
|
||||
$location->addressLines = array( $event['location'] );
|
||||
$location->getLatLong( TRUE );
|
||||
|
||||
$newEvent->location = json_encode( $location );
|
||||
}
|
||||
catch( \BadFunctionCallException $e ){}
|
||||
catch( BadFunctionCallException $e ){}
|
||||
}
|
||||
|
||||
/* Save */
|
||||
@@ -545,17 +580,17 @@ class _ICSParser
|
||||
/* Increment only if this is a new event */
|
||||
if( $_new )
|
||||
{
|
||||
\IPS\Api\Webhook::fire( str_replace( '\\', '', \substr( \get_class( $newEvent ), 3 ) ) . '_create', $newEvent, $newEvent->webhookFilters() );
|
||||
Webhook::fire( str_replace( '\\', '', substr( get_class( $newEvent ), 3 ) ) . '_create', $newEvent, $newEvent->webhookFilters() );
|
||||
$_newEvents++;
|
||||
}
|
||||
|
||||
/* Add to index */
|
||||
\IPS\Content\Search\Index::i()->index( $newEvent );
|
||||
Index::i()->index( $newEvent );
|
||||
|
||||
/* Update map */
|
||||
if( $this->feed !== NULL AND !$eventId )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'calendar_import_map', array(
|
||||
Db::i()->insert( 'calendar_import_map', array(
|
||||
'import_feed_id' => $this->feed->id,
|
||||
'import_event_id' => $newEvent->id,
|
||||
'import_guid' => $event['uid'],
|
||||
@@ -563,17 +598,17 @@ class _ICSParser
|
||||
}
|
||||
|
||||
/* Add any event attendees that are members of our installation */
|
||||
if( !$eventId AND isset($event['attendee']) AND \count($event['attendee']) )
|
||||
if( !$eventId AND isset($event['attendee']) AND count($event['attendee']) )
|
||||
{
|
||||
foreach( $event['attendee'] as $attendee )
|
||||
{
|
||||
if( $attendee['email'] )
|
||||
{
|
||||
$_loadedMember = \IPS\Member::load( $attendee['email'] );
|
||||
$_loadedMember = Member::load( $attendee['email'] );
|
||||
|
||||
if( $_loadedMember->member_id )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'calendar_event_rsvp', array(
|
||||
Db::i()->insert( 'calendar_event_rsvp', array(
|
||||
'rsvp_member_id' => $_loadedMember->member_id,
|
||||
'rsvp_event_id' => $newEvent->id,
|
||||
'rsvp_date' => time(),
|
||||
@@ -600,29 +635,29 @@ class _ICSParser
|
||||
/**
|
||||
* @brief Array of calendar events we are adding to an iCalendar export
|
||||
*/
|
||||
protected $_events = array();
|
||||
protected array $_events = array();
|
||||
|
||||
/**
|
||||
* Add an event
|
||||
*
|
||||
* @param \IPS\calendar\Event $event Event data
|
||||
* @param Event $event Event data
|
||||
* @return void
|
||||
*/
|
||||
public function addEvent( $event )
|
||||
public function addEvent( Event $event ) : void
|
||||
{
|
||||
if( $event->id )
|
||||
{
|
||||
$this->_events[ $event->id ] = $event;
|
||||
$this->_events[ $event->id ] = $event;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an event
|
||||
*
|
||||
* @param int $eventId Event id
|
||||
* @param int $eventId Event id
|
||||
* @return void
|
||||
*/
|
||||
public function removeEvent( $eventId )
|
||||
public function removeEvent( int $eventId ) : void
|
||||
{
|
||||
if( $eventId )
|
||||
{
|
||||
@@ -633,18 +668,18 @@ class _ICSParser
|
||||
/**
|
||||
* Build iCalendar feed and return
|
||||
*
|
||||
* @param int|\IPS\calendar\Calendar|NULL $calendar The calendar the feed belongs to
|
||||
* @param int|Calendar|null $calendar The calendar the feed belongs to
|
||||
* @return string iCalendar feed (can be downloaded or sent as webcal subscription)
|
||||
*/
|
||||
public function buildICalendarFeed( $calendar=NULL )
|
||||
public function buildICalendarFeed( Calendar|int $calendar=NULL ): string
|
||||
{
|
||||
/* Load the calendar */
|
||||
$this->calendar = ( $calendar instanceof \IPS\calendar\Calendar ) ? $calendar : ( $calendar !== NULL ? \IPS\calendar\Calendar::load( $calendar ) : NULL );
|
||||
$this->calendar = ( $calendar instanceof Calendar ) ? $calendar : ( $calendar !== NULL ? Calendar::load( $calendar ) : NULL );
|
||||
|
||||
/* Start formatting the output */
|
||||
$output = "BEGIN:VCALENDAR\r\n";
|
||||
$output .= "VERSION:2.0\r\n";
|
||||
$output .= "PRODID:-//InvisionCommunity Events " . \IPS\Application::load( 'calendar' )->version . "//EN\r\n";
|
||||
$output .= "PRODID:-//InvisionCommunity Events " . Application::load( 'calendar' )->version . "//EN\r\n";
|
||||
$output .= "METHOD:PUBLISH\r\n";
|
||||
$output .= "CALSCALE:GREGORIAN\r\n";
|
||||
$output .= "REFRESH-INTERVAL:PT15M\r\n";
|
||||
@@ -656,9 +691,9 @@ class _ICSParser
|
||||
}
|
||||
else
|
||||
{
|
||||
$text = \IPS\Member::loggedIn()->language()->get('all_calendars');
|
||||
$output .= "X-WR-CALNAME:" . $this->_encodeSpecialCharacters( $text . ' - ' . \IPS\Settings::i()->board_name ) . "\r\n";
|
||||
$output .= "NAME:" . $this->_encodeSpecialCharacters( $text . ' - ' . \IPS\Settings::i()->board_name ) . "\r\n";
|
||||
$text = Member::loggedIn()->language()->get('all_calendars');
|
||||
$output .= "X-WR-CALNAME:" . $this->_encodeSpecialCharacters( $text . ' - ' . Settings::i()->board_name ) . "\r\n";
|
||||
$output .= "NAME:" . $this->_encodeSpecialCharacters( $text . ' - ' . Settings::i()->board_name ) . "\r\n";
|
||||
}
|
||||
|
||||
/* Add the time zones to the export */
|
||||
@@ -679,7 +714,7 @@ class _ICSParser
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _addTimezones()
|
||||
protected function _addTimezones(): string
|
||||
{
|
||||
/* Initialize */
|
||||
$output = '';
|
||||
@@ -687,7 +722,7 @@ class _ICSParser
|
||||
/* Get the years that all events span */
|
||||
$years = array();
|
||||
|
||||
if( \count( $this->_events ) )
|
||||
if( count( $this->_events ) )
|
||||
{
|
||||
foreach( $this->_events as $event )
|
||||
{
|
||||
@@ -718,14 +753,14 @@ class _ICSParser
|
||||
|
||||
$output .= "BEGIN:VTIMEZONE\r\n";
|
||||
$output .= "TZID:Europe/London\r\n";
|
||||
$output .= "TZURL:http://tzurl.org/zoneinfo/Europe/London\r\n";
|
||||
$output .= "TZURL:https://tzurl.org/zoneinfo/Europe/London\r\n";
|
||||
$output .= "X-LIC-LOCATION:Europe/London\r\n";
|
||||
|
||||
$output .= "BEGIN:DAYLIGHT\r\n";
|
||||
$output .= "TZOFFSETFROM:+0000\r\n";
|
||||
$output .= "TZOFFSETTO:+0100\r\n";
|
||||
$output .= "TZNAME:BST\r\n";
|
||||
$output .= "DTSTART:" . \IPS\calendar\Date::ts( $_daylight )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTART:" . Date::ts( $_daylight )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\n";
|
||||
$output .= "END:DAYLIGHT\r\n";
|
||||
|
||||
@@ -733,7 +768,7 @@ class _ICSParser
|
||||
$output .= "TZOFFSETFROM:+0100\r\n";
|
||||
$output .= "TZOFFSETTO:+0000\r\n";
|
||||
$output .= "TZNAME:GMT\r\n";
|
||||
$output .= "DTSTART:" . \IPS\calendar\Date::ts( $_standard )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTART:" . Date::ts( $_standard )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\n";
|
||||
$output .= "END:STANDARD\r\n";
|
||||
|
||||
@@ -747,12 +782,12 @@ class _ICSParser
|
||||
/**
|
||||
* Return a UID for iCalendar
|
||||
*
|
||||
* @param \IPS\calendar\Event $event Event
|
||||
* @param string
|
||||
* @param Event $event Event
|
||||
* @return string
|
||||
*/
|
||||
protected static function _buildUid( $event )
|
||||
protected static function _buildUid( Event $event ): string
|
||||
{
|
||||
$baseUrl = \IPS\Http\Url::internal('');
|
||||
$baseUrl = Url::internal('');
|
||||
return $event->id . '-' . $event->calendar_id . '-' . md5( (string) $baseUrl ) . '@' . $baseUrl->data['host'];
|
||||
}
|
||||
|
||||
@@ -761,30 +796,30 @@ class _ICSParser
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _addEvents()
|
||||
protected function _addEvents(): string
|
||||
{
|
||||
/* Basic Init */
|
||||
$output = '';
|
||||
|
||||
/* Loop over the events */
|
||||
if( \count( $this->_events ) )
|
||||
if( count( $this->_events ) )
|
||||
{
|
||||
foreach( $this->_events as $event )
|
||||
{
|
||||
/* Normal stuff */
|
||||
$output .= "BEGIN:VEVENT\r\n";
|
||||
$output .= "SUMMARY:" . $this->_encodeSpecialCharacters( $event->title ) . "\r\n";
|
||||
$output .= "DTSTAMP:" . \IPS\calendar\Date::ts( $event->saved )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTAMP:" . Date::ts( $event->saved )->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "SEQUENCE:" . $event->sequence . "\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";
|
||||
$output .= $this->_foldLines( "ORGANIZER;CN=\"" . $this->_encodeSpecialCharacters( $event->author()->name, false ) . '":' . Settings::i()->email_out ) . "\r\n";
|
||||
|
||||
/* Attachments */
|
||||
$attachments = array();
|
||||
|
||||
preg_match_all( "/(http.+?attachment\.php\?id=(\d+))/i", $event->content, $matches );
|
||||
|
||||
if( \is_array($matches) AND \count($matches) )
|
||||
if( is_array($matches) AND count($matches) )
|
||||
{
|
||||
foreach( $matches[2] as $k => $v )
|
||||
{
|
||||
@@ -792,12 +827,12 @@ class _ICSParser
|
||||
}
|
||||
}
|
||||
|
||||
if( \count( $attachments ) )
|
||||
if( count( $attachments ) )
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_attachments', 'attach_id IN(' . implode( ',', array_keys( $attachments ) ) . ')' ) as $attachment )
|
||||
foreach( Db::i()->select( '*', 'core_attachments', 'attach_id IN(' . implode( ',', array_keys( $attachments ) ) . ')' ) as $attachment )
|
||||
{
|
||||
$file = \IPS\File::get( 'core_Attachment', $attachment['attach_location'] );
|
||||
$output .= "ATTACH;FMTTYPE=" . \IPS\File::getMimeType( $file->originalFilename ) . ":" . $attachments[ $attachment['attach_id'] ] . "\r\n";
|
||||
$file = File::get( 'core_Attachment', $attachment['attach_location'] );
|
||||
$output .= "ATTACH;FMTTYPE=" . File::getMimeType( $file->originalFilename ) . ":" . $attachments[ $attachment['attach_id'] ] . "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,7 +845,7 @@ class _ICSParser
|
||||
if( $event->all_day )
|
||||
{
|
||||
$output .= "DTSTART;VALUE=DATE:" . $event->_start_date->modifiedIso8601( FALSE ) . "\r\n";
|
||||
$output .= "DTEND;VALUE=DATE:" . $event->_end_date->add( new \DateInterval( 'P1D' ) )->modifiedIso8601( FALSE ) . "\r\n";
|
||||
$output .= "DTEND;VALUE=DATE:" . $event->_end_date->add( new DateInterval( 'P1D' ) )->modifiedIso8601( FALSE ) . "\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -839,12 +874,12 @@ class _ICSParser
|
||||
/* Any attendees to the event? */
|
||||
try
|
||||
{
|
||||
foreach( $event->attendees( \IPS\calendar\Event::RSVP_YES ) as $attendee )
|
||||
foreach( $event->attendees( Event::RSVP_YES ) as $attendee )
|
||||
{
|
||||
$output .= $this->_foldLines( "ATTENDEE;CN=\"" . $this->_encodeSpecialCharacters( $attendee->name, false ) . '";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:' . \IPS\Settings::i()->email_out ) . "\r\n";
|
||||
$output .= $this->_foldLines( "ATTENDEE;CN=\"" . $this->_encodeSpecialCharacters( $attendee->name, false ) . '";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:' . Settings::i()->email_out ) . "\r\n";
|
||||
}
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
catch( BadMethodCallException $e ){}
|
||||
|
||||
/* End */
|
||||
$output .= "END:VEVENT\r\n";
|
||||
@@ -858,11 +893,11 @@ class _ICSParser
|
||||
/**
|
||||
* Encode special characters in a string for iCalendar
|
||||
*
|
||||
* @param string $text String to encode
|
||||
* @param bool $lineFold Line-fold
|
||||
* @param string $text String to encode
|
||||
* @param bool $lineFold Line-fold
|
||||
* @return string Encoded string
|
||||
*/
|
||||
protected function _encodeSpecialCharacters( $text, $lineFold=true )
|
||||
protected function _encodeSpecialCharacters( string $text, bool $lineFold=true ): string
|
||||
{
|
||||
$text = strip_tags( str_replace( array( "<br>", "<br />" ), "\n", $text ) );
|
||||
$text = str_replace( "\\", "\\\\", $text );
|
||||
@@ -883,16 +918,16 @@ class _ICSParser
|
||||
/**
|
||||
* Fold lines per RFC2445
|
||||
*
|
||||
* @param string $text String to fold
|
||||
* @param string $text String to fold
|
||||
* @return string
|
||||
* @link https://gist.github.com/81747
|
||||
*/
|
||||
protected function _foldLines( $text )
|
||||
protected function _foldLines( string $text ): string
|
||||
{
|
||||
$return = array();
|
||||
$_extra = 15; /* Takes into account line beginning, i.e. "DESCRIPTION:" */
|
||||
|
||||
while( \strlen($text) > 60 )
|
||||
while( strlen($text) > 60 )
|
||||
{
|
||||
$space = 75 - $_extra; /* Remove line beginning - subsequent loops this will be tab character */
|
||||
$mbcc = $space;
|
||||
@@ -900,7 +935,7 @@ class _ICSParser
|
||||
while( $mbcc )
|
||||
{
|
||||
$line = mb_substr( $text, 0, $mbcc ); /* Get first chunk of chars */
|
||||
$octet = \strlen( $line ); /* Determine how long this really is (3-byte letters could triple the size) */
|
||||
$octet = strlen( $line ); /* Determine how long this really is (3-byte letters could triple the size) */
|
||||
|
||||
/* Too long ? */
|
||||
if( $octet > $space )
|
||||
@@ -937,38 +972,38 @@ class _ICSParser
|
||||
/**
|
||||
* @brief Type of begin block we are currently parsing
|
||||
*/
|
||||
protected $_begin = '';
|
||||
protected string $_begin = '';
|
||||
|
||||
/**
|
||||
* @brief Raw iCalendar feed data after parsing
|
||||
*/
|
||||
protected $_parsedIcsData = array();
|
||||
protected array $_parsedIcsData = array();
|
||||
|
||||
/**
|
||||
* @brief Raw iCalendar data before parsing
|
||||
*/
|
||||
protected $_rawIcsData = array();
|
||||
protected array $_rawIcsData = array();
|
||||
|
||||
/**
|
||||
* @brief Earliest timestamp from feed
|
||||
*/
|
||||
protected $_feedEarliest = 0;
|
||||
protected int $_feedEarliest = 0;
|
||||
|
||||
/**
|
||||
* @brief Latest timestamp from feed
|
||||
*/
|
||||
protected $_feedLatest = 0;
|
||||
protected int $_feedLatest = 0;
|
||||
|
||||
/**
|
||||
* Un-encode special characters in a string coming from iCalendar feed
|
||||
*
|
||||
* @param string $text String to unencode
|
||||
* @param string $text String to unencode
|
||||
* @return string Unencoded string
|
||||
*/
|
||||
protected function _unencodeSpecialCharacters( $text )
|
||||
protected function _unencodeSpecialCharacters( string $text ): string
|
||||
{
|
||||
/* Reverse encoding */
|
||||
if( \stripos( $text, 'encoding=' ) === 0 )
|
||||
if( stripos( $text, 'encoding=' ) === 0 )
|
||||
{
|
||||
preg_match( "#encoding=(.+?):(.+?)$#i", $text, $matches );
|
||||
|
||||
@@ -1003,11 +1038,11 @@ class _ICSParser
|
||||
/**
|
||||
* Unfold lines per RFC2445 4.1
|
||||
*
|
||||
* @param string $string Starting string
|
||||
* @param int $line Starting line number
|
||||
* @param string $string Starting string
|
||||
* @param int $line Starting line number
|
||||
* @return string
|
||||
*/
|
||||
protected function _unfoldLines( $string, $line )
|
||||
protected function _unfoldLines( string $string, int $line ): string
|
||||
{
|
||||
/* Recursively unfold lines as needed */
|
||||
if( isset( $this->_rawIcsData[ $line + 1 ] ) AND ( mb_substr( $this->_rawIcsData[ $line + 1 ], 0, 1 ) == ' ' OR mb_substr( $this->_rawIcsData[ $line + 1 ], 0, 1 ) == "\t" ) )
|
||||
@@ -1022,10 +1057,10 @@ class _ICSParser
|
||||
/**
|
||||
* Unparse time information from iCalendar datetime info
|
||||
*
|
||||
* @param string $string iCalendar line
|
||||
* @param string $string iCalendar line
|
||||
* @return array Time information
|
||||
*/
|
||||
protected function _unparseTimeInfo( $string )
|
||||
protected function _unparseTimeInfo( string $string ): array
|
||||
{
|
||||
/* init */
|
||||
$value = NULL;
|
||||
@@ -1089,11 +1124,11 @@ class _ICSParser
|
||||
/**
|
||||
* Parse a 'BEGIN:' block in an iCalendar feed
|
||||
*
|
||||
* @param string $type Type of 'BEGIN' object
|
||||
* @param int $start Line number
|
||||
* @param string $type Type of 'BEGIN' object
|
||||
* @param int $start Line number
|
||||
* @return void
|
||||
*/
|
||||
protected function _parseBeginBlock( $type, $start )
|
||||
protected function _parseBeginBlock( string $type, int $start ) : void
|
||||
{
|
||||
switch( $type )
|
||||
{
|
||||
@@ -1123,15 +1158,15 @@ class _ICSParser
|
||||
/**
|
||||
* @brief Keep track of object we are parsing inside an event object
|
||||
*/
|
||||
protected $currentlyParsing = NULL;
|
||||
protected ?string $currentlyParsing = NULL;
|
||||
|
||||
/**
|
||||
* Parse event object in an ical feed
|
||||
*
|
||||
* @param int $start Line number
|
||||
* @param int $start Line number
|
||||
* @return void
|
||||
*/
|
||||
protected function _processEventObject( $start )
|
||||
protected function _processEventObject( int $start ) : void
|
||||
{
|
||||
/* Init */
|
||||
$_break = false;
|
||||
@@ -1142,7 +1177,7 @@ class _ICSParser
|
||||
/* Loop over the lines */
|
||||
$_recid = null;
|
||||
|
||||
for( $i = $start, $j = \count( $this->_rawIcsData ); $i < $j; $i++ )
|
||||
for( $i = $start, $j = count( $this->_rawIcsData ); $i < $j; $i++ )
|
||||
{
|
||||
/* Unparse and get content */
|
||||
$tmp = $this->_unparseContent( $this->_rawIcsData[$i], $i );
|
||||
@@ -1155,7 +1190,7 @@ class _ICSParser
|
||||
$_type = $tmp['type'];
|
||||
$_data = $tmp['data'];
|
||||
|
||||
if( $this->currentlyParsing != 'EVENT' AND !\in_array( $_type, array( 'END', 'BEGIN' ) ) )
|
||||
if( $this->currentlyParsing != 'EVENT' AND !in_array( $_type, array( 'END', 'BEGIN' ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1258,7 +1293,7 @@ class _ICSParser
|
||||
break;
|
||||
|
||||
case 'SEQUENCE':
|
||||
$_event['sequence'] = \intval($_data);
|
||||
$_event['sequence'] = intval($_data);
|
||||
break;
|
||||
|
||||
case 'RRULE':
|
||||
@@ -1302,13 +1337,13 @@ class _ICSParser
|
||||
/**
|
||||
* Parse core vcalendar object in an ical feed
|
||||
*
|
||||
* @param int $start Line number
|
||||
* @param int $start Line number
|
||||
* @return void
|
||||
*/
|
||||
protected function _processVcalendarObject( $start )
|
||||
protected function _processVcalendarObject( int $start ) : void
|
||||
{
|
||||
/* Loop over the lines */
|
||||
for( $i = $start, $j = \count( $this->_rawIcsData ); $i < $j; $i++ )
|
||||
for( $i = $start, $j = count( $this->_rawIcsData ); $i < $j; $i++ )
|
||||
{
|
||||
/* Unparse and get the data */
|
||||
$tmp = $this->_unparseContent( $this->_rawIcsData[$i], $i );
|
||||
@@ -1341,7 +1376,6 @@ class _ICSParser
|
||||
|
||||
case 'END':
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1349,14 +1383,14 @@ class _ICSParser
|
||||
/**
|
||||
* Unformat content from incoming ical feed
|
||||
*
|
||||
* @param string $string String content to unparse
|
||||
* @param int $line Line number
|
||||
* @param string $string String content to unparse
|
||||
* @param int $line Line number
|
||||
* @return mixed Array of data, or false
|
||||
*/
|
||||
protected function _unparseContent( $string, $line )
|
||||
protected function _unparseContent( string $string, int $line ): mixed
|
||||
{
|
||||
/* If the line starts with a space it was folded (skip it) */
|
||||
if( \substr( $this->_rawIcsData[ $line ], 0, 1 ) == ' ' )
|
||||
if( substr( $this->_rawIcsData[ $line ], 0, 1 ) == ' ' )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1376,13 +1410,13 @@ class _ICSParser
|
||||
/**
|
||||
* Convert times to GMT based on timezones
|
||||
*
|
||||
* @param array $data Parsed data
|
||||
* @param array $data Parsed data
|
||||
* @return array
|
||||
*/
|
||||
protected function _convertToGmt( $data )
|
||||
protected function _convertToGmt( array $data ): array
|
||||
{
|
||||
/* Fix events */
|
||||
if ( isset( $data['events'] ) AND \is_array( $data['events'] ) AND \count( $data['events'] ) )
|
||||
if ( isset( $data['events'] ) AND is_array( $data['events'] ) AND count( $data['events'] ) )
|
||||
{
|
||||
foreach( $data['events'] as $id => $event )
|
||||
{
|
||||
@@ -1394,20 +1428,20 @@ class _ICSParser
|
||||
/* Let's test it first... */
|
||||
$timezone = NULL;
|
||||
|
||||
if( \in_array( $event[ $method ]['tzid'], \IPS\DateTime::getTimezoneIdentifiers() ) )
|
||||
if( in_array( $event[ $method ]['tzid'], DateTime::getTimezoneIdentifiers() ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$timezone = new \DateTimeZone( $event[ $method ]['tzid'] );
|
||||
$timezone = new DateTimeZone( $event[ $method ]['tzid'] );
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
catch ( Exception $e ) {}
|
||||
}
|
||||
|
||||
$event[ $method ]['utc_time'] = new \IPS\DateTime( $event[ $method ]['raw'], $timezone );
|
||||
$event[ $method ]['utc_time'] = new DateTime( $event[ $method ]['raw'], $timezone );
|
||||
}
|
||||
elseif( isset( $event[ $method ]['raw'] ) )
|
||||
{
|
||||
$event[ $method ]['utc_time'] = new \IPS\DateTime( $event[ $method ]['raw'] );
|
||||
$event[ $method ]['utc_time'] = new DateTime( $event[ $method ]['raw'] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user