Merge branch 'pu/cal2013'
authorPhilipp Schüle <p.schuele@metaways.de>
Thu, 21 Feb 2013 14:46:38 +0000 (15:46 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 21 Feb 2013 14:46:38 +0000 (15:46 +0100)
Conflicts:
tests/tine20/Calendar/JsonTests.php

1  2 
tests/tine20/Calendar/Controller/EventNotificationsTests.php
tests/tine20/Calendar/JsonTests.php
tine20/Calendar/Controller/Event.php
tine20/Calendar/Frontend/Json.php
tine20/Calendar/js/MainScreenCenterPanel.js
tine20/Calendar/js/Model.js
tine20/Tinebase/Timemachine/ModificationLog.php

@@@ -802,87 -811,236 +811,321 @@@ class Calendar_JsonTests extends Calend
      }
      
      /**
 +     * assert grant handling
 +     */
 +    public function testSaveResource($grants = array('readGrant' => true,'editGrant' => true))
 +    {
 +        $resoureData = array(
 +            'name'  => Tinebase_Record_Abstract::generateUID(),
 +            'email' => Tinebase_Record_Abstract::generateUID() . '@unittest.com',
 +            'grants' => array(array_merge($grants, array(
 +                'account_id' => Tinebase_Core::getUser()->getId(),
 +                'account_type' => 'user'
 +            )))
 +        );
 +        
 +        $resoureData = $this->_uit->saveResource($resoureData);
 +        $this->assertTrue(is_array($resoureData['grants']), 'grants are not resolved');
 +        
 +        return $resoureData;
 +    }
 +    
 +    /**
 +     * assert only resources with read grant are returned if the user has no manage right
 +     */
 +    public function testSearchResources()
 +    {
 +        $readableResoureData = $this->testSaveResource();
 +        $nonReadableResoureData = $this->testSaveResource(array());
 +        
 +        $filer = array(
 +            array('field' => 'name', 'operator' => 'in', 'value' => array(
 +                $readableResoureData['name'],
 +                $nonReadableResoureData['name'],
 +            ))
 +        );
 +        
 +        $searchResultManager = $this->_uit->searchResources($filer, array());
 +        $this->assertEquals(2, count($searchResultManager['results']), 'with manage grants all records should be found');
 +        
 +        // steal manage right
 +        Tinebase_Acl_Roles::getInstance()->deleteAllRoles();
 +        
 +        $searchResult = $this->_uit->searchResources($filer, array());
 +        $this->assertEquals(1, count($searchResult['results']), 'without manage grants only one record should be found');
 +    }
 +    
 +    /**
 +     * assert status authkey with editGrant
 +     * assert stauts can be set with editGrant
 +     * assert stauts can't be set without editGrant
 +     */
 +    public function testResourceAttendeeGrants()
 +    {
 +        $editableResoureData = $this->testSaveResource();
 +        $nonEditableResoureData = $this->testSaveResource(array('readGrant'));
 +        
 +        $event = $this->_getEvent();
 +        $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
 +            array(
 +                'user_type'  => Calendar_Model_Attender::USERTYPE_RESOURCE,
 +                'user_id'    => $editableResoureData['id'],
 +                'status'     => Calendar_Model_Attender::STATUS_ACCEPTED
 +            ),
 +            array(
 +                'user_type'  => Calendar_Model_Attender::USERTYPE_RESOURCE,
 +                'user_id'    => $nonEditableResoureData['id'],
 +                'status'     => Calendar_Model_Attender::STATUS_ACCEPTED
 +            )
 +        ));
 +        
 +        $persistentEventData = $this->_uit->saveEvent($event->toArray());
 +        
 +        $attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', $persistentEventData['attendee']);
 +        $this->assertEquals(1, count($attendee->filter('status', Calendar_Model_Attender::STATUS_ACCEPTED)), 'one accepted');
 +        $this->assertEquals(1, count($attendee->filter('status', Calendar_Model_Attender::STATUS_NEEDSACTION)), 'one needs action');
 +        
 +        $this->assertEquals(1, count($attendee->filter('status_authkey', '/[a-z0-9]+/', TRUE)), 'one has authkey');
 +        
 +        $attendee->status = Calendar_Model_Attender::STATUS_TENTATIVE;
 +        $persistentEventData['attendee'] = $attendee->toArray();
 +        
 +        $updatedEventData = $this->_uit->saveEvent($persistentEventData);
 +        $attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', $updatedEventData['attendee']);
 +        $this->assertEquals(1, count($attendee->filter('status', Calendar_Model_Attender::STATUS_TENTATIVE)), 'one tentative');
 +    }
++
++    /**
+      * testExdateUpdateAllSummary
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateAllSummary()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         $exception['summary'] = 'new summary';
+         
+         $event = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_ALL);
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             $this->assertEquals('new summary', $event['summary']);
+         }
+     }
+     /**
+      * testExdateUpdateAllDtStart
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      * 
+      * @todo finish
+      */
+     public function testExdateUpdateAllDtStart()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         $exception['dtstart'] = '2009-04-01 08:00:00';
+         $exception['dtend'] = '2009-04-01 08:15:00';
+         
+         $event = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_ALL);
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             $this->assertContains('08:00:00', $event['dtstart'], 'wrong dtstart: ' . print_r($event, TRUE));
+             $this->assertContains('08:15:00', $event['dtend']);
+         }
+     }
+     
+     /**
+      * testExdateUpdateThis
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateThis()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         $exception['summary'] = 'exception';
+         
+         $event = $this->_uit->saveEvent($exception);
+         $this->assertEquals('exception', $event['summary']);
+         
+         // check for summary (only changed in one event)
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             if (! empty($event['recurid']) && ! preg_match('/^fakeid/', $event['id'])) {
+                 $this->assertEquals('exception', $event['summary'], 'summary not changed in exception: ' . print_r($event, TRUE));
+             } else {
+                 $this->assertEquals('Wakeup', $event['summary']);
+             }
+         }
+     }
+     /**
+      * testExdateUpdateThisAndFuture
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateThisAndFuture()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         $exception['summary'] = 'new summary';
+         
+         $updatedEvent = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_THISANDFUTURE);
+         $this->assertEquals('new summary', $updatedEvent['summary'], 'summary not changed in exception: ' . print_r($updatedEvent, TRUE));
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             if ($event['dtstart'] >= $updatedEvent['dtstart']) {
+                 $this->assertEquals('new summary', $event['summary'], 'summary not changed in event: ' . print_r($event, TRUE));
+             } else {
+                 $this->assertEquals('Wakeup', $event['summary']);
+             }
+         }
+     }
+     
+     /**
+      * testExdateUpdateThisAndFutureRemoveAttendee
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateThisAndFutureRemoveAttendee()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         // remove susan from attendee
+         unset($exception['attendee'][0]);
+         
+         $updatedEvent = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_THISANDFUTURE);
+         $this->assertEquals(1, count($updatedEvent['attendee']), 'attender not removed from exception: ' . print_r($updatedEvent, TRUE));
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             if ($event['dtstart'] >= $updatedEvent['dtstart']) {
+                 $this->assertEquals(1, count($event['attendee']), 'attendee count mismatch: ' . print_r($event, TRUE));
+             } else {
+                 $this->assertEquals(2, count($event['attendee']), 'attendee count mismatch: ' . print_r($event, TRUE));
+             }
+         }
+     }
+     /**
+      * testExdateUpdateAllAddAttendee
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateAllAddAttendee()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         // add new attender
+         $exception['attendee'][] = $this->_getUserTypeAttender();
+         
+         $updatedEvent = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_ALL);
+         $this->assertEquals(3, count($updatedEvent['attendee']), 'attender not added to exception: ' . print_r($updatedEvent, TRUE));
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             $this->assertEquals(3, count($event['attendee']), 'attendee count mismatch: ' . print_r($event, TRUE));
+         }
+     }
+     
+     /**
+      * testExdateUpdateThisAndFutureChangeDtstart
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateThisAndFutureChangeDtstart()
+     {
+         $events = $this->testCreateRecurException();
+         $exception = $this->_getException($events, 1);
+         $exception['dtstart'] = '2009-04-01 08:00:00';
+         $exception['dtend'] = '2009-04-01 08:15:00';
+         
+         $updatedEvent = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_THISANDFUTURE);
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             if ($event['dtstart'] >= $updatedEvent['dtstart']) {
+                 $this->assertContains('08:00:00', $event['dtstart'], 'wrong dtstart: ' . print_r($event, TRUE));
+                 $this->assertContains('08:15:00', $event['dtend']);
+             } else {
+                 $this->assertContains('06:00:00', $event['dtstart'], 'wrong dtstart: ' . print_r($event, TRUE));
+                 $this->assertContains('06:15:00', $event['dtend']);
+             }
+         }
+     }
+     
+     /**
+      * testExdateUpdateAllWithModlog
+      * - change base event, then update all
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      */
+     public function testExdateUpdateAllWithModlog()
+     {
+         $events = $this->testCreateRecurException();
+         $baseEvent = $events['results'][0];
+         $exception = $this->_getException($events, 1);
+         
+         $baseEvent['summary'] = 'Get up, lazyboy!';
+         $baseEvent = $this->_uit->saveEvent($baseEvent);
+         sleep(1);
+         
+         $exception['summary'] = 'new summary';
+         $updatedEvent = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_ALL);
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             if ($event['dtstart'] == $updatedEvent['dtstart']) {
+                 $this->assertEquals('new summary', $event['summary'], 'Recur exception should have the new summary');
+             } else {
+                 $this->assertEquals('Get up, lazyboy!', $event['summary'], 'Wrong summary in base/recur event: ' . print_r($event, TRUE));
+             }
+         }
+     }
+     /**
+      * testExdateUpdateAllWithModlogAddAttender
+      * - change base event, then update all
+      * 
+      * @see 0007690: allow to update the whole series / thisandfuture when updating recur exceptions
+      * @see 0007826: add attendee changes to modlog
+      * 
+      * @todo activate!
+      */
+     public function testExdateUpdateAllWithModlogAddAttender()
+     {
+         $this->markTestSkipped('need to resolve #7826 first');
+         
+         $events = $this->testCreateRecurException();
+         $baseEvent = $events['results'][0];
+         $exception = $this->_getException($events, 1);
+         
+         // add new attender
+         $baseEvent['attendee'][] = $this->_getUserTypeAttender();
+         $baseEvent = $this->_uit->saveEvent($baseEvent);
+         $this->assertEquals(3, count($baseEvent['attendee']), 'Attendee count mismatch in baseEvent: ' . print_r($baseEvent, TRUE));
+         sleep(1);
+         
+         // check recent changes (needs to contain attendee change)
+         $exdate = Calendar_Controller_Event::getInstance()->get($exception['id']);
+         $recentChanges = Tinebase_Timemachine_ModificationLog::getInstance()->getModifications('Calendar', $baseEvent['id'], NULL, 'Sql', $exdate->creation_time);
+         $this->assertEquals(4, count($recentChanges), 'Did not get all recent changes: ' . print_r($recentChanges->toArray(), TRUE));
+         $this->assertTrue(in_array('attendee', $recentChanges->modified_attribute), 'Attendee change missing: ' . print_r($recentChanges->toArray(), TRUE));
+         
+         $exception['attendee'][] = $this->_getUserTypeAttender('unittestnotexists@example.com');
+         $updatedEvent = $this->_uit->saveEvent($exception, FALSE, Calendar_Model_Event::RANGE_ALL);
+         
+         $search = $this->_uit->searchEvents($events['filter'], NULL);
+         foreach ($search['results'] as $event) {
+             if ($event['dtstart'] == $updatedEvent['dtstart']) {
+                 $this->assertEquals(3, count($event['attendee']), 'Attendee count mismatch in exdate: ' . print_r($event, TRUE));
+             } else {
+                 $this->assertEquals(4, count($event['attendee']), 'Attendee count mismatch: ' . print_r($event, TRUE));
+             }
+         }
+     }
  }
@@@ -422,9 -428,8 +423,9 @@@ class Calendar_Controller_Event extend
              $sendNotifications = $this->sendNotifications(FALSE);
              
              $event = $this->get($_record->getId());
 +            //NOTE we check via get(full rights) here whereas _updateACLCheck later checks limited rights from search
              if ($this->_doContainerACLChecks === FALSE || $event->hasGrant(Tinebase_Model_Grants::GRANT_EDIT)) {
-                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " updating event: {$_record->id} ");
+                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " updating event: {$_record->id} (range: {$range})");
                  
                  // we need to resolve groupmembers before free/busy checking
                  Calendar_Model_Attender::resolveGroupMembers($_record->attendee);
Simple merge
@@@ -617,9 -595,9 +617,9 @@@ Tine.Calendar.MainScreenCenterPanel = E
          }
          
          var panel = this.getCalendarPanel(this.activeView),
 -            store = panel.getStore(),
 +            store = event.store,
              view = panel.getView();
-                         
+         
          Tine.Calendar.backend.saveRecord(event, {
              scope: this,
              success: function(createdEvent) {
Simple merge