1#!/usr/bin/env php 2<?php 3/** 4 * Copyright 2003-2017 Horde LLC (http://www.horde.org/) 5 * 6 * See the enclosed file COPYING for license information (GPL). If you 7 * did not receive this file, see http://www.horde.org/licenses/gpl. 8 * 9 * @author Chuck Hagenbuch <chuck@horde.org> 10 */ 11 12if (file_exists(__DIR__ . '/../../kronolith/lib/Application.php')) { 13 $baseDir = __DIR__ . '/../'; 14} else { 15 require_once 'PEAR/Config.php'; 16 $baseDir = PEAR_Config::singleton() 17 ->get('horde_dir', null, 'pear.horde.org') . '/kronolith/'; 18} 19require_once $baseDir . 'lib/Application.php'; 20Horde_Registry::appInit('kronolith', array('cli' => true)); 21 22send_agendas(); 23 24/** 25 */ 26function send_agendas() 27{ 28 if (isset($_SERVER['REQUEST_TIME'])) { 29 $runtime = $_SERVER['REQUEST_TIME']; 30 } else { 31 $runtime = time(); 32 } 33 34 $kronolith_shares = $GLOBALS['injector']->getInstance('Kronolith_Shares'); 35 $calendars = $kronolith_shares->listAllShares(); 36 37 // If there are no calendars to check, we're done. 38 if (!count($calendars)) { 39 return; 40 } 41 42 if (empty($GLOBALS['conf']['reminder']['server_name']) || 43 empty($GLOBALS['conf']['reminder']['from_addr'])) { 44 die('You must configure the server_name and from_addr settings for reminders in the calendar configuration.'); 45 } 46 47 $_SERVER['SERVER_NAME'] = $GLOBALS['conf']['server']['name'] = $GLOBALS['conf']['reminder']['server_name']; 48 49 // Retrieve a list of users associated with each calendar, and 50 // thus a list of users who have used kronolith and 51 // potentially have an agenda preference set. 52 $users = array(); 53 foreach (array_keys($calendars) as $calendarId) { 54 try { 55 $calendar = $kronolith_shares->getShare($calendarId); 56 } catch (Exception $e) { 57 continue; 58 } 59 $users = array_merge($users, $calendar->listUsers(Horde_Perms::READ)); 60 } 61 62 // Remove duplicates. 63 $users = array_unique($users); 64 65 // Generate image mime part first and only once, because we need 66 // the Content-ID. 67 $image = Kronolith::getImagePart('big_agenda.png'); 68 69 $runtime = new Horde_Date($runtime); 70 $default_timezone = date_default_timezone_get(); 71 $kronolith_driver = Kronolith::getDriver(); 72 $view = new Horde_View(array('templatePath' => KRONOLITH_TEMPLATES . '/agenda', 'encoding' => 'UTF-8')); 73 new Horde_View_Helper_Text($view); 74 $view->imageId = $image->getContentId(); 75 $view->date = $runtime; 76 if (!$GLOBALS['prefs']->isLocked('daily_agenda')) { 77 $view->prefsUrl = Horde::url($GLOBALS['registry']->getServiceLink('prefs', 'kronolith'), true)->remove(session_name()); 78 } 79 80 // Loop through the users and generate an agenda for them 81 foreach ($users as $user) { 82 $prefs = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Prefs')->create('kronolith', array( 83 'user' => $user 84 )); 85 $agenda_calendars = $prefs->getValue('daily_agenda'); 86 87 if (!$agenda_calendars) { 88 continue; 89 } 90 91 // Initialize the CalendarsManager for this user. 92 $GLOBALS['calendar_manager'] = new Kronolith_CalendarsManager($user); 93 94 // Try to find an email address for the user. 95 $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($user); 96 $email = $identity->getDefaultFromAddress(true); 97 98 // Check if user has a timezone pref, and set it. Otherwise, make 99 // sure to use the server's default timezone. 100 $tz = $prefs->getValue('timezone'); 101 date_default_timezone_set(empty($tz) ? $default_timezone : $tz); 102 103 // If we found an email address, generate the agenda. 104 switch ($agenda_calendars) { 105 case 'owner': 106 $calendars = $kronolith_shares->listShares( 107 $user, 108 array('perm' => Horde_Perms::SHOW, 109 'attributes' => $user)); 110 $calendars = array_keys($calendars); 111 break; 112 113 case 'read': 114 $calendars = $kronolith_shares->listShares( 115 $user, 116 array('perm' => Horde_Perms::READ)); 117 $calendars = array_keys($calendars); 118 break; 119 120 case 'show': 121 default: 122 $calendars = array(); 123 $shown_calendars = unserialize($prefs->getValue('display_cals')); 124 $cals = $kronolith_shares->listShares( 125 $user, 126 array('perm' => Horde_Perms::SHOW)); 127 foreach (array_keys($cals) as $calId) { 128 if (in_array($calId, $shown_calendars)) { 129 $calendars[] = $calId; 130 } 131 } 132 } 133 134 // Get a list of events for today 135 $eventlist = array(); 136 foreach ($calendars as $calId) { 137 $kronolith_driver->open($calId); 138 $events = $kronolith_driver->listEvents( 139 $runtime, $runtime, array('show_recurrence' => true)); 140 foreach ($events as $dayevents) { 141 foreach ($dayevents as $event) { 142 // The event list contains events starting at 12am. 143 if ($event->start->compareDate($runtime) || $event->isPrivate($user)) { 144 continue; 145 } 146 $eventlist[] = $event; 147 } 148 } 149 } 150 151 if (!count($eventlist)) { 152 continue; 153 } 154 155 // If there are any events, generate and send the email. 156 usort($eventlist, 'sort_events'); 157 $GLOBALS['registry']->setLanguageEnvironment($prefs->getValue('language')); 158 $twentyFour = $prefs->getValue('twentyFour'); 159 160 $view->pad = max(Horde_String::length(_("All day")) + 2, $twentyFour ? 6 : 8); 161 $view->dateFormat = $prefs->getValue('date_format'); 162 $view->timeformat = $twentyFour ? 'H:i' : 'h:ia'; 163 $view->user = $user; 164 $view->events = $eventlist; 165 166 $mime_mail = new Horde_Mime_Mail(array( 167 'Subject' => sprintf(_("Your daily agenda for %s"), $runtime->strftime($view->dateFormat)), 168 'To' => $email, 169 'From' => $GLOBALS['conf']['reminder']['from_addr'], 170 'User-Agent' => 'Kronolith ' . $GLOBALS['registry']->getVersion(), 171 'Auto-Submitted' => 'auto-generated')); 172 try { 173 $mime_mail->addRecipients($email); 174 } catch (Horde_Mime_Exception $e) {} 175 176 $mime_mail->setBasePart(Kronolith::buildMimeMessage($view, 'notification', $image)); 177 178 Horde::log(sprintf('Sending daily agenda to %s', $email), 'DEBUG'); 179 try { 180 $mime_mail->send($GLOBALS['injector']->getInstance('Horde_Mail')); 181 } catch (Horde_Mime_Exception $e) { 182 Horde::log(sprintf('Error sending daily agenda to %s: %s', $email, $e->getMessage()), 'WARN'); 183 } 184 } 185} 186 187function sort_events($a, $b) 188{ 189 if ($a->allday && $b->allday) { 190 return 0; 191 } 192 193 if ($a->allday || $b->allday) { 194 return ($a->allday) ? -1 : 1; 195 } 196 197 if ($a->start == $b->start) { 198 return 0; 199 } 200 201 return ($a->start < $b->start) ? -1 : 1; 202} 203