month view recurinstances not selectable
[tine20] / tests / tine20 / Calendar / Controller / EventTests.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-2016 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Cornelius Weiss <c.weiss@metaways.de>
9  */
10
11 /**
12  * Test class for Calendar_Controller_Event
13  * 
14  * @package     Calendar
15  */
16 class Calendar_Controller_EventTests extends Calendar_TestCase
17 {
18     /**
19      * @var Calendar_Controller_Event controller unter test
20      */
21     protected $_controller;
22     
23     /**
24      * (non-PHPdoc)
25      * @see Calendar_TestCase::setUp()
26      */
27     public function setUp()
28     {
29         parent::setUp();
30         $this->_controller = Calendar_Controller_Event::getInstance();
31     }
32     
33     /**
34      * testCreateEvent
35      * 
36      * @return Calendar_Model_Event
37      */
38     public function testCreateEvent()
39     {
40         $event = $this->_getEvent();
41         $persistentEvent = $this->_controller->create($event);
42         
43         $this->assertEquals($event->description, $persistentEvent->description);
44         $this->assertTrue($event->dtstart->equals($persistentEvent->dtstart));
45         $this->assertEquals(Tinebase_Core::getUserTimezone(), $persistentEvent->originator_tz);
46         
47         return $persistentEvent;
48     }
49     
50     /**
51      * testCreateAlldayEventWithoutDtend
52      */
53     public function testCreateAlldayEventWithoutDtend()
54     {
55         $event = $this->_getEvent();
56         $event->is_all_day_event = true;
57         $event->dtend = null;
58         
59         $persistentEvent = $this->_controller->create($event);
60         $persistentEvent->setTimezone(Tinebase_Core::getUserTimezone());
61         $this->assertEquals('2009-04-06 23:59:59', $persistentEvent->dtend->toString());
62     }
63     
64     /**
65      * testGetEvent
66      */
67     public function testGetEvent()
68     {
69         $persistentEvent = $this->testCreateEvent();
70         $this->assertTrue((bool) $persistentEvent->{Tinebase_Model_Grants::GRANT_READ});
71         $this->assertTrue((bool) $persistentEvent->{Tinebase_Model_Grants::GRANT_EDIT});
72         $this->assertTrue((bool) $persistentEvent->{Tinebase_Model_Grants::GRANT_DELETE});
73         
74         $loadedEvent = $this->_controller->get($persistentEvent->getId());
75         $this->assertTrue((bool) $loadedEvent->{Tinebase_Model_Grants::GRANT_READ});
76         $this->assertTrue((bool) $loadedEvent->{Tinebase_Model_Grants::GRANT_EDIT});
77         $this->assertTrue((bool) $loadedEvent->{Tinebase_Model_Grants::GRANT_DELETE});
78     }
79
80     public function testGetRecurInstance()
81     {
82         // create event and invite admin group
83         $event = $this->_getEvent();
84         $event->rrule = 'FREQ=DAILY;INTERVAL=1';
85
86         $persistentEvent = $this->_controller->create($event);
87         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
88         $nextOccurance = Calendar_Model_Rrule::computeNextOccurrence($persistentEvent, $exceptions, Tinebase_DateTime::now());
89
90         $deepLink = $nextOccurance->getDeepLink();
91         preg_match('/fakeid.*$/', $deepLink, $matches);
92         $id = $matches[0];
93
94         $recurInstance = $this->_controller->get($id);
95         $this->assertTrue($recurInstance->isRecurInstance());
96         $this->assertEquals($nextOccurance->getId(), $recurInstance->getId());
97
98         // create recur exception in the meantime
99         $nextOccurance->summary = 'exception';
100         $this->_controller->createRecurException($nextOccurance);
101         $recurInstance = $this->_controller->get($id);
102 //        print_r($recurInstance->toArray());
103         $this->assertFalse($recurInstance->isRecurInstance());
104         $this->assertEquals($nextOccurance->summary, $recurInstance->summary);
105     }
106
107     /**
108      * testUpdateEvent
109      */
110     public function testUpdateEvent()
111     {
112         $persistentEvent = $this->testCreateEvent();
113         
114         $currentTz = Tinebase_Core::getUserTimezone();
115         Tinebase_Core::set(Tinebase_Core::USERTIMEZONE, 'farfaraway');
116         
117         $persistentEvent->summary = 'Lunchtime';
118         $updatedEvent = $this->_controller->update($persistentEvent);
119         $this->assertEquals($persistentEvent->summary, $updatedEvent->summary);
120         $this->assertEquals($currentTz, $updatedEvent->originator_tz, 'originator_tz must not be touchet if dtsart is not updatet!');
121         
122         $updatedEvent->dtstart->addHour(1);
123         $updatedEvent->dtend->addHour(1);
124         $secondUpdatedEvent = $this->_controller->update($updatedEvent);
125         $this->assertEquals(Tinebase_Core::getUserTimezone(), $secondUpdatedEvent->originator_tz, 'originator_tz must be adopted if dtsart is updatet!');
126     
127         Tinebase_Core::set(Tinebase_Core::USERTIMEZONE, $currentTz);
128     }
129     
130     public function testConcurrentUpdate()
131     {
132         $event = $this->testCreateEvent();
133         
134         sleep(1);
135         $resolvableConcurrentEvent1 = clone $event;
136         $resolvableConcurrentEvent1->dtstart = $resolvableConcurrentEvent1->dtstart->addMonth(1);
137         $resolvableConcurrentEvent1->dtend = $resolvableConcurrentEvent1->dtend->addMonth(1);
138         $resolvableConcurrentEvent1Update = $this->_controller->update($resolvableConcurrentEvent1);
139         
140         sleep(1);
141         $resolvableConcurrentEvent2 = clone $event;
142         $resolvableConcurrentEvent2->summary = 'Updated Event';
143         $resolvableConcurrentEvent2Update = $this->_controller->update($resolvableConcurrentEvent2);
144         
145         $this->assertEquals($resolvableConcurrentEvent1Update->dtstart, $resolvableConcurrentEvent2Update->dtstart);
146     }
147     
148     public function testUpdateAttendeeStatus()
149     {
150         $event = $this->_getEvent();
151         $event->attendee = $this->_getAttendee();
152         $event->attendee[1] = new Calendar_Model_Attender(array(
153             'user_type' => Calendar_Model_Attender::USERTYPE_USER,
154             'user_id'   => $this->_getPersonasContacts('pwulf')->getId(),
155         ));
156         
157         $persistentEvent = $this->_controller->create($event);
158         
159         foreach ($persistentEvent->attendee as $attender) {
160             $attender->status = Calendar_Model_Attender::STATUS_DECLINED;
161             $this->_controller->attenderStatusUpdate($persistentEvent, $attender, $attender->status_authkey);
162         }
163         
164         
165         $persistentEvent->last_modified_time = $this->_controller->get($persistentEvent->getId())->last_modified_time;
166         
167         // update time
168         $persistentEvent->dtstart->addHour(2);
169         $persistentEvent->dtend->addHour(2);
170         // NOTE: in normal operations the status authkey is removed by resolveAttendee
171         //       we simulate this here by removeing the keys per hand. (also note that current user does not need an authkey)
172         $persistentEvent->attendee->status_authkey = null;
173         $updatedEvent = $this->_controller->update($persistentEvent);
174
175         $currentUser = $updatedEvent->attendee
176             ->filter('user_type', Calendar_Model_Attender::USERTYPE_USER)
177             ->filter('user_id', Tinebase_Core::getUser()->contact_id)
178             ->getFirstRecord();
179             
180         $pwulf = $updatedEvent->attendee
181             ->filter('user_type', Calendar_Model_Attender::USERTYPE_USER)
182             ->filter('user_id', $this->_getPersonasContacts('pwulf')->getId())
183             ->getFirstRecord();
184
185         $this->assertEquals(Calendar_Model_Attender::STATUS_DECLINED, $currentUser->status, 'current users status must not be touched');
186         $this->assertEquals(Calendar_Model_Attender::STATUS_NEEDSACTION, $pwulf->status, 'pwulfs status must be reset');
187     }
188     
189     public function testUpdateMultiple()
190     {
191         $persistentEvent = $this->testCreateEvent();
192         
193         $filter = new Calendar_Model_EventFilter(array(
194             array('field' => 'id', 'operator' => 'in', 'value' => array($persistentEvent->getId()))
195         ));
196         
197         $data = array(
198             'summary' => 'multipleTest'
199         );
200         
201         $this->_controller->updateMultiple($filter, $data);
202         
203         $updatedEvent = $this->_controller->get($persistentEvent->getId());
204         $this->assertEquals('multipleTest', $updatedEvent->summary);
205     }
206     
207     public function testAttendeeBasics()
208     {
209         $event = $this->_getEvent();
210         $event->attendee = $this->_getAttendee();
211         $event->attendee[1] = new Calendar_Model_Attender(array(
212             'user_type' => Calendar_Model_Attender::USERTYPE_USER,
213             'user_id'   => $this->_getPersonasContacts('pwulf')->getId()
214         ));
215         
216         $persistendEvent = $this->_controller->create($event);
217         $this->assertEquals(2, count($persistendEvent->attendee));
218         
219         unset($persistendEvent->attendee[0]);
220         $updatedEvent = $this->_controller->update($persistendEvent);
221         $this->assertEquals(1, count($updatedEvent->attendee));
222         
223         $updatedEvent->attendee->getFirstRecord()->role = Calendar_Model_Attender::ROLE_OPTIONAL;
224         $updatedEvent->attendee->getFirstRecord()->transp = Calendar_Model_Event::TRANSP_TRANSP;
225         
226         $secondUpdatedEvent = $this->_controller->update($updatedEvent);
227         $this->assertEquals(1, count($secondUpdatedEvent->attendee));
228         $this->assertEquals(Calendar_Model_Attender::ROLE_OPTIONAL, $secondUpdatedEvent->attendee->getFirstRecord()->role);
229         $this->assertEquals(Calendar_Model_Event::TRANSP_TRANSP, $secondUpdatedEvent->attendee->getFirstRecord()->transp);
230     }
231     
232     public function testAttendeeFilter()
233     {
234         $event1 = $this->_getEvent();
235         $event1->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
236             array('user_id' => Tinebase_Core::getUser()->contact_id),
237             array('user_id' => $this->_getPersonasContacts('pwulf')->getId())
238         ));
239         $this->_controller->create($event1);
240         
241         $event2 = $this->_getEvent();
242         $event2->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
243             array('user_id' => Tinebase_Core::getUser()->contact_id),
244             array('user_id' => $this->_getPersonasContacts('sclever')->getId()),
245         ));
246         $this->_controller->create($event2);
247         
248         $event3 = $this->_getEvent();
249         $event3->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
250             array('user_id' => Tinebase_Core::getUser()->contact_id),
251             array('user_id' => $this->_getPersonasContacts('sclever')->getId()),
252         ));
253         $this->_controller->create($event3);
254         
255         // test sclever
256         $filter = new Calendar_Model_EventFilter(array(
257             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()),
258             array('field' => 'attender'    , 'operator' => 'equals', 'value' => array(
259                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
260                 'user_id'   => $this->_getPersonasContacts('sclever')->getId()
261             )),
262         ));
263         $eventsFound = $this->_controller->search($filter, new Tinebase_Model_Pagination());
264         $this->assertEquals(2, count($eventsFound), 'sclever attends to two events');
265         
266         // test pwulf
267         $filter = new Calendar_Model_EventFilter(array(
268             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()),
269             array('field' => 'attender'    , 'operator' => 'equals', 'value' => array(
270                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
271                 'user_id'   => $this->_getPersonasContacts('pwulf')->getId()
272             )),
273         ));
274         $eventsFound = $this->_controller->search($filter, new Tinebase_Model_Pagination());
275         $this->assertEquals(1, count($eventsFound), 'pwulf attends to one events');
276         
277         // test sclever OR pwulf
278         $filter = new Calendar_Model_EventFilter(array(
279             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()),
280             array('field' => 'attender'    , 'operator' => 'in',     'value' => array(
281                 array(
282                     'user_type' => Calendar_Model_Attender::USERTYPE_USER,
283                     'user_id'   => $this->_getPersonasContacts('sclever')->getId()
284                 ),
285                 array (
286                     'user_type' => Calendar_Model_Attender::USERTYPE_USER,
287                     'user_id'   => $this->_getPersonasContacts('pwulf')->getId()
288                 )
289             )),
290         ));
291         $eventsFound = $this->_controller->search($filter, new Tinebase_Model_Pagination());
292         $this->assertEquals(3, count($eventsFound), 'sclever OR pwulf attends to tree events');
293     }
294     
295     public function testAttendeeGroupFilter()
296     {
297         $event = $this->_getEvent();
298         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
299             array('user_id' => Tinebase_Core::getUser()->contact_id),
300             array('user_id' => $this->_getPersonasContacts('sclever')->getId())
301         ));
302         $this->_controller->create($event);
303         
304         $filter = new Calendar_Model_EventFilter(array(
305             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()),
306             array('field' => 'attender'    , 'operator' => 'in',     'value' => array(
307                 array(
308                     'user_type' => Calendar_Model_AttenderFilter::USERTYPE_MEMBEROF,
309                     'user_id'   => $this->_getPersona('sclever')->accountPrimaryGroup
310                 )
311             )),
312         ));
313         $eventsFound = $this->_controller->search($filter, new Tinebase_Model_Pagination());
314         $this->assertEquals(1, count($eventsFound), 'sclever is groupmember');
315     }
316
317     /**
318      * @see 0006702: CalDAV: single event appears in personal and shared calendar
319      *
320      * TODO fix for pgsql: Failed asserting that 0 matches expected 1.
321      *
322      */
323     public function testAttendeeNotInFilter()
324     {
325         if ($this->_dbIsPgsql()) {
326             $this->markTestSkipped('0011674: problem with Attendee "NotIn" Filter (pgsql)');
327         }
328
329         foreach(array(Tinebase_Core::getUser()->contact_id, $this->_personasContacts['sclever']->getId()) as $attId) {
330             $event = $this->_getEvent();
331             $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
332                     array('user_id' => $attId),
333             ));
334             $this->_controller->create($event);
335         }
336     
337         $filter = new Calendar_Model_EventFilter(array(
338                 array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()),
339                 array('field' => 'attender'    , 'operator' => 'notin',  'value' => array(
340                         array(
341                                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
342                                 'user_id'   => $this->_personasContacts['sclever']->getId()
343                         )
344                 )),
345         ));
346         $eventsFound = $this->_controller->search($filter, new Tinebase_Model_Pagination());
347         $this->assertEquals(1, count($eventsFound), 'should be exactly one event');
348         $this->assertEquals(
349                 Tinebase_Core::getUser()->contact_id, 
350                 $eventsFound->getFirstRecord()->attendee->getFirstRecord()->user_id,
351                 'sclevers event should not be found');
352     }
353     
354     /**
355      * test get free busy info with single event
356      * 
357      * @return Calendar_Model_Event
358      */
359     public function testGetFreeBusyInfo()
360     {
361         $event = $this->_getEvent();
362         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
363             array('user_id' => $this->_getPersonasContacts('sclever')->getId()),
364             array('user_id' => $this->_getPersonasContacts('pwulf')->getId())
365         ));
366         $persistentEvent = $this->_controller->create($event);
367
368         $period = new Calendar_Model_EventFilter(array(array(
369             'field'     => 'period',
370             'operator'  => 'within',
371             'value'     => array(
372                 'from'      => $persistentEvent->dtstart,
373                 'until'     => $persistentEvent->dtend
374             ),
375         )));
376         $fbinfo = $this->_controller->getFreeBusyInfo($period, $persistentEvent->attendee);
377        
378         $this->assertGreaterThanOrEqual(2, count($fbinfo));
379         
380         return $persistentEvent;
381     }
382
383     /**
384      * test get free busy info with single event
385      *
386      * @return Calendar_Model_Event
387      */
388     public function testGetFreeBusyInfoWithGroup()
389     {
390         $event = $this->_getEvent();
391         $attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
392             array(
393                 'user_id' => Tinebase_Group::getInstance()->getDefaultGroup(),
394                 'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
395                 'role' => Calendar_Model_Attender::ROLE_OPTIONAL,
396             ),
397         ));
398         $event->attendee = clone $attendee;
399         $persistentEvent = $this->_controller->create($event);
400
401         $period = new Calendar_Model_EventFilter(array(array(
402             'field'     => 'period',
403             'operator'  => 'within',
404             'value'     => array(
405                 'from'      => $persistentEvent->dtstart,
406                 'until'     => $persistentEvent->dtend
407             ),
408         )));
409         $fbinfo = $this->_controller->getFreeBusyInfo($period, $attendee);
410
411         $this->assertGreaterThanOrEqual(1, count($fbinfo));
412
413         return $persistentEvent;
414     }
415
416     public function testSearchFreeTime()
417     {
418         $event = $this->_getEvent();
419         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
420             array('user_id' => $this->_getPersonasContacts('sclever')->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER),
421             array('user_id' => $this->_getPersonasContacts('pwulf')->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER)
422         ));
423         $event->rrule = 'FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,FR';
424
425         $options = array(
426             'constraints' => array(array(
427                 'dtstart'   => $event->dtstart->getClone()->setHour(6),
428                 'dtend'     => $event->dtstart->getClone()->setHour(22),
429                 'rrule'     => 'FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR'
430             )),
431         );
432
433         $result = $this->_controller->searchFreeTime($event, $options);
434         static::assertEquals(1, $result->count());
435         /** @var Calendar_Model_Event $suggestedEvent */
436         $suggestedEvent = $result->getFirstRecord();
437         $dtstartExpected = $event->dtstart->getClone()->addDay(1)->setHour(6); // '2009-04-07 06:00:00'
438         $dtendExpected = $event->dtend->getClone()->addDay(1)->setHour(6); // '2009-04-07 06:30:00'
439         static::assertEquals($dtstartExpected, $suggestedEvent->dtstart);
440         static::assertEquals($dtendExpected, $suggestedEvent->dtend);
441
442         $newEvent = clone $event;
443         $newEvent->rrule = null;
444         $newEvent->dtstart = $dtstartExpected->getClone()->addMinute(29); // '2009-04-07 06:29:00'
445         $newEvent->dtend = $dtendExpected->getClone(); // '2009-04-07 06:30:00'
446         $this->_controller->create($newEvent);
447         $newEvent->setId(null);
448         $newEvent->uid = null;
449         $newEvent->attendee->id = null;
450         $newEvent->attendee->cal_event_id = null;
451         $newEvent->dtstart->addDay(7); // '2009-04-14 06:29:00'
452         $newEvent->dtend->addDay(7); // '2009-04-14 06:30:00'
453         $this->_controller->create($newEvent);
454
455         $result = $this->_controller->searchFreeTime($event, $options);
456         static::assertEquals(1, $result->count());
457         /** @var Calendar_Model_Event $suggestedEvent */
458         $suggestedEvent = $result->getFirstRecord();
459         static::assertEquals($dtstartExpected->addMinute(30), $suggestedEvent->dtstart); // '2009-04-07 06:30:00'
460         static::assertEquals($dtendExpected->addMinute(30), $suggestedEvent->dtend); // '2009-04-07 07:00:00'
461
462         $newEvent->setId(null);
463         $newEvent->uid = null;
464         $newEvent->attendee->id = null;
465         $newEvent->attendee->cal_event_id = null;
466         $newEvent->dtstart->addMinute(1); // '2009-04-14 06:30:00'
467         $newEvent->dtend->addMinute(1); // '2009-04-14 06:31:00'
468         $this->_controller->create($newEvent);
469
470         $result = $this->_controller->searchFreeTime($event, $options);
471         static::assertEquals(1, $result->count());
472         /** @var Calendar_Model_Event $suggestedEvent */
473         $suggestedEvent = $result->getFirstRecord();
474         static::assertEquals($dtstartExpected->addMinute(15), $suggestedEvent->dtstart); // '2009-04-07 06:45:00'
475         static::assertEquals($dtendExpected->addMinute(15), $suggestedEvent->dtend); // '2009-04-07 07:15:00'
476     }
477     
478     /**
479      * events from deleted calendars should not be shown
480      */
481     public function testSearchEventFromDeletedCalendar() {
482         $testCal = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
483             'name'           => 'PHPUnit test calendar',
484             'type'           => Tinebase_Model_Container::TYPE_PERSONAL,
485             'owner_id'       => Tinebase_Core::getUser(),
486             'backend'        => $this->_backend->getType(),
487             'application_id' => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId()
488         ), true));
489         
490         $this->_getTestCalendars()->addRecord($testCal);
491         
492         // create event in testcal
493         $event = $this->_getEvent();
494         $event->container_id = $testCal->getId();
495         $event->attendee = $this->_getAttendee();
496         $persistentEvent = $this->_controller->create($event);
497
498         // delete testcal
499         Tinebase_Container::getInstance()->deleteContainer($testCal, TRUE);
500         
501         // search by attendee
502         $events = $this->_controller->search(new Calendar_Model_EventFilter(array(
503             array('field' => 'attender', 'operator' => 'equals', 'value' => array(
504                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
505                 'user_id'   => $this->_getTestUserContact()->getId()
506             ))
507         )), NULL, FALSE, FALSE);
508         
509         $this->assertFalse(in_array($persistentEvent->getId(), $events->getId()), 'event in deleted (display) container shuld not be found');
510     }
511     
512     public function testCreateEventWithConflict()
513     {
514         $this->_testNeedsTransaction();
515         
516         $event = $this->_getEvent();
517         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
518             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('sclever')->getId()),
519             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('pwulf')->getId())
520         ));
521         $this->_controller->create($event);
522         
523         $conflictEvent = $this->_getEvent();
524         $conflictEvent->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
525             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('sclever')->getId()),
526             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('pwulf')->getId())
527         ));
528         
529         try {
530             $exectionRaised = FALSE;
531             $this->_controller->create($conflictEvent, TRUE);
532         } catch (Calendar_Exception_AttendeeBusy $busyException) {
533             $fbData = $busyException->toArray();
534             $this->assertGreaterThanOrEqual(2, count($fbData['freebusyinfo']));
535             $exectionRaised = TRUE;
536         }
537         if (! $exectionRaised) {
538             $this->fail('An expected exception has not been raised.');
539         }
540         $persitentConflictEvent = $this->_controller->create($conflictEvent, FALSE);
541         
542         return $persitentConflictEvent;
543     }
544     
545     public function testCreateEventWithConflictFromGroupMember()
546     {
547         $event = $this->_getEvent();
548         $event->attendee = $this->_getAttendee();
549         $this->_controller->create($event);
550         
551         $conflictEvent = $this->_getEvent();
552         $conflictEvent->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
553             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('sclever')->getId()),
554             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('pwulf')->getId())
555         ));
556         
557         try {
558             $this->_controller->create($conflictEvent, TRUE);
559             $this->assertTrue(false, 'Failed to detect conflict from groupmember');
560         } catch (Calendar_Exception_AttendeeBusy $busyException) {
561             $fbData = $busyException->toArray();
562             $this->assertGreaterThanOrEqual(2, count($fbData['freebusyinfo']));
563             return;
564         }
565         
566         $this->fail('An expected exception has not been raised.');
567     }
568     
569     public function testCreateTransparentEventNoConflict()
570     {
571         $event = $this->_getEvent();
572         $event->attendee = $this->_getAttendee();
573         $this->_controller->create($event);
574         
575         $nonConflictEvent = $this->_getEvent();
576         $nonConflictEvent->transp = Calendar_Model_Event::TRANSP_TRANSP;
577         $nonConflictEvent->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
578             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('sclever')->getId()),
579             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('pwulf')->getId())
580         ));
581         
582         $this->_controller->create($nonConflictEvent, TRUE);
583     }
584     
585     public function testCreateNoConflictParallelTrasparentEvent()
586     {
587         $event = $this->_getEvent();
588         $event->attendee = $this->_getAttendee();
589         $event->transp = Calendar_Model_Event::TRANSP_TRANSP;
590         $this->_controller->create($event);
591         
592         $nonConflictEvent = $this->_getEvent();
593         $nonConflictEvent->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
594             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('sclever')->getId()),
595             array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('pwulf')->getId())
596         ));
597         
598         $this->_controller->create($nonConflictEvent, TRUE);
599     }
600     
601     public function testCreateNoConflictParallelAtendeeTrasparentEvent()
602     {
603         $event = $this->_getEvent();
604         $event->attendee = $this->_getAttendee();
605         unset ($event->attendee[1]); // no group here
606         $event->attendee->transp = Calendar_Model_Event::TRANSP_TRANSP;
607         $this->_controller->create($event);
608         
609         $nonConflictEvent = $this->_getEvent();
610         $nonConflictEvent->attendee = $this->_getAttendee();
611         
612         $this->_controller->create($nonConflictEvent, TRUE);
613     }
614
615     public function testCreateConflictResourceUnavailable()
616     {
617         $event = $this->_getEvent();
618
619         // create & add resource
620         $rt = new Calendar_Controller_ResourceTest();
621         $rt->setUp();
622         $resource = $rt->testCreateResource();
623         $resource->busy_type = Calendar_Model_FreeBusy::FREEBUSY_BUSY_UNAVAILABLE;
624         Calendar_Controller_Resource::getInstance()->update($resource);
625
626         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(new Calendar_Model_Attender(array(
627             'user_type' => Calendar_Model_Attender::USERTYPE_RESOURCE,
628             'user_id'   => $resource->getId()
629         ))));
630
631         $conflictEvent = clone $event;
632         $this->_controller->create($event);
633         try {
634             $this->_controller->create($conflictEvent, TRUE);
635             $this->fail('Calendar_Exception_AttendeeBusy was not thrown');
636         } catch (Calendar_Exception_AttendeeBusy $abe) {
637             $fb = $abe->getFreeBusyInfo();
638             $this->assertEquals(Calendar_Model_FreeBusy::FREEBUSY_BUSY_UNAVAILABLE, $fb[0]->type);
639         }
640
641     }
642
643     public function testUpdateWithConflictNoTimechange()
644     {
645         $persitentConflictEvent = $this->testCreateEventWithConflict();
646         $persitentConflictEvent->summary = 'only time updates should recheck free/busy';
647         
648         $this->_controller->update($persitentConflictEvent, TRUE);
649     }
650     
651     public function testUpdateWithConflictAttendeeChange()
652     {
653         $persitentConflictEvent = $this->testCreateEventWithConflict();
654         $persitentConflictEvent->summary = 'attendee adds should recheck free/busy';
655         
656         $defaultUserGroup = Tinebase_Group::getInstance()->getDefaultGroup();
657         $persitentConflictEvent->attendee->addRecord(new Calendar_Model_Attender(array(
658             'user_id'   => $defaultUserGroup->getId(),
659             'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
660             'role'      => Calendar_Model_Attender::ROLE_REQUIRED
661         )));
662         
663         $this->setExpectedException('Calendar_Exception_AttendeeBusy');
664         $this->_controller->update($persitentConflictEvent, TRUE);
665     }
666     
667     public function testUpdateWithConflictWithTimechange()
668     {
669         $persitentConflictEvent = $this->testCreateEventWithConflict();
670         $persitentConflictEvent->summary = 'time updates should recheck free/busy';
671         $persitentConflictEvent->dtend->addHour(1);
672         
673         $this->setExpectedException('Calendar_Exception_AttendeeBusy');
674         $this->_controller->update($persitentConflictEvent, TRUE);
675     }
676
677     public function testAttendeeAuthKeyPreserv()
678     {
679         $event = $this->_getEvent();
680         $event->attendee = $this->_getAttendee();
681         
682         $persistendEvent = $this->_controller->create($event);
683         $newAuthKey = Tinebase_Record_Abstract::generateUID();
684         $persistendEvent->attendee->status_authkey = $newAuthKey;
685         
686         $updatedEvent = $this->_controller->update($persistendEvent);
687         foreach ($updatedEvent->attendee as $attender) {
688             $this->assertNotEquals($newAuthKey, $attender->status_authkey);
689         }
690     }
691     
692     public function testAttendeeStatusPreservViaSave()
693     {
694         $event = $this->_getEvent();
695         $event->attendee = $this->_getAttendee();
696         $event->attendee[0]->user_id = Tinebase_User::getInstance()->getUserByLoginName('sclever')->contact_id;
697         $event->attendee[0]->status = Calendar_Model_Attender::STATUS_ACCEPTED;
698         unset($event->attendee[1]);
699         
700         $persistendEvent = $this->_controller->create($event);
701         $this->assertEquals(Calendar_Model_Attender::STATUS_NEEDSACTION, $persistendEvent->attendee[0]->status, 'creation of other attedee must not set status');
702         
703         $persistendEvent->attendee[0]->status = Calendar_Model_Attender::STATUS_ACCEPTED;
704         $persistendEvent->attendee[0]->status_authkey = NULL;
705         $updatedEvent = $this->_controller->update($persistendEvent);
706         $this->assertEquals(Calendar_Model_Attender::STATUS_NEEDSACTION, $updatedEvent->attendee[0]->status, 'updateing of other attedee must not set status');
707     }
708     
709     public function testAttendeeSetStatus()
710     {
711         $event = $this->_getEvent();
712         $event->attendee = $this->_getAttendee();
713         unset($event->attendee[1]);
714         
715         $persistendEvent = $this->_controller->create($event);
716         $attendee = $persistendEvent->attendee[0];
717         
718         $attendee->status = Calendar_Model_Attender::STATUS_DECLINED;
719         $this->_controller->attenderStatusUpdate($persistendEvent, $attendee, $attendee->status_authkey);
720         
721         $loadedEvent = $this->_controller->get($persistendEvent->getId());
722         $this->assertEquals(Calendar_Model_Attender::STATUS_DECLINED, $loadedEvent->attendee[0]->status, 'status not set');
723         
724     }
725     
726     public function testAttendeeStatusFilter()
727     {
728         $event = $this->_getEvent();
729         $event->attendee = $this->_getAttendee();
730         unset($event->attendee[1]);
731         
732         $persistentEvent = $this->_controller->create($event);
733         
734         $filter = new Calendar_Model_EventFilter(array(
735             array('field' => 'uid',             'operator' => 'equals', 'value' => $persistentEvent->uid),
736             array('field' => 'attender_status', 'operator' => 'not',    'value' => Calendar_Model_Attender::STATUS_DECLINED),
737         ));
738         
739         $events = $this->_controller->search($filter);
740         $this->assertEquals(1, count($events), 'event should be found, but is not');
741         
742         $attender = $persistentEvent->attendee[0];
743         $attender->status = Calendar_Model_Attender::STATUS_DECLINED;
744         $this->_controller->update($persistentEvent);
745         
746         $events = $this->_controller->search($filter);
747         $this->assertEquals(0, count($events), 'event should _not_ be found, but is');
748         
749     }
750     
751     public function testAttendeeDisplaycontainerContact()
752     {
753         $contact = Addressbook_Controller_Contact::getInstance()->create(new Addressbook_Model_Contact(array(
754            'n_given'  => 'phpunit',
755            'n_family' => 'cal attender'
756         )));
757          
758         $event = $this->_getEvent();
759         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
760             array(
761                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
762                 'user_id'   => $contact->getId(),
763                 'role'      => Calendar_Model_Attender::ROLE_REQUIRED
764             ),
765         ));
766         $persistentEvent = $this->_controller->create($event);
767         $attender = $persistentEvent->attendee[0];
768         
769         $this->assertTrue(empty($attender->displaycontainer_id), 'displaycontainer_id must not be set for contacts');
770     }
771     
772     public function testAttendeeGroupMembersResolving()
773     {
774         if (Tinebase_User::getConfiguredBackend() === Tinebase_User::ACTIVEDIRECTORY) {
775             $this->markTestSkipped('only working in non-AD setups');
776         }
777
778         $defaultUserGroup = Tinebase_Group::getInstance()->getDefaultGroup();
779         Tinebase_Group::getInstance()->getDefaultAdminGroup();
780         
781         $event = $this->_getEvent();
782         $event->attendee = $this->_getAttendee();
783         $event->attendee[1] = new Calendar_Model_Attender(array(
784             'user_id'   => $defaultUserGroup->getId(),
785             'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
786             'role'      => Calendar_Model_Attender::ROLE_REQUIRED
787         ));
788         
789         $persistentEvent = $this->_controller->create($event);
790         $defaultUserGroupMembers = Tinebase_Group::getInstance()->getGroupMembers($defaultUserGroup->getId());
791         // user as attender + group + all members
792         $expectedAttendeeCount = 1 + 1 + count($defaultUserGroupMembers);
793         if (in_array(Tinebase_Core::getUser()->getId(), $defaultUserGroupMembers)) {
794             // remove suppressed user (only if user is member of default group)
795             $expectedAttendeeCount--;
796         }
797         $this->assertEquals($expectedAttendeeCount, count($persistentEvent->attendee),
798             'attendee: ' . print_r($persistentEvent->attendee->toArray(), true));
799         
800         $groupAttender = $persistentEvent->attendee->find('user_type', Calendar_Model_Attender::USERTYPE_GROUP);
801         $persistentEvent->attendee->removeRecord($groupAttender);
802         
803         $updatedPersistentEvent = $this->_controller->update($persistentEvent);
804         $this->assertEquals(1, count($updatedPersistentEvent->attendee));
805     }
806     
807     public function testAttendeeGroupMembersChange()
808     {
809         $defaultAdminGroup = Tinebase_Group::getInstance()->getDefaultAdminGroup();
810         
811         // create event and invite admin group
812         $event = $this->_getEvent();
813         
814         // only events in future will be changed!
815         $event->dtstart = Tinebase_DateTime::now()->addHour(1);
816         $event->dtend = Tinebase_DateTime::now()->addHour(2);
817         
818         $event->attendee = $this->_getAttendee();
819         $event->attendee[1] = new Calendar_Model_Attender(array(
820             'user_id'   => $defaultAdminGroup->getId(),
821             'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
822             'role'      => Calendar_Model_Attender::ROLE_REQUIRED
823         ));
824         $persistentEvent = $this->_controller->create($event);
825         
826         // assert test condition
827         $pwulf = $persistentEvent->attendee
828             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
829             ->filter('user_id', $this->_getPersonasContacts('pwulf')->getId());
830         $this->assertEquals(0, count($pwulf), 'invalid test condition, pwulf should not be member or admin group');
831         
832         Admin_Controller_Group::getInstance()->addGroupMember($defaultAdminGroup->getId(), $this->_getPersonasContacts('pwulf')->account_id);
833         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
834             Tinebase_ActionQueue::getInstance()->processQueue(10000);
835         }
836         
837         $loadedEvent = $this->_controller->get($persistentEvent->getId());
838         // assert pwulf is in
839         $pwulf = $loadedEvent->attendee
840             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
841             ->filter('user_id', $this->_getPersonasContacts('pwulf')->getId());
842         $this->assertEquals(1, count($pwulf), 'pwulf is not attender of event, but should be');
843         
844         
845         Admin_Controller_Group::getInstance()->removeGroupMember($defaultAdminGroup->getId(), $this->_getPersonasContacts('pwulf')->account_id);
846         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
847             Tinebase_ActionQueue::getInstance()->processQueue(10000);
848         }
849         
850         $loadedEvent = $this->_controller->get($persistentEvent->getId());
851         // assert pwulf is missing
852         $pwulf = $loadedEvent->attendee
853             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
854             ->filter('user_id', $this->_getPersonasContacts('pwulf')->getId());
855         $this->assertEquals(0, count($pwulf), 'pwulf is attender of event, but not should be');
856         
857         // Test the same with update
858         $group = Admin_Controller_Group::getInstance()->get($defaultAdminGroup->getId());
859         $group->members = array_merge(Admin_Controller_Group::getInstance()->getGroupMembers($defaultAdminGroup->getId()), array(Tinebase_Helper::array_value('pwulf', Zend_Registry::get('personas'))->getId()));
860         Admin_Controller_Group::getInstance()->update($group);
861         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
862             Tinebase_ActionQueue::getInstance()->processQueue(10000);
863         }
864         
865         // assert pwulf is in
866         $loadedEvent = $this->_controller->get($persistentEvent->getId());
867         $pwulf = $loadedEvent->attendee
868             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
869             ->filter('user_id', $this->_getPersonasContacts('pwulf')->getId());
870         $this->assertEquals(1, count($pwulf), 'pwulf is not attender of event, but should be (via update)');
871         
872         $group->members = array_diff(Admin_Controller_Group::getInstance()->getGroupMembers($defaultAdminGroup->getId()), array(Tinebase_Helper::array_value('pwulf', Zend_Registry::get('personas'))->getId()));
873         Admin_Controller_Group::getInstance()->update($group);
874         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
875             Tinebase_ActionQueue::getInstance()->processQueue(10000);
876         }
877         // assert pwulf is missing
878         $loadedEvent = $this->_controller->get($persistentEvent->getId());
879         $pwulf = $loadedEvent->attendee
880             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
881             ->filter('user_id', $this->_getPersonasContacts('pwulf')->getId());
882         $this->assertEquals(0, count($pwulf), 'pwulf is attender of event, but not should be');
883     }
884     
885     public function testAttendeeGroupMembersAddUser()
886     {
887         try {
888             // clean up if exists
889             $cleanupUser = Tinebase_User::getInstance()->getFullUserByLoginName('testAttendeeGroupMembersAddUser');
890             Tinebase_User::getInstance()->deleteUser($cleanupUser);
891         } catch (Exception $e) {
892             // do nothing
893         }
894         
895         
896         $defaultGroup = Tinebase_Group::getInstance()->getDefaultGroup();
897         
898         // create event and invite admin group
899         $event = $this->_getEvent();
900         
901         // only events in future will be changed!
902         $event->dtstart = Tinebase_DateTime::now()->addHour(1);
903         $event->dtend = Tinebase_DateTime::now()->addHour(2);
904         
905         $event->attendee = $this->_getAttendee();
906         $event->attendee[1] = new Calendar_Model_Attender(array(
907             'user_id'   => $defaultGroup->getId(),
908             'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
909             'role'      => Calendar_Model_Attender::ROLE_REQUIRED
910         ));
911         $persistentEvent = $this->_controller->create($event);
912         
913         $newUser = $this->_createNewUser();
914         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
915             Tinebase_ActionQueue::getInstance()->processQueue(10000);
916         }
917         
918         // check if this user was added to event
919         $loadedEvent = $this->_controller->get($persistentEvent->getId());
920         $user = $loadedEvent->attendee
921             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
922             ->filter('user_id', $newUser->contact_id);
923         $this->assertEquals(1, count($user), 'added user is not attender of event, but should be. user: ' . print_r($newUser->toArray(), TRUE));
924         
925         // cleanup user
926         Admin_Controller_User::getInstance()->delete($newUser->getId());
927         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
928             Tinebase_ActionQueue::getInstance()->processQueue(10000);
929         }
930         
931         // check if user was removed from event
932         $loadedEvent = $this->_controller->get($persistentEvent->getId());
933         $user = $loadedEvent->attendee
934             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
935             ->filter('user_id', $newUser->contact_id);
936         $this->assertEquals(0, count($user), 'added user is attender of event, but should be (after deleting user)');
937     }
938     
939     /**
940      * testAttendeeGroupMembersRecurringAddUser
941      * 
942      * FIXME 0007352: fix Calendar_Controller_EventTests::testAttendeeGroupMembersRecurringAddUser
943      */
944     public function testAttendeeGroupMembersRecurringAddUser()
945     {
946         $this->markTestIncomplete('test fails sometimes / needs fixing');
947         
948         try {
949             // cleanup if exists
950             $cleanupUser = Tinebase_User::getInstance()->getFullUserByLoginName('testAttendeeGroupMembersAddUser');
951             Tinebase_User::getInstance()->deleteUser($cleanupUser);
952         } catch (Exception $e) {
953             // do nothing
954         }
955         
956         $defaultGroup = Tinebase_Group::getInstance()->getDefaultGroup();
957         
958         // create event and invite admin group
959         $event = $this->_getEvent();
960         $event->rrule = 'FREQ=DAILY;INTERVAL=1';
961         
962         $event->attendee = $this->_getAttendee();
963         $event->attendee[1] = new Calendar_Model_Attender(array(
964             'user_id'   => $defaultGroup->getId(),
965             'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
966             'role'      => Calendar_Model_Attender::ROLE_REQUIRED
967         ));
968         $persistentEvent = $this->_controller->create($event);
969
970         $newUser = $this->_createNewUser();
971         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
972             Tinebase_ActionQueue::getInstance()->processQueue(10000);
973         }
974         
975         $events = $this->_backend->search(new Calendar_Model_EventFilter(array(
976             array('field' => 'container_id', 'operator' => 'in', 'value' => $this->_getTestCalendars()->getId()),
977         )), new Tinebase_Model_Pagination(array()));
978         
979         $oldSeries = $events->filter('rrule_until', '/.+/', TRUE)->getFirstRecord();
980         $newSeries = $events->filter('rrule_until', '/^$/', TRUE)->getFirstRecord();
981         
982         $this->assertEquals(2, $events->count(), 'recur event must be splitted '. print_r($events->toArray(), TRUE));
983         // check if this user was added to event
984         $this->_controller->get($persistentEvent->getId());
985         $user = $oldSeries->attendee
986             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
987             ->filter('user_id', $newUser->contact_id);
988         $this->assertEquals(0, count($user), 'added user is attender of old event, but should not be');
989         $user = $newSeries->attendee
990             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
991             ->filter('user_id', $newUser->contact_id);
992         $this->assertEquals(1, count($user), 'added user is not attender of new event, but should be');
993         
994         // cleanup user
995         Admin_Controller_User::getInstance()->delete($newUser->getId());
996         if (isset(Tinebase_Core::getConfig()->actionqueue)) {
997             Tinebase_ActionQueue::getInstance()->processQueue(10000);
998         }
999         
1000         $events = $this->_backend->search(new Calendar_Model_EventFilter(array(
1001             array('field' => 'container_id', 'operator' => 'in', 'value' => $this->_getTestCalendars()->getId()),
1002         )), new Tinebase_Model_Pagination(array()));
1003         
1004         $newSeries = $events->filter('rrule_until', '/^$/', TRUE)->getFirstRecord();
1005         
1006         // check if this user was deleted from event
1007         $user = $newSeries->attendee
1008             ->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER)
1009             ->filter('user_id', $newUser->contact_id);
1010         $this->assertEquals(0, count($user), 'deleted user is attender of new event, but should not be');
1011     }
1012
1013     protected function _createNewUser()
1014     {
1015         $pw = Tinebase_Record_Abstract::generateUID(10) . '*A53x';
1016         $newUser = Admin_Controller_User::getInstance()->create(new Tinebase_Model_FullUser(array(
1017             'accountLoginName'      => 'testAttendeeGroupMembersAddUser',
1018             'accountStatus'         => 'enabled',
1019             'accountExpires'        => NULL,
1020             'accountPrimaryGroup'   => Tinebase_Group::getInstance()->getDefaultGroup()->getId(),
1021             'accountLastName'       => 'Tine 2.0',
1022             'accountFirstName'      => 'PHPUnit',
1023             'accountEmailAddress'   => 'phpunit@metaways.de'
1024         )), $pw, $pw);
1025         return $newUser;
1026     }
1027
1028     public function testRruleUntil()
1029     {
1030         $event = $this->_getEvent();
1031         
1032         $event->rrule_until = Tinebase_DateTime::now();
1033         $persistentEvent = $this->_controller->create($event);
1034         $this->assertNull($persistentEvent->rrule_until, 'rrul_until is not unset');
1035         
1036         $persistentEvent->rrule = 'FREQ=YEARLY;INTERVAL=1;BYMONTH=2;UNTIL=2010-04-01 21:59:59';
1037         $updatedEvent = $this->_controller->update($persistentEvent);
1038         $this->assertEquals('2010-04-01 21:59:59', $updatedEvent->rrule_until->get(Tinebase_Record_Abstract::ISO8601LONG));
1039     }
1040     
1041     public function testUpdateRecuingDtstart()
1042     {
1043         $event = $this->_getEvent();
1044         $event->rrule = 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-30 21:59:59';
1045         $event->exdate = array(new Tinebase_DateTime('2009-04-07 13:00:00'));
1046         $persistentEvent = $this->_controller->create($event);
1047         
1048         $this->assertEquals('2009-04-30 21:59:59', $persistentEvent->rrule->until->toString(), 'rrule is not adapted');
1049         
1050         $exception = clone $persistentEvent;
1051         $exception->dtstart->addDay(2);
1052         $exception->dtend->addDay(2);
1053         
1054         $exception->setId(NULL);
1055         unset($exception->rrule);
1056         unset($exception->exdate);
1057         $exception->setRecurId($event->getId());
1058         $persistentException = $this->_controller->create($exception);
1059         
1060         $persistentEvent->dtstart->addHour(5);
1061         $persistentEvent->dtend->addHour(5);
1062         
1063         $updatedEvent = $this->_controller->update($persistentEvent);
1064         
1065         $updatedException = $this->_controller->get($persistentException->getId());
1066         
1067         $this->assertEquals(1, count($updatedEvent->exdate), 'failed to reset exdate');
1068         $this->assertEquals('2009-04-08 18:00:00', $updatedEvent->exdate[0]->get(Tinebase_Record_Abstract::ISO8601LONG), 'failed to update exdate');
1069         $this->assertEquals('2009-04-08 18:00:00', substr($updatedException->recurid, -19), 'failed to update persistent exception');
1070         $this->assertEquals('2009-04-30 21:59:59', Calendar_Model_Rrule::getRruleFromString($updatedEvent->rrule)->until->get(Tinebase_Record_Abstract::ISO8601LONG), 'until in rrule must not be changed');
1071         $this->assertEquals('2009-04-30 21:59:59', $updatedEvent->rrule_until->get(Tinebase_Record_Abstract::ISO8601LONG), 'rrule_until must not be changed');
1072         
1073         $updatedEvent->dtstart->subHour(5);
1074         $updatedEvent->dtend->subHour(5);
1075         $secondUpdatedEvent = $this->_controller->update($updatedEvent);
1076         $secondUpdatedException = $this->_controller->get($persistentException->getId());
1077         $this->assertEquals('2009-04-08 13:00:00', $secondUpdatedEvent->exdate[0]->get(Tinebase_Record_Abstract::ISO8601LONG), 'failed to update exdate (sub)');
1078         $this->assertEquals('2009-04-08 13:00:00', substr($secondUpdatedException->recurid, -19), 'failed to update persistent exception (sub)');
1079     }
1080     
1081     /**
1082      * testUpdateRecurDtstartOverDst
1083      */
1084     public function testUpdateRecurDtstartOverDst()
1085     {
1086         // note: 2009-03-29 Europe/Berlin switched to DST
1087         $event = new Calendar_Model_Event(array(
1088             'uid'           => Tinebase_Record_Abstract::generateUID(),
1089             'summary'       => 'Abendessen',
1090             'dtstart'       => '2009-03-25 18:00:00',
1091             'dtend'         => '2009-03-25 18:30:00',
1092             'originator_tz' => 'Europe/Berlin',
1093             'rrule'         => 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-02 21:59:59',
1094             'exdate'        => '2009-03-27 18:00:00,2009-03-31 17:00:00',
1095             'container_id'  => $this->_getTestCalendar()->getId(),
1096             Tinebase_Model_Grants::GRANT_EDIT     => true,
1097         ));
1098         
1099         $persistentEvent = $this->_controller->create($event);
1100         
1101         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
1102         $from = new Tinebase_DateTime('2009-03-26 00:00:00');
1103         $until = new Tinebase_DateTime('2009-04-03 23:59:59');
1104         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until); // 9 days
1105         
1106         // skip 27(exception), 31(exception), 03(until)
1107         $this->assertEquals(6, count($recurSet));
1108         
1109         $exceptionBeforeDstBoundary = clone $recurSet[1]; // 28. 
1110         $persistentExceptionBeforeDstBoundary = $this->_controller->createRecurException($exceptionBeforeDstBoundary);
1111         
1112         $updatedBaseEvent = $this->_controller->getRecurBaseEvent($recurSet[5]);
1113         $recurSet[5]->last_modified_time = $updatedBaseEvent->last_modified_time;
1114         $exceptionAfterDstBoundary = clone $recurSet[5]; // 02.
1115         $persistentExceptionAfterDstBoundary = $this->_controller->createRecurException($exceptionAfterDstBoundary);
1116         
1117         $persistentEvent->dtstart->addDay(5); //30.
1118         $persistentEvent->dtend->addDay(5);
1119         $from->addDay(5); //31
1120         $until->addDay(5); //08
1121         
1122         $this->_controller->get($persistentEvent);
1123         $persistentEvent->seq = 3; // satisfy modlog
1124         $updatedPersistenEvent = $this->_controller->update($persistentEvent);
1125         
1126         $persistentEvents = $this->_controller->search(new Calendar_Model_EventFilter(array(
1127             array('field' => 'period', 'operator' => 'within', 'value' => array('from' => $from, 'until' => $until)),
1128             array('field' => 'uid', 'operator' => 'equals', 'value' => $persistentEvent->uid)
1129         )));
1130         
1131         // we don't 'see' the persistent exception from 28/
1132         $this->assertEquals(2, count($persistentEvents));
1133                 
1134         $exceptions = $persistentEvents->filter('recurid', "/^{$persistentEvent->uid}-.*/", TRUE);
1135         $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($updatedPersistenEvent, $exceptions, $from, $until);
1136         
1137         // 31, 01, 02
1138         $this->assertEquals(3, count($recurSet));
1139     }
1140     
1141     public function testDeleteImplicitDeleteRcuringExceptions()
1142     {
1143         $event = $this->_getEvent();
1144         $event->rrule = 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-30 13:30:00';
1145         $event->exdate = array(new Tinebase_DateTime('2009-04-07 13:00:00'));
1146         $persistentEvent = $this->_controller->create($event);
1147         
1148         $exception = clone $persistentEvent;
1149         $exception->dtstart->addDay(2);
1150         $exception->dtend->addDay(2);
1151         $exception->setId(NULL);
1152         unset($exception->rrule);
1153         unset($exception->exdate);
1154         $exception->setRecurId($persistentEvent->getId());
1155         $persistentException = $this->_controller->create($exception);
1156         
1157         unset($persistentEvent->rrule);
1158         $this->_controller->delete($persistentEvent);
1159         $this->setExpectedException('Tinebase_Exception_NotFound');
1160         $this->_controller->get($persistentException->getId());
1161     }
1162     
1163     /**
1164      * test delete event
1165      * - check here if content sequence of container has been increased
1166      */
1167     public function testDeleteEvent()
1168     {
1169         $event = $this->_getEvent();
1170         $persistentEvent = $this->_controller->create($event);
1171         
1172         $this->_controller->delete($persistentEvent->getId());
1173         
1174         $contentSeq = Tinebase_Container::getInstance()->getContentSequence($this->_getTestCalendar());
1175         $this->assertEquals(3, $contentSeq, 'container content seq should be increased 3 times!');
1176         
1177         $this->setExpectedException('Tinebase_Exception_NotFound');
1178         $this->_controller->get($persistentEvent->getId());
1179     }
1180     
1181     /**
1182      * @todo use exception api once we have it!
1183      *
1184      */
1185     public function testDeleteRecurExceptions()
1186     {
1187         $event = $this->_getEvent();
1188         $event->rrule = 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-30 13:30:00';
1189         $event->exdate = array(new Tinebase_DateTime('2009-04-07 13:00:00'));
1190         $persistentEvent = $this->_controller->create($event);
1191         
1192         $exception = clone $persistentEvent;
1193         $exception->dtstart->addDay(2);
1194         $exception->dtend->addDay(2);
1195         $exception->setId(NULL);
1196         unset($exception->rrule);
1197         unset($exception->exdate);
1198         $exception->setRecurId($persistentEvent->getId());
1199         $persistentException = $this->_controller->create($exception);
1200         
1201         $this->_controller->delete($persistentEvent->getId());
1202         $this->setExpectedException('Tinebase_Exception_NotFound');
1203         $this->_controller->get($persistentException->getId());
1204     }
1205     
1206     public function testDeleteNonPersistentRecurException()
1207     {
1208         $event = $this->_getEvent();
1209         $event->rrule = 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-30 13:30:00';
1210         $persistentEvent = $this->_controller->create($event);
1211         
1212         // create an exception (a fallout)
1213         $exception = clone $persistentEvent;
1214         $exception->dtstart->addDay(3);
1215         $exception->dtend->addDay(3);
1216         $exception->summary = 'Abendbrot';
1217         $exception->recurid = $exception->uid . '-' . $exception->dtstart->get(Tinebase_Record_Abstract::ISO8601LONG);
1218         $persistentEventWithExdate = $this->_controller->createRecurException($exception, true);
1219         
1220         $persistentEvent = $this->_controller->get($persistentEvent->getId());
1221         $this->assertEquals('Tinebase_DateTime', get_class($persistentEventWithExdate->exdate[0]));
1222         $this->assertEquals($persistentEventWithExdate->exdate[0]->format('c'), $persistentEvent->exdate[0]->format('c'));
1223         $events = $this->_controller->search(new Calendar_Model_EventFilter(array(
1224             array('field' => 'uid',     'operator' => 'equals', 'value' => $persistentEvent->uid),
1225         )));
1226         $this->assertEquals(1, count($events));
1227     }
1228     
1229     public function testDeletePersistentRecurException()
1230     {
1231         $event = $this->_getEvent();
1232         $event->rrule = 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-30 13:30:00';
1233         $persistentEvent = $this->_controller->create($event);
1234         
1235         $exception = clone $persistentEvent;
1236         $exception->dtstart->addDay(3);
1237         $exception->dtend->addDay(3);
1238         $exception->summary = 'Abendbrot';
1239         $exception->recurid = $exception->uid . '-' . $exception->dtstart->get(Tinebase_Record_Abstract::ISO8601LONG);
1240         $persistentException = $this->_controller->createRecurException($exception);
1241         
1242         $this->_controller->delete($persistentException->getId());
1243         
1244         $persistentEvent = $this->_controller->get($persistentEvent->getId());
1245         
1246         $this->assertEquals('Tinebase_DateTime', get_class($persistentEvent->exdate[0]));
1247         $events = $this->_controller->search(new Calendar_Model_EventFilter(array(
1248             array('field' => 'uid',     'operator' => 'equals', 'value' => $persistentEvent->uid),
1249         )));
1250         $this->assertEquals(1, count($events));
1251     }
1252     
1253     public function testSetAlarm()
1254     {
1255         $event = $this->_getEvent();
1256         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
1257             new Tinebase_Model_Alarm(array(
1258                 'minutes_before' => 30
1259             ), TRUE)
1260         ));
1261         $persistentEvent = $this->_controller->create($event);
1262         $alarmTime = clone $persistentEvent->dtstart;
1263         $alarmTime->subMinute(30);
1264         $this->assertTrue($alarmTime->equals($persistentEvent->alarms->getFirstRecord()->alarm_time), 'initial alarm is not at expected time');
1265         
1266         
1267         $persistentEvent->dtstart->addHour(5);
1268         $persistentEvent->dtend->addHour(5);
1269         $updatedEvent = $this->_controller->update($persistentEvent);
1270         $alarmTime = clone $updatedEvent->dtstart;
1271         $alarmTime->subMinute(30);
1272         $this->assertTrue($alarmTime->equals($updatedEvent->alarms->getFirstRecord()->alarm_time), 'alarm of updated event is not adjusted');
1273     }
1274     
1275     /**
1276      * testSetAlarmOfRecurSeries
1277      */
1278     public function testSetAlarmOfRecurSeries()
1279     {
1280         $event = $this->_getEvent();
1281         $event->dtstart = Tinebase_DateTime::now()->addHour(1);
1282         $event->dtend = Tinebase_DateTime::now()->addHour(2);
1283         
1284         $event->rrule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;INTERVAL=1';
1285         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
1286             new Tinebase_Model_Alarm(array(
1287                 'minutes_before' => 30
1288             ), TRUE)
1289         ));
1290         $persistentEvent = $this->_controller->create($event);
1291         $alarm = $persistentEvent->alarms->getFirstRecord();
1292         $this->assertEquals($event->dtstart->subMinute(30)->toString(), $alarm->alarm_time->toString(),
1293             'inital alarm fails: ' . print_r($alarm->toArray(), TRUE));
1294         
1295         // move whole series
1296         $persistentEvent->dtstart->addHour(5);
1297         $persistentEvent->dtend->addHour(5);
1298         $updatedEvent = $this->_controller->update($persistentEvent);
1299         $this->assertEquals($persistentEvent->dtstart->subMinute(30)->toString(), $updatedEvent->alarms->getFirstRecord()->alarm_time->toString(),
1300             'update alarm fails');
1301     }
1302     
1303     /**
1304      * testSetAlarmOfRecurSeriesException
1305      */
1306     public function testSetAlarmOfRecurSeriesException()
1307     {
1308         $event = $this->_getEvent();
1309         $event->rrule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;INTERVAL=1';
1310         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
1311             new Tinebase_Model_Alarm(array(
1312                 'minutes_before' => 30
1313             ), TRUE)
1314         ));
1315         $persistentEvent = $this->_controller->create($event);
1316         
1317         $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
1318         $exception = Calendar_Model_Rrule::computeNextOccurrence($persistentEvent, $exceptions, new Tinebase_DateTime());
1319         $exception->dtstart->subHour(6);
1320         $exception->dtend->subHour(6);
1321         $persistentException = $this->_controller->createRecurException($exception);
1322         
1323         $baseEvent = $this->_controller->getRecurBaseEvent($persistentException);
1324         $this->_controller->getAlarms($baseEvent);
1325         
1326         $exceptions = $this->_controller->getRecurExceptions($persistentException);
1327         $nextOccurance = Calendar_Model_Rrule::computeNextOccurrence($baseEvent, $exceptions, Tinebase_DateTime::now());
1328         
1329         $nextAlarmEventStart = new Tinebase_DateTime(substr($baseEvent->alarms->getFirstRecord()->getOption('recurid'), -19));
1330         
1331         $this->assertTrue($nextOccurance->dtstart->equals($nextAlarmEventStart), 'next alarm got not adjusted');
1332         
1333         $alarmTime = clone $persistentException->dtstart;
1334         $alarmTime->subMinute(30);
1335         $this->assertTrue($alarmTime->equals($persistentException->alarms->getFirstRecord()->alarm_time), 'alarmtime of persistent exception is not correnct/set');
1336     }
1337     
1338     /**
1339      * testAdoptAlarmTimeOfYearlyEvent
1340      * 
1341      * @see 0009320: Wrong notification on first occurrence exceptions
1342      */
1343     public function testAdoptAlarmTimeOfYearlyEvent()
1344     {
1345         $event = $this->_getEvent();
1346         $event->dtstart = new Tinebase_DateTime('2012-10-26 22:00:00');
1347         $event->dtend = new Tinebase_DateTime('2012-10-27 21:59:00');
1348         $event->is_all_day_event = 1;
1349         $event->rrule = 'FREQ=YEARLY;BYMONTH=10;BYMONTHDAY=27;INTERVAL=1';
1350         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
1351             new Tinebase_Model_Alarm(array(
1352                 'minutes_before' => 2880
1353             ), TRUE)
1354         ));
1355         $persistentEvent = $this->_controller->create($event);
1356         $alarm = $persistentEvent->alarms->getFirstRecord();
1357         $this->_controller->adoptAlarmTime($persistentEvent, $alarm);
1358         
1359         $now = Tinebase_DateTime::now();
1360         $year = $now->get('Y');
1361         if ($now->isLater(new Tinebase_DateTime($year . '-10-27'))) {
1362             $year++;
1363         }
1364         // might be at 22:00 or 23.00 (daylight saving ...)
1365         // TODO verify that (@see 0011404: fix failing testAdoptAlarmTimeOfYearlyEvent)
1366         $expectedAlarmTimes = array($year . '-10-24 22:00:00', $year . '-10-24 23:00:00');
1367         $this->assertTrue(in_array($alarm->alarm_time->toString(), $expectedAlarmTimes),
1368             'alarm time mismatch:' . print_r($alarm->toArray(), true)
1369             . ' expected: ' . print_r($expectedAlarmTimes, true));
1370
1371         if ($now->isLater(new Tinebase_DateTime($year . '-10-24'))) {
1372             // FIXME test fails if current date is between 10-24 and 10-27
1373             // @see 0011404: fix failing testAdoptAlarmTimeOfYearlyEvent
1374             return;
1375         }
1376         
1377         // mock send alarm and check next occurrence
1378         $alarm->sent_status = Tinebase_Model_Alarm::STATUS_PENDING;
1379         $alarm->sent_time = new Tinebase_DateTime('2012-10-24 22:01:03');
1380         $alarm->alarm_time = new Tinebase_DateTime('2013-10-24 22:00:00');
1381         $alarm->options = '{"custom":false,"minutes_before":2880,"recurid":"' . $persistentEvent->uid . '-2013-10-26 22:00:00"}';
1382         $alarmBackend = new Tinebase_Backend_Sql(array(
1383             'modelName' => 'Tinebase_Model_Alarm', 
1384             'tableName' => 'alarm',
1385         ));
1386         
1387         $updatedAlarm = $alarmBackend->update($alarm);
1388         
1389         $updatedAlarm->sent_time = Tinebase_DateTime::now();
1390         $updatedAlarm->sent_status = Tinebase_Model_Alarm::STATUS_SUCCESS;
1391         $updatedAlarm->minutes_before = 2880;
1392         
1393         $this->_controller->adoptAlarmTime($persistentEvent, $updatedAlarm, 'instance');
1394         $this->assertTrue(in_array($updatedAlarm->alarm_time->toString(), $expectedAlarmTimes),
1395             'alarm time mismatch:' . print_r($updatedAlarm->toArray(), true)
1396             . ' expected: ' . print_r($expectedAlarmTimes, true));
1397     }
1398     
1399     public function testPeriodFilter()
1400     {
1401         $this->testCreateEvent();
1402         
1403         $events = $this->_controller->search(new Calendar_Model_EventFilter(array(
1404             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()),
1405             array('field' => 'period', 'operator' => 'within', 'value' => array(
1406                 'from'  => '2009-04-07',
1407                 'until' => '2010-04-07'
1408             ))
1409         )), NULL, FALSE, FALSE);
1410         
1411         $this->assertEquals(0, count($events));
1412     }
1413     
1414     /**
1415      * returns a simple event
1416      *
1417      * @return Calendar_Model_Event
1418      * @param bool $_now
1419      * @param bool $mute
1420      * @todo replace with TestCase::_getEvent
1421      */
1422     public function _getEvent($_now = FALSE, $mute = NULL)
1423     {
1424         $event = new Calendar_Model_Event(array(
1425             'summary'     => 'Mittagspause',
1426             'dtstart'     => '2009-04-06 13:00:00',
1427             'dtend'       => '2009-04-06 13:30:00',
1428             'description' => 'Wieslaw Brudzinski: Das Gesetz garantiert zwar die Mittagspause, aber nicht das Mittagessen...',
1429         
1430             'container_id' => $this->_getTestCalendar()->getId(),
1431             Tinebase_Model_Grants::GRANT_EDIT    => true,
1432         ));
1433         
1434         if ($_now) {
1435             $event->dtstart = Tinebase_DateTime::now();
1436             $event->dtend = Tinebase_DateTime::now()->addMinute(15);
1437         }
1438         
1439         return $event;
1440     }
1441     
1442     /**
1443      * (non-PHPdoc)
1444      * @see Calendar_TestCase::_getAttendee()
1445      */
1446     protected function _getAttendee()
1447     {
1448         return new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
1449             array(
1450                 'user_id'   => Tinebase_Core::getUser()->contact_id,
1451                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
1452                 'role'      => Calendar_Model_Attender::ROLE_REQUIRED
1453             ),
1454             array(
1455                 'user_id'   => Tinebase_Group::getInstance()->getDefaultGroup()->getId(),
1456                 'user_type' => Calendar_Model_Attender::USERTYPE_GROUP,
1457                 'role'      => Calendar_Model_Attender::ROLE_REQUIRED
1458             )
1459         ));
1460     }
1461     
1462     /**
1463      * tests if customfields gets saved properly
1464      */
1465     public function testCustomFields()
1466     {
1467         $cfData = new Tinebase_Model_CustomField_Config(array(
1468             'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(),
1469             'name'              => 'unittest',
1470             'model'             => 'Calendar_Model_Event',
1471             'definition'        => array(
1472                 'label' => Tinebase_Record_Abstract::generateUID(),
1473                 'type'  => 'string',
1474                 'uiconfig' => array(
1475                     'xtype'  => Tinebase_Record_Abstract::generateUID(),
1476                     'length' => 10,
1477                     'group'  => 'unittest',
1478                     'order'  => 100,
1479                 )
1480             )
1481         ));
1482     
1483         try {
1484             Tinebase_CustomField::getInstance()->addCustomField($cfData);
1485         } catch (Zend_Db_Statement_Exception $zdse) {
1486             // custom field already exists
1487         }
1488     
1489         $event = new Calendar_Model_Event(array(
1490             'summary'     => 'Abendessen',
1491             'dtstart'     => '2014-04-06 18:00:00',
1492             'dtend'       => '2014-04-06 19:00:00',
1493             'description' => 'Guten Appetit',
1494             
1495             'container_id' => $this->_getTestCalendar()->getId(),
1496             Tinebase_Model_Grants::GRANT_EDIT    => true,
1497             'customfields' => array('unittest' => 'Hello')
1498         ));
1499         
1500         $event = $this->_controller->create($event);
1501         
1502         $this->assertEquals('Hello', $event->customfields['unittest']);
1503     }
1504
1505     /**
1506      * @see 0010454: cli script for comparing calendars
1507      */
1508     public function testCompareCalendars()
1509     {
1510         $cal1 = $this->_testCalendar;
1511         $cal2 = $this->_getTestContainer('Calendar');
1512         
1513         $this->_buildCompareCalendarsFixture($cal1, $cal2);
1514         
1515         $from = Tinebase_DateTime::now()->subDay(1);
1516         $until = Tinebase_DateTime::now()->addWeek(2);
1517         $result = Calendar_Controller_Event::getInstance()->compareCalendars($cal1->getId(), $cal2->getId(), $from, $until);
1518         
1519         $this->assertEquals(2, count($result['matching']), 'events 3+4 / 8+9 should have matched: ' . print_r($result['matching']->toArray(), true));
1520         $this->assertEquals(1, count($result['changed']), 'event 5 should appear in changed: ' . print_r($result['changed']->toArray(), true));
1521         $this->assertEquals(1, count($result['missingInCal1']), 'event 2 should miss from cal1: ' . print_r($result['missingInCal1']->toArray(), true));
1522         $this->assertEquals(1, count($result['missingInCal2']), 'event 6 should miss from cal2 ' . print_r($result['missingInCal2']->toArray(), true));
1523     }
1524     
1525     /**
1526      *  create some events to compare
1527      *  
1528      * - event1: in calendar 1
1529      * - event2: only in calendar 2
1530      * - event3+4: in both calendars
1531      * - event5: slightly different from event1 (same summary) / in cal2
1532      * - event6: only in cal1 (next week)
1533      * - event7: only in displaycontainer
1534      * - event8+9: in both calendars (whole day)
1535      * 
1536      * @param Tinebase_Model_Container $cal1
1537      * @param Tinebase_Model_Container $cal2
1538      */
1539     protected function _buildCompareCalendarsFixture($cal1, $cal2)
1540     {
1541         $event1 = $this->_getEvent(true);
1542         $event1->summary = 'event 1';
1543         $this->_controller->create($event1);
1544         
1545         $event2 =  $this->_getEvent(true);
1546         $event2->dtstart->addDay(1);
1547         $event2->dtend->addDay(1);
1548         $event2->summary = 'event 2';
1549         $event2->container_id = $cal2->getId();
1550         $this->_controller->create($event2);
1551         
1552         $event3 = $this->_getEvent(true);
1553         $event3->dtstart->addDay(2);
1554         $event3->dtend->addDay(2);
1555         $event3->summary = 'event 3';
1556         $event4 = clone $event3;
1557         $this->_controller->create($event3);
1558         
1559         $event4->container_id = $cal2->getId();
1560         $this->_controller->create($event4);
1561         
1562         $event5 = $this->_getEvent(true);
1563         $event5->summary = 'event 1';
1564         $event5->dtstart->addMinute(30);
1565         $event5->container_id = $cal2->getId();
1566         $this->_controller->create($event5);
1567         
1568         // this tests weekly processing, too
1569         $event6 = $this->_getEvent(true);
1570         $event6->summary = 'event 6';
1571         $event6->dtstart->addDay(8);
1572         $event6->dtend->addDay(8);
1573         $this->_controller->create($event6);
1574         
1575         // add event that is only in displaycontainer (should not appear in report)
1576         $currentDefault = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::DEFAULTCALENDAR, Tinebase_Core::getUser()->getId());
1577         Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $cal1->getId());
1578         $event7 = $this->_getEvent(true);
1579         $event7->summary = 'event 7';
1580         $event7->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
1581             array(
1582                 'user_id'   => Tinebase_Core::getUser()->contact_id,
1583                 'user_type' => Calendar_Model_Attender::USERTYPE_USER,
1584                 'role'      => Calendar_Model_Attender::ROLE_REQUIRED,
1585             ),
1586         ));
1587         Tinebase_Core::set(Tinebase_Core::USER, $this->_personas['sclever']);
1588         $cal3 = $this->_getTestContainer('Calendar');
1589         $event7->container_id = $cal3->getId();
1590         $this->_controller->create($event7);
1591         Tinebase_Core::set(Tinebase_Core::USER, $this->_originalTestUser);
1592         Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $currentDefault);
1593         
1594         $event8 = $this->_getEvent(true);
1595         $event8->summary = 'event 8';
1596         $event8->is_all_day_event = true;
1597         $event9 = clone $event8;
1598         $this->_controller->create($event8);
1599         
1600         $event9->container_id = $cal2->getId();
1601         $this->_controller->create($event9);
1602     }
1603     
1604     public function testRepairAttendee()
1605     {
1606         $event = $this->_getEvent(true);
1607         $event->attendee = null;
1608         $persistentEvent = $this->_controller->create($event);
1609         
1610         $result = $this->_controller->repairAttendee($persistentEvent->container_id, Tinebase_DateTime::now()->subDay(1), Tinebase_DateTime::now());
1611         
1612         $this->assertEquals(1, $result, 'should repair 1 event');
1613         
1614         $repairedEvent = $this->_controller->get($persistentEvent->getId());
1615         $this->assertEquals(1, count($repairedEvent->attendee));
1616         $ownAttender = Calendar_Model_Attender::getOwnAttender($repairedEvent->attendee);
1617         $this->assertTrue($ownAttender !== null);
1618     }
1619
1620     /**
1621      * @see 0011130: handle bad originator timzone in VCALENDAR converter
1622      */
1623     public function testBrokenTimezoneInEvent()
1624     {
1625         $event = $this->_getEvent(true);
1626         $event->originator_tz = 'AWSTTTT';
1627         try {
1628             $event = $this->_controller->create($event);
1629             $this->fail('should throw Tinebase_Exception_Record_Validation because of bad TZ: ' . print_r($event->toArray(), true));
1630         } catch (Tinebase_Exception_Record_Validation $terv) {
1631             $this->assertEquals('Bad Timezone: AWSTTTT', $terv->getMessage());
1632         }
1633     }
1634 }