tine20/Calendar/Controller.php
Rama main · réplica de lectura del repositorio original.
<?php
/**
* Sql Calendar
*
* @package Calendar
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @author Cornelius Weiss <c.weiss@metaways.de>
* @copyright Copyright (c) 2009-2023 Metaways Infosystems GmbH (http://www.metaways.de)
*/
/**
* main controller for Calendar
*
* @package Calendar
*/
class Calendar_Controller extends Tinebase_Controller_Event implements
Tinebase_Application_Container_Interface,
Felamimail_Controller_MassMailingPluginInterface
{
/**
* holds the instance of the singleton
*
* @var Calendar_Controller
*/
private static $_instance = NULL;
/**
* holds the default Model of this application
* @var string
*/
protected static $_defaultModel = 'Calendar_Model_Event';
/**
* application name (is needed in checkRight())
*
* @var string
*/
protected $_applicationName = 'Calendar';
const XPROP_EXTERNAL_INVITATION_CALENDAR = 'externalInvitationCalendar';
/**
* don't clone. Use the singleton.
*
*/
private function __clone()
{
}
/**
* the singleton pattern
*
* @return Calendar_Controller
*/
public static function getInstance()
{
if (self::$_instance === NULL) {
self::$_instance = new Calendar_Controller();
}
return self::$_instance;
}
/**
* event handler function
*
* all events get routed through this function
*
* @param Tinebase_Event_Abstract $_eventObject the eventObject
*/
protected function _handleEvent(Tinebase_Event_Abstract $_eventObject)
{
switch (get_class($_eventObject)) {
case 'Admin_Event_AddAccount':
Tinebase_Core::getPreference('Calendar')->getValueForUser(
Calendar_Preference::DEFAULTCALENDAR, $_eventObject->account->getId());
break;
case 'Calendar_Event_DeleteResource':
/**
* @var Calendar_Event_DeleteResource $_eventObject
*/
$this->_deleteEventAttenders($_eventObject);
break;
case 'Tinebase_Event_User_DeleteAccount':
/**
* @var Tinebase_Event_User_DeleteAccount $_eventObject
*/
$this->_handleDeleteUserEvent($_eventObject);
// let event bubble
parent::_handleEvent($_eventObject);
break;
case 'Admin_Event_UpdateGroup':
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__ . ' updated group '
. $_eventObject->group->name);
}
Tinebase_ActionQueue::getInstance()->queueAction('Calendar.onUpdateGroup', $_eventObject->group->getId());
break;
case 'Addressbook_Event_DeleteList':
$this->_deleteEventAttenders($_eventObject);
break;
case Tinebase_Event_AddGroupMember::class:
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__ . ' Add group member '
. $_eventObject->userId . ' to group ' . $_eventObject->groupId);
}
Tinebase_ActionQueue::getInstance()->queueAction('Calendar.onUpdateGroup', $_eventObject->groupId);
break;
case Tinebase_Event_RemoveGroupMember::class:
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__ . ' Remove group member '
. $_eventObject->userId . ' from group ' . $_eventObject->groupId);
}
Tinebase_ActionQueue::getInstance()->queueAction('Calendar.onUpdateGroup', $_eventObject->groupId);
break;
case Tinebase_Event_Container_BeforeCreate::class:
$this->_handleContainerBeforeCreateEvent($_eventObject);
break;
case Tinebase_Event_Container_AfterCreate::class:
$this->_handleContainerAfterCreateEvent($_eventObject);
break;
}
}
protected function _handleDeleteUserEvent($_eventObject)
{
// this needs to happen before deletePersonalFolder. Otherwise the attender display container (the personal folder) is gone and the attendee filter doesnt work anymore!
if (!$_eventObject->keepAsContact()) {
// remove all event attenders for this contact
$this->_deleteEventAttenders($_eventObject);
}
if ($_eventObject->keepOrganizerEvents()) {
$this->_keepOrganizerEvents($_eventObject);
}
if ($_eventObject->deletePersonalContainers()) {
$this->deletePersonalFolder($_eventObject->account, Calendar_Model_Event::class);
}
}
/**
* @param Tinebase_Event_Abstract $_eventObject
*/
protected function _deleteEventAttenders(Tinebase_Event_Abstract $_eventObject)
{
if ($_eventObject instanceof Tinebase_Event_User_DeleteAccount) {
$attenderId = $_eventObject->account->contact_id;
$type = Calendar_Model_Attender::USERTYPE_USER;
} elseif ($_eventObject instanceof Calendar_Event_DeleteResource) {
$attenderId = $_eventObject->resource->getId();
$type = Calendar_Model_Attender::USERTYPE_RESOURCE;
} else if ($_eventObject instanceof Addressbook_Event_DeleteList) {
$attenderId = $_eventObject->list->getId();
$type = Calendar_Model_Attender::USERTYPE_GROUP;
} else {
Tinebase_Core::getLogger()->err(__METHOD__ . ' ' . __LINE__ . ' unknown event type: ' .
get_class($_eventObject));
return;
}
$filter = new Calendar_Model_EventFilter(array(array(
'field' => 'attender', 'operator' => 'in', 'value' => array(array(
'user_type' => $type,
'user_id' => $attenderId,
))
)));
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . ' '
. __LINE__ . ' Deleting Event Attender ' . $attenderId . ' (type: ' . $type . ')');
$eventController = Calendar_Controller_Event::getInstance();
$oldAcl = $eventController->doContainerACLChecks(false);
$oldSendNotification = $eventController->sendNotifications(false);
$events = $eventController->search($filter);
/** @var Calendar_Model_Event $event */
foreach ($events as $event) {
$toRemove = array();
foreach ($event->attendee as $key => $attendee) {
$attendeeUserId = $attendee->user_id instanceof Tinebase_Record_Interface
? $attendee->user_id->getId()
: $attendee->user_id;
if ($attendeeUserId === $attenderId &&
($attendee->user_type === Calendar_Model_Attender::USERTYPE_USER ||
$attendee->user_type === Calendar_Model_Attender::USERTYPE_GROUPMEMBER ||
$attendee->user_type === Calendar_Model_Attender::USERTYPE_RESOURCE ||
$attendee->user_type === Calendar_Model_Attender::USERTYPE_GROUP
)) {
$toRemove[] = $key;
}
}
if (count($toRemove) > 0) {
foreach ($toRemove as $index) {
$event->attendee->offsetUnset($index);
}
$eventController->update($event);
}
}
$eventController->doContainerACLChecks($oldAcl);
$eventController->sendNotifications($oldSendNotification);
}
protected function _keepOrganizerEvents($_eventObject)
{
$accountId = $_eventObject->account->getId();
$contactId = $_eventObject->account->contact_id;
$contact = null;
$newContact = null;
$contactEmail = null;
if ($_eventObject->keepAsContact()) {
try {
$contact = Addressbook_Controller_Contact::getInstance()->get($contactId);
$contactEmail = $contact->getPreferredEmailAddress();
} catch (Tinebase_Exception_NotFound $tenf) {
// ignore
$contactEmail = $_eventObject->account->accountEmailAddress;
}
} else {
$contactEmail = $_eventObject->account->accountEmailAddress;
}
if (null === $contact) {
$newContact = Calendar_Model_Attender::resolveEmailToContact(array(
'email' => $contactEmail,
));
}
$eventController = Calendar_Controller_Event::getInstance();
$oldState = $eventController->doContainerACLChecks(false);
// delete all events where our deletee is organizer and that are private (no matter if they have attendees or not)
/*$filter = new Calendar_Model_EventFilter(array(
array('field' => 'class', 'operator' => 'equals', 'value' => Calendar_Model_Event::CLASS_PRIVATE),
array('field' => 'organizer', 'operator' => 'equals', 'value' => $contactId),
));
$eventController->deleteByFilter($filter);*/
// delete all events where our deletee is organizer and that dont have any additional attenders except the organizer / deletee himself
$filter = new Calendar_Model_EventFilter(array(
array('field' => 'organizer', 'operator' => 'equals', 'value' => $contactId),
array('field' => 'attender', 'operator' => 'notHasSomeExcept', 'value' => array(
'user_type' => Calendar_Model_Attender::USERTYPE_USER,
'user_id' => $contactId,
)),
));
$eventController->deleteByFilter($filter);
$eventController->doContainerACLChecks($oldState);
// get all personal containers
$containers = Tinebase_Container::getInstance()->getPersonalContainer($accountId, Calendar_Model_Event::class, $accountId, '*', true);
if ($containers->count() > 0) {
// take the first one and make it an invitation container
$container = $containers->getByIndex(0);
$this->convertToInvitationContainer($container, $contactEmail);
// if there are more than 1 container, move contents to invitation container, then delete them
$i = 1;
while ($containers->count() > 1) {
$moveContainer = $containers->getByIndex($i);
$containers->offsetUnset($i++);
//move $moveContainer content to $container
$eventController->getBackend()->moveEventsToContainer($moveContainer, $container);
//delete $moveContainer
Tinebase_Container::getInstance()->deleteContainer($moveContainer, true);
}
}
// replace old contactId with newContact->getId()
if (null !== $newContact) {
$eventController->getBackend()->replaceContactId($contactId, $newContact->getId());
}
}
/**
* Converts the calendar to be a calendar for external organizer
*
* @param Tinebase_Model_Container $container
*/
public function convertToInvitationContainer(Tinebase_Model_Container $container, $emailAddress)
{
if ($container->model !== 'Calendar_Model_Event') {
Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' container provided needs to have the model Calendar_Model_Event instead of ' . $container->model);
throw Tinebase_Exception_UnexpectedValue('container provided needs to have the model Calendar_Model_Event instead of ' . $container->model);
}
$tbc = Tinebase_Container::getInstance();
try {
$oldContainer = $tbc->getContainerByName(Calendar_Model_Event::class, $emailAddress, Tinebase_Model_Container::TYPE_SHARED);
// TODO fix me!
// bad, we should move the events from $oldContainer to $container
$tbc->deleteContainer($oldContainer, true);
} catch (Tinebase_Exception_NotFound $tenf) {
//good, ignore
}
$container->name = $emailAddress;
$container->color = '#333399';
$container->type = Tinebase_Model_Container::TYPE_SHARED;
$tbc->update($container);
$grants = new Tinebase_Record_RecordSet($container->getGrantClass(), array(
array(
'account_id' => '0',
'account_type' => Tinebase_Acl_Rights::ACCOUNT_TYPE_ANYONE,
Tinebase_Model_Grants::GRANT_ADD => true,
Tinebase_Model_Grants::GRANT_EDIT => true,
// Tinebase_Model_Grants::GRANT_DELETE => true,
)
));
$tbc->setGrants($container->getId(), $grants, true, false);
}
/**
* Get/Create Calendar for external organizer
*
* @param Addressbook_Model_Contact|null $organizer organizer id
* @param string $emailAddress
* @return Tinebase_Model_Container container id
*/
public function getInvitationContainer($organizer, $emailAddress = null)
{
if (null !== $organizer) {
$containerName = $organizer->getPreferredEmailAddress();
} else {
$containerName = $emailAddress;
}
if (empty($containerName)) {
throw new Tinebase_Exception_UnexpectedValue('Event organizer does not have an email address');
}
try {
$container = Tinebase_Container::getInstance()->getContainerByName(Calendar_Model_Event::class, $containerName, Tinebase_Model_Container::TYPE_SHARED);
} catch (Tinebase_Exception_NotFound $tenf) {
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
. ' No invitation container found. Creating a new one for organizer ' . $containerName);
}
$container = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
'name' => $containerName,
'color' => '#333399',
'type' => Tinebase_Model_Container::TYPE_SHARED,
'backend' => Tinebase_User::SQL,
'application_id' => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(),
'model' => 'Calendar_Model_Event',
'xprops' => [self::XPROP_EXTERNAL_INVITATION_CALENDAR => true],
)), NULL, TRUE);
$grants = new Tinebase_Record_RecordSet($container->getGrantClass(), array(
array(
'account_id' => '0',
'account_type' => Tinebase_Acl_Rights::ACCOUNT_TYPE_ANYONE,
Tinebase_Model_Grants::GRANT_ADD => true,
Tinebase_Model_Grants::GRANT_EDIT => true,
// Tinebase_Model_Grants::GRANT_DELETE => true,
)
));
Tinebase_Container::getInstance()->setGrants($container, $grants, true, false);
}
return $container;
}
/**
* creates the initial folder for new accounts
*
* @param mixed[int|Tinebase_Model_User] $_account the account object
* @return Tinebase_Record_RecordSet of subtype Tinebase_Model_Container
*/
public function createPersonalFolder($_account)
{
$result = new Tinebase_Record_RecordSet(Tinebase_Model_Container::class);
$translation = Tinebase_Translation::getTranslation($this->_applicationName);
$account = Tinebase_User::getInstance()->getUserById($_account);
$name = sprintf($translation->_("%s's personal calendar"), $account->accountFullName);
$container = Tinebase_Container::getInstance()->createDefaultContainer(
static::$_defaultModel,
$this->_applicationName,
$account,
$name
);
$result->addRecord($container);
return $result;
}
protected function _handleContainerAfterCreateEvent(Tinebase_Event_Container_AfterCreate $event): void
{
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->INFO(__METHOD__ . ' ' . __LINE__
. ' about to handle Tinebase_Event_Container_AfterCreate' );
if ($syncConfig = $event->container->getRecordFromXProps([Calendar_Controller_Event::SYNC_CONTAINER], Calendar_Model_SyncContainerConfig::class)) {
$syncConfig->sync($event->container, skipReadCollectionMetaData: true);
$event->container->xprops()[Calendar_Controller_Event::SYNC_CONTAINER] = $syncConfig->dehydrate();
}
}
/**
* handler for Tinebase_Event_Container_BeforeCreate
* - give owner of personal container all grants
* - give freebusy grants to anyone for personal container
*
* @param Tinebase_Event_Container_BeforeCreate $_eventObject
*/
protected function _handleContainerBeforeCreateEvent(Tinebase_Event_Container_BeforeCreate $_eventObject)
{
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . ' ' . __LINE__
. ' about to handle Tinebase_Event_Container_BeforeCreate' );
if ($syncConfig = $_eventObject->container->getRecordFromXProps([Calendar_Controller_Event::SYNC_CONTAINER], Calendar_Model_SyncContainerConfig::class)) {
$syncConfig->sync();
$_eventObject->container->xprops()[Calendar_Controller_Event::SYNC_CONTAINER] = $syncConfig->dehydrate();
}
$this->_addDefaultPersonalGrantsToContainer(
$_eventObject->container,
'Calendar',
$_eventObject->grants,
$_eventObject->accountId,
[
Calendar_Model_Event::class,
],
Calendar_Model_EventPersonalGrants::class,
! Tinebase_Config::getInstance()->get(Tinebase_Config::ANYONE_ACCOUNT_DISABLED) ?
[
new Calendar_Model_EventPersonalGrants(array(
'account_id' => '0',
'account_type' => Tinebase_Acl_Rights::ACCOUNT_TYPE_ANYONE,
Calendar_Model_EventPersonalGrants::GRANT_FREEBUSY => true
), true)
] : []
);
}
/**
* send notifications
*
* @param Calendar_Model_Event $_event
* @param Tinebase_Model_FullUser $_updater
* @param String $_action
* @param Calendar_Model_Event $_oldEvent
* @return void
*/
public function sendEventNotifications($_event, $_updater, $_action, $_oldEvent = NULL)
{
Calendar_Controller_EventNotifications::getInstance()->doSendNotifications($_event, $_updater, $_action, $_oldEvent);
}
/**
* update group events
*
* @param string $_groupId
* @return void
*/
public function onUpdateGroup($_groupId)
{
Calendar_Controller_Event::getInstance()->onUpdateGroup($_groupId);
}
/**
* get core data for this application
*
* @return Tinebase_Record_RecordSet
*/
public function getCoreDataForApplication()
{
$result = parent::getCoreDataForApplication();
$application = Tinebase_Application::getInstance()->getApplicationByName($this->_applicationName);
if (Tinebase_Core::getUser()->hasRight($application, Calendar_Acl_Rights::MANAGE_RESOURCES)) {
$result->addRecord(new CoreData_Model_CoreData(array(
'id' => 'cal_resources',
'application_id' => $application,
'model' => 'Calendar_Model_Resource',
'label' => 'Resources' // _('Resources')
)));
}
if (Tinebase_Core::getUser()->hasRight($application, Calendar_Acl_Rights::MANAGE_EVENT_TYPES) &&
Calendar_Config::getInstance()->featureEnabled(Calendar_Config::FEATURE_EVENT_TYPE)
) {
$result->addRecord(new CoreData_Model_CoreData(array(
'id' => 'cal_event_types',
'application_id' => $application,
'model' => 'Calendar_Model_EventType',
'label' => 'Event Types' // _('Event Types')
)));
}
return $result;
}
/**
* @param Felamimail_Model_Message $_message
* @return null
*/
public function prepareMassMailingMessage(Felamimail_Model_Message $_message, Tinebase_Twig $_twig, &$context)
{
if (Calendar_Config::getInstance()->featureEnabled(Calendar_Config::FEATURE_POLLS)) {
Calendar_Controller_Poll::getInstance()->prepareMassMailingMessage($_message, $_twig, $context);
}
return;
}
public static function addFastRoutes(\FastRoute\RouteCollector $routeCollector): void
{
$routeCollector->addRoute('PROPFIND', '/.well-known/caldav', (new Tinebase_Expressive_RouteHandler(
self::class, 'publicWellKnownCalDav', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true
]))->toArray());
$routeCollector->addGroup('/Calendar', function (\FastRoute\RouteCollector $routeCollector) {
if (Calendar_Config::getInstance()->featureEnabled(Calendar_Config::FEATURE_POLLS)) {
$routeCollector->get('/view/pollagb', (new Tinebase_Expressive_RouteHandler(
Calendar_Controller_Poll::class, 'publicApiGetAGB', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true
]))->toArray());
$routeCollector->get('/view/poll/{pollId}[/{userKey}[/{authKey}]]', (new Tinebase_Expressive_RouteHandler(
Calendar_Controller_Poll::class, 'publicApiMainScreen', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true,
Tinebase_Expressive_RouteHandler::UNAUTHORIZED_REDIRECT_LOGIN => true,
]))->toArray());
$routeCollector->get('/poll/{pollId}[/{userKey}[/{authKey}]]', (new Tinebase_Expressive_RouteHandler(
Calendar_Controller_Poll::class, 'publicApiGetPoll', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true
]))->toArray());
$routeCollector->post('/poll/{pollId}', (new Tinebase_Expressive_RouteHandler(
Calendar_Controller_Poll::class, 'publicApiUpdateAttendeeStatus', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true
]))->toArray());
$routeCollector->post('/poll/join/{pollId}', (new Tinebase_Expressive_RouteHandler(
Calendar_Controller_Poll::class, 'publicApiAddAttendee', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true
]))->toArray());
}
$routeCollector->get('/view/floorplan[/{floorplan}]', (new Tinebase_Expressive_RouteHandler(
self::class, 'floorplanMainScreen', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => false,
Tinebase_Expressive_RouteHandler::UNAUTHORIZED_REDIRECT_LOGIN => true,
]))->toArray());
$routeCollector->get('/freebusy/{urlId}', (new Tinebase_Expressive_RouteHandler(
self::class, 'publicFreeBusy', [
Tinebase_Expressive_RouteHandler::IS_PUBLIC => true,
]))->toArray());
});
}
public function publicFreeBusy(string $urlId): \Psr\Http\Message\ResponseInterface
{
$freeBusyUrlCtrlRaii = new Tinebase_RAII(Calendar_Controller_FreeBusyUrl::getInstance()->assertPublicUsage());
$resourceCtrlRaii = new Tinebase_RAII(Calendar_Controller_Resource::getInstance()->assertPublicUsage());
$fbUrl = Calendar_Controller_FreeBusyUrl::getInstance()->get($urlId);
switch ($fbUrl->{Calendar_Model_FreeBusyUrl::FLD_OWNER_CLASS}) {
case Tinebase_Model_User::class:
$oldUser = Tinebase_Core::getUser();
$resetUser = new Tinebase_RAII(fn() => $oldUser ? Tinebase_Core::setUser($oldUser) : Tinebase_Core::unsetUser());
Tinebase_Core::setUser($user = Tinebase_User::getInstance()->getUserById(
$fbUrl->getIdFromProperty(Calendar_Model_FreeBusyUrl::FLD_OWNER_ID)
));
$response = $this->_getFBResponse(new Calendar_Model_Attender([
Calendar_Model_Attender::FLD_USER_TYPE => Calendar_Model_Attender::USERTYPE_USER,
Calendar_Model_Attender::FLD_USER_ID => $user->contact_id,
], true), $user->accountEmailAddress);
unset($resetUser);
break;
case Calendar_Model_Resource::class:
$eventCtrlRaii = new Tinebase_RAII(Calendar_Controller_Event::getInstance()->assertPublicUsage());
$response = $this->_getFBResponse(new Calendar_Model_Attender([
Calendar_Model_Attender::FLD_USER_TYPE => Calendar_Model_Attender::USERTYPE_RESOURCE,
Calendar_Model_Attender::FLD_USER_ID => $fbUrl->{Calendar_Model_FreeBusyUrl::FLD_OWNER_ID}->getId(),
], true), $fbUrl->{Calendar_Model_FreeBusyUrl::FLD_OWNER_ID}->email); // TODO FIXME email might be empty?
unset($eventCtrlRaii);
break;
default:
throw new Tinebase_Exception_NotFound('free busy url owner class not supported');
}
unset($resourceCtrlRaii);
unset($freeBusyUrlCtrlRaii);
return $response;
}
protected function _getFBResponse(Calendar_Model_Attender $attendee, string $organizer): \Psr\Http\Message\ResponseInterface
{
$calendarController = Calendar_Controller_Event::getInstance();
$allFb = $calendarController->getFreeBusyInfo(new Calendar_Model_EventFilter([[
'field' => 'period',
'operator' => 'within',
'value' => ['from' => $from = Tinebase_DateTime::now(), 'until' => $until = Tinebase_DateTime::now()->addYear(1)],
]]), new Tinebase_Record_RecordSet(Calendar_Model_Attender::class, [$attendee]));
$vcalendar = new \Sabre\VObject\Component\VCalendar();
$vcalendar->METHOD = 'PUBLISH'; // @phpstan-ignore-line
$vFree = $vcalendar->createComponent('VFREEBUSY', [
'DTSTAMP' => Tinebase_DateTime::now(),
'DTSTART' => $from->getClone(),
'DTEND' => $until->getClone(),
'ORGANIZER' => $organizer,
]);
$vcalendar->add($vFree);
/** @var Calendar_Model_FreeBusy $freeBusy */
foreach ($allFb as $freeBusy) {
if (Calendar_Model_FreeBusy::FREEBUSY_FREE === $freeBusy->type) {
continue;
}
$type = 'BUSY';
if (Calendar_Model_FreeBusy::FREEBUSY_BUSY_TENTATIVE === $freeBusy->type) {
$type = 'BUSY-TENTATIVE';
}
$vFree->add('FREEBUSY', $freeBusy->dtstart->format('Ymd\THis\Z') . '/' . $freeBusy->dtend->format('Ymd\THis\Z'), ['FBTYPE' => $type]);
}
$response = new \Laminas\Diactoros\Response(headers: [
'Content-Type' => 'text/calendar; charset=utf-8',
'Cache-Control' => 'no-store',
]);
$response->getBody()->write($vcalendar->serialize());
return $response;
}
public function publicWellKnownCalDav(): \Psr\Http\Message\ResponseInterface
{
return new \Laminas\Diactoros\Response(status: 301, headers: ['Location' => '/calendars']);
}
public function floorplanMainScreen($floorplan=0)
{
$locale = Tinebase_Core::getLocale();
$jsFiles[] = "index.php?method=Tinebase.getJsTranslations&locale={$locale}&app=Calendar";
$jsFiles[] = 'Calendar/js/floorplan/src/index.es6.js';
$user = Tinebase_Core::getUser();
$userContactArray = array();
if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
try {
$userContactArray = Addressbook_Controller_Contact::getInstance()->getContactByUserId($user->getId(), TRUE)->toArray();
} catch (Addressbook_Exception_NotFound $aenf) {
if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) /** @noinspection PhpUndefinedMethodInspection */
Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__
. ' User not found in Addressbook: ' . $user->accountDisplayName);
}
}
return Tinebase_Frontend_Http_SinglePageApplication::getClientHTML($jsFiles, Calendar_Config::APP_NAME, context: [
'base' => Tinebase_Core::getUrl(Tinebase_Core::GET_URL_PATH),
'lang' => $locale,
'initialData' => [
'floorplans' => Calendar_Config::getInstance()->{Calendar_Config::FLOORPLANS},
'resources' => Calendar_Controller_Resource::getInstance()->getAll()->toArray(),
'currentContact' => $userContactArray,
'jsonKey' => Tinebase_Core::get('jsonKey'),
'locale' => $locale->toString(),
'broadcasthubConfig' => Tinebase_Config::getInstance()->getClientRegistryConfig()['Tinebase']['broadcasthub']['value']
]
]);
}
}