Merge branch '2013.03' into 2013.10
[tine20] / tests / tine20 / Calendar / Controller / EventNotificationsTests.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Calendar
6  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
7  * @copyright   Copyright (c) 2009-2013 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Cornelius Weiss <c.weiss@metaways.de>
9  */
10
11 /**
12  * Test helper
13  */
14 require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
15
16 /**
17  * Test class for Calendar_Controller_EventNotifications
18  * 
19  * @package     Calendar
20  */
21 class Calendar_Controller_EventNotificationsTests extends Calendar_TestCase
22 {
23     /**
24      * @var Calendar_Controller_Event controller unter test
25      */
26     protected $_eventController;
27     
28     /**
29      * @var Calendar_Controller_EventNotifications controller unter test
30      */
31     protected $_notificationController;
32     
33     /**
34      * @var Zend_Mail_Transport_Array
35      */
36     protected static $_mailer = NULL;
37     
38     /**
39      * @var Tinebase_Model_Container
40      */
41     protected $_testCalendar;
42     
43    /**
44     * email test class
45     *
46     * @var Felamimail_Controller_MessageTest
47     */
48     protected $_emailTestClass;
49     
50     /**
51      * (non-PHPdoc)
52      * @see tests/tine20/Calendar/Calendar_TestCase::setUp()
53      */
54     public function setUp()
55     {
56         parent::setUp();
57         
58         $smtpConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::SMTP, new Tinebase_Config_Struct())->toArray();
59         if (empty($smtpConfig)) {
60              $this->markTestSkipped('No SMTP config found: this is needed to send notifications.');
61         }
62         
63         $this->_eventController = Calendar_Controller_Event::getInstance();
64         $this->_notificationController = Calendar_Controller_EventNotifications::getInstance();
65         
66         $this->_setupPreferences();
67     }
68     
69     /**
70      * Tears down the fixture
71      * This method is called after a test is executed.
72      *
73      * @access protected
74      */
75     public function tearDown()
76     {
77         parent::tearDown();
78         
79         if ($this->_emailTestClass instanceof Felamimail_Controller_MessageTest) {
80             $this->_emailTestClass->tearDown();
81         }
82     }
83     
84     /**
85      * testInvitation
86      */
87     public function testInvitation()
88     {
89         $event = $this->_getEvent(TRUE);
90         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf, sclever, jmcblack, rwright');
91         
92         self::flushMailer();
93         $persistentEvent = $this->_eventController->create($event);
94         $this->_assertMail('jsmith', NULL);
95         $this->_assertMail('pwulf, sclever, jmcblack, rwright', 'invit');
96         
97         self::flushMailer();
98         $persistentEvent = $this->_eventController->delete($persistentEvent);
99         $this->_assertMail('jsmith', NULL);
100         $this->_assertMail('pwulf, sclever, jmcblack, rwright', 'cancel');
101     }
102
103     /**
104      * testInvitationWithAttachment
105      * 
106      * @see 0008592: append event file attachments to invitation mail
107      */
108     public function testInvitationWithAttachment()
109     {
110         $event = $this->_getEvent(TRUE);
111         $event->attendee = $this->_getPersonaAttendee('pwulf');
112         
113         $tempFileBackend = new Tinebase_TempFile();
114         $tempFile = $tempFileBackend->createTempFile(dirname(dirname(dirname(__FILE__))) . '/Filemanager/files/test.txt');
115         $event->attachments = array(array('tempFile' => array('id' => $tempFile->getId())));
116         
117         self::flushMailer();
118         $persistentEvent = $this->_eventController->create($event);
119         
120         $messages = self::getMessages();
121         
122         $this->assertEquals(1, count($messages));
123         $parts = $messages[0]->getParts();
124         $this->assertEquals(2, count($parts));
125         $fileAttachment = $parts[1];
126         $this->assertEquals('text/plain; name="=?utf-8?Q?tempfile.tmp?="', $fileAttachment->type);
127         
128         // @todo assert attachment content (this seems to not work with array mailer, maybe we need a "real" email test here)
129 //         $content = $fileAttachment->getDecodedContent();
130 //         $this->assertEquals('test file content', $content);
131     }
132     
133     /**
134      * testUpdateEmpty
135      */
136     public function testUpdateEmpty()
137     {
138         $event = $this->_getEvent();
139         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf, sclever, jmcblack, rwright');
140         $persistentEvent = $this->_eventController->create($event);
141         
142         // no updates
143         self::flushMailer();
144         $updatedEvent = $this->_eventController->update($persistentEvent);
145         $this->_assertMail('jsmith, pwulf, sclever, jmcblack, rwright', NULL);
146     }
147     
148     /**
149      * testUpdateChangeAttendee
150      */
151     public function testUpdateChangeAttendee()
152     {
153         $event = $this->_getEvent(TRUE);
154         $event->attendee = $this->_getPersonaAttendee('pwulf, jmcblack, rwright');
155         $persistentEvent = $this->_eventController->create($event);
156         
157         $persistentEvent->attendee->merge($this->_getPersonaAttendee('jsmith, sclever'));
158         $persistentEvent->attendee->removeRecord(
159             $persistentEvent->attendee->find('user_id', $this->_personasContacts['pwulf']->getId())
160         );
161         $persistentEvent->attendee->find('user_id', $this->_personasContacts['rwright']->getId())->status =
162             Calendar_Model_Attender::STATUS_ACCEPTED;
163         $persistentEvent->attendee->find('user_id', $this->_personasContacts['jmcblack']->getId())->status =
164             Calendar_Model_Attender::STATUS_DECLINED;
165             
166         self::flushMailer();
167         $updatedEvent = $this->_eventController->update($persistentEvent);
168         $this->_assertMail('jsmith, jmcblack', NULL);
169         $this->_assertMail('sclever', 'invit');
170         $this->_assertMail('pwulf', 'cancel');
171         $this->_assertMail('rwright', 'Attendee');
172     }
173     
174     /**
175      * testUpdateReschedule
176      */
177     public function testUpdateReschedule()
178     {
179         $event = $this->_getEvent(TRUE);
180         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf, sclever, jmcblack, rwright');
181         $persistentEvent = $this->_eventController->create($event);
182         
183         $persistentEvent->summary = 'reschedule notification has precedence over normal update';
184         $persistentEvent->dtstart->addHour(1);
185         $persistentEvent->dtend->addHour(1);
186         
187         self::flushMailer();
188         $updatedEvent = $this->_eventController->update($persistentEvent);
189         $this->_assertMail('jsmith, pwulf', NULL);
190         $this->_assertMail('sclever, jmcblack, rwright', 'reschedul');
191     }
192     
193     /**
194      * testUpdateDetails
195      */
196     public function testUpdateDetails()
197     {
198         $event = $this->_getEvent(TRUE);
199         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf, sclever, jmcblack, rwright');
200         $persistentEvent = $this->_eventController->create($event);
201         
202         $persistentEvent->summary = 'detail update notification has precedence over attendee update';
203         $persistentEvent->url = 'http://somedetail.com';
204         $persistentEvent->attendee[1]->status = Calendar_Model_Attender::STATUS_ACCEPTED;
205         
206         self::flushMailer();
207         $updatedEvent = $this->_eventController->update($persistentEvent);
208         $this->_assertMail('jsmith, pwulf, sclever', NULL);
209         $this->_assertMail('jmcblack, rwright', 'update');
210     }
211         
212     /**
213      * testUpdateAttendeeStatus
214      */
215     public function testUpdateAttendeeStatus()
216     {
217         $event = $this->_getEvent(TRUE);
218         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf, sclever, jmcblack, rwright');
219         $persistentEvent = $this->_eventController->create($event);
220         
221         $persistentEvent->attendee[1]->status = Calendar_Model_Attender::STATUS_DECLINED;
222         
223         self::flushMailer();
224         $updatedEvent = $this->_eventController->update($persistentEvent);
225         $this->_assertMail('jsmith, pwulf, sclever, jmcblack', NULL);
226         $this->_assertMail('rwright', 'decline');
227     }
228     
229     /**
230      * testOrganizerNotificationSupress
231      */
232     public function testOrganizerNotificationSupress()
233     {
234         $event = $this->_getEvent();
235         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf');
236         $event->organizer = $this->_personasContacts['jsmith']->getId();
237         $persistentEvent = $this->_eventController->create($event);
238         
239         $persistentEvent->attendee[1]->status = Calendar_Model_Attender::STATUS_DECLINED;
240         
241         self::flushMailer();
242         $updatedEvent = $this->_eventController->update($persistentEvent);
243         $this->_assertMail('jsmith, pwulf', NULL);
244     }
245     
246     /**
247      * testOrganizerNotificationSend
248      */
249     public function testOrganizerNotificationSend()
250     {
251         $event = $this->_getEvent(TRUE);
252         $event->attendee = $this->_getPersonaAttendee('jsmith, pwulf');
253         $event->organizer = $this->_personasContacts['pwulf']->getId();
254         $persistentEvent = $this->_eventController->create($event);
255         
256         $persistentEvent->attendee[1]->status = Calendar_Model_Attender::STATUS_DECLINED;
257         
258         self::flushMailer();
259         $updatedEvent = $this->_eventController->update($persistentEvent);
260         $this->_assertMail('jsmith', NULL);
261         $this->_assertMail('pwulf', 'decline');
262     }
263     
264     /**
265      * testNotificationToNonAccounts
266      */
267     public function testNotificationToNonAccounts()
268     {
269         $event = $this->_getEvent(TRUE);
270         $event->attendee = $this->_getPersonaAttendee('pwulf');
271         $event->organizer = $this->_personasContacts['pwulf']->getId();
272         
273         // add nonaccount attender
274         $nonAccountEmail = 'externer@example.org';
275         $nonAccountAttender = Addressbook_Controller_Contact::getInstance()->create(new Addressbook_Model_Contact(array(
276             'n_family'  => 'externer',
277             'email'     => $nonAccountEmail,
278         )));
279         $event->attendee->addRecord($this->_createAttender($nonAccountAttender->getId()));
280         
281         $persistentEvent = $this->_eventController->create($event);
282         
283         // add alarm
284         $persistentEvent->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
285             new Tinebase_Model_Alarm(array(
286                 'minutes_before' => 30
287             ), TRUE)
288         ));
289         $updatedEvent = $this->_eventController->update($persistentEvent);
290         
291         self::flushMailer();
292
293         $persistentEvent->attendee[1]->status = Calendar_Model_Attender::STATUS_DECLINED;
294         $updatedEvent = $this->_eventController->update($persistentEvent);
295         
296         // make sure messages are sent if queue is activated
297         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
298             Tinebase_ActionQueue::getInstance()->processQueue();
299         }
300         
301         // check mailer messages
302         $foundNonAccountMessage = FALSE;
303         $foundPWulfMessage = FALSE;
304         foreach(self::getMailer()->getMessages() as $message) {
305             if (in_array($nonAccountEmail, $message->getRecipients())) {
306                 $foundNonAccountMessage = TRUE;
307             }
308             if (in_array($this->_personas['pwulf']->accountEmailAddress, $message->getRecipients())) {
309                 $foundPWulfMessage = TRUE;
310             }
311         }
312         
313         $this->assertTrue($foundNonAccountMessage, 'notification has not been sent to non-account');
314         $this->assertTrue($foundPWulfMessage, 'notfication for pwulf not found');
315     }
316     
317     /**
318      * testRecuringExceptions
319      */
320     public function testRecuringExceptions()
321     {
322         $from = new Tinebase_DateTime('2012-03-01 00:00:00');
323         $until = new Tinebase_DateTime('2012-03-31 23:59:59');
324         
325         $event = new Calendar_Model_Event(array(
326                 'summary'       => 'Some Daily Event',
327                 'dtstart'       => '2012-03-14 09:00:00',
328                 'dtend'         => '2012-03-14 10:00:00',
329                 'rrule'         => 'FREQ=DAILY;INTERVAL=1',
330                 'container_id'  => $this->_testCalendar->getId(),
331                 'attendee'      => $this->_getPersonaAttendee('jmcblack'),
332         ));
333         
334         self::flushMailer();
335         $persistentEvent = $this->_eventController->create($event);
336         $this->_assertMail('jmcblack', 'Recurrance rule:    Daily', 'body');
337         
338         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
339         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until);
340         
341         // cancel instance
342         self::flushMailer();
343         $this->_eventController->createRecurException($recurSet[4], TRUE, FALSE); //2012-03-19
344         $this->_assertMail('jmcblack', 'cancel');
345         
346         // update instance
347         self::flushMailer();
348         $updatedBaseEvent = $this->_eventController->getRecurBaseEvent($recurSet[5]);
349         $recurSet[5]->last_modified_time = $updatedBaseEvent->last_modified_time;
350         $recurSet[5]->summary = 'exceptional summary';
351         $this->_eventController->createRecurException($recurSet[5], FALSE, FALSE); //2012-03-20
352         $this->_assertMail('jmcblack', 'This is an event series exception', 'body');
353         $this->_assertMail('jmcblack', 'update');
354         
355         // reschedule instance
356         self::flushMailer();
357         $updatedBaseEvent = $this->_eventController->getRecurBaseEvent($recurSet[6]);
358         $recurSet[6]->last_modified_time = $updatedBaseEvent->last_modified_time;
359         $recurSet[6]->dtstart->addHour(2);
360         $recurSet[6]->dtend->addHour(2);
361         $this->_eventController->createRecurException($recurSet[6], FALSE, FALSE); //2012-03-21
362         $this->_assertMail('jmcblack', 'reschedule');
363         
364         // cancle thisandfuture
365         // @TODO check RANGE in ics
366         // @TODO add RANGE text to message
367         self::flushMailer();
368         $updatedBaseEvent = $this->_eventController->getRecurBaseEvent($recurSet[16]);
369         $recurSet[16]->last_modified_time = $updatedBaseEvent->last_modified_time;
370         $this->_eventController->createRecurException($recurSet[16], TRUE, TRUE); //2012-03-31
371         $this->_assertMail('jmcblack', 'cancel');
372         
373         // update thisandfuture
374         
375         // reschedule thisandfuture
376         
377         
378     }
379     public function testAttendeeAlarmSkip()
380     {
381         $event = $this->_getEvent();
382         $event->attendee = $this->_getPersonaAttendee('sclever, pwulf');
383         $event->organizer = $this->_personasContacts['sclever']->getId();
384         
385         $event->dtstart = Tinebase_DateTime::now()->addMinute(25);
386         $event->dtend = clone $event->dtstart;
387         $event->dtend->addMinute(30);
388         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
389             new Tinebase_Model_Alarm(array(
390                 'minutes_before' => 30
391             ), TRUE)
392         ));
393         
394         // pwulf skips alarm
395         $event->alarms->setOption('skip', array(
396             array(
397                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
398                 'user_id'   => $this->_personasContacts['pwulf']->getId(),
399             )
400         ));
401         
402         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
403         $persistentEvent = $this->_eventController->create($event);
404         self::flushMailer();
405         
406         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
407         $this->_assertMail('sclever', 'Alarm for event');
408         $this->_assertMail('pwulf');
409     }
410     
411     public function testAttendeeAlarmOnly()
412     {
413         $event = $this->_getEvent();
414         $event->attendee = $this->_getPersonaAttendee('sclever, pwulf');
415         $event->organizer = $this->_personasContacts['sclever']->getId();
416         
417         $event->dtstart = Tinebase_DateTime::now()->addMinute(25);
418         $event->dtend = clone $event->dtstart;
419         $event->dtend->addMinute(30);
420         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
421             new Tinebase_Model_Alarm(array(
422                 'minutes_before' => 30
423             ), TRUE)
424         ));
425         $event->alarms->setOption('attendee', array(
426             'user_type' => Calendar_Model_Attender::USERTYPE_USER,
427             'user_id'   => $this->_personasContacts['pwulf']->getId()
428         ));
429         
430         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
431         $persistentEvent = $this->_eventController->create($event);
432         self::flushMailer();
433         
434         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
435         $this->_assertMail('pwulf', 'Alarm for event');
436         $this->_assertMail('sclever');
437         
438     }
439     
440     public function testAlarm()
441     {
442         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
443         
444         $event = $this->_getEvent();
445         $event->dtstart = Tinebase_DateTime::now()->addMinute(15);
446         $event->dtend = clone $event->dtstart;
447         $event->dtend->addMinute(30);
448         $event->attendee = $this->_getAttendee();
449         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
450             new Tinebase_Model_Alarm(array(
451                     'minutes_before' => 30
452             ), TRUE)
453         ));
454         
455         $persistentEvent = $this->_eventController->create($event);
456         Calendar_Model_Attender::getOwnAttender($persistentEvent->attendee)->status = Calendar_Model_Attender::STATUS_DECLINED;
457         
458         // hack to get declined attendee
459         $this->_eventController->sendNotifications(FALSE);
460         $updatedEvent = $this->_eventController->update($persistentEvent);
461         $this->_eventController->sendNotifications(TRUE);
462         
463         self::flushMailer();
464         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
465         $this->_assertMail('sclever', 'Alarm');
466         $this->assertEquals(1, count(self::getMessages()));
467     }
468     
469     /**
470      * CalDAV/Custom can have alarms with odd times
471      */
472     public function testAlarmRoundMinutes()
473     {
474         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
475         
476         $event = $this->_getEvent();
477         $event->dtstart = Tinebase_DateTime::now()->addMinute(15);
478         $event->dtend = clone $event->dtstart;
479         $event->dtend->addMinute(30);
480         $event->attendee = $this->_getAttendee();
481         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
482             new Tinebase_Model_Alarm(array(
483                     'minutes_before' => 12.1
484             ), TRUE)
485         ));
486         
487         $persistentEvent = $this->_eventController->create($event);
488         
489         $this->assertEquals(12, $persistentEvent->alarms->getFirstRecord()->getOption('minutes_before'));
490     }
491     
492     public function testSkipPastAlarm()
493     {
494         $event = $this->_getEvent();
495         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
496             new Tinebase_Model_Alarm(array(
497                     'minutes_before' => 30
498             ), TRUE)
499         ));
500         
501         $persistentEvent = $this->_eventController->create($event);
502         self::flushMailer();
503         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
504         $this->_assertMail('sclever');
505     }
506     
507     /**
508      * testParallelAlarmTrigger
509      * 
510      * @see 0004878: improve asyncJob fencing
511      */
512     public function testParallelAlarmTrigger()
513     {
514         $this->markTestSkipped('TODO fixme: 0009116: fix Calendar_Controller_EventNotificationsTests::testParallelAlarmTrigger');
515         
516         $this->_testNeedsTransaction();
517         
518         try {
519             $this->_emailTestClass = new Felamimail_Controller_MessageTest();
520             $this->_emailTestClass->setup();
521         } catch (Exception $e) {
522             $this->markTestIncomplete('email not available.');
523         }
524         
525         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
526         self::flushMailer();
527         $this->_getAlarmMails(TRUE);
528         
529         $event = $this->_getEvent();
530         $event->dtstart = Tinebase_DateTime::now()->addMinute(15);
531         $event->dtend = clone $event->dtstart;
532         $event->dtend->addMinute(30);
533         $event->attendee = $this->_getAttendee();
534         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
535             new Tinebase_Model_Alarm(array(
536                     'minutes_before' => 30
537             ), TRUE)
538         ));
539         
540         $persistentEvent = $this->_eventController->create($event);
541         try {
542             Tinebase_AsyncJobTest::triggerAsyncEvents();
543         } catch (Exception $e) {
544             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
545                 . ' Something strange happened and the async jobs did not complete ... maybe the test system is not configured correctly for this: ' . $e);
546             $this->markTestIncomplete($e->getMessage());
547         }
548         
549         $result = $this->_getAlarmMails(TRUE);
550         $this->assertEquals(1, count($result), 'expected exactly 1 alarm mail, got: ' . print_r($result->toArray(), TRUE));
551     }
552     
553     /**
554      * testRecuringAlarm
555      */
556     public function testRecuringAlarm()
557     {
558         $event = $this->_getEvent();
559         $event->attendee = $this->_getPersonaAttendee('pwulf');
560         $event->organizer = $this->_personasContacts['pwulf']->getId();
561         
562         // lets flush mailer so next flushing ist faster!
563         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
564         self::flushMailer();
565         
566         // make sure next occurence contains now
567         // next occurance now+29min 
568         $event->dtstart = Tinebase_DateTime::now()->subDay(1)->addMinute(28);
569         $event->dtend = clone $event->dtstart;
570         $event->dtend->addMinute(30);
571         $event->rrule = 'FREQ=DAILY;INTERVAL=1';
572         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
573             new Tinebase_Model_Alarm(array(
574                 'minutes_before' => 30
575             ), TRUE)
576         ));
577         
578         $persistentEvent = $this->_eventController->create($event);
579         
580         // assert alarm
581         self::flushMailer();
582         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
583         $assertString = ' at ' . Tinebase_DateTime::now()->format('M j');
584         $this->_assertMail('pwulf', $assertString);
585
586         // check adjusted alarm time
587         $loadedEvent = $this->_eventController->get($persistentEvent->getId());
588         $recurid = $loadedEvent->alarms->getFirstRecord()->getOption('recurid');
589         $nextAlarmEventStart = new Tinebase_DateTime(substr($recurid, -19));
590         
591         $this->assertTrue($nextAlarmEventStart > Tinebase_DateTime::now()->addDay(1), 'alarmtime is not adjusted');
592         $this->assertEquals(Tinebase_Model_Alarm::STATUS_PENDING, $loadedEvent->alarms->getFirstRecord()->sent_status, 'alarmtime is set to pending');
593         
594         // update series @see #7430: Calendar sends too much alarms for recurring events
595         $this->_eventController->update($loadedEvent);
596         $recurid = $loadedEvent->alarms->getFirstRecord()->getOption('recurid');
597         $nextAlarmEventStart = new Tinebase_DateTime(substr($recurid, -19));
598         
599         $this->assertTrue($nextAlarmEventStart > Tinebase_DateTime::now()->addDay(1), 'alarmtime is wrong');
600     }
601     
602     /**
603      * if an event with an alarm gets an exception instance, also the alarm gets an exception instance
604      * @see #6328
605      */
606     public function testRecuringAlarmException()
607     {
608         $event = $this->_getEvent();
609         $event->attendee = $this->_getPersonaAttendee('pwulf');
610         $event->organizer = $this->_personasContacts['pwulf']->getId();
611         
612         $event->dtstart = Tinebase_DateTime::now()->subDay(1)->addMinute(15);
613         $event->dtend = clone $event->dtstart;
614         $event->dtend->addMinute(30);
615         $event->rrule = 'FREQ=DAILY;INTERVAL=1';
616         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
617                 new Tinebase_Model_Alarm(array(
618                         'minutes_before' => 30
619                 ), TRUE)
620         ));
621         
622         $persistentEvent = $this->_eventController->create($event);
623         
624         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
625         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $persistentEvent->dtstart, Tinebase_DateTime::now()->addDay(1));
626         $exceptionEvent = $this->_eventController->createRecurException($recurSet->getFirstRecord());
627         
628         // assert one alarm only
629         self::flushMailer();
630         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
631         $assertString = ' at ' . Tinebase_DateTime::now()->format('M j');
632         $this->_assertMail('pwulf', $assertString);
633         
634         // check series
635         $loadedEvent = $this->_eventController->get($persistentEvent->getId());
636         $recurid = $loadedEvent->alarms->getFirstRecord()->getOption('recurid');
637         $nextAlarmEventStart = new Tinebase_DateTime(substr($recurid, -19));
638         
639         $this->assertTrue($nextAlarmEventStart > Tinebase_DateTime::now(), 'alarmtime of series is not adjusted');
640         
641         // check exception
642         $recurid = $exceptionEvent->alarms->getFirstRecord()->getOption('recurid');
643         $nextAlarmEventStart = new Tinebase_DateTime(substr($recurid, -19));
644         
645         $this->assertTrue($nextAlarmEventStart < Tinebase_DateTime::now()->addHour(1), 'alarmtime of exception is not adjusted');
646         
647         // update exception @see #7430: Calendar sends too much alarms for recurring events
648         $exceptionEvent = $this->_eventController->update($exceptionEvent);
649         $recurid = $exceptionEvent->alarms->getFirstRecord()->getOption('recurid');
650         $nextAlarmEventStart = new Tinebase_DateTime(substr($recurid, -19));
651         
652         $this->assertTrue($nextAlarmEventStart < Tinebase_DateTime::now()->addHour(1), 'alarmtime of exception is wrong');
653     }
654     
655     public function testRecuringAlarmCustomDate()
656     {
657         $event = $this->_getEvent();
658         $event->attendee = $this->_getPersonaAttendee('pwulf');
659         $event->organizer = $this->_personasContacts['pwulf']->getId();
660         
661         $event->dtstart = Tinebase_DateTime::now()->addWeek(1)->addMinute(15);
662         $event->dtend = clone $event->dtstart;
663         $event->dtend->addMinute(30);
664         $event->rrule = 'FREQ=YEARLY;INTERVAL=1;BYDAY=2TH;BYMONTH=12';
665         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
666             new Tinebase_Model_Alarm(array(
667                 'minutes_before' => Tinebase_Model_Alarm::OPTION_CUSTOM,
668                 // NOTE: user means one week and 30 mins before
669                 'alarm_time'     => Tinebase_DateTime::now()->subMinute(15)
670             ), TRUE)
671         ));
672         
673         $persistentEvent = $this->_eventController->create($event);
674         
675         // assert one alarm only
676         self::flushMailer();
677         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
678         $assertString = ' at ' . Tinebase_DateTime::now()->addWeek(1)->format('M j');
679         $this->_assertMail('pwulf', $assertString);
680         
681         // check adjusted alarm time
682         $loadedEvent = $this->_eventController->get($persistentEvent->getId());
683         $recurid = $loadedEvent->alarms->getFirstRecord()->getOption('recurid');
684         $nextAlarmEventStart = new Tinebase_DateTime(substr($recurid, -19));
685         
686         $this->assertTrue($nextAlarmEventStart > Tinebase_DateTime::now(), 'alarmtime of series is not adjusted');
687     }
688     
689     /**
690      * test alarm inspection from 24.03.2012 -> 25.03.2012
691      */
692     public function testAdoptAlarmDSTBoundary()
693     {
694         $event = $this->_getEvent();
695         $event->rrule = 'FREQ=DAILY;INTERVAL=1';
696         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
697             new Tinebase_Model_Alarm(array(
698                 'minutes_before' => 30
699             ), TRUE)
700         ));
701         $persistentEvent = $this->_eventController->create($event);
702         
703         // prepare alarm for last non DST instance
704         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
705         $from = new Tinebase_DateTime('2012-03-24 00:00:00');
706         $until = new Tinebase_DateTime('2012-03-24 23:59:59');
707         $recurSet =Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until);
708         
709         $alarm = $persistentEvent->alarms->getFirstRecord();
710         $alarm->setOption('recurid', $recurSet[0]->recurid);
711         Tinebase_Alarm::getInstance()->update($alarm);
712         
713         $loadedBaseEvent = $this->_eventController->get($persistentEvent->getId());
714         $alarm = $loadedBaseEvent->alarms->getFirstRecord();
715         $this->assertEquals('2012-03-24', substr($alarm->getOption('recurid'), -19, -9), 'precondition failed');
716         
717         // adopt alarm
718         $this->_eventController->adoptAlarmTime($loadedBaseEvent, $alarm, 'instance');
719         $this->assertEquals('2012-03-25', substr($alarm->getOption('recurid'), -19, -9), 'alarm adoption failed');
720     }
721     
722     /**
723      * test alarm inspection from 24.03.2012 -> 25.03.2012
724      */
725     public function testAdoptAlarmDSTBoundaryWithSkipping()
726     {
727         $event = new Calendar_Model_Event(array(
728             'summary'      => 'Cleanup',
729             'dtstart'      => '2012-01-31 07:30:00',
730             'dtend'        => '2012-01-31 10:30:00',
731             'container_id' => $this->_testCalendar->getId(),
732             'uid'          => Calendar_Model_Event::generateUID(),
733             'rrule'        => 'FREQ=WEEKLY;INTERVAL=1;WKST=MO;BYDAY=TU',
734             'originator_tz'=> 'Europe/Berlin',
735         ));
736         
737         $alarm = new Tinebase_Model_Alarm(array(
738             'model'        => 'Calendar_Model_Event',
739             'alarm_time'   => '2012-03-26 06:30:00',
740             'minutes_before' => 1440,
741             'options'      => '{"minutes_before":1440,"recurid":"a7c55ce09cea9aec4ac37d9d72789183b12cad7c-2012-03-27 06:30:00","custom":false}',
742         ));
743         
744         $this->_eventController->adoptAlarmTime($event, $alarm, 'instance');
745         
746         $this->assertEquals('2012-04-02 06:30:00', $alarm->alarm_time->toString());
747     }
748     
749     public function testAlarmSkipDeclined()
750     {
751         $event = $this->_getEvent();
752         $event->attendee = $this->_getPersonaAttendee('sclever, pwulf');
753         $event->organizer = $this->_personasContacts['sclever']->getId();
754         
755         $event->dtstart = Tinebase_DateTime::now()->addMinute(25);
756         $event->dtend = clone $event->dtstart;
757         $event->dtend->addMinute(30);
758         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
759             new Tinebase_Model_Alarm(array(
760                 'minutes_before' => 30
761             ), TRUE)
762         ));
763         
764         $persistentEvent = $this->_eventController->create($event);
765         $sclever = Calendar_Model_Attender::getAttendee($persistentEvent->attendee, $event->attendee[0]);
766         $sclever->status = Calendar_Model_Attender::STATUS_DECLINED;
767         $this->_eventController->attenderStatusUpdate($persistentEvent, $sclever, $sclever->status_authkey);
768         
769         self::flushMailer();
770         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
771         $this->_assertMail('pwulf', 'Alarm');
772         $this->assertEquals(1, count(self::getMessages()));
773     }
774     
775     /**
776      * testRecuringAlarmAfterSeriesEnds
777      * 
778      * @see 0008386: alarm is sent for recur series that is already over
779      */
780     public function testRecuringAlarmAfterSeriesEnds()
781     {
782         $this->_recurAlarmTestHelper();
783     }
784     
785     /**
786      * helper for recurring alarm tests
787      * 
788      * @param boolean $allFollowing
789      * @param integer $alarmMinutesBefore
790      */
791     protected function _recurAlarmTestHelper($allFollowing = TRUE, $alarmMinutesBefore = 60)
792     {
793         $event = $this->_getEvent();
794         
795         // lets flush mailer so next flushing ist faster!
796         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
797         self::flushMailer();
798         
799         // make sure next occurence contains now
800         $event->dtstart = Tinebase_DateTime::now()->subDay(2)->addHour(1);
801         $event->dtend = clone $event->dtstart;
802         $event->dtend->addMinute(60);
803         $event->rrule = 'FREQ=DAILY;INTERVAL=1';
804         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
805             new Tinebase_Model_Alarm(array(
806                 'minutes_before' => $alarmMinutesBefore
807             ), TRUE)
808         ));
809         
810         // check alarm
811         $persistentEvent = $this->_eventController->create($event);
812         $this->assertEquals(1, count($persistentEvent->alarms));
813         $alarm = $persistentEvent->alarms->getFirstRecord();
814         $this->assertEquals(Tinebase_Model_Alarm::STATUS_PENDING, $alarm->sent_status);
815         $persistentDtstart = clone $persistentEvent->dtstart;
816         $this->assertEquals($persistentDtstart->subMinute($alarmMinutesBefore), $alarm->alarm_time, print_r($alarm->toArray(), TRUE));
817         
818         // delete all following
819         $from = $event->dtstart;
820         $until = $event->dtend->addDay(3);
821         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
822         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until);
823         $recurEvent = $recurSet[1]; // today
824         $persistentEvent = $this->_eventController->createRecurException($recurEvent, TRUE, $allFollowing);
825         
826         $baseEvent = $this->_eventController->getRecurBaseEvent($persistentEvent);
827         if ($allFollowing) {
828             $this->assertEquals('FREQ=DAILY;INTERVAL=1;UNTIL=' . $recurEvent->dtstart->subHour(1)->toString(), (string) $baseEvent->rrule, 'rrule mismatch');
829             $this->assertEquals(1, count($baseEvent->alarms));
830             $this->assertEquals('Nothing to send, series is over', $baseEvent->alarms->getFirstRecord()->sent_message,
831                 'alarm adoption failed: ' . print_r($baseEvent->alarms->getFirstRecord()->toArray(), TRUE));
832         } else {
833             $this->assertEquals('FREQ=DAILY;INTERVAL=1', (string) $baseEvent->rrule);
834             $this->assertEquals(Tinebase_Model_Alarm::STATUS_PENDING, $baseEvent->alarms->getFirstRecord()->sent_status);
835             $this->assertEquals('', $baseEvent->alarms->getFirstRecord()->sent_message);
836         }
837         
838         // assert no alarm
839         self::flushMailer();
840         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
841         $messages = self::getMessages();
842         $this->assertEquals(0, count($messages), 'no alarm message should be sent: ' . print_r($messages, TRUE));
843     }
844     
845     /**
846      * testRecuringAlarmWithRecurException
847      * 
848      * @see 0008386: alarm is sent for recur series that is already over
849      */
850     public function testRecuringAlarmWithRecurException()
851     {
852         $this->_recurAlarmTestHelper(FALSE);
853     }
854
855     /**
856      * testRecuringAlarmWithRecurException120MinutesBefore
857      * 
858      * @see 0008386: alarm is sent for recur series that is already over
859      */
860     public function testRecuringAlarmWithRecurException120MinutesBefore()
861     {
862         $this->_recurAlarmTestHelper(FALSE, 120);
863     }
864
865     /**
866      * testRecuringAlarmWithRecurExceptionMoved
867      * 
868      * @see 0008386: alarm is sent for recur series that is already over
869      */
870     public function testRecuringAlarmWithRecurExceptionMoved()
871     {
872         $event = $this->_getEvent();
873         
874         // lets flush mailer so next flushing ist faster!
875         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
876         self::flushMailer();
877         
878         // make sure next occurence contains now
879         $event->dtstart = Tinebase_DateTime::now()->subWeek(2)->addDay(1);
880         $event->dtend = clone $event->dtstart;
881         $event->dtend->addMinute(60);
882         $event->rrule = 'FREQ=WEEKLY;INTERVAL=1;WKST=MO;BYDAY=' . array_search($event->dtstart->format('w'), Calendar_Model_Rrule::$WEEKDAY_DIGIT_MAP);
883         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
884             new Tinebase_Model_Alarm(array(
885                 'minutes_before' => 1440
886             ), TRUE)
887         ));
888         
889         $persistentEvent = $this->_eventController->create($event);
890         
891         // adopt alarm time (previous alarms have been sent already)
892         $alarm = $persistentEvent->alarms->getFirstRecord();
893         $alarm->alarm_time->addWeek(2);
894         Tinebase_Alarm::getInstance()->update($alarm);
895         
896         // move next occurrence
897         $from = $event->dtstart;
898         $until = $event->dtend->addWeek(3);
899         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
900         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until);
901         $recurEvent = $recurSet[1]; // tomorrow
902         
903         $recurEvent->dtstart->addDay(5);
904         $recurEvent->dtend = clone $recurEvent->dtstart;
905         $recurEvent->dtend->addMinute(60);
906         $persistentEvent = $this->_eventController->createRecurException($recurEvent);
907         
908         $baseEvent = $this->_eventController->getRecurBaseEvent($persistentEvent);
909         $alarm = $baseEvent->alarms->getFirstRecord();
910         $this->assertEquals(Tinebase_Model_Alarm::STATUS_PENDING, $alarm->sent_status);
911         
912         // assert no alarm
913         sleep(1);
914         self::flushMailer();
915         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
916         $messages = self::getMessages();
917         $this->assertEquals(0, count($messages), 'no alarm message should be sent: ' . print_r($messages, TRUE));
918     }
919
920     /**
921      * testRecuringAlarmWithThisAndFutureSplit
922      * 
923      * @see 0008386: alarm is sent for recur series that is already over
924      */
925     public function testRecuringAlarmWithThisAndFutureSplit()
926     {
927         $event = $this->_getEvent();
928         
929         // lets flush mailer so next flushing ist faster!
930         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
931         self::flushMailer();
932         
933         // make sure next occurence contains now
934         $event->dtstart = Tinebase_DateTime::now()->subMonth(1)->addDay(1)->subHour(2);
935         $event->dtend = clone $event->dtstart;
936         $event->dtend->addMinute(60);
937         $event->rrule = 'FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=' . $event->dtstart->format('d');
938         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
939             new Tinebase_Model_Alarm(array(
940                 'minutes_before' => 2880
941             ), TRUE)
942         ));
943         
944         $persistentEvent = $this->_eventController->create($event);
945         
946         // make sure, next alarm is for next month's event
947         Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
948         self::flushMailer();
949         
950         // split THISANDFUTURE, alarm of old series should be set to SUCCESS because it no longer should be sent
951         $from = $event->dtstart;
952         $until = $event->dtend->addMonth(2);
953         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
954         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until);
955         $recurEvent = (count($recurSet) > 1) ? $recurSet[1] : $recurSet[0]; // next month
956         $recurEvent->summary = 'split series';
957         $newPersistentEvent = $this->_eventController->createRecurException($recurEvent, FALSE, TRUE);
958         
959         // check alarms
960         $oldSeriesAlarm = Tinebase_Alarm::getInstance()
961             ->getAlarmsOfRecord('Calendar_Model_Event', $persistentEvent->getId())
962             ->getFirstRecord();
963         $this->assertEquals(Tinebase_Model_Alarm::STATUS_SUCCESS, $oldSeriesAlarm->sent_status,
964             'no pending alarm should exist for old series: ' . print_r($oldSeriesAlarm->toArray(), TRUE));
965     }
966     
967     /**
968      * get test alarm emails
969      * 
970      * @param boolean $deleteThem
971      * @return Tinebase_Record_RecordSet
972      */
973     protected function _getAlarmMails($deleteThem = FALSE)
974     {
975         // search and assert alarm mail
976         $folder = $this->_emailTestClass->getFolder('INBOX');
977         $folder = Felamimail_Controller_Cache_Message::getInstance()->updateCache($folder, 10, 1);
978         $i = 0;
979         while ($folder->cache_status != Felamimail_Model_Folder::CACHE_STATUS_COMPLETE && $i < 10) {
980             $folder = Felamimail_Controller_Cache_Message::getInstance()->updateCache($folder, 10);
981             $i++;
982         }
983         $account = Felamimail_Controller_Account::getInstance()->search()->getFirstRecord();
984         $filter = new Felamimail_Model_MessageFilter(array(
985             array('field' => 'folder_id',  'operator' => 'equals',     'value' => $folder->getId()),
986             array('field' => 'account_id', 'operator' => 'equals',     'value' => $account->getId()),
987             array('field' => 'subject',    'operator' => 'startswith', 'value' => 'Alarm for event "Wakeup" at'),
988         ));
989         
990         $result = Felamimail_Controller_Message::getInstance()->search($filter);
991         
992         if ($deleteThem) {
993             Felamimail_Controller_Message_Move::getInstance()->moveMessages($filter, Felamimail_Model_Folder::FOLDER_TRASH);
994         }
995         
996         return $result;
997     }
998     
999     /**
1000      * get messages
1001      * 
1002      * @return array
1003      */
1004     public static function getMessages()
1005     {
1006         // make sure messages are sent if queue is activated
1007         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
1008             Tinebase_ActionQueue::getInstance()->processQueue(100);
1009         }
1010         
1011         return self::getMailer()->getMessages();
1012     }
1013     
1014     /**
1015      * get mailer
1016      * 
1017      * @return Zend_Mail_Transport_Abstract
1018      */
1019     public static function getMailer()
1020     {
1021         if (! self::$_mailer) {
1022             self::$_mailer = Tinebase_Smtp::getDefaultTransport();
1023         }
1024         
1025         return self::$_mailer;
1026     }
1027     
1028     /**
1029      * flush mailer (send all remaining mails first)
1030      */
1031     public static function flushMailer()
1032     {
1033         // make sure all messages are sent if queue is activated
1034         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
1035             Tinebase_ActionQueue::getInstance()->processQueue(10000);
1036         }
1037         
1038         self::getMailer()->flush();
1039     }
1040     
1041     /**
1042      * checks if mail for persona got send
1043      * 
1044      * @param string $_personas
1045      * @param string $_assertString
1046      * @return void
1047      * 
1048      * @see #6800: add message-id to notification mails
1049      */
1050     protected function _assertMail($_personas, $_assertString = NULL, $_location = 'subject')
1051     {
1052         $messages = self::getMessages();
1053         
1054         foreach (explode(',', $_personas) as $personaName) {
1055             $mailsForPersona = array();
1056             $personaEmail = $this->_personas[trim($personaName)]->accountEmailAddress;
1057             
1058             foreach ($messages as $message) {
1059                 if (array_value(0, $message->getRecipients()) == $personaEmail) {
1060                     array_push($mailsForPersona, $message);
1061                 }
1062             }
1063             
1064             if (! $_assertString) {
1065                 $this->assertEquals(0, count($mailsForPersona), 'No mail should be send for '. $personaName);
1066             } else {
1067                 $this->assertEquals(1, count($mailsForPersona), 'One mail should be send for '. $personaName);
1068                 $this->assertEquals('UTF-8', $mailsForPersona[0]->getCharset());
1069                 
1070                 switch ($_location) {
1071                     case 'subject':
1072                         $subject = $mailsForPersona[0]->getSubject();
1073                         $this->assertTrue(FALSE !== strpos($subject, $_assertString), 'Mail subject for ' . $personaName . ' should contain "' . $_assertString . '" but '. $subject . ' is given');
1074                         break;
1075                         
1076                     case 'body':
1077                         $bodyPart = $mailsForPersona[0]->getBodyText(FALSE);
1078                         
1079                         // so odd!
1080                         $s = fopen('php://temp','r+');
1081                         fputs($s, $bodyPart->getContent());
1082                         rewind($s);
1083                         $bodyPartStream = new Zend_Mime_Part($s);
1084                         $bodyPartStream->encoding = $bodyPart->encoding;
1085                         $bodyText = $bodyPartStream->getDecodedContent();
1086                         
1087                         $this->assertContains($_assertString, $bodyText);
1088                         break;
1089                         
1090                     default:
1091                         throw new Exception('no such location '. $_location);
1092                         break;
1093                 }
1094                 
1095                 $headers = $mailsForPersona[0]->getHeaders();
1096                 $this->assertTrue(isset($headers['Message-Id']), 'message-id header not found');
1097                 $this->assertContains('@' . php_uname('n'), $headers['Message-Id'][0], 'hostname not in message-id');
1098             }
1099         }
1100     }
1101     
1102     /**
1103      * get attendee
1104      * 
1105      * @param string $_personas
1106      * @return Tinebase_Record_RecordSet
1107      */
1108     protected function _getPersonaAttendee($_personas)
1109     {
1110         $attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender');
1111         foreach (explode(',', $_personas) as $personaName) {
1112             $attendee->addRecord($this->_createAttender($this->_personasContacts[trim($personaName)]->getId()));
1113         }
1114         
1115         return $attendee;
1116     }
1117     
1118     /**
1119      * create new attender
1120      * 
1121      * @param string $_userId
1122      * @return Calendar_Model_Attender
1123      */
1124     protected function _createAttender($_userId)
1125     {
1126         return new Calendar_Model_Attender(array(
1127             'user_id'        => $_userId,
1128             'user_type'      => Calendar_Model_Attender::USERTYPE_USER,
1129             'role'           => Calendar_Model_Attender::ROLE_REQUIRED,
1130             'status_authkey' => Tinebase_Record_Abstract::generateUID(),
1131         ));
1132     }
1133     
1134     /**
1135      * setup preferences for personas
1136      * 
1137      * jsmith   -> no updates
1138      * pwulf    -> on invitaion/cancelation
1139      * sclever  -> on reschedules
1140      * jmblack  -> on updates except answers
1141      * rwright  -> even on ansers
1142      * 
1143      * @return void
1144      */
1145     protected function _setupPreferences()
1146     {
1147         // set notification levels
1148         $calPreferences = Tinebase_Core::getPreference('Calendar');
1149         $calPreferences->setValueForUser(
1150             Calendar_Preference::NOTIFICATION_LEVEL, 
1151             Calendar_Controller_EventNotifications::NOTIFICATION_LEVEL_NONE,
1152             $this->_personas['jsmith']->getId(), TRUE
1153         );
1154         $calPreferences->setValueForUser(
1155             Calendar_Preference::NOTIFICATION_LEVEL, 
1156             Calendar_Controller_EventNotifications::NOTIFICATION_LEVEL_INVITE_CANCEL,
1157             $this->_personas['pwulf']->getId(), TRUE
1158         );
1159         $calPreferences->setValueForUser(
1160             Calendar_Preference::NOTIFICATION_LEVEL, 
1161             Calendar_Controller_EventNotifications::NOTIFICATION_LEVEL_EVENT_RESCHEDULE,
1162             $this->_personas['sclever']->getId(), TRUE
1163         );
1164         $calPreferences->setValueForUser(
1165             Calendar_Preference::NOTIFICATION_LEVEL, 
1166             Calendar_Controller_EventNotifications::NOTIFICATION_LEVEL_EVENT_UPDATE,
1167             $this->_personas['jmcblack']->getId(), TRUE
1168         );
1169         $calPreferences->setValueForUser(
1170             Calendar_Preference::NOTIFICATION_LEVEL, 
1171             Calendar_Controller_EventNotifications::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE,
1172             $this->_personas['rwright']->getId(), TRUE
1173         );
1174         
1175         // set all languages to en
1176         $preferences = Tinebase_Core::getPreference('Tinebase');
1177         foreach ($this->_personas as $name => $account) {
1178             $preferences->setValueForUser(Tinebase_Preference::LOCALE, 'en', $account->getId(), TRUE);
1179         }
1180     }
1181 }