* @copyright Copyright (c) 2009-2025 Metaways Infosystems GmbH (http://www.metaways.de) */ /** * backend for Calendar preferences * * @package Calendar */ class Calendar_Preference extends Tinebase_Preference_Abstract { /** * where daysview should be scrolled to */ const DAYSVIEW_STARTTIME = 'daysviewstarttime'; /** * where daysvoew should be scrolled maximum up to */ const DAYSVIEW_ENDTIME = 'daysviewendtime'; /** * where daysview should be scrolled to */ const DAYSVIEW_DEFAULT_STARTTIME = 'daysviewdefaultstarttime'; /** * time in minutes to be visible in dayviews at once */ const DAYSVIEW_TIME_VISIBLE = 'daysviewtimevisible'; /** * default calendar all newly created/invited events are placed in */ const DEFAULTCALENDAR = 'defaultCalendar'; /** * have name of default favorite an a central palce * _("All my events") */ const DEFAULTPERSISTENTFILTER_NAME = "All my events"; /** * general notification level */ const NOTIFICATION_LEVEL = 'notificationLevel'; /** * send notifications of own updates */ const SEND_NOTIFICATION_OF_OWN_ACTIONS = 'sendnotificationsofownactions'; /** * send notifications of tentative events */ const SEND_NOTIFICATION_FOR_TENTATIVE = 'sendnotificationsfortentative'; /** * send alarm notifications */ const SEND_ALARM_NOTIFICATIONS = 'sendalarmnotifications'; /** * enable default alarm */ const DEFAULTALARM_ENABLED = 'defaultalarmenabled'; /** * default alarm time in minutes before */ const DEFAULTALARM_MINUTESBEFORE = 'defaultalarmminutesbefore'; /** * default alarm time in minutes before */ const DEFAULTATTENDEE_STRATEGY = 'defaultAttendeeStrategy'; /** * default set events to privat */ const DEFAULT_EVENTS_RRIVATE = 'defaultSetEventsToPrivat'; /** * timeIncrement */ const DEFAULT_TIMEINCREMENT = 'timeIncrement'; public const EXCLUDE_CANCELLED_EVENTS_WEBDAV = 'excludeCancelledEventsWebDav'; /** * firstdayofweek */ const FIRSTDAYOFWEEK = 'firstdayofweek'; /** * default calendar strategy */ const DEFAULT_CALENDAR_STRATEGY = 'defaultCalendarStrategy'; /** * remove all filters on change selection */ const REMOVE_FILTERS_ON_SELECT_CONTAINER = 'removeFiltersOnSelectContainer'; /** * fixedCalendars */ const FIXED_CALENDARS = 'fixedCalendars'; const WEB_EVENT_TITLE_TEMPLATE = 'webEventTitleTemplate'; const SYNC_FREE_BUSY_EVENTS = 'syncFreeBusyEvents'; /** * @var string application */ protected $_application = 'Calendar'; /** * get all possible application prefs * * @return array all application prefs */ public function getAllApplicationPreferences() { $cropDays = Calendar_Config::getInstance()->get(Calendar_Config::CROP_DAYS_VIEW); $allPrefs = array( self::DAYSVIEW_STARTTIME, self::DAYSVIEW_ENDTIME, self::DAYSVIEW_TIME_VISIBLE, self::DEFAULTCALENDAR, self::DEFAULTPERSISTENTFILTER, self::WEB_EVENT_TITLE_TEMPLATE, self::NOTIFICATION_LEVEL, self::SEND_NOTIFICATION_OF_OWN_ACTIONS, self::SEND_NOTIFICATION_FOR_TENTATIVE, self::SEND_ALARM_NOTIFICATIONS, self::DEFAULTALARM_ENABLED, self::DEFAULTALARM_MINUTESBEFORE, self::DEFAULTATTENDEE_STRATEGY, self::DEFAULT_TIMEINCREMENT, self::DEFAULTATTENDEE_STRATEGY, self::DEFAULT_EVENTS_RRIVATE, self::FIRSTDAYOFWEEK, self::DEFAULT_CALENDAR_STRATEGY, self::REMOVE_FILTERS_ON_SELECT_CONTAINER, self::FIXED_CALENDARS, self::SYNC_FREE_BUSY_EVENTS, self::EXCLUDE_CANCELLED_EVENTS_WEBDAV, ); if ($cropDays) { array_unshift($allPrefs, self::DAYSVIEW_DEFAULT_STARTTIME); } return $allPrefs; } /** * get translated right descriptions * * @return array with translated descriptions for this applications preferences */ public function getTranslatedPreferences() { $translate = Tinebase_Translation::getTranslation($this->_application); $prefDescriptions = array( self::DAYSVIEW_STARTTIME => array( 'label' => $translate->_('Start Time'), 'description' => $translate->_('Position on the left time axis, day and week view should start with'), ), self::DAYSVIEW_ENDTIME => array( 'label' => $translate->_('End Time'), 'description' => $translate->_('Position on the left time axis, day and week view should end with'), ), self::DAYSVIEW_DEFAULT_STARTTIME => array( 'label' => $translate->_('Default Start Time'), 'description' => $translate->_('Scroll position on the left time axis, day and week view should start with'), ), self::DAYSVIEW_TIME_VISIBLE => array( 'label' => $translate->_('Visible Time'), 'description' => $translate->_('Time to be displayed at once'), ), self::DEFAULTCALENDAR => array( 'label' => $translate->_('Default Calendar'), 'description' => $translate->_('The default calendar for invitations and new events'), ), self::DEFAULTPERSISTENTFILTER => array( 'label' => $translate->_('Default Favorite'), 'description' => $translate->_('The default favorite which is loaded on calendar startup'), ), self::WEB_EVENT_TITLE_TEMPLATE => [ 'label' => $translate->_('Web Event Title Template'), 'description' => $translate->_('How to build event titles in web UI.'), ], self::NOTIFICATION_LEVEL => array( 'label' => $translate->_('Get Notification Emails'), 'description' => $translate->_('The level of actions you want to be notified about. Please note that organizers will get notifications for all updates including attendee answers unless this preference is set to "Never"'), ), self::SEND_NOTIFICATION_OF_OWN_ACTIONS => array( 'label' => $translate->_('Send notification emails for your own actions.'), 'description' => $translate->_('Get notification emails for actions you did yourself'), ), self::SEND_NOTIFICATION_FOR_TENTATIVE => array( 'label' => $translate->_('Send notification emails of tentative events'), 'description' => $translate->_('Get notification emails of tentative events'), ), self::SEND_ALARM_NOTIFICATIONS => array( 'label' => $translate->_('Send Alarm Notification Emails'), 'description' => $translate->_('Get event alarms via email'), ), self::DEFAULTALARM_ENABLED => array( 'label' => $translate->_('Enable Standard Alarm'), 'description' => $translate->_('New events get a standard alarm as defined below'), ), self::DEFAULTALARM_MINUTESBEFORE => array( 'label' => $translate->_('Standard Alarm Time'), 'description' => $translate->_('Minutes before the event starts'), ), self::DEFAULTATTENDEE_STRATEGY => array( 'label' => $translate->_('Default Attendee Strategy'), 'description' => $translate->_('Default Attendee Strategy for new events'), ), self::DEFAULT_TIMEINCREMENT => array( 'label' => $translate->_('Time Increment'), 'description' => $translate->_('Increment of event time steps'), ), self::DEFAULT_EVENTS_RRIVATE => array( 'label' => $translate->_('Default set events to privat'), 'description' => $translate->_('If enabled, every created event is always private.'), ), self::FIRSTDAYOFWEEK => array( 'label' => $translate->_('First Day of Week'), 'description' => $translate->_('On what day the week should be starting'), ), self::DEFAULT_CALENDAR_STRATEGY => array( 'label' => $translate->_('Default calendar strategy'), 'description' => $translate->_('The calendar for new events, if no container is selected.'), ), self::REMOVE_FILTERS_ON_SELECT_CONTAINER => array( 'label' => $translate->_('Remove all filters on change selection'), 'description' => $translate->_('Changing the calendar will remove all filters.') ), self::FIXED_CALENDARS => array( 'label' => $translate->_('Fixed Calendars'), 'description' => $translate->_('Calendars are always selected, regardless of any filter parameters.'), ), self::SYNC_FREE_BUSY_EVENTS => [ 'label' => $translate->_('Sync FreeBusy events'), 'description' => $translate->_('Receive FreeBusy events via CalDAV and ActiveSync.'), ], self::EXCLUDE_CANCELLED_EVENTS_WEBDAV => [ 'label' => $translate->_('Exclude cancelled events from CalDAV'), 'description' => $translate->_('Do not transfer events via CalDAV where the attendee status of the calendar owner is set to "declined"'), ], ); return $prefDescriptions; } /** * Creates XML Data for a combobox * * Hours: 0 to 24 * * @param string $default * @return string */ protected function _createTimespanDataXML($start=0, $end=24) { $doc = new DomDocument('1.0'); $options = $doc->createElement('options'); $doc->appendChild($options); $time = new Tinebase_DateTime('@0'); for ($i=$start; $i<=$end; $i++) { $time->setHour($i); $timeString = $time->format('H:i'); if ($i == $end && $timeString == '00:00') { $timeString = '24:00'; } $value = $doc->createElement('value'); $value->appendChild($doc->createTextNode($timeString)); $label = $doc->createElement('label'); $label->appendChild($doc->createTextNode($timeString)); // @todo l10n $option = $doc->createElement('option'); $option->appendChild($value); $option->appendChild($label); $options->appendChild($option); } return $doc->saveXML(); } /** * get preference defaults if no default is found in the database * * @param string $_preferenceName * @param string|Tinebase_Model_User $_accountId * @param string $_accountType * @return Tinebase_Model_Preference */ public function getApplicationPreferenceDefaults($_preferenceName, $_accountId = NULL, $_accountType = Tinebase_Acl_Rights::ACCOUNT_TYPE_USER) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Get default value for ' . $_preferenceName . ' of account id '. $_accountId); $preference = $this->_getDefaultBasePreference($_preferenceName); switch ($_preferenceName) { case self::DAYSVIEW_STARTTIME: $preference->value = '08:00'; $preference->options = $this->_createTimespanDataXML(0, 23); break; case self::DAYSVIEW_ENDTIME: $preference->value = '18:00'; $preference->options = $this->_createTimespanDataXML(1, 24); break; case self::DAYSVIEW_DEFAULT_STARTTIME: $preference->value = '08:00'; $preference->options = $this->_createTimespanDataXML(0, 23); break; case self::DAYSVIEW_TIME_VISIBLE: $preference->value = '10:00'; $preference->options = $this->_createTimespanDataXML(1, 24); break; case self::DEFAULTCALENDAR: $this->_getDefaultContainerPreferenceDefaults($preference, $_accountId); break; case self::DEFAULTPERSISTENTFILTER: $preference->value = Tinebase_PersistentFilter::getPreferenceValues('Calendar', $_accountId, "All my events"); break; case self::WEB_EVENT_TITLE_TEMPLATE: $translate = Tinebase_Translation::getTranslation($this->_application); $preference->uiconfig = [ self::CLIENT_NEEDS_RELOAD => true ]; $preference->value = '{{ summary }}'; $preference->options = ' '; break; case self::NOTIFICATION_LEVEL: $translate = Tinebase_Translation::getTranslation($this->_application); // need to put the translations strings here because they were not found in the xml below :/ // _('Never') _('Only on invitation and cancellation.') _('On time changes') _('On all updates, except attendee responses.') _('On attendee responses too') $preference->value = Calendar_Controller_EventNotifications::NOTIFICATION_LEVEL_EVENT_RESCHEDULE; $preference->options = ' '; break; case self::SEND_NOTIFICATION_OF_OWN_ACTIONS: $preference->value = 0; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::EXCLUDE_CANCELLED_EVENTS_WEBDAV: $preference->value = 0; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::SEND_NOTIFICATION_FOR_TENTATIVE: $preference->value = 1; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::SEND_ALARM_NOTIFICATIONS: $preference->value = 1; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::DEFAULTALARM_ENABLED: $preference->value = 0; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::DEFAULTATTENDEE_STRATEGY: $translate = Tinebase_Translation::getTranslation($this->_application); $preference->value = 'me'; $preference->options = ' '; break; case self::DEFAULTALARM_MINUTESBEFORE: case self::DEFAULT_TIMEINCREMENT: $preference->value = 15; $preference->options = ' '; break; case self::DEFAULT_EVENTS_RRIVATE: $preference->value = 0; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::FIRSTDAYOFWEEK: $translate = Tinebase_Translation::getTranslation($this->_application); $preference->value = 1; $preference->options = ' '; break; case self::DEFAULT_CALENDAR_STRATEGY: $translate = Tinebase_Translation::getTranslation($this->_application); $preference->value = 'default'; $preference->options = ' '; break; case self::REMOVE_FILTERS_ON_SELECT_CONTAINER: $preference->value = 0; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; case self::FIXED_CALENDARS: $preference->value = array(); // TODO set better (?) options / maybe this could be removed $preference->options = ' ' . Tinebase_Preference_Abstract::DEFAULTCONTAINER_OPTIONS . ' '; $preference->uiconfig = array( 'xtype' => 'containerspicker', 'appName' => 'Calendar', 'model' => 'Event', ); $preference->personal_only = true; break; case self::SYNC_FREE_BUSY_EVENTS: $preference->value = true; $preference->options = ' ' . Tinebase_Preference_Abstract::YES_NO_OPTIONS . ' '; break; default: throw new Tinebase_Exception_NotFound('Default preference with name ' . $_preferenceName . ' not found.'); } return $preference; } /** * overwrite this in concrete classes if needed * * @param $_preferenceName * @return array */ public function _getPrefRecordConfig($_preferenceName) { switch ($_preferenceName) { case self::FIXED_CALENDARS: return array( 'modelName' => 'Tinebase_Model_Container', ); break; default: return parent::_getPrefRecordConfig($_preferenceName); } } }