public function testRruleDiff()
 {
     $event = $event = new Calendar_Model_Event(array('dtstart' => new Tinebase_DateTime('2011-11-23 14:25:00'), 'dtend' => new Tinebase_DateTime('2011-11-23 15:25:00'), 'rrule' => 'FREQ=WEEKLY;INTERVAL=1;WKST=MO;BYDAY=TH;UNTIL=2011-12-24 15:25:00', 'summary' => 'test event', 'organizer' => Tinebase_Core::getUser()->contact_id));
     $update = clone $event;
     $update->rrule = 'FREQ=WEEKLY;INTERVAL=1;BYDAY=TH;WKST=MO;UNTIL=2011-12-24 22:59:59';
     $diff = $event->diff($update);
     $this->assertFalse(isset($diff->diff['rrule']) || array_key_exists('rrule', $diff->diff), 'parts order change:' . print_r($diff->toArray(), TRUE));
     // real change
     $update->rrule = 'FREQ=WEEKLY;INTERVAL=;BYDAY=TH;WKST=SU';
     $diff = $event->diff($update);
     $this->assertTrue(isset($diff->diff['rrule']) || array_key_exists('rrule', $diff->diff), 'real change should have diff! diff:' . print_r($diff->toArray(), TRUE));
 }
 /**
  * get updates of human interest
  * 
  * @param  Calendar_Model_Event $_event
  * @param  Calendar_Model_Event $_oldEvent
  * @return array
  */
 protected function _getUpdates($_event, $_oldEvent)
 {
     // check event details
     $diff = $_event->diff($_oldEvent);
     $orderedUpdateFieldOfInterest = array('dtstart', 'dtend', 'summary', 'location', 'description', 'organizer', 'transp', 'priority', 'status_id', 'class', 'url', 'rrule', 'is_all_day_event', 'originator_tz');
     $updates = array();
     foreach ($orderedUpdateFieldOfInterest as $field) {
         if (array_key_exists($field, $diff)) {
             $updates[$field] = $diff[$field];
         }
     }
     // check attendee updates
     $attendeeMigration = $_oldEvent->attendee->getMigration($_event->attendee->getArrayOfIds());
     foreach ($attendeeMigration['toUpdateIds'] as $key => $attenderId) {
         $currAttender = $_event->attendee[$_event->attendee->getIndexById($attenderId)];
         $oldAttender = $_oldEvent->attendee[$_oldEvent->attendee->getIndexById($attenderId)];
         if ($currAttender->status != $oldAttender->status) {
             $attendeeMigration['toUpdateIds'][$key] = $currAttender;
         } else {
             unset($attendeeMigration['toUpdateIds'][$key]);
         }
     }
     foreach ($attendeeMigration['toCreateIds'] as $key => $attenderId) {
         $attender = $_event->attendee[$_event->attendee->getIndexById($attenderId)];
         $attendeeMigration['toCreateIds'][$key] = $attender;
     }
     foreach ($attendeeMigration['toDeleteIds'] as $key => $attenderId) {
         $attender = $_oldEvent->attendee[$_oldEvent->attendee->getIndexById($attenderId)];
         $attendeeMigration['toDeleteIds'][$key] = $attender;
     }
     $attendeeUpdates = array();
     foreach (array('toCreateIds', 'toDeleteIds', 'toUpdateIds') as $action) {
         if (!empty($attendeeMigration[$action])) {
             $attendeeUpdates[substr($action, 0, -3)] = array_values($attendeeMigration[$action]);
         }
     }
     if (!empty($attendeeUpdates)) {
         $updates['attendee'] = $attendeeUpdates;
     }
     return $updates;
 }
 /**
  * get updates of human interest
  * 
  * @param  Calendar_Model_Event $_event
  * @param  Calendar_Model_Event $_oldEvent
  * @return array
  */
 protected function _getUpdates($_event, $_oldEvent)
 {
     // check event details
     $diff = $_event->diff($_oldEvent)->diff;
     $orderedUpdateFieldOfInterest = array('dtstart', 'dtend', 'rrule', 'summary', 'location', 'description', 'transp', 'priority', 'status', 'class', 'url', 'is_all_day_event', 'originator_tz');
     $updates = array();
     foreach ($orderedUpdateFieldOfInterest as $field) {
         if (isset($diff[$field]) || array_key_exists($field, $diff)) {
             $updates[$field] = $diff[$field];
         }
     }
     // rrule legacy
     if (isset($updates['rrule']) || array_key_exists('rrule', $updates)) {
         $updates['rrule'] = $_oldEvent->rrule;
     }
     // check for organizer update
     if (Tinebase_Record_Abstract::convertId($_event['organizer'], 'Addressbook_Model_Contact') != Tinebase_Record_Abstract::convertId($_oldEvent['organizer'], 'Addressbook_Model_Contact')) {
         $updates['organizer'] = $_event->resolveOrganizer();
     }
     // check attendee updates
     $attendeeMigration = Calendar_Model_Attender::getMigration($_oldEvent->attendee, $_event->attendee);
     foreach ($attendeeMigration['toUpdate'] as $attendee) {
         $oldAttendee = Calendar_Model_Attender::getAttendee($_oldEvent->attendee, $attendee);
         if ($attendee->status == $oldAttendee->status) {
             $attendeeMigration['toUpdate']->removeRecord($attendee);
         }
     }
     foreach ($attendeeMigration as $action => $migration) {
         Calendar_Model_Attender::resolveAttendee($migration, FALSE);
         if (!count($migration)) {
             unset($attendeeMigration[$action]);
         }
     }
     if (!empty($attendeeMigration)) {
         $updates['attendee'] = $attendeeMigration;
     }
     return $updates;
 }