diff --git a/src/Entity/AbstractEntity.php b/src/Entity/AbstractEntity.php index 247744a..577726a 100644 --- a/src/Entity/AbstractEntity.php +++ b/src/Entity/AbstractEntity.php @@ -502,6 +502,17 @@ public function addRecurrencePeriods(array $periods, array $parameters = null) { public function setRecurrenceRule(RecurrenceRule $rule) { $this->instance->add($this->calendar->createProperty('RRULE', $rule->toString())); } + + /** + * Add alarm component to current entity + * + * @see https://tools.ietf.org/html/rfc5545#section-3.6.6 + * + * @return Alarm + */ + public function addAlarm() { + return new Alarm($this->calendar); + } /** * Creates a new date time property including check for floating date time diff --git a/src/Entity/Alarm.php b/src/Entity/Alarm.php new file mode 100644 index 0000000..b95c918 --- /dev/null +++ b/src/Entity/Alarm.php @@ -0,0 +1,154 @@ +calendar = $calendar; + $this->instance = $this->calendar->add('VALARM'); + } + + /** + * This property specifies a trigger + * + * @param Duration $duration + * @param array $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.2.5 + */ + public function setTrigger(Duration $duration, array $parameters = null) { + $this->instance->add($this->calendar->createProperty('TRIGGER', $duration->toString(), $parameters)); + } + + /** + * This property provides the capability to associate a document object + * + * Currently only a URI is supported! + * + * @param string $attachmentPath + * @param array $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.1 + */ + public function addAttachment($attachmentPath, array $parameters = null) { + + if (!empty($attachmentPath)) { + $this->instance->add($this->calendar->createProperty('ATTACH', $attachmentPath, $parameters)); + } + } + + /** + * Defines action for alarm + * + * @param Action $action + * @param array|null $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.6.1 + */ + public function setAction($action, array $parameters = null) { + + if (!Action::has($action)) { + throw new \InvalidArgumentException('This action is not allowed for current entity!'); + } + + $this->instance->add($this->calendar->createProperty('ACTION', $action, $parameters)); + } + + /** + * This property provides a more complete description + * + * @param string $description + * @param array $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.5 + */ + public function setDescription($description, array $parameters = null) { + + if (!empty($description)) { + $this->instance->add($this->calendar->createProperty('DESCRIPTION', $description, $parameters)); + } + } + + /** + * This property specifies a duration of time + * + * @param Duration $duration + * @param array $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.2.5 + */ + public function setDuration(Duration $duration, array $parameters = null) { + $this->instance->add($this->calendar->createProperty('DURATION', $duration->toString(), $parameters)); + } + + /** + * This property specifies the repeat count + * + * @param int $repeatCount + * @param array $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.6.2 + */ + public function setRepeatCount($repeatCount, array $parameters = null) { + if (!is_int($repeatCount)) { + throw new \InvalidArgumentException('repeat count should be an integer value!'); + } + + if (0 >= $repeatCount) { + throw new \OutOfRangeException('repeat count should be greater than 0!'); + } + + $this->instance->add($this->calendar->createProperty('REPEAT', $repeatCount, $parameters)); + } + + /** + * This property defines an "Attendee" + * + * @param Attendee $attendee + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.4.1 + */ + public function addAttendee(Attendee $attendee) { + $this->instance->add($this->calendar->createProperty('ATTENDEE', $attendee->getAddress(), $attendee->getParameters())); + } + + /** + * This property defines a short summary or subject + * + * @param string $summary + * @param array $parameters + * + * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.12 + */ + public function setSummary($summary, array $parameters = null) { + + if (!empty($summary)) { + $this->instance->add($this->calendar->createProperty('SUMMARY', $summary, $parameters)); + } + } + +} \ No newline at end of file diff --git a/src/Enum/Action.php b/src/Enum/Action.php new file mode 100644 index 0000000..e36b3bc --- /dev/null +++ b/src/Enum/Action.php @@ -0,0 +1,22 @@ +assertInstanceOf($expectedException, $e); diff --git a/src/Type/Duration.php b/src/Type/Duration.php index 0c72fc1..55822e5 100644 --- a/src/Type/Duration.php +++ b/src/Type/Duration.php @@ -42,6 +42,11 @@ class Duration implements StringTypeInterface { * @var int */ protected $week = 0; + + /** + * @var bool + */ + protected $negative = false; /** * Returns the string representation of the object @@ -55,8 +60,12 @@ public function toString() { if (0 === $this->day && 0 === $this->hour && 0 === $this->minute && 0 === $this->second && 0 === $this->week) { throw new \UnexpectedValueException('At least one duration value must be set!'); } - - $duration = 'P'; + + if ($this->negative) { + $duration = '-P'; + } else { + $duration = 'P'; + } if (0 !== $this->week) { $duration .= $this->week . 'W'; @@ -165,4 +174,20 @@ public function setWeek($week) { return $this; } + + /** + * @param bool $negative + * + * @return Duration + */ + public function setNegative($negative = true) { + + if (!is_bool($negative)) { + throw new \InvalidArgumentException('Value for negative must be a boolean'); + } + + $this->negative = $negative; + + return $this; + } } \ No newline at end of file diff --git a/tests/Unit/Entity/AlarmTest.php b/tests/Unit/Entity/AlarmTest.php new file mode 100644 index 0000000..6d65884 --- /dev/null +++ b/tests/Unit/Entity/AlarmTest.php @@ -0,0 +1,189 @@ +calendar = new VCalendar(); + $this->todo = new Todo($this->calendar); + $this->alarm = $this->todo->addAlarm(); + } + + /* + * The following tests are only for To-do + */ + + public function testConstruct() { + $this->assertException(function () { + new Alarm('Calendar', $this->todo); + }, TypeError::class); + + $alarm = new Alarm($this->calendar, $this->todo); + + $vAlarm = $this->invokeProperty($alarm, 'instance'); + + $this->assertTrue($vAlarm instanceof VAlarm); + } + + public function testSetSummary() { + $this->alarm->setSummary(''); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertNotContains('SUMMARY:', $iCalendarString); + + $this->alarm->setSummary('My first event'); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains('SUMMARY:My first event', $iCalendarString); + } + + public function testSetDescription() { + $this->alarm->setDescription(''); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertNotContains('DESCRIPTION:', $iCalendarString); + + $this->alarm->setDescription('Description for my first event'); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains('DESCRIPTION:Description for my first event', $iCalendarString); + } + + public function testAddAttachment() { + $this->todo->addAttachment(''); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertNotContains('ATTACH:', $iCalendarString); + + $this->todo->addAttachment('http://domain.tdn/myImage.gif'); + $this->todo->addAttachment('http://domain.tdn/myImage.png'); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains('ATTACH:http://domain.tdn/myImage.gif', $iCalendarString); + $this->assertContains('ATTACH:http://domain.tdn/myImage.png', $iCalendarString); + } + + public function testSetRepeatCount() { + $this->assertException(function () { + $this->alarm->setRepeatCount('Some text'); + }, InvalidArgumentException::class, null, 'repeat count should be an integer value!'); + $this->assertException(function () { + $this->alarm->setRepeatCount(false); + }, InvalidArgumentException::class, null, 'repeat count should be an integer value!'); + $this->assertException(function () { + $this->alarm->setRepeatCount(-1); + }, OutOfRangeException::class, null, 'repeat count should be greater than 0!'); + + $this->alarm->setRepeatCount(4); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains('REPEAT:4', $iCalendarString); + } + + public function testSetDuration() { + $this->assertException(function () { + $this->alarm->setDuration('P4W'); + }, TypeError::class); + + $duration = new Duration(); + $duration->setWeek(5); + + $this->alarm->setDuration($duration); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains("DURATION:P5W\r\n", $iCalendarString); + } + + public function testAddAttendee() { + $this->assertException(function () { + $this->alarm->addAttendee('John Doe'); + }, TypeError::class); + + $attendee = new Attendee('address@domain.tdn', 'Todo'); + + $this->alarm->addAttendee($attendee); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains('ATTENDEE:mailto:address@domain.tdn', $iCalendarString); + } + + public function testSetTrigger() { + $this->assertException(function () { + $this->alarm->setTrigger('P4W'); + }, TypeError::class); + + $duration = new Duration(); + $duration->setWeek(5); + + $this->alarm->setTrigger($duration); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains("TRIGGER:P5W\r\n", $iCalendarString); + } + + public function testSetAction() { + $this->assertException(function () { + $this->alarm->setAction('UnknownFrequency'); + }, InvalidArgumentException::class, null, 'This action is not allowed for current entity!'); + + $this->alarm->setAction(Action::DISPLAY); + + $iCalendarString = $this->calendar->serialize(); + + $this->assertInternalType('string', $iCalendarString); + $this->assertContains("ACTION:DISPLAY\r\n", $iCalendarString); + } + +} \ No newline at end of file diff --git a/tests/Unit/Entity/EventTest.php b/tests/Unit/Entity/EventTest.php index 88cedb7..31aeaf8 100644 --- a/tests/Unit/Entity/EventTest.php +++ b/tests/Unit/Entity/EventTest.php @@ -47,7 +47,7 @@ public function setUp() { public function testConstruct() { $this->assertException(function() { new Event('Calendar'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $event = new Event($this->calendar); @@ -63,7 +63,7 @@ public function testConstruct() { public function testSetDateEnd() { $this->assertException(function() { $this->event->setDateEnd('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); // test date time with time zone $this->event->setDateEnd(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -322,7 +322,7 @@ public function testSetStatus() { public function testSetDateStart() { $this->assertException(function() { $this->event->setDateStart('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); // test date time with time zone $this->event->setDateStart(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -363,7 +363,7 @@ public function testSetDateStart() { public function testSetDuration() { $this->assertException(function() { $this->event->setDuration('P4W'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $duration = new Duration(); $duration->setWeek(5); @@ -418,7 +418,7 @@ public function testSetUrl() { public function testAddAttendee() { $this->assertException(function() { $this->event->addAttendee('John Doe'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $wrongAttendeeType = new Attendee('address@domain.tdn', 'Todo'); @@ -438,7 +438,7 @@ public function testAddAttendee() { public function testSetContact() { $this->assertException(function() { $this->event->setContact('John Doe'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $contact = new Contact('John Doe'); @@ -453,7 +453,7 @@ public function testSetContact() { public function testSetOrganizer() { $this->assertException(function() { $this->event->setOrganizer('John Doe'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $organizer = new Organizer('address@domain.tdn'); @@ -468,7 +468,7 @@ public function testSetOrganizer() { public function testSetDateCreated() { $this->assertException(function() { $this->event->setDateCreated('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $this->event->setDateCreated(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -485,7 +485,7 @@ public function testSetDateCreated() { public function testSetDateLastModified() { $this->assertException(function() { $this->event->setDateLastModified('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $this->event->setDateLastModified(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -601,7 +601,7 @@ public function testAddRecurrencePeriods() { public function testSetRecurrenceRule() { $this->assertException(function() { $this->event->setRecurrenceRule('FREQ=DAILY;COUNT=10'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $recurrenceRule = new RecurrenceRule(); $recurrenceRule->setFrequency(RecurrenceFrequency::HOURLY); @@ -621,7 +621,7 @@ public function testCreateDateProperty() { $this->invokeMethod($this->event, 'createDateProperty', [ 'DTSTART', '2016-12-12 11:00:00', false ]); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); // check normal date time value $dateTimeProperty = $this->invokeMethod($this->event, 'createDateProperty', [ @@ -655,7 +655,7 @@ public function testCheckTimeZone() { $this->invokeMethod($this->event, 'checkTimeZone', [ '2016-12-12 11:00:00' ]); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $timeZoneAdded = $this->invokeMethod($this->event, 'checkTimeZone', [ new \DateTime('2016-12-12 11:00:00', new DateTimeZone('UTC')) diff --git a/tests/Unit/Entity/TodoTest.php b/tests/Unit/Entity/TodoTest.php index dd56528..0678fc7 100644 --- a/tests/Unit/Entity/TodoTest.php +++ b/tests/Unit/Entity/TodoTest.php @@ -46,7 +46,7 @@ public function setUp() { public function testConstruct() { $this->assertException(function() { new Todo('Calendar'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $event = new Todo($this->calendar); @@ -84,7 +84,7 @@ public function testSetPercentComplete() { public function testSetCompleted() { $this->assertException(function() { $this->todo->setCompleted('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $this->todo->setCompleted(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -101,7 +101,7 @@ public function testSetCompleted() { public function testSetDue() { $this->assertException(function() { $this->todo->setDue('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); // test date time with time zone $this->todo->setDue(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -347,7 +347,7 @@ public function testSetStatus() { public function testSetDateStart() { $this->assertException(function() { $this->todo->setDateStart('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); // test date time with time zone $this->todo->setDateStart(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -388,7 +388,7 @@ public function testSetDateStart() { public function testSetDuration() { $this->assertException(function() { $this->todo->setDuration('P4W'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $duration = new Duration(); $duration->setWeek(5); @@ -443,7 +443,7 @@ public function testSetUrl() { public function testAddAttendee() { $this->assertException(function() { $this->todo->addAttendee('John Doe'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $wrongAttendeeType = new Attendee('address@domain.tdn', 'Event'); @@ -463,7 +463,7 @@ public function testAddAttendee() { public function testSetContact() { $this->assertException(function() { $this->todo->setContact('John Doe'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $contact = new Contact('John Doe'); @@ -478,7 +478,7 @@ public function testSetContact() { public function testSetOrganizer() { $this->assertException(function() { $this->todo->setOrganizer('John Doe'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $organizer = new Organizer('address@domain.tdn'); @@ -493,7 +493,7 @@ public function testSetOrganizer() { public function testSetDateCreated() { $this->assertException(function() { $this->todo->setDateCreated('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $this->todo->setDateCreated(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -510,7 +510,7 @@ public function testSetDateCreated() { public function testSetDateLastModified() { $this->assertException(function() { $this->todo->setDateLastModified('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $this->todo->setDateLastModified(new \DateTime('2016-12-12 11:00:00', new DateTimeZone('Europe/Berlin'))); @@ -626,7 +626,7 @@ public function testAddRecurrencePeriods() { public function testSetRecurrenceRule() { $this->assertException(function() { $this->todo->setRecurrenceRule('FREQ=DAILY;COUNT=10'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $recurrenceRule = new RecurrenceRule(); $recurrenceRule->setFrequency(RecurrenceFrequency::HOURLY); @@ -646,7 +646,7 @@ public function testCreateDateProperty() { $this->invokeMethod($this->todo, 'createDateProperty', [ 'DTSTART', '2016-12-12 11:00:00', false ]); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); // check normal date time value $dateTimeProperty = $this->invokeMethod($this->todo, 'createDateProperty', [ @@ -680,7 +680,7 @@ public function testCheckTimeZone() { $this->invokeMethod($this->todo, 'checkTimeZone', [ '2016-12-12 11:00:00' ]); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $timeZoneAdded = $this->invokeMethod($this->todo, 'checkTimeZone', [ new \DateTime('2016-12-12 11:00:00', new DateTimeZone('UTC')) diff --git a/tests/Unit/Type/PeriodTest.php b/tests/Unit/Type/PeriodTest.php index e727d01..0c8d3f3 100644 --- a/tests/Unit/Type/PeriodTest.php +++ b/tests/Unit/Type/PeriodTest.php @@ -24,7 +24,7 @@ public function setUp() { public function testSetStart() { $this->assertException(function() { $this->period->setStart('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function () { $newYorkTime = new DateTime('2016-12-12 11:00:00', new DateTimeZone('America/New_York')); @@ -37,7 +37,7 @@ public function testSetStart() { public function testSetEnd() { $this->assertException(function() { $this->period->setEnd('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function () { $newYorkTime = new DateTime('2016-12-12 11:00:00', new DateTimeZone('America/New_York')); @@ -50,7 +50,7 @@ public function testSetEnd() { public function testSetDuration() { $this->assertException(function() { $this->period->setDuration('P4W'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $duration = new Duration(); $this->period->setDuration($duration); diff --git a/tests/Unit/Type/RecurrenceRuleTest.php b/tests/Unit/Type/RecurrenceRuleTest.php index f18b094..92b8bee 100644 --- a/tests/Unit/Type/RecurrenceRuleTest.php +++ b/tests/Unit/Type/RecurrenceRuleTest.php @@ -46,7 +46,7 @@ public function testSetFrequency() { public function testSetUntil() { $this->assertException(function() { $this->recurrenceRule->setUntil('2016-12-12 11:00:00'); - }, PHPUnit_Framework_Error::class); + }, TypeError::class); $this->assertException(function() { $americanDateTime = new DateTime('2016-12-12 11:00:00', new DateTimeZone('America/New_York'));