Skip to content

Commit

Permalink
[FEATURE] Added a viewHelper to event to online calendars
Browse files Browse the repository at this point in the history
Refs #850
  • Loading branch information
derhansen committed May 2, 2021
1 parent f60b9db commit 268f81f
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 4 deletions.
22 changes: 22 additions & 0 deletions Classes/Domain/Model/Location.php
Expand Up @@ -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 = '<br/>'): 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);
}
}
139 changes: 139 additions & 0 deletions Classes/ViewHelpers/Uri/OnlineCalendarViewHelper.php
@@ -0,0 +1,139 @@
<?php

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace DERHANSEN\SfEventMgt\ViewHelpers\Uri;

use DERHANSEN\SfEventMgt\Domain\Model\Event;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;

/**
* ViewHelper to render a link to add an event to a given online calender
* Currently supports the following online calendar types:
*
* - Google Calendar
* - Outlook Calendar
* - Office 365 Calendar
* - Yahoo Calendar
*/
class OnlineCalendarViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;

/**
* Initialize arguments
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->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);
}
}
19 changes: 18 additions & 1 deletion Documentation/ForAdministrators/Templates/Viewhelpers/Index.rst
Expand Up @@ -80,6 +80,23 @@ given page in you TYPO3 website.

<e:uri.page pageUid="4" additionalParams="{tx_sfeventmgt_pievent:{event: registration.event, action: 'detail', controller: 'Event'}}" absolute="1"/>

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**::

<e:uri.onlineCalendar type="google" event="{event}" />


Event.SimultaneousRegistrationsViewHelper
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -142,4 +159,4 @@ Use this viewhelper to set the page title and indexed search title on event-deta

**Example**::

<e:title pageTitle="{event.title}" indexedDocTitle="A custom title for indexed search"/>
<e:title pageTitle="{event.title}" indexedDocTitle="A custom title for indexed search"/>
16 changes: 13 additions & 3 deletions Resources/Private/Templates/Event/Detail.html
Expand Up @@ -172,7 +172,7 @@ <h2 class="event-title">
</div>
<div class="clear"></div>
</div>

<f:if condition='{event.enableWaitlist}'>
<div class="event-detail-row">
<div class="event-detail-label">
Expand Down Expand Up @@ -305,8 +305,6 @@ <h2 class="event-title">
</div>
</f:if>

<f:link.action action="icalDownload" arguments="{event : event}" class="button"><f:translate key="event.icalDownload" /></f:link.action>

<f:link.action action="list" pageUid="{settings.listPid}" class="button"><f:translate key="event.backtext" /></f:link.action>
<f:if condition="{event.registrationPossible}">
<f:if condition="{settings.registrationPid} !=''">
Expand All @@ -315,6 +313,18 @@ <h2 class="event-title">
</f:link.action>
</f:if>
</f:if>

<div>
<br/>
<strong>Add event to calendar:</strong>
<ul>
<li><f:link.action action="icalDownload" arguments="{event : event}" class="button"><f:translate key="event.icalDownload" /></f:link.action></li>
<li><f:link.external uri="{e:uri.onlineCalendar(type: 'google', event: event)}" target="_blank">Add to Google Calendar</f:link.external></li>
<li><f:link.external uri="{e:uri.onlineCalendar(type: 'outlook', event: event)}" target="_blank">Add to Outlook Calendar</f:link.external></li>
<li><f:link.external uri="{e:uri.onlineCalendar(type: 'office365', event: event)}" target="_blank">Add to Office 365 Calendar</f:link.external></li>
<li><f:link.external uri="{e:uri.onlineCalendar(type: 'yahoo', event: event)}" target="_blank">Add to Yahoo Calendar</f:link.external></li>
</ul>
</div>
</f:if>
</f:section>

Expand Down
64 changes: 64 additions & 0 deletions Tests/Unit/Domain/Model/LocationTest.php
Expand Up @@ -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(),
'<br/>',
''
],
'location with all data with br as separator' => [
$location1,
'<br/>',
'Address 123<br/>12345 A City<br/>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);
}
}

0 comments on commit 268f81f

Please sign in to comment.