/** * repairs container names * * @param Zend_Console_Getopt $opts */ public function repairContainerName($opts) { if (!$this->_checkAdminRight()) { return FALSE; } $dryrun = $opts->d; $this->_addOutputLogWriter(); $args = $this->_parseArgs($opts); $containersWithBadNames = Tinebase_Container::getInstance()->getContainersWithBadNames(); $locale = Tinebase_Translation::getLocale(isset($args['locale']) ? $args['locale'] : 'auto'); if ($dryrun) { print_r($containersWithBadNames->toArray()); echo "Using Locale " . $locale . "\n"; } $appContainerNames = array('Calendar' => 'calendar', 'Tasks' => 'tasks', 'Addressbook' => 'addressbook'); foreach ($containersWithBadNames as $container) { if (empty($container->owner_id)) { if ($dryrun) { echo "Don't rename shared container " . $container->id . "\n"; } continue; } $app = Tinebase_Application::getInstance()->getApplicationById($container->application_id); $appContainerName = isset($appContainerNames[$app->name]) ? $appContainerNames[$app->name] : "container"; $translation = Tinebase_Translation::getTranslation($app->name, $locale); $account = Tinebase_User::getInstance()->getUserByPropertyFromSqlBackend('accountId', $container->owner_id); $newName = $newBaseName = sprintf($translation->_("%s's personal " . $appContainerName), $account->accountFullName); $count = 1; do { try { Tinebase_Container::getInstance()->getContainerByName($app->name, $newName, Tinebase_Model_Container::TYPE_PERSONAL, $container->owner_id); $found = true; $newName = $newBaseName . ' ' . ++$count; } catch (Tinebase_Exception_NotFound $tenf) { $found = false; } } while ($found); if ($dryrun) { echo "Rename container id " . $container->id . ' to ' . $newName . "\n"; } else { $container->name = $newName; Tinebase_Container::getInstance()->update($container); } } $result = 0; exit($result); }
/** * sets the user locale * * @param string $localeString */ public static function setupUserLocale($localeString = 'auto') { try { $session = Tinebase_Session::getSessionNamespace(); } catch (Zend_Session_Exception $zse) { $session = null; } if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " given localeString '{$localeString}'"); } // get locale object from session or ... if ($session !== NULL && isset($session->userLocale) && is_object($session->userLocale) && ($session->userLocale->toString() === $localeString || $localeString === 'auto')) { $locale = $session->userLocale; if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Got locale from session : " . (string) $locale); } // ... create new locale object } else { if ($localeString === 'auto') { // check if cookie or pref with language is available if (isset($_COOKIE['TINE20LOCALE'])) { $localeString = $_COOKIE['TINE20LOCALE']; if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Got locale from cookie: '{$localeString}'"); } } elseif (isset($session->currentAccount)) { $localeString = self::getPreference()->getValue(Tinebase_Preference::LOCALE, 'auto'); if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Got locale from preference: '{$localeString}'"); } } else { if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Try to detect the locale of the user (browser, environment, default)"); } } } $locale = Tinebase_Translation::getLocale($localeString); // save in session if ($session !== NULL) { $session->userLocale = $locale; } // check if the detected locale should be saved in preferences if ($localeString === 'auto' && is_object(Tinebase_Core::getUser()) && (string) $locale !== 'en') { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Saving locale: " . (string) $locale); } self::getPreference()->{Tinebase_Preference::LOCALE} = (string) $locale; } } // save in registry self::set('locale', $locale); $localeString = (string) $locale; if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { self::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Setting user locale: " . $localeString); } // set correct ctype locale, to make sure that the filesystem functions like basename() are working correctly with utf8 chars $ctypeLocale = setlocale(LC_CTYPE, 0); if (!preg_match('/utf-?8/i', $ctypeLocale)) { // use en_US as fallback locale if region string is missing $newCTypeLocale = (strpos($localeString, '_') !== FALSE ? $localeString : 'en_US') . '.UTF8'; if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Setting CTYPE locale from "' . $ctypeLocale . '" to "' . $newCTypeLocale . '".'); } setlocale(LC_CTYPE, $newCTypeLocale); } }
/** * send notification to a single attender * * @param Calendar_Model_Attender $_attender * @param Calendar_Model_Event $_event * @param Tinebase_Model_FullAccount $_updater * @param Sting $_action * @param String $_notificationLevel * @param array $_updates * @param array $attachs * @return void */ public function sendNotificationToAttender($_attender, $_event, $_updater, $_action, $_notificationLevel, $_updates = NULL, $attachs = FALSE) { try { // find organizer account if ($_event->organizer && $_event->resolveOrganizer()->account_id) { $organizer = Tinebase_User::getInstance()->getFullUserById($_event->resolveOrganizer()->account_id); } else { // use creator as organizer $organizer = Tinebase_User::getInstance()->getFullUserById($_event->created_by); } // get prefered language, timezone and notification level $prefUser = $_attender->getUserAccountId(); $locale = Tinebase_Translation::getLocale(Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::LOCALE, $prefUser ? $prefUser : $organizer->getId())); $timezone = Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::TIMEZONE, $prefUser ? $prefUser : $organizer->getId()); $translate = Tinebase_Translation::getTranslation('Calendar', $locale); // check if user wants this notification $sendLevel = $prefUser ? Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::NOTIFICATION_LEVEL, $prefUser) : 100; $sendOnOwnActions = $prefUser ? Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::SEND_NOTIFICATION_OF_OWN_ACTIONS, $prefUser) : 0; // NOTE: organizer gets mails unless she set notificationlevel to NONE if ($prefUser == $_updater->getId() && !$sendOnOwnActions || $sendLevel < $_notificationLevel && ($prefUser != $organizer->getId() || $sendLevel == self::NOTIFICATION_LEVEL_NONE)) { return; } // get date strings $startDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_event->dtstart, $timezone, $locale); $endDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_event->dtend, $timezone, $locale); switch ($_action) { case 'alarm': $messageSubject = sprintf($translate->_('Alarm for event "%1$s" at %2$s'), $_event->summary, $startDateString); break; case 'created': $messageSubject = sprintf($translate->_('Event invitation "%1$s" at %2$s'), $_event->summary, $startDateString); $method = Calendar_Model_iMIP::METHOD_REQUEST; break; case 'deleted': $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been canceled'), $_event->summary, $startDateString); $method = Calendar_Model_iMIP::METHOD_CANCEL; break; case 'changed': switch ($_notificationLevel) { case self::NOTIFICATION_LEVEL_EVENT_RESCHEDULE: $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been rescheduled'), $_event->summary, $startDateString); $method = Calendar_Model_iMIP::METHOD_REQUEST; break; case self::NOTIFICATION_LEVEL_EVENT_UPDATE: $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been updated'), $_event->summary, $startDateString); $method = Calendar_Model_iMIP::METHOD_REQUEST; break; case self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE: if (!empty($_updates['attendee']) && !empty($_updates['attendee']['toUpdate']) && count($_updates['attendee']['toUpdate']) == 1) { // single attendee status update $attender = $_updates['attendee']['toUpdate'][0]; switch ($attender->status) { case Calendar_Model_Attender::STATUS_ACCEPTED: $messageSubject = sprintf($translate->_('%1$s accepted event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString); break; case Calendar_Model_Attender::STATUS_DECLINED: $messageSubject = sprintf($translate->_('%1$s declined event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString); break; case Calendar_Model_Attender::STATUS_TENTATIVE: $messageSubject = sprintf($translate->_('Tentative response from %1$s for event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString); break; case Calendar_Model_Attender::STATUS_NEEDSACTION: $messageSubject = sprintf($translate->_('No response from %1$s for event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString); break; } } else { $messageSubject = sprintf($translate->_('Attendee changes for event "%1$s" at %2$s'), $_event->summary, $startDateString); } // we don't send iMIP parts to organizers with an account cause event is already up to date if ($_event->organizer && !$_event->resolveOrganizer()->account_id) { $method = Calendar_Model_iMIP::METHOD_REPLY; } break; } break; default: if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " unknown action '{$_action}'"); } break; } $view = new Zend_View(); $view->setScriptPath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'views'); $view->translate = $translate; $view->timezone = $timezone; $view->event = $_event; $view->updater = $_updater; $view->updates = $_updates; $messageBody = $view->render('eventNotification.php'); if (isset($method) && version_compare(PHP_VERSION, '5.3.0', '>=')) { $converter = Calendar_Convert_Event_VCalendar_Factory::factory(Calendar_Convert_Event_VCalendar_Factory::CLIENT_GENERIC); $converter->setMethod($method); $vcalendar = $converter->fromTine20Model($_event); // in Tine 2.0 non organizers might be given the grant to update events // @see rfc6047 section 2.2.1 & rfc5545 section 3.2.18 if ($method != Calendar_Model_iMIP::METHOD_REPLY && $_event->organizer !== $_updater->contact_id) { foreach ($vcalendar->children() as $component) { if ($component->name == 'VEVENT') { if (isset($component->{'ORGANIZER'})) { $component->{'ORGANIZER'}->add(new Sabre_VObject_Parameter('SEND-BY', 'mailto:' . $_updater->accountEmailAddress)); } } } } /* not yet supported // in Tine 2.0 status updater might not be updater if ($method == Calendar_Model_iMIP::METHOD_REPLY) { } */ $calendarPart = new Zend_Mime_Part($vcalendar->serialize()); $calendarPart->charset = 'UTF-8'; $calendarPart->type = 'text/calendar; method=' . $method; $calendarPart->encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE; $attachment = new Zend_Mime_Part($vcalendar->serialize()); $attachment->type = 'application/ics'; $attachment->encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE; $attachment->disposition = Zend_Mime::DISPOSITION_ATTACHMENT; $attachment->filename = 'event.ics'; $attachments = array($attachment); if ($attachs) { foreach ($attachs as $file) { $stream = fopen($file['tempFile']['path'], 'r'); $part = new Zend_Mime_Part($stream); $part->type = $file['tempFile']['type']; $part->encoding = Zend_Mime::ENCODING_BASE64; $part->disposition = Zend_Mime::DISPOSITION_ATTACHMENT; $part->filename = $file['tempFile']['name']; $attachments[] = $part; } } } else { $calendarPart = null; $attachments = null; } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " receiver: '{$_attender->getEmail()}'"); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " subject: '{$messageSubject}'"); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " body: {$messageBody}"); } // NOTE: this is a contact as we only support users and groupmembers $contact = $_attender->getResolvedUser(); $sender = $_action == 'alarm' ? $organizer : $_updater; Tinebase_Notification::getInstance()->send($sender, array($contact), $messageSubject, $messageBody, $calendarPart, $attachments); } catch (Exception $e) { Tinebase_Core::getLogger()->WARN(__METHOD__ . '::' . __LINE__ . " could not send notification :" . $e); return; } }
/** * send notification to a single attender * * @param Calendar_Model_Attender $_attender * @param Calendar_Model_Event $_event * @param Tinebase_Model_FullAccount $_updater * @param string $_action * @param string $_notificationLevel * @param array $_updates * @return void * * TODO this needs major refactoring */ public function sendNotificationToAttender(Calendar_Model_Attender $_attender, $_event, $_updater, $_action, $_notificationLevel, $_updates = NULL) { try { $organizer = $_event->resolveOrganizer(); $organizerAccountId = $organizer->account_id; $attendee = $_attender->getResolvedUser(); if ($attendee instanceof Addressbook_Model_List) { // don't send notification to lists as we already resolved the list members for individual mails if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skip notification for list " . $attendee->name); } return; } $attendeeAccountId = $_attender->getUserAccountId(); $prefUserId = $attendeeAccountId ? $attendeeAccountId : ($organizerAccountId ? $organizerAccountId : $_event->created_by); try { $prefUser = Tinebase_User::getInstance()->getFullUserById($prefUserId); } catch (Exception $e) { $prefUser = Tinebase_Core::getUser(); $prefUserId = $prefUser->getId(); } // get prefered language, timezone and notification level $locale = Tinebase_Translation::getLocale(Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::LOCALE, $prefUserId)); $timezone = Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::TIMEZONE, $prefUserId); $translate = Tinebase_Translation::getTranslation('Calendar', $locale); $sendLevel = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::NOTIFICATION_LEVEL, $prefUserId); $sendOnOwnActions = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::SEND_NOTIFICATION_OF_OWN_ACTIONS, $prefUserId); $sendAlarms = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::SEND_ALARM_NOTIFICATIONS, $prefUserId); // external (non account) notification if (!$attendeeAccountId) { // external organizer needs status updates $sendLevel = is_object($organizer) && $_attender->getEmail() == $organizer->getPreferedEmailAddress() ? 40 : 30; $sendOnOwnActions = false; $sendAlarms = false; } $recipients = array($attendee); $this->_handleResourceEditors($_attender, $_notificationLevel, $recipients, $_action, $sendLevel, $_updates); // check if user wants this notification NOTE: organizer gets mails unless she set notificationlevel to NONE // NOTE prefUser is organizer for external notifications if ($attendeeAccountId == $_updater->getId() && !$sendOnOwnActions || $sendLevel < $_notificationLevel && (is_object($organizer) && method_exists($attendee, 'getPreferedEmailAddress') && $attendee->getPreferedEmailAddress() != $organizer->getPreferedEmailAddress() || is_object($organizer) && !method_exists($attendee, 'getPreferedEmailAddress') && $attendee->email != $organizer->getPreferedEmailAddress() || $sendLevel == self::NOTIFICATION_LEVEL_NONE)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Preferred notification level not reached -> skipping notification for {$_attender->getEmail()}"); } return; } if ($_action == 'alarm' && !$sendAlarms) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " User does not want alarm mails -> skipping notification for {$_attender->getEmail()}"); } return; } $method = NULL; // NOTE $method gets set in _getSubject as referenced param $messageSubject = $this->_getSubject($_event, $_notificationLevel, $_action, $_updates, $timezone, $locale, $translate, $method, $_attender); // we don't send iMIP parts to external attendee if config is active if (Calendar_Config::getInstance()->get(Calendar_Config::DISABLE_EXTERNAL_IMIP) && !$attendeeAccountId) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " External iMIP is disabled."); } $method = NULL; } $view = new Zend_View(); $view->setScriptPath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'views'); $view->translate = $translate; $view->timezone = $timezone; $view->event = $_event; $view->updater = $_updater; $view->updates = $_updates; $messageBody = $view->render('eventNotification.php'); $calendarPart = null; $attachments = $this->_getAttachments($method, $_event, $_action, $_updater, $calendarPart); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " receiver: '{$_attender->getEmail()}'"); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " subject: '{$messageSubject}'"); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " body: {$messageBody}"); } $sender = $_action == 'alarm' ? $prefUser : $_updater; Tinebase_Notification::getInstance()->send($sender, $recipients, $messageSubject, $messageBody, $calendarPart, $attachments); } catch (Exception $e) { Tinebase_Exception::log($e); return; } }
/** * create notification message for task alarm * * @return string * * @todo should we get the locale pref for each single user here instead of the default? * @todo move lead stuff to Crm(_Model_Lead)? * @todo add getSummary to Addressbook_Model_Contact for linked contacts? */ public function getNotificationMessage() { // get locale from prefs $localePref = Tinebase_Core::getPreference()->getValue(Tinebase_Preference::LOCALE); $locale = Tinebase_Translation::getLocale($localePref); $translate = Tinebase_Translation::getTranslation($this->_application, $locale); // get date strings $timezone = $this->originator_tz ? $this->originator_tz : Tinebase_Core::get(Tinebase_Core::USERTIMEZONE); $dueDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($this->due, $timezone, $locale); // resolve values Tinebase_User::getInstance()->resolveUsers($this, 'organizer', true); $status = Tasks_Config::getInstance()->get(Tasks_Config::TASK_STATUS)->records->getById($this->status); $organizerName = $this->organizer ? $this->organizer->accountDisplayName : ''; //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($this->toArray(), TRUE)); $text = $this->summary . "\n\n" . $translate->_('Due') . ': ' . $dueDateString . "\n" . $translate->_('Organizer') . ': ' . $organizerName . "\n" . $translate->_('Description') . ': ' . $this->description . "\n" . $translate->_('Priority') . ': ' . $this->priority . "\n" . $translate->_('Status') . ': ' . $translate->_($status['value']) . "\n" . $translate->_('Percent') . ': ' . $this->percent . "%\n\n"; // add relations (get with ignore acl) $relations = Tinebase_Relations::getInstance()->getRelations(get_class($this), 'Sql', $this->getId(), NULL, array('TASK'), TRUE); foreach ($relations as $relation) { if ($relation->related_model == 'Crm_Model_Lead') { $lead = $relation->related_record; $text .= $translate->_('Lead') . ': ' . $lead->lead_name . "\n"; $leadRelations = Tinebase_Relations::getInstance()->getRelations(get_class($lead), 'Sql', $lead->getId()); foreach ($leadRelations as $leadRelation) { if ($leadRelation->related_model == 'Addressbook_Model_Contact') { $contact = $leadRelation->related_record; $text .= $leadRelation->type . ': ' . $contact->n_fn . ' (' . $contact->org_name . ')' . "\n" . (!empty($contact->tel_work) ? "\t" . $translate->_('Telephone') . ': ' . $contact->tel_work . "\n" : '') . (!empty($contact->email) ? "\t" . $translate->_('Email') . ': ' . $contact->email . "\n" : ''); } } } } //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $text); return $text; }
/** * sets the user locale * * @param string $localeString * @param bool $saveaspreference */ public static function setupUserLocale($localeString = 'auto', $saveaspreference = FALSE) { $session = self::get(self::SESSION); if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " given localeString '{$localeString}'"); } // get locale object from session or ... if ($session !== NULL && isset($session->userLocale) && is_object($session->userLocale) && ($session->userLocale->toString() === $localeString || $localeString === 'auto')) { $locale = $session->userLocale; if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " session value: " . (string) $locale); } // ... create new locale object } else { if ($localeString === 'auto') { // check if cookie or pref with language is available if (isset($_COOKIE['TINE20LOCALE'])) { $localeString = $_COOKIE['TINE20LOCALE']; if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Got locale from cookie: '{$localeString}'"); } } else { if (isset($session->currentAccount)) { $localeString = self::getPreference()->getValue(Tinebase_Preference::LOCALE, 'auto'); if (self::isLogLevel(Zend_Log::DEBUG)) { self::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Got locale from preference: '{$localeString}'"); } } else { $localeString = new Zend_Locale(); } } } $locale = Tinebase_Translation::getLocale($localeString); // save in session and registry if ($session !== NULL) { $session->userLocale = $locale; } } self::getLogger()->info(__METHOD__ . '::' . __LINE__ . " user locale: " . (string) $locale); self::set('locale', $locale); // save locale as preference if (is_object(Tinebase_Core::getUser()) && ($saveaspreference || self::getPreference()->{Tinebase_Preference::LOCALE} === 'auto')) { self::getPreference()->{Tinebase_Preference::LOCALE} = (string) $locale; } }