Added jsvrcek\ics composer package.

This commit is contained in:
alext 2017-11-01 14:23:44 +01:00
parent 32e618975a
commit 6aab04ce17
26 changed files with 3470 additions and 37 deletions

View file

@ -34,6 +34,7 @@
"roave/security-advisories": "dev-master",
"gregwar/captcha": "^1.1",
"phpmailer/phpmailer": "^5.2",
"codeigniter/framework": "3.1.6"
"codeigniter/framework": "3.1.6",
"jsvrcek/ics": "^0.5.1"
}
}

50
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "8c888cb85f0aee3ee5b357c38a3182e4",
"content-hash": "cc53442fb0e3041fbf3d22ed9f5bcca5",
"packages": [
{
"name": "codeigniter/framework",
@ -87,6 +87,54 @@
],
"time": "2015-09-11T15:23:20+00:00"
},
{
"name": "jsvrcek/ics",
"version": "0.5.1",
"source": {
"type": "git",
"url": "https://github.com/jasvrcek/ICS.git",
"reference": "c93b8dba37b35dd0b65d7b76c7d5b8bc38ecc74c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jasvrcek/ICS/zipball/c93b8dba37b35dd0b65d7b76c7d5b8bc38ecc74c",
"reference": "c93b8dba37b35dd0b65d7b76c7d5b8bc38ecc74c",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Jsvrcek\\ICS\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Justin Svrcek",
"homepage": "https://github.com/jasvrcek"
}
],
"description": "abstraction layer for creating multi-byte safe RFC 5545 compliant .ics files",
"homepage": "https://github.com/jasvrcek/ICS",
"keywords": [
".ics",
"RFC 5545",
"calendar",
"export",
"ical",
"multi-byte safe"
],
"time": "2017-02-01T20:10:20+00:00"
},
{
"name": "phpmailer/phpmailer",
"version": "v5.2.23",

View file

@ -9,6 +9,7 @@ return array(
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
'Jsvrcek\\ICS\\' => array($vendorDir . '/jsvrcek/ics/src'),
'Gregwar\\Captcha\\' => array($vendorDir . '/gregwar/captcha'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),

View file

@ -19,6 +19,10 @@ class ComposerStaticInit745c9af234090db98769aa0b5014bcf4
array (
'Symfony\\Component\\Yaml\\' => 23,
),
'J' =>
array (
'Jsvrcek\\ICS\\' => 12,
),
'G' =>
array (
'Gregwar\\Captcha\\' => 16,
@ -45,6 +49,10 @@ class ComposerStaticInit745c9af234090db98769aa0b5014bcf4
array (
0 => __DIR__ . '/..' . '/symfony/yaml',
),
'Jsvrcek\\ICS\\' =>
array (
0 => __DIR__ . '/..' . '/jsvrcek/ics/src',
),
'Gregwar\\Captcha\\' =>
array (
0 => __DIR__ . '/..' . '/gregwar/captcha',

View file

@ -1,39 +1,4 @@
[
{
"name": "codeigniter/framework",
"version": "3.1.5",
"version_normalized": "3.1.5.0",
"source": {
"type": "git",
"url": "https://github.com/bcit-ci/CodeIgniter.git",
"reference": "6c7a4266410070d30f8f6bcdf9c9e67f3d6478e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bcit-ci/CodeIgniter/zipball/6c7a4266410070d30f8f6bcdf9c9e67f3d6478e3",
"reference": "6c7a4266410070d30f8f6bcdf9c9e67f3d6478e3",
"shasum": ""
},
"require": {
"php": ">=5.3.7"
},
"require-dev": {
"mikey179/vfsstream": "1.1.*",
"phpunit/phpunit": "4.* || 5.*"
},
"suggest": {
"paragonie/random_compat": "Provides better randomness in PHP 5.x"
},
"time": "2017-06-19T08:33:58+00:00",
"type": "project",
"installation-source": "dist",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "The CodeIgniter framework",
"homepage": "https://codeigniter.com"
},
{
"name": "gregwar/captcha",
"version": "v1.1.1",
@ -1649,5 +1614,90 @@
"testing",
"xunit"
]
},
{
"name": "codeigniter/framework",
"version": "3.1.6",
"version_normalized": "3.1.6.0",
"source": {
"type": "git",
"url": "https://github.com/bcit-ci/CodeIgniter.git",
"reference": "7e4f63cd4b792e7dc2dc4b8b0183a6072a3f9462"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bcit-ci/CodeIgniter/zipball/7e4f63cd4b792e7dc2dc4b8b0183a6072a3f9462",
"reference": "7e4f63cd4b792e7dc2dc4b8b0183a6072a3f9462",
"shasum": ""
},
"require": {
"php": ">=5.3.7"
},
"require-dev": {
"mikey179/vfsstream": "1.1.*",
"phpunit/phpunit": "4.* || 5.*"
},
"suggest": {
"paragonie/random_compat": "Provides better randomness in PHP 5.x"
},
"time": "2017-09-25T16:43:58+00:00",
"type": "project",
"installation-source": "dist",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "The CodeIgniter framework",
"homepage": "https://codeigniter.com"
},
{
"name": "jsvrcek/ics",
"version": "0.5.1",
"version_normalized": "0.5.1.0",
"source": {
"type": "git",
"url": "https://github.com/jasvrcek/ICS.git",
"reference": "c93b8dba37b35dd0b65d7b76c7d5b8bc38ecc74c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jasvrcek/ICS/zipball/c93b8dba37b35dd0b65d7b76c7d5b8bc38ecc74c",
"reference": "c93b8dba37b35dd0b65d7b76c7d5b8bc38ecc74c",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.5"
},
"time": "2017-02-01T20:10:20+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Jsvrcek\\ICS\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Justin Svrcek",
"homepage": "https://github.com/jasvrcek"
}
],
"description": "abstraction layer for creating multi-byte safe RFC 5545 compliant .ics files",
"homepage": "https://github.com/jasvrcek/ICS",
"keywords": [
".ics",
"RFC 5545",
"calendar",
"export",
"ical",
"multi-byte safe"
]
}
]

View file

@ -0,0 +1,295 @@
<?php
namespace Jsvrcek\ICS;
use Jsvrcek\ICS\Model\CalendarAlarm;
use Jsvrcek\ICS\Model\Recurrence\RecurrenceRule;
use Jsvrcek\ICS\Utility\Formatter;
use Jsvrcek\ICS\Model\Calendar;
use Jsvrcek\ICS\Model\CalendarEvent;
use Jsvrcek\ICS\Model\Description\Location;
use Jsvrcek\ICS\Model\Relationship\Attendee;
use Jsvrcek\ICS\Model\Relationship\Organizer;
use Jsvrcek\ICS\CalendarStream;
class CalendarExport
{
/**
*
* @var array
*/
private $calendars = array();
/**
*
* @var CalendarStream;
*/
private $stream;
/**
*
* @var Formatter
*/
private $formatter;
public function __construct(CalendarStream $stream, Formatter $formatter)
{
$this->stream = $stream;
$this->formatter = $formatter;
}
/**
* @return CalendarStream
*/
public function getStreamObject()
{
return $this->stream;
}
/**
* @return string
*/
public function getStream()
{
$this->stream->reset();
/* @var $cal Calendar */
foreach ($this->getCalendars() as $cal)
{
//start calendar
$this->stream->addItem('BEGIN:VCALENDAR')
->addItem('VERSION:'.$cal->getVersion())
->addItem('PRODID:'.$cal->getProdId())
->addItem('CALSCALE:'.$cal->getCalendarScale())
->addItem('METHOD:'.$cal->getMethod());
//custom headers
foreach ($cal->getCustomHeaders() as $key => $value)
{
$this->stream->addItem($key.':'.$value);
}
//timezone
$this->stream->addItem('BEGIN:VTIMEZONE');
$tz = $cal->getTimezone();
$transitions = $tz->getTransitions(strtotime('1970-01-01'), strtotime('1970-12-31'));
$daylightSavings = array(
'exists' => false,
'start' => '',
'offsetTo' => '',
'offsetFrom' => ''
);
$standard = array(
'start' => '',
'offsetTo' => '',
'offsetFrom' => ''
);
foreach ($transitions as $transition)
{
$varName = ($transition['isdst']) ? 'daylightSavings' : 'standard';
${$varName}['exists'] = true;
${$varName}['start'] = $this->formatter->getFormattedDateTime(new \DateTime($transition['time']));
${$varName}['offsetTo'] = $this->formatter->getFormattedTimeOffset($transition['offset']);
//get previous offset
$previousTimezoneObservance = $transition['ts'] - 100;
$tzDate = new \DateTime('now', $tz);
$tzDate->setTimestamp($previousTimezoneObservance);
$offset = $tzDate->getOffset();
${$varName}['offsetFrom'] = $this->formatter->getFormattedTimeOffset($offset);
}
$this->stream->addItem('TZID:'.$tz->getName());
$this->stream->addItem('BEGIN:STANDARD')
->addItem('DTSTART:'.$standard['start'])
->addItem('TZOFFSETTO:'.$standard['offsetTo'])
->addItem('TZOFFSETFROM:'.$standard['offsetFrom']);
if ($daylightSavings['exists'])
{
$this->stream->addItem('RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU');
}
$this->stream->addItem('END:STANDARD');
if ($daylightSavings['exists'])
{
$this->stream->addItem('BEGIN:DAYLIGHT')
->addItem('DTSTART:'.$daylightSavings['start'])
->addItem('TZOFFSETTO:'.$daylightSavings['offsetTo'])
->addItem('TZOFFSETFROM:'.$daylightSavings['offsetFrom'])
->addItem('RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU')
->addItem('END:DAYLIGHT');
}
$this->stream->addItem('END:VTIMEZONE');
//add events
/* @var $event CalendarEvent */
foreach ($cal->getEvents() as $event)
{
$dtStart = $event->isAllDay() ?
$this->formatter->getFormattedDate($event->getStart()) :
$this->formatter->getFormattedDateTime($event->getStart());
$dtEnd = $event->isAllDay() ?
$this->formatter->getFormattedDate($event->getEnd()) :
$this->formatter->getFormattedDateTime($event->getEnd());
$this->stream->addItem('BEGIN:VEVENT')
->addItem('UID:'.$event->getUid())
->addItem('DTSTART:'. $dtStart)
->addItem('DTEND:'. $dtEnd);
if ($event->getRecurrenceRule() instanceof RecurrenceRule)
$this->stream->addItem($event->getRecurrenceRule()->__toString());
foreach ($event->getExceptionDates() as $date)
{
$this->stream->addItem('EXDATE:'.$this->formatter->getFormattedDateTime($date));
}
if ($event->getSequence())
$this->stream->addItem('SEQUENCE:'.$event->getSequence());
$this->stream->addItem('STATUS:'.$event->getStatus())
->addItem('SUMMARY:'.$event->getSummary())
->addItem('DESCRIPTION:'.$event->getDescription());
if ($event->getClass())
$this->stream->addItem('CLASS:'.$event->getClass());
/* @var $location Location */
foreach ($event->getLocations() as $location)
{
$this->stream
->addItem('LOCATION'.$location->getUri().$location->getLanguage().':'.$location->getName());
}
if ($event->getPriority() > 0 && $event->getPriority() <= 9)
$this->stream->addItem('PRIORITY:'.$event->getPriority());
if ($event->getGeo())
$this->stream->addItem('GEO:'.$event->getGeo()->getLatitude().';'.$event->getGeo()->getLongitude());
if ($event->getUrl())
$this->stream->addItem('URL:'.$event->getUrl());
if ($event->getTimestamp())
{
$this->stream->addItem('DTSTAMP:'.$this->formatter->getFormattedUTCDateTime($event->getTimestamp()));
}
else
{
$this->stream->addItem('DTSTAMP:'.$this->formatter->getFormattedUTCDateTime(new \DateTime()));
}
if ($event->getCreated())
$this->stream->addItem('CREATED:'.$this->formatter->getFormattedUTCDateTime($event->getCreated()));
if ($event->getLastModified())
$this->stream->addItem('LAST-MODIFIED:'.$this->formatter->getFormattedUTCDateTime($event->getLastModified()));
foreach ($event->getAttendees() as $attendee)
{
$this->stream->addItem($attendee->__toString());
}
if ($event->getOrganizer())
$this->stream->addItem($event->getOrganizer()->__toString());
/** @var CalendarAlarm $alarm */
foreach ($event->getAlarms() as $alarm)
{
//basic requirements for all types of alarm
$this->stream->addItem('BEGIN:VALARM')
->addItem('TRIGGER;VALUE=DATE-TIME:'.$this->formatter->getFormattedUTCDateTime($alarm->getTrigger()))
->addItem('ACTION:'.$alarm->getAction());
//only handle repeats if both repeat and duration are set
if ($alarm->getRepeat() && $alarm->getDuration()) {
$this->stream->addItem('REPEAT:'.$alarm->getRepeat())
->addItem('DURATION:'.$this->formatter->getFormattedDateInterval($alarm->getDuration()));
}
//action specific logic
switch ($alarm->getAction())
{
case 'AUDIO':
$attachments = $alarm->getAttachments();
$this->stream->addItem('ATTACH;'.$attachments[0]);
break;
case 'DISPLAY':
$this->stream->addItem('DESCRIPTION:'.$alarm->getDescription());
break;
case 'EMAIL':
$this->stream->addItem('SUMMARY:'.$alarm->getSummary())
->addItem('DESCRIPTION:'.$alarm->getDescription());
foreach ($alarm->getAttendees() as $attendee)
{
$this->stream->addItem($attendee->__toString());
}
foreach ($alarm->getAttachments() as $attachment)
{
$this->stream->addItem('ATTACH;'.$attachment);
}
break;
default:
throw new \Exception("Unknown ALARM action: '{$alarm->getAction()}'");
break;
}
$this->stream->addItem('END:VALARM');
}
$this->stream->addItem('END:VEVENT');
}
//end calendar
$this->stream->addItem('END:VCALENDAR');
}
return $this->stream->getStream();
}
/**
* @return array
*/
public function getCalendars()
{
return $this->calendars;
}
/**
* @param array $calendars
* @return CalendarExport
*/
public function setCalendars(array $calendars)
{
$this->calendars = $calendars;
return $this;
}
/**
* @param Calendar $cal
* @return CalendarExport
*/
public function addCalendar(Calendar $cal)
{
$this->calendars[] = $cal;
return $this;
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace Jsvrcek\ICS;
use Jsvrcek\ICS\Constants;
class CalendarStream
{
//length of line in bytes
const LINE_LENGTH = 70;
/**
* echo items as they are set rather than building stream in memory, for use with streaming a large calendar
*
* @var boolean
*/
private $doImmediateOutput = false;
/**
*
* @var string
*/
private $stream = '';
/**
* @param boolean $doImmediateOutput
*/
public function setDoImmediateOutput($doImmediateOutput)
{
$this->doImmediateOutput = $doImmediateOutput;
}
/**
* resets stream to blank string
*/
public function reset()
{
$this->stream = '';
}
/**
* @return string
*/
public function getStream()
{
return $this->stream;
}
/**
* splits item into new lines if necessary
* @param string $item
* @return CalendarStream
*/
public function addItem($item)
{
//get number of bytes
$length = strlen($item);
$block = '';
if ($length > 75)
{
$start = 0;
while ($start < $length)
{
$block .= mb_strcut($item, $start, self::LINE_LENGTH, 'UTF-8');
$start = $start + self::LINE_LENGTH;
//add space if not last line
if ($start < $length) $block .= Constants::CRLF.' ';
}
}
else
{
$block = $item;
}
$this->stream .= $block.Constants::CRLF;
if ($this->doImmediateOutput)
{
echo $this;
$this->reset();
}
return $this;
}
/**
* @return string
*/
public function __toString()
{
return $this->getStream();
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace Jsvrcek\ICS;
class Constants
{
const CRLF = "\r\n";
}

View file

@ -0,0 +1,8 @@
<?php
namespace Jsvrcek\ICS\Exception;
class CalendarEventException extends CalendarException
{
}

View file

@ -0,0 +1,8 @@
<?php
namespace Jsvrcek\ICS\Exception;
class CalendarException extends \Exception
{
}

View file

@ -0,0 +1,8 @@
<?php
namespace Jsvrcek\ICS\Exception;
class CalendarRecurrenceException extends CalendarException
{
}

View file

@ -0,0 +1,293 @@
<?php
namespace Jsvrcek\ICS\Model;
use Jsvrcek\ICS\Utility\Provider;
class Calendar
{
/**
*
* @var string $version
*/
private $version = '2.0';
/**
*
* @var string $prodId
*/
private $prodId = '';
/**
*
* @var string $calendarScale
*/
private $calendarScale = 'GREGORIAN';
/**
*
* @var string $method
*/
private $method = 'PUBLISH';
/**
*
* @var array $customHeaders
*/
private $customHeaders = array();
/**
*
* @var \DateTimeZone $timezone
*/
private $timezone;
/**
*
* @var Provider
*/
private $events;
/**
*
* @var Provider
*/
private $todos;
/**
*
* @var Provider
*/
private $freeBusy;
/**
*
*/
public function __construct()
{
$this->timezone = new \DateTimeZone('America/New_York');
$this->events = new Provider();
$this->todos = new Provider();
$this->freeBusy = new Provider();
}
/**
* For use if you want CalendarExport::getStream to get events in batches from a database during
* the output of the ics feed, instead of adding all events to the Calendar object before outputting
* the ics feed.
* - CalendarExport::getStream iterates through the Calendar::$events internal data array. The $eventsProvider
* closure will be called every time this data array reaches its end during iteration, and the closure should
* return the next batch of events
* - A $startKey argument with the current key of the data array will be passed to the $eventsProvider closure
* - The $eventsProvider must return an array of CalendarEvent objects
*
* Example: Calendar::setEventsProvider(function($startKey){
* //get database rows starting with $startKey
* //return an array of CalendarEvent objects
* })
*
* @param \Closure $eventsProvider
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setEventsProvider(\Closure $eventsProvider)
{
$this->events = new Provider($eventsProvider);
return $this;
}
/**
* @return string
*/
public function getVersion()
{
return $this->version;
}
/**
* @param string $version
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setVersion($version)
{
$this->version = $version;
return $this;
}
/**
* @return string
*/
public function getProdId()
{
return $this->prodId;
}
/**
* @param string $prodId
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setProdId($prodId)
{
$this->prodId = $prodId;
return $this;
}
/**
* @return string
*/
public function getCalendarScale()
{
return $this->calendarScale;
}
/**
* @param string $calendarScale
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setCalendarScale($calendarScale)
{
$this->calendarScale = $calendarScale;
return $this;
}
/**
* @return string
*/
public function getMethod()
{
return $this->method;
}
/**
* @param string $method
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setMethod($method)
{
$this->method = $method;
return $this;
}
/**
* @return array
*/
public function getCustomHeaders()
{
return $this->customHeaders;
}
/**
* use to add custom headers as array key-value pairs<br>
* <strong>Example:</strong> $customHeaders = array('X-WR-TIMEZONE' => 'America/New_York')
*
* @param array $customHeaders
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setCustomHeaders(array $customHeaders)
{
$this->customHeaders = $customHeaders;
return $this;
}
/**
* @param string $key
* @param string $value
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function addCustomHeader($key, $value)
{
$this->customHeaders[$key] = $value;
return $this;
}
/**
* @return \DateTimeZone
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* @param \DateTimeZone $timezone
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setTimezone(\DateTimeZone $timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* @return Provider
*/
public function getEvents()
{
return $this->events;
}
/**
* @param CalendarEvent $event
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function addEvent(CalendarEvent $event)
{
$this->events->add($event);
return $this;
}
/**
* @return array $todos returs array of CalendarTodo objects
*/
public function getTodos()
{
return $this->todos;
}
/**
* @param CalendarTodo $todo
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function addTodo(CalendarTodo $todo)
{
$this->todos[] = $todo;
return $this;
}
/**
* @param array $todos
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setTodos(array $todos)
{
$this->todos = $todos;
return $this;
}
/**
* @return array $freeBusy returs array of CalendarFreeBusy objects
*/
public function getFreeBusy()
{
return $this->freeBusy;
}
/**
* @param CalendarFreeBusy $todo
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function addFreeBusy(CalendarFreeBusy $todo)
{
$this->freeBusy[] = $todo;
return $this;
}
/**
* @param array $freeBusy
* @return \Jsvrcek\ICS\Model\Calendar
*/
public function setFreeBusy(array $freeBusy)
{
$this->freeBusy = $freeBusy;
return $this;
}
}

View file

@ -0,0 +1,246 @@
<?php
namespace Jsvrcek\ICS\Model;
use Jsvrcek\ICS\Model\Relationship\Attendee;
use Jsvrcek\ICS\Utility\Formatter;
/**
* See http://icalendar.org/iCalendar-RFC-5545/3-6-6-alarm-component.html
*
* Class CalendarAlarm
* @package Jsvrcek\ICS\Model
*/
class CalendarAlarm
{
/**
*
* @var string $action
*/
private $action;
/**
* RFC 5545 supports triggers relative to the parent VEVENT or VTODO, but Jsvrcek\ICS does not.
* Only absolute trigger times are supported.
* @todo Support RELATED, DTSTART, and DTEND.
*
* @var \DateTime $trigger
*/
private $trigger;
/**
* For AUDIO and EMAIL actions only.
* For AUDIO there must be exactly one attachment, which must point to a sound resource.
* For EMAIL there can be any number of attachments, including zero.
*
* Should be a string including a path and a file type, like so:
*
* "FMTTYPE=application/msword:http://example.com/agenda.doc"
*
* @var array $attachments
*/
private $attachments = array();
/**
* For DISPLAY and EMAIL actions only. For EMAIL this is the body.
*
* @var string $description
*/
private $description;
/**
* For EMAIL action only. This is the email subject.
*
* @var string $summary
*/
private $summary;
/**
* For EMAIL action only. This is the email recipients.
*
* @var array $attendees
*/
private $attendees = array();
/**
* For all actions. The number of times to repeat the alarm.
* If REPEAT is set then DURATION must also be set.
*
* @var integer $repeat
*/
private $repeat;
/**
* For all actions. The duration of the alarm.
* If DURATION is set then REPEAT must also be set.
*
* @var \DateInterval $duration
*/
private $duration;
/**
* @return string
*
*/
public function getAction()
{
return $this->action;
}
/**
* @param string $action
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setAction($action)
{
$action = strtoupper($action);
$this->action = $action;
return $this;
}
/**
* @return \DateTime
*/
public function getTrigger()
{
return $this->trigger;
}
/**
* @param \DateTime $trigger
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setTrigger($trigger)
{
$this->trigger = $trigger;
return $this;
}
/**
* @return array
*/
public function getAttachments()
{
return $this->attachments;
}
/**
* @param array $attachments
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setAttachments($attachments)
{
$this->attachments = $attachments;
return $this;
}
/**
* @param string $attachment
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function addAttachment($attachment)
{
$this->attachments[] = $attachment;
return $this;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return string
*/
public function getSummary()
{
return $this->summary;
}
/**
* @param string $summary
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setSummary($summary)
{
$this->summary = $summary;
return $this;
}
/**
* @return array $attendees array of Attendee objects
*/
public function getAttendees()
{
return $this->attendees;
}
/**
* @param array $attendees array of Attendee objects
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setAttendees(array $attendees)
{
$this->attendees = $attendees;
return $this;
}
/**
* @param Attendee $attendee
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function addAttendee(Attendee $attendee)
{
$this->attendees[] = $attendee;
return $this;
}
/**
* @return int
*/
public function getRepeat()
{
return $this->repeat;
}
/**
* @param int $repeat
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setRepeat($repeat)
{
$this->repeat = $repeat;
return $this;
}
/**
* @return \DateInterval
*/
public function getDuration()
{
return $this->duration;
}
/**
* @param \DateInterval $duration
* @return \Jsvrcek\ICS\Model\CalendarAlarm
*/
public function setDuration($duration)
{
$this->duration = $duration;
return $this;
}
}

View file

@ -0,0 +1,620 @@
<?php
namespace Jsvrcek\ICS\Model;
use Jsvrcek\ICS\Model\Recurrence\RecurrenceRule;
use Jsvrcek\ICS\Model\Description\Geo;
use Jsvrcek\ICS\Model\Description\Location;
use Jsvrcek\ICS\Model\Relationship\Organizer;
use Jsvrcek\ICS\Model\Relationship\Attendee;
use Jsvrcek\ICS\Model\CalendarAlarm;
use Jsvrcek\ICS\Exception\CalendarEventException;
/**
* @author justinsvrcek
* http://tools.ietf.org/html/rfc5545#page-52
*/
class CalendarEvent
{
/**
*
* @var string $uid
*/
private $uid;
/**
*
* @var \DateTime $start
*/
private $start;
/**
*
* @var \DateTime $end
*/
private $end;
/**
*
* @var RecurrenceRule
*/
private $recurrenceRule;
/**
* array of dates to skip
* https://tools.ietf.org/html/rfc5545#page-120
*
* @var array
*/
private $exceptionDates = array();
/**
* @var string $class
*/
private $class;
/**
* @var \DateTime $created
*/
private $created;
/**
*
* @var string $description
*/
private $description;
/**
* @var Geo $geo
*/
private $geo;
/**
* @var string $lastModified
*/
private $lastModified;
/**
* @var array $locations
*/
private $locations = array();
/**
*
* @var Organizer $organizer
*/
private $organizer;
/**
*
* @var string $priority
*/
private $priority;
/**
*
* @var \DateTime $timestamp
*/
private $timestamp;
/**
*
* @var string $status
*/
private $status;
/**
*
* @var string $summary
*/
private $summary;
/**
* @todo add support in CalendarExport
* @var string $recuringId
*/
private $recuringId;
/**
*
* @var integer
*/
private $sequence;
/**
*
* @var array $attendees
*/
private $attendees = array();
/**
*
* @var array $alarms
*/
private $alarms = array();
/**
* @var string $url
*/
private $url;
/**
* @var boolean
*/
private $allDay = false;
/**
* @return boolean
*/
public function isAllDay()
{
return $this->allDay;
}
/**
* @param boolean $allDay
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setAllDay($allDay)
{
$this->allDay = $allDay;
return $this;
}
/**
* @return string
*/
public function getUid()
{
return $this->uid;
}
/**
* @param string $uid
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setUid($uid)
{
$this->uid = $uid;
return $this;
}
/**
* @return \DateTime
*/
public function getStart()
{
return $this->start;
}
/**
* also sets end time to 30 minutes after start as default<br>
* - end time can be overridden with setEnd()
*
* @param \DateTime $start
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setStart(\DateTime $start)
{
$this->start = $start;
$end = clone $start;
$this->setEnd($end->add(\DateInterval::createFromDateString('30 minutes')));
return $this;
}
/**
* @return \DateTime
*/
public function getEnd()
{
return $this->end;
}
/**
* @param \DateTime $end
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setEnd(\DateTime $end)
{
//check End is greater than Start
if ($this->getStart() instanceof \DateTime)
{
if ($this->getStart() > $end)
throw new CalendarEventException('End DateTime must be greater than Start DateTime');
}
else
{
throw new CalendarEventException('You must set the Start time before setting the End Time of a CalendarEvent');
}
$this->end = $end;
return $this;
}
/**
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function getRecurrenceRule()
{
return $this->recurrenceRule;
}
/**
* @param RecurrenceRule $recurrenceRule
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
{
$this->recurrenceRule = $recurrenceRule;
return $this;
}
/**
* array of DateTime instances
* @param array $dates
*/
public function setExceptionDates(array $dates)
{
$this->exceptionDates = $dates;
return $this;
}
/**
* @return array
*/
public function getExceptionDates()
{
return $this->exceptionDates;
}
/**
* @param \DateTime $date
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function addExceptionDate(\DateTime $date)
{
$this->exceptionDates[] = $date;
return $this;
}
/**
* @return the string
*/
public function getSummary()
{
return $this->summary;
}
/**
* @param string $summary
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setSummary($summary)
{
$this->summary = $summary;
return $this;
}
/**
* @return the string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return array $alarms returs array of CalendarAlarm objects
*/
public function getAlarms()
{
return $this->alarms;
}
/**
* @param CalendarAlarm $alarm
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function addAlarm(CalendarAlarm $alarm)
{
$this->alarms[] = $alarm;
return $this;
}
/**
* @param array $alarms
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setAlarms(array $alarms)
{
$this->alarms = $alarms;
return $this;
}
/**
*
* @return string
*/
public function getClass()
{
return $this->class;
}
/**
*
* @param string $class
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setClass($class)
{
$this->class = $class;
return $this;
}
/**
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
*
* @param \DateTime $created
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setCreated(\DateTime $created)
{
$this->created = $created;
return $this;
}
/**
*
* @return Geo|null
*/
public function getGeo()
{
return $this->geo;
}
/**
*
* @param Geo $geo
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setGeo(Geo $geo)
{
$this->geo = $geo;
return $this;
}
/**
*
* @return \DateTime
*/
public function getLastModified()
{
return $this->lastModified;
}
/**
*
* @param \DateTime $lastModified
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setLastModified(\DateTime $lastModified)
{
$this->lastModified = $lastModified;
return $this;
}
/**
*
* @return array $locations array of Location objects
*/
public function getLocations()
{
return $this->locations;
}
/**
*
* @param array $locations array of Location objects
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setLocations(array $locations)
{
$this->locations = $locations;
return $this;
}
/**
*
* @param Location $location
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function addLocation(Location $location)
{
$this->locations[] = $location;
return $this;
}
/**
*
* @return Organizer
*/
public function getOrganizer()
{
return $this->organizer;
}
/**
*
* @param Organizer $organizer
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setOrganizer(Organizer $organizer)
{
$this->organizer = $organizer;
return $this;
}
/**
*
* @return string
*/
public function getPriority()
{
return $this->priority;
}
/**
*
* @param string $priority
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setPriority($priority)
{
$this->priority = $priority;
return $this;
}
/**
*
* @return \DateTime
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
*
* @param \DateTime $timestamp
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setTimestamp(\DateTime $timestamp)
{
$this->timestamp = $timestamp;
return $this;
}
/**
*
* @return string
*/
public function getStatus()
{
return $this->status;
}
/**
*
* @param string $status
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
*
* @return string
*/
public function getRecuringId()
{
return $this->recuringId;
}
/**
*
* @param string $recuringId
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setRecuringId($recuringId)
{
$this->recuringId = $recuringId;
return $this;
}
/**
* @return integer
*/
public function getSequence()
{
return $this->sequence;
}
/**
* @param integer $sequence
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setSequence($sequence)
{
$this->sequence = $sequence;
return $this;
}
/**
*
* @return array $attendees array of Attendee objects
*/
public function getAttendees()
{
return $this->attendees;
}
/**
*
* @param array $attendees array of Attendee objects
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setAttendees(array $attendees)
{
$this->attendees = $attendees;
return $this;
}
/**
* @param Attendee $attendee
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function addAttendee(Attendee $attendee)
{
$this->attendees[] = $attendee;
return $this;
}
/**
* @param string $url
* @return \Jsvrcek\ICS\Model\CalendarEvent
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return string
*/
public function getUrl()
{
return $this->url;
}
}

View file

@ -0,0 +1,8 @@
<?php
namespace Jsvrcek\ICS\Model;
class CalendarFreeBusy
{
}

View file

@ -0,0 +1,8 @@
<?php
namespace Jsvrcek\ICS\Model;
class CalendarTodo
{
}

View file

@ -0,0 +1,53 @@
<?php
namespace Jsvrcek\ICS\Model\Description;
class Geo
{
/**
* @var float $latitude
*/
private $latitude;
/**
*
* @var float $longitude
*/
private $longitude;
/**
* @return number
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* @param float $latitude
* @return \Jsvrcek\ICS\Model\Description\Geo
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* @return number
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* @param float $longitude
* @return \Jsvrcek\ICS\Model\Description\Geo
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace Jsvrcek\ICS\Model\Description;
class Location
{
/**
*
* @var string $name
*/
private $name;
/**
*
* @var string $uri
*/
private $uri;
/**
*
* @var string $language
*/
private $language;
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
* @return \Jsvrcek\ICS\Model\Description\Location
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getUri()
{
return $this->uri;
}
/**
* @param string $uri uri to vCard or other uri
* @return \Jsvrcek\ICS\Model\Description\Location
*/
public function setUri($uri)
{
$this->uri = ';ALTREP="' . $uri . '"';
return $this;
}
/**
* @return string
*/
public function getLanguage()
{
return $this->language;
}
/**
* @param string $language RFC 1766 language identifier
* @return \Jsvrcek\ICS\Model\Description\Location
*/
public function setLanguage($language)
{
$this->language = ';LANGUAGE='.$language;
return $this;
}
}

View file

@ -0,0 +1,90 @@
<?php
namespace Jsvrcek\ICS\Model\Recurrence\DataType;
use Jsvrcek\ICS\Exception\CalendarRecurrenceException;
/**
* @author justinsvrcek
* http://tools.ietf.org/html/rfc5545#page-38
*/
class Frequency
{
const KEY = 'FREQ';
const SECONDLY = 1;
const MINUTELY = 2;
const HOURLY = 3;
const DAILY = 4;
const WEEKLY = 5;
const MONTHLY = 6;
const YEARLY = 7;
/**
*
* @var integer
*/
private $freq;
public static $values = array(
self::SECONDLY => 'SECONDLY',
self::MINUTELY => 'MINUTELY',
self::HOURLY => 'HOURLY',
self::DAILY => 'DAILY',
self::WEEKLY => 'WEEKLY',
self::MONTHLY => 'MONTHLY',
self::YEARLY => 'YEARLY'
);
/**
* @param integer $frequency Frequency::SECONDLY, Frequency::MINUTELY,
* Frequency::HOURLY, Frequency::DAILY, Frequency::WEEKLY,
* Frequency::MONTHLY, Frequency::YEARLY
*/
public function __construct($frequency)
{
$this->validateFrequency($frequency);
$this->freq = $frequency;
}
/**
* @return number
*/
public function getFreq()
{
return $this->freq;
}
/**
* @param integer $freq
* @return \Jsvrcek\ICS\Model\Recurrence\DataType\Frequency
*/
public function setFreq($freq)
{
$this->validateFrequency($freq);
$this->freq = $freq;
return $this;
}
/**
* @param integer $frequency
* @throws CalendarRecurrenceException
*/
private function validateFrequency($frequency)
{
if (!is_int($frequency) || $frequency < 1 || $frequency > 7)
{
throw new CalendarRecurrenceException('You must pass a Frequency constant to the contructor.');
}
}
/**
* @return string
*/
public function __toString()
{
return self::KEY.'='.self::$values[$this->freq];
}
}

View file

@ -0,0 +1,92 @@
<?php
namespace Jsvrcek\ICS\Model\Recurrence\DataType;
use Jsvrcek\ICS\Exception\CalendarRecurrenceException;
/**
* @author justinsvrcek
* http://tools.ietf.org/html/rfc5545#page-38
*/
class Weekday
{
const SUNDAY = 1;
const MONDAY = 2;
const TUESDAY = 3;
const WEDNESDAY = 4;
const THURSDAY = 5;
const FRIDAY = 6;
const SATURDAY = 7;
/**
*
* @var integer
*/
private $weekday;
/**
*
* @var array
*/
protected $values = array(
self::SUNDAY => 'SU',
self::MONDAY => 'MO',
self::TUESDAY => 'TU',
self::WEDNESDAY => 'WE',
self::THURSDAY => 'TH',
self::FRIDAY => 'FR',
self::SATURDAY => 'SA'
);
/**
* @param integer $weekday Weekday::SUNDAY, Weekday::MONDAY,
* Weekday::TUESDAY, Weekday::WEDNESDAY, Weekday::THURSDAY,
* Weekday::FRIDAY, Weekday::SATURDAY
*/
public function __construct($weekday)
{
$this->validateWeekday($weekday);
$this->weekday = $weekday;
}
/**
* @return number
*/
public function getWeekday()
{
return $this->weekday;
}
/**
* @param integer $weekday
* @return \Jsvrcek\ICS\Model\Recurrence\DataType\Weekday
*/
public function setWeekday($weekday)
{
$this->validateWeekday($weekday);
$this->weekday = $weekday;
return $this;
}
/**
* @param integer $weekday
* @throws CalendarRecurrenceException
*/
private function validateWeekday($weekday)
{
if (!is_int($weekday) || $weekday < 1 || $weekday > 7)
{
throw new CalendarRecurrenceException('You must pass a Weekday constant to the contructor.');
}
}
/**
* @return string
*/
public function __toString()
{
return $this->values[$this->weekday];
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace Jsvrcek\ICS\Model\Recurrence\DataType;
use Jsvrcek\ICS\Exception\CalendarRecurrenceException;
/**
* @author justinsvrcek
* http://tools.ietf.org/html/rfc5545#page-38
*/
class WeekdayNum extends Weekday
{
const COUNT_FROM_START = null;
const COUNT_FROM_END = '-';
/**
*
* @var integer 1-53
*/
private $weekdaynum;
/**
*
* @var mixed
*/
private $countFromStartOrEnd;
/**
* WeekdayNum(Weekday::MONDAY, 2, WeekdayNum:COUNT_FROM_END) will convert to the
* string "-2MO", or "second from last Monday"
*
* @param integer $weekday
* @param integer $weekdaynum
* @param string $countFromStartOrEnd
*/
public function __construct($weekday, $weekdaynum = null, $countFromStartOrEnd = null)
{
parent::__construct($weekday);
$this->validateWeekdayNum($weekdaynum);
$this->validateCountFromStartOrEnd($countFromStartOrEnd);
$this->weekdaynum = $weekdaynum;
$this->countFromStartOrEnd = $countFromStartOrEnd;
}
/* (non-PHPdoc)
* @see Jsvrcek\ICS\Model\Recurrence\DataType.Weekday::__toString()
*/
public function __toString()
{
return $this->countFromStartOrEnd.$this->weekdaynum.parent::__toString();
}
/**
* @param mixed $countFromStartOrEnd
* @throws CalendarRecurrenceException
*/
private function validateCountFromStartOrEnd($countFromStartOrEnd)
{
if ($countFromStartOrEnd !== self::COUNT_FROM_START && $countFromStartOrEnd !== self::COUNT_FROM_END)
{
throw new CalendarRecurrenceException('You must use WeekdayNum::COUNT_FROM_START or WeekdayNum::COUNT_FROM_END');
}
}
/**
* @param integer $weekdaynum
* @throws CalendarRecurrenceException
*/
private function validateWeekdayNum($weekdaynum)
{
if (!is_int($weekdaynum) || $weekdaynum < 1 || $weekdaynum > 53)
{
throw new CalendarRecurrenceException('$weekdaynum must be an integer between 1 and 53');
}
}
}

View file

@ -0,0 +1,536 @@
<?php
namespace Jsvrcek\ICS\Model\Recurrence;
use Jsvrcek\ICS\Utility\Formatter;
use Jsvrcek\ICS\Model\Recurrence\DataType\Frequency;
use Jsvrcek\ICS\Model\Recurrence\DataType\Weekday;
use Jsvrcek\ICS\Model\Recurrence\DataType\WeekdayNum;
use Jsvrcek\ICS\Exception\CalendarRecurrenceException;
/**
* @todo BYSECOND, BYMINUTE, BYHOUR, BYMONTHDAY, BYYEARDAY, BYWEEKNO, BYMONTH, BYSETPOS, and WKST
* are not implemented in the __toString function yet
*
* @author justinsvrcek
* http://tools.ietf.org/html/rfc5545#page-37
*/
class RecurrenceRule
{
const KEY = 'RRULE:';
/**
*
* @var Frequency
*/
private $frequency;
/**
*
* @var \DateTime
*/
private $until;
/**
*
* @var integer
*/
private $count;
/**
*
* @var integer
*/
private $interval;
/**
*
* @var array
*/
private $bySecondList = array();
/**
*
* @var array
*/
private $byMinuteList = array();
/**
*
* @var array
*/
private $byHourList = array();
/**
*
* @var array
*/
private $byDayList = array();
/**
* @todo need to add to RecurrenceRule::__toString()
*
* @var array
*/
private $byMonthDayList = array();
/**
* @todo need to add to RecurrenceRule::__toString()
*
* @var array
*/
private $byYearDayList = array();
/**
* @todo need to add to RecurrenceRule::__toString()
*
* @var array
*/
private $byWeekNumberList = array();
/**
* @todo need to add to RecurrenceRule::__toString()
*
* @var array
*/
private $byMonthList = array();
/**
* @todo need to add to RecurrenceRule::__toString()
*
* @var array
*/
private $bySetPosYearDayList = array();
/**
* @todo need to add to RecurrenceRule::__toString()
*
* @var Weekday
*/
private $weekStart;
/**
*
* @var Formatter
*/
private $formatter;
/**
* @param Formatter $formatter
*/
public function __construct(Formatter $formatter)
{
$this->formatter = $formatter;
}
/**
* @return \Jsvrcek\ICS\Model\Recurrence\Frequency
*/
public function getFrequency()
{
return $this->frequency;
}
/**
* @param Frequency $frequency
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setFrequency(Frequency $frequency)
{
$this->frequency = $frequency;
return $this;
}
/**
*
* @return \DateTime
*/
public function getUntil()
{
return $this->until;
}
/**
*
* @param \DateTime $until = null
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setUntil(\DateTime $until = null)
{
$this->until = $until;
return $this;
}
/**
*
* @return integer
*/
public function getCount()
{
return $this->count;
}
/**
* @param integer $count
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setCount($count)
{
$this->validateInteger($count);
$this->count = $count;
return $this;
}
/**
*
* @return integer
*/
public function getInterval()
{
return $this->interval;
}
/**
* @param integer $interval
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setInterval($interval)
{
$this->validateInteger($interval);
$this->interval = $interval;
return $this;
}
/**
* @return array
*/
public function getBySecondList()
{
return $this->bySecondList;
}
/**
* @param array $bySecondList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setBySecondList(array $bySecondList)
{
$this->bySecondList = $bySecondList;
return $this;
}
/**
* @param integer $integer 0-60
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function addBySecond($integer)
{
$this->validateInteger($integer);
$this->bySecondList[] = $integer;
return $this;
}
/**
*
* @return array
*/
public function getByMinuteList()
{
return $this->byMinuteList;
}
/**
* @param array $byMinuteList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByMinuteList(array $byMinuteList)
{
$this->byMinuteList = $byMinuteList;
return $this;
}
/**
* @param integer $integer 0-59
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function addByMinute($integer)
{
$this->validateInteger($integer);
$this->byMinuteList[] = $integer;
return $this;
}
/**
*
* @return array
*/
public function getByHourList()
{
return $this->byHourList;
}
/**
* @param array $byHourList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByHourList(array $byHourList)
{
$this->byHourList = $byHourList;
return $this;
}
/**
* @param integer $integer 0-23
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function addByHour($integer)
{
$this->validateInteger($integer);
$this->byHourList[] = $integer;
return $this;
}
/**
*
* @return array
*/
public function getByDayList()
{
return $this->byDayList;
}
/**
* @param array $byDayList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByDayList(array $byDayList)
{
$this->byDayList = $byDayList;
return $this;
}
/**
* @param WeekdayNum $weekdaynum
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function addByDay(WeekdayNum $weekdaynum)
{
$this->byDayList[] = $weekdaynum;
return $this;
}
/**
*
* @return array
*/
public function getByMonthDayList()
{
return $this->byMonthDayList;
}
/**
* @param array $byMonthDayList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByMonthDayList(array $byMonthDayList)
{
$this->byMonthDayList = $byMonthDayList;
return $this;
}
/**
* @param integer $integer
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function addByMonthDay($integer)
{
$this->validateInteger($integer);
$this->byMonthDayList[] = $bySecond;
return $this;
}
/**
*
* @return array
*/
public function getByYearDayList()
{
return $this->byYearDayList;
}
/**
* @param array $byYearDayList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByYearDayList(array $byYearDayList)
{
$this->byYearDayList = $byYearDayList;
return $this;
}
/**
*
* @return array
*/
public function getByWeekNumberList()
{
return $this->byWeekNumberList;
}
/**
* @param array $byWeekNumberList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByWeekNumberList(array $byWeekNumberList)
{
$this->byWeekNumberList = $byWeekNumberList;
return $this;
}
/**
*
* @return array
*/
public function getByMonthList()
{
return $this->byMonthList;
}
/**
* @param array $byMonthList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setByMonthList(array $byMonthList)
{
$this->byMonthList = $byMonthList;
return $this;
}
/**
*
* @return array
*/
public function getBySetPosYearDayList()
{
return $this->bySetPosYearDayList;
}
/**
* @param array $bySetPosYearDayList
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setBySetPosYearDayList(array $bySetPosYearDayList)
{
$this->bySetPosYearDayList = $bySetPosYearDayList;
return $this;
}
/**
*
* @return Weekday
*/
public function getWeekStart()
{
return $this->weekStart;
}
/**
* @param Weekday $weekStart
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function setWeekStart(Weekday $weekStart)
{
$this->weekStart = $weekStart;
return $this;
}
/**
* parses an RRULE string, hydrates self with values
*
* @param string $rRuleString
* @return \Jsvrcek\ICS\Model\Recurrence\RecurrenceRule
*/
public function parse($rRuleString)
{
//remove RRULE:
$string = str_replace(self::KEY, null, $rRuleString);
$attributes = explode(';', $string);
foreach ($attributes as $attribute)
{
list($key, $value) = explode('=', $attribute);
switch ($key)
{
case Frequency::KEY:
if ($valueStringKey = array_search($value, Frequency::$values))
{
$this->setFrequency(new Frequency($valueStringKey));
}
else
{
throw new CalendarRecurrenceException('Unsupported FREQ value in Recurrence Rule (RRULE) string: '.$value);
}
break;
case 'INTERVAL':
$this->setInterval((int)$value);
break;
case 'UNTIL':
$untilDate = new \DateTime(str_replace('Z', '', $value), new \DateTimeZone('UTC'));
$this->setUntil($untilDate);
break;
default:
throw new CalendarRecurrenceException('Unsupported attribute in Recurrence Rule (RRULE) string: '.$key);
}
}
return $this;
}
/**
* @return string
*/
public function __toString()
{
$items = array($this->getFrequency()->__toString());
if ($this->interval)
$items[] = 'INTERVAL='.$this->interval;
if ($this->until)
$items[] = 'UNTIL='.$this->formatter->getFormattedUTCDateTime($this->until);
if ($this->count)
$items[] = 'COUNT='.$this->count;
if ($this->byDayList)
$items[] = 'BYDAY='.implode(',', $this->byDayList);
return self::KEY.implode(';', $items);
}
/**
* @param integer $integer
* @throws CalendarRecurrenceException
*/
private function validateInteger($integer)
{
if (!is_int($integer))
{
throw new CalendarRecurrenceException('Value must be an integer');
}
}
}

View file

@ -0,0 +1,438 @@
<?php
namespace Jsvrcek\ICS\Model\Relationship;
use Jsvrcek\ICS\Utility\Formatter;
class Attendee
{
/**
*
* @var Formatter
*/
private $formatter;
/**
* RFC 5545 cal-address
* @var string $value
*/
private $value;
/**
* RFC 5545 cutypeparam
* @var string $calendarUserType
*/
private $calendarUserType;
/**
* RFC 5545 memberparam
* @var array $calendarMember array of uri values
*/
private $calendarMembers = array();
/**
* RFC 5545 roleparam
* @var string $role
*/
private $role;
/**
* RFC 5545 partstatparam
* @var string $participationStatus
*/
private $participationStatus;
/**
* RFC 5545 rsvpparam
* @var string $rsvp
*/
private $rsvp;
/**
* RFC 5545 deltoparam
* @var array $delegatedTo array of uri values
*/
private $delegatedTo = array();
/**
* RFC 5545 delfromparam
* @var array $delegatedFrom array of uri values
*/
private $delegatedFrom = array();
/**
* RFC 5545 sentbyparam
* @var string $sentBy
*/
private $sentBy;
/**
* RFC 5545 cnparam
* @var string $name
*/
private $name;
/**
* RFC 5545 dirparam
* @var string $directory
*/
private $directory;
/**
* RFC 5545 languageparam
* @var string $language
*/
private $language;
/**
* @param Formatter $formatter
*/
public function __construct(Formatter $formatter)
{
$this->formatter = $formatter;
}
/**
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* RFC 5545 cal-address http://tools.ietf.org/html/rfc5545#section-3.3.3
* @param string $uri
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setValue($uri)
{
$this->value = $this->formatter->getFormattedUri($uri);
return $this;
}
/**
* @return string
*/
public function getCalendarUserType()
{
return $this->calendarUserType;
}
/**
* RFC 5545 cutypeparam http://tools.ietf.org/html/rfc5545#section-3.2.3
*
* @param string $calendarUserType
* "INDIVIDUAL" ; An individual<br>
* "GROUP" ; A group of individuals<br>
* "RESOURCE" ; A physical resource<br>
* "ROOM" ; A room resource<br>
* "UNKNOWN" ; Otherwise not known<br>
* x-name ; Experimental type<br>
* iana-token) ; Other IANA-registered type
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setCalendarUserType($calendarUserType)
{
$this->calendarUserType = $calendarUserType;
return $this;
}
/**
* @return array
*/
public function getCalendarMembers()
{
return $this->calendarMembers;
}
/**
* RFC 5545 memberparam http://tools.ietf.org/html/rfc5545#section-3.2.11
* @param array $calendarMemberUris array of uri values for calendar users ex. array('sue@example.com', 'joe@example.com')
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setCalendarMembers($calendarMemberUris)
{
foreach ($calendarMemberUris as &$uri)
{
$uri = $this->formatter->getFormattedUri($uri);
}
$this->calendarMembers = $calendarMemberUris;
return $this;
}
/**
* RFC 5545 memberparam http://tools.ietf.org/html/rfc5545#section-3.2.11
* @param string $uri
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function addCalendarMember($uri)
{
$this->calendarMembers[] = $this->formatter->getFormattedUri($uri);
return $this;
}
/**
* @return string
*/
public function getRole()
{
return $this->role;
}
/**
* RFC 5545 roleparam http://tools.ietf.org/html/rfc5545#section-3.2.16
* @param string $role
* "CHAIR" ; Indicates chair of the calendar entity <br>
* "REQ-PARTICIPANT" ; Indicates a participant whose participation is required <br>
* "OPT-PARTICIPANT" ; Indicates a participant whose participation is optional <br>
* "NON-PARTICIPANT" ; Indicates a participant who is copied for information purposes only <br>
* x-name ; Experimental role
* iana-token ; Other IANA role
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* @return string
*/
public function getParticipationStatus()
{
return $this->participationStatus;
}
/**
* RFC 5545 partstatparam http://tools.ietf.org/html/rfc5545#section-3.2.12
* @param string $participationStatus
* Example values for an Event: <br>
* "NEEDS-ACTION" ; Event needs action <br>
* "ACCEPTED" ; Event accepted <br>
* "DECLINED" ; Event declined <br>
* "TENTATIVE" ; Event tentatively accepted <br>
* "DELEGATED" ; Event delegated
*
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setParticipationStatus($participationStatus)
{
$this->participationStatus = $participationStatus;
return $this;
}
/**
* @return string
*/
public function getRsvp()
{
return $this->rsvp;
}
/**
* RFC 5545 rsvpparam http://tools.ietf.org/html/rfc5545#section-3.2.17
* @param string $rsvp "TRUE" or "FALSE"
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setRsvp($rsvp)
{
$this->rsvp = $rsvp;
return $this;
}
/**
* @return array
*/
public function getDelegatedTo()
{
return $this->delegatedTo;
}
/**
* RFC 5545 deltoparam http://tools.ietf.org/html/rfc5545#section-3.2.5
* @param array $delegatedToUris array of uri values for calendar users ex. array('sue@example.com', 'joe@example.com')
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setDelegatedTo(array $delegatedToUris)
{
foreach ($delegatedToUris as &$uri)
{
$uri = $this->formatter->getFormattedUri($uri);
}
$this->delegatedTo = $delegatedToUris;
return $this;
}
/**
* @param string $uri uri value for calendar users ex. 'mary@example.com'
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function addDelegatedTo($uri)
{
$this->delegatedTo[] = $this->formatter->getFormattedUri($uri);
return $this;
}
/**
* @return array
*/
public function getDelegatedFrom()
{
return $this->delegatedFrom;
}
/**
* RFC 5545 delfromparam http://tools.ietf.org/html/rfc5545#section-3.2.4
* @param array $delegatedFromUris array of uri values for calendar users ex. array('sue@example.com', 'joe@example.com')
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setDelegatedFrom(array $delegatedFromUris)
{
foreach ($delegatedFromUris as &$uri)
{
$uri = $this->formatter->getFormattedUri($uri);
}
$this->delegatedFrom = $delegatedFromUris;
return $this;
}
/**
* @param string $uri uri value for calendar users ex. 'mary@example.com'
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function addDelegatedFrom($uri)
{
$this->delegatedFrom[] = $this->formatter->getFormattedUri($uri);
return $this;
}
/**
* @return string
*/
public function getSentBy()
{
return $this->sentBy;
}
/**
* RFC 5545 sentbyparam http://tools.ietf.org/html/rfc5545#section-3.2.18
* @param string $sentBy email address
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setSentBy($sentBy)
{
$this->sentBy = $sentBy;
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getDirectory()
{
return $this->directory;
}
/**
* RFC 5545 dirparam http://tools.ietf.org/html/rfc5545#section-3.2.6
* @param string $directory uri directory entry associated with the calendar user
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setDirectory($uri)
{
$this->directory = $uri;
return $this;
}
/**
* @return string
*/
public function getLanguage()
{
return $this->language;
}
/**
* @param string $language RFC 1766 language identifier
* @return \Jsvrcek\ICS\Model\Relationship\Attendee
*/
public function setLanguage($language)
{
$this->language = $language;
return $this;
}
/**
* @return string
*/
public function __toString()
{
$string = 'ATTENDEE';
if ($this->calendarUserType)
$string .= ';CUTYPE='.$this->calendarUserType;
if (count($this->calendarMembers))
{
$string .= ';MEMBER="'.implode('","', $this->calendarMembers).'"';
}
if ($this->role)
$string .= ';ROLE='.$this->role;
if ($this->participationStatus)
$string .= ';PARTSTAT='.$this->participationStatus;
if ($this->rsvp)
$string .= ';RSVP='.$this->rsvp;
if (count($this->delegatedTo))
{
$string .= ';DELEGATED-TO="'.implode('","', $this->delegatedTo).'"';
}
if (count($this->delegatedFrom))
{
$string .= ';DELEGATED-FROM="'.implode('","', $this->delegatedFrom).'"';
}
if ($this->sentBy)
$string .= ';SENT-BY="'.$this->sentBy.'"';
if ($this->name)
$string .= ';CN='.$this->name;
if ($this->directory)
$string .= ';DIR="'.$this->directory.'"';
if ($this->language)
$string .= ';LANGUAGE='.$this->language;
$string .= ':'.$this->value;
return $string;
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace Jsvrcek\ICS\Model\Relationship;
use Jsvrcek\ICS\Utility\Formatter;
class Organizer
{
/**
*
* @var Formatter
*/
private $formatter;
/**
* RFC 5545 cal-address
* @var string $value
*/
private $value;
/**
* RFC 5545 cnparam
* @var string $name
*/
private $name;
/**
* RFC 5545 dirparam
* @var string $directory
*/
private $directory;
/**
* RFC 5545 sentbyparam
* @var string $sentBy
*/
private $sentBy;
/**
* RFC 5545 languageparam
* @var string $language
*/
private $language;
/**
* @param Formatter $formatter
*/
public function __construct(Formatter $formatter)
{
$this->formatter = $formatter;
}
/**
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* RFC 5545 cal-address http://tools.ietf.org/html/rfc5545#section-3.3.3
* @param string $uri
* @return \Jsvrcek\ICS\Model\Relationship\Organizer
*/
public function setValue($uri)
{
$this->value = $this->formatter->getFormattedUri($uri);
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
* @return \Jsvrcek\ICS\Model\Relationship\Organizer
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getDirectory()
{
return $this->directory;
}
/**
* RFC 5545 dirparam http://tools.ietf.org/html/rfc5545#section-3.2.6
* @param string $directory uri directory entry associated with the calendar user
* @return \Jsvrcek\ICS\Model\Relationship\Organizer
*/
public function setDirectory($uri)
{
$this->directory = $uri;
return $this;
}
/**
* @return string
*/
public function getSentBy()
{
return $this->sentBy;
}
/**
* RFC 5545 sentbyparam http://tools.ietf.org/html/rfc5545#section-3.2.18
* @param string $sentBy email address
* @return \Jsvrcek\ICS\Model\Relationship\Organizer
*/
public function setSentBy($sentBy)
{
$this->sentBy = $sentBy;
return $this;
}
/**
* @return string
*/
public function getLanguage()
{
return $this->language;
}
/**
* @param string $language RFC 1766 language identifier
* @return \Jsvrcek\ICS\Model\Relationship\Organizer
*/
public function setLanguage($language)
{
$this->language = $language;
return $this;
}
public function __toString()
{
$string = 'ORGANIZER';
if ($this->sentBy)
$string .= ';SENT-BY="'.$this->sentBy.'"';
if ($this->name)
$string .= ';CN='.$this->name;
if ($this->directory)
$string .= ';DIR="'.$this->directory.'"';
if ($this->language)
$string .= ';LANGUAGE='.$this->language;
$string .= ':'.$this->value;
return $string;
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace Jsvrcek\ICS\Utility;
class Formatter
{
const DATE_TIME = 'Ymd\THis';
const DATE_TIME_UTC = 'Ymd\THis\Z';
const DATE = 'Ymd';
/**
* @param \DateTime $dateTime
* @return string
*/
public function getFormattedDateTime(\DateTime $dateTime)
{
return $dateTime->format(self::DATE_TIME);
}
/**
* @param int $offset
* @return string
*/
public function getFormattedTimeOffset($offset)
{
$prefix = ($offset < 0) ? '-' : '+';
return $prefix.gmdate('Hi', abs($offset));
}
/**
* @param \DateTime $dateTime
* @return string
*/
public function getFormattedUTCDateTime(\DateTime $dateTime)
{
return $dateTime->setTimezone(new \DateTimeZone('UTC'))
->format(self::DATE_TIME_UTC);
}
/**
* @param \DateTime $dateTime
* @return string
*/
public function getFormattedDate(\DateTime $dateTime)
{
return $dateTime->format(self::DATE);
}
/**
* converts email addresses into mailto: uri
* @param string $uri
* @return string
*/
public function getFormattedUri($uri)
{
if (strpos($uri, '@') && stripos($uri, 'mailto:') === false)
$uri = 'mailto:'.$uri;
return $uri;
}
/**
* converts DateInterval object to string that can be used for a VALARM DURATION
* @param \DateInterval $interval
* @return string
*/
public function getFormattedDateInterval(\DateInterval $interval)
{
$format = "P";
if ($interval->y) { $format .= '%yY'; }
if ($interval->m) { $format .= '%mM'; }
if ($interval->d) { $format .= '%dD'; }
if ($interval->h || $interval->i || $interval->s) {
$format .= "T";
}
if ($interval->h) { $format .= '%hH'; }
if ($interval->i) { $format .= '%iM'; }
if ($interval->s) { $format .= '%sS'; }
return $interval->format($format);
}
}

View file

@ -0,0 +1,110 @@
<?php
namespace Jsvrcek\ICS\Utility;
class Provider implements \Iterator
{
/**
*
* @var \Closure
*/
private $provider;
/**
*
* @var array
*/
public $data = array();
/**
*
* @var array
*/
public $manuallyAddedData = array();
/**
*
* @var integer
*/
private $key;
/**
* @param \Closure $provider An optional closure for adding items in batches during iteration. The closure will be
* called each time the end of the internal data array is reached during iteration, and the current data
* array key value will be passed as an argument. The closure should return an array containing the next
* batch of items.
*/
public function __construct(\Closure $provider = null)
{
$this->provider = $provider;
}
/**
* for manually adding items, rather than using a provider closure to add items in batches during iteration
* Cannot be used in conjunction with a provider closure!
*
* @param mixed $item
*/
public function add($item)
{
$this->manuallyAddedData[] = $item;
}
/* (non-PHPdoc)
* @see Iterator::current()
*/
public function current()
{
return current($this->data);
}
/* (non-PHPdoc)
* @see Iterator::key()
*/
public function key()
{
return $this->key;
}
/* (non-PHPdoc)
* @see Iterator::next()
*/
public function next()
{
array_shift($this->data);
$this->key++;
}
/* (non-PHPdoc)
* @see Iterator::rewind()
*/
public function rewind()
{
$this->data = array();
$this->key = 0;
}
/**
* get next batch from provider if data array is at the end
*
* (non-PHPdoc)
* @see Iterator::valid()
*/
public function valid()
{
if (count($this->data) < 1)
{
if ($this->provider instanceof \Closure)
{
$this->data = $this->provider->__invoke($this->key);
}
else
{
$this->data = $this->manuallyAddedData;
$this->manuallyAddedData = array();
}
}
return count($this->data) > 0;
}
}