diff --git a/Classes/Domain/Model/Location.php b/Classes/Domain/Model/Location.php index c5256841..d845ff99 100644 --- a/Classes/Domain/Model/Location.php +++ b/Classes/Domain/Model/Location.php @@ -256,4 +256,26 @@ public function setLatitude($latitude) { $this->latitude = $latitude; } + + /** + * Special getter to return the full address of the location + * + * @param string $separator + * @return string + */ + public function getFullAddress(string $separator = '
'): string + { + $locationData = []; + $locationData[] = $this->getTitle(); + $locationData[] = $this->getAddress(); + $locationData[] = trim($this->getZip() . ' ' . $this->getCity()); + $locationData[] = $this->getCountry(); + $locationData = array_filter( + $locationData, + function ($value) { + return str_replace(' ', '', $value) !== ''; + } + ); + return implode($separator, $locationData); + } } diff --git a/Classes/ViewHelpers/Uri/OnlineCalendarViewHelper.php b/Classes/ViewHelpers/Uri/OnlineCalendarViewHelper.php new file mode 100755 index 00000000..995a3458 --- /dev/null +++ b/Classes/ViewHelpers/Uri/OnlineCalendarViewHelper.php @@ -0,0 +1,139 @@ +registerArgument('type', 'string', 'The type of online calender', true, 'google'); + $this->registerArgument('event', 'DERHANSEN\SfEventMgt\Domain\Model\Event', 'The event'); + } + + /** + * @param array $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + */ + public static function renderStatic( + array $arguments, + \Closure $renderChildrenClosure, + RenderingContextInterface $renderingContext + ) { + /** @var Event $event */ + $event = $arguments['event']; + $type = strtolower($arguments['type']); + + switch ($type) { + case 'google': + $link = self::getGoogleCalendarLink($event); + break; + case 'outlook': + $link = self::getMicrosoftCalendarLink($event, 'live'); + break; + case 'office365': + $link = self::getMicrosoftCalendarLink($event, 'office'); + break; + case 'yahoo': + $link = self::getYahooCalendarLink($event); + break; + default: + $link = ''; + } + + return $link; + } + + private static function getGoogleCalendarLink(Event $event): string + { + $baseLink = 'https://www.google.com/calendar/render?'; + + $dateFormat = 'Ymd\\THi00\\ZO'; + $arguments = [ + 'action' => 'TEMPLATE', + 'text' => $event->getTitle(), + 'dates' => $event->getStartdate()->format($dateFormat) . '/' . $event->getEnddate()->format($dateFormat), + 'details' => strip_tags($event->getDescription()), + ]; + + if ($event->getLocation()) { + $arguments['location'] = $event->getLocation()->getFullAddress(', '); + } + + return $baseLink . http_build_query($arguments, '', '&', PHP_QUERY_RFC3986); + } + + private static function getMicrosoftCalendarLink(Event $event, string $product): string + { + $baseLink = 'https://outlook.' . $product . '.com/calendar/0/deeplink/compose?'; + + $dateFormat = 'Y-m-d\\TH:i:00O'; + $arguments = [ + 'subject' => $event->getTitle(), + 'startdt' => $event->getStartdate()->format($dateFormat), + 'enddt' => $event->getEnddate()->format($dateFormat), + 'body' => strip_tags($event->getDescription()), + 'path' => '/calendar/action/compose&rru=addevent', + ]; + + if ($event->getLocation()) { + $arguments['location'] = $event->getLocation()->getFullAddress(', '); + } + + return $baseLink . http_build_query($arguments, '', '&', PHP_QUERY_RFC3986); + } + + private static function getYahooCalendarLink(Event $event): string + { + $baseLink = 'https://calendar.yahoo.com/?'; + + $dateFormat = 'Ymd\\THi00\\ZO'; + $arguments = [ + 'title' => $event->getTitle(), + 'st' => $event->getStartdate()->format($dateFormat), + 'et' => $event->getEnddate()->format($dateFormat), + 'desc' => strip_tags($event->getDescription()), + 'v' => 60, + ]; + + if ($event->getLocation()) { + $arguments['in_loc'] = $event->getLocation()->getFullAddress(', '); + } + + return $baseLink . http_build_query($arguments, '', '&', PHP_QUERY_RFC3986); + } +} diff --git a/Documentation/ForAdministrators/Templates/Viewhelpers/Index.rst b/Documentation/ForAdministrators/Templates/Viewhelpers/Index.rst index 2e7fc20c..6b274d6a 100644 --- a/Documentation/ForAdministrators/Templates/Viewhelpers/Index.rst +++ b/Documentation/ForAdministrators/Templates/Viewhelpers/Index.rst @@ -80,6 +80,23 @@ given page in you TYPO3 website. +Uri.OnlineCalendar +~~~~~~~~~~~~~~~~~~ + +This viewhelper renders a link which will add the given event to an online +calendar of either Google, Outlook, Office 365 or Yahoo. + +Available types: + +* google +* outlook +* office365 +* yahoo + +**Example**:: + + + Event.SimultaneousRegistrationsViewHelper ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -142,4 +159,4 @@ Use this viewhelper to set the page title and indexed search title on event-deta **Example**:: - \ No newline at end of file + diff --git a/Resources/Private/Templates/Event/Detail.html b/Resources/Private/Templates/Event/Detail.html index f4fd6484..4b71d062 100644 --- a/Resources/Private/Templates/Event/Detail.html +++ b/Resources/Private/Templates/Event/Detail.html @@ -172,7 +172,7 @@

- +
@@ -305,8 +305,6 @@

- - @@ -315,6 +313,18 @@

+ +
+
+ Add event to calendar: +
    +
  • +
  • Add to Google Calendar
  • +
  • Add to Outlook Calendar
  • +
  • Add to Office 365 Calendar
  • +
  • Add to Yahoo Calendar
  • +
+
diff --git a/Tests/Unit/Domain/Model/LocationTest.php b/Tests/Unit/Domain/Model/LocationTest.php index 97e9bbb9..a60a05a5 100644 --- a/Tests/Unit/Domain/Model/LocationTest.php +++ b/Tests/Unit/Domain/Model/LocationTest.php @@ -233,4 +233,68 @@ public function setLatitudeSetsLatitude() $this->subject->setLatitude(12.345678); self::assertSame(12.345678, $this->subject->getLatitude()); } + + public function getFullAddressReturnsExpectedResultDataProvider(): array + { + $location1 = new Location(); + $location1->setAddress('Address 123'); + $location1->setCity('A City'); + $location1->setZip('12345'); + $location1->setCountry('A Country'); + + $location2 = new Location(); + $location2->setAddress('Address 123'); + + $location3 = new Location(); + $location3->setAddress('Address 123'); + $location3->setZip('12345'); + + $location4 = new Location(); + $location4->setAddress('Address 123'); + $location4->setCity('A City'); + + return [ + 'default location' => [ + new Location(), + '
', + '' + ], + 'location with all data with br as separator' => [ + $location1, + '
', + 'Address 123
12345 A City
A Country' + ], + 'location with all data with comma as separator' => [ + $location1, + ',', + 'Address 123,12345 A City,A Country' + ], + 'location with no zip and city' => [ + $location2, + ',', + 'Address 123' + ], + 'location with no city' => [ + $location3, + ',', + 'Address 123,12345' + ], + 'location with no zip' => [ + $location4, + ',', + 'Address 123,A City' + ], + ]; + } + + /** + * @test + * @dataProvider getFullAddressReturnsExpectedResultDataProvider + */ + public function getFullAddressReturnsExpectedResult($location, $separator, $expected) + { + /** @var Location $location */ + $result = $location->getFullAddress($separator); + $this->assertEquals($expected, $result); + } } diff --git a/Tests/Unit/ViewHelpers/Uri/OnlineCalendarViewHelperTest.php b/Tests/Unit/ViewHelpers/Uri/OnlineCalendarViewHelperTest.php new file mode 100644 index 00000000..c20c2ad6 --- /dev/null +++ b/Tests/Unit/ViewHelpers/Uri/OnlineCalendarViewHelperTest.php @@ -0,0 +1,99 @@ +viewHelper = new OnlineCalendarViewHelper(); + $this->injectDependenciesIntoViewHelper($this->viewHelper); + $this->viewHelper->initializeArguments(); + } + + /** + * Teardown + */ + protected function tearDown(): void + { + unset($this->viewHelper); + } + + public function onlineCalendarViewHelperReturnsExpectedResultsDataProvider(): array + { + return [ + 'google' => [ + 'google', + 'https://www.google.com/calendar/render?action=TEMPLATE&text=A%20test%20event&dates=20210101T180000Z%2B0100%2F20210101T200000Z%2B0100&details=A%20description%20for%20the%20event' + ], + 'outlook' => [ + 'outlook', + 'https://outlook.live.com/calendar/0/deeplink/compose?subject=A%20test%20event&startdt=2021-01-01T18%3A00%3A00%2B0100&enddt=2021-01-01T20%3A00%3A00%2B0100&body=A%20description%20for%20the%20event&path=%2Fcalendar%2Faction%2Fcompose%26rru%3Daddevent' + ], + 'office365' => [ + 'office365', + 'https://outlook.office.com/calendar/0/deeplink/compose?subject=A%20test%20event&startdt=2021-01-01T18%3A00%3A00%2B0100&enddt=2021-01-01T20%3A00%3A00%2B0100&body=A%20description%20for%20the%20event&path=%2Fcalendar%2Faction%2Fcompose%26rru%3Daddevent' + ], + 'yahoo' => [ + 'yahoo', + 'https://calendar.yahoo.com/?title=A%20test%20event&st=20210101T180000Z%2B0100&et=20210101T200000Z%2B0100&desc=A%20description%20for%20the%20event&v=60' + ], + ]; + } + + /** + * @test + * @dataProvider onlineCalendarViewHelperReturnsExpectedResultsDataProvider + */ + public function onlineCalendarViewHelperReturnsExpectedResults(string $type, string $expected) + { + $location = new Location(); + $location->setTitle('A location'); + $location->setAddress('Street 123'); + $location->setZip('12345'); + $location->setCity('A City'); + $location->setCountry('A Country'); + + $event = new Event(); + $event->setTitle('A test event'); + $event->setDescription('A description for the event'); + $event->setStartdate(new \DateTime('01.01.2021 18:00:00')); + $event->setEnddate(new \DateTime('01.01.2021 20:00:00')); + + $result = $this->viewHelper::renderStatic( + [ + 'event' => $event, + 'type' => $type + ], + function () { + }, + $this->prophesize(RenderingContextInterface::class)->reveal() + ); + self::assertEquals($expected, $result); + } +}