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