Merge branch 'pu/2013.03/modelconfig-hr'
authorPhilipp Schüle <p.schuele@metaways.de>
Thu, 4 Jul 2013 11:32:54 +0000 (13:32 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 4 Jul 2013 11:32:54 +0000 (13:32 +0200)
Conflicts:
tests/tine20/Calendar/JsonTests.php
tine20/Calendar/Convert/Event/Json.php
tine20/Calendar/Model/Event.php
tine20/Tasks/Model/Task.php
tine20/Tinebase/Convert/Json.php
tine20/Tinebase/User/Sql.php

18 files changed:
1  2 
tests/tine20/Calendar/Convert/Event/VCalendar/GenericTest.php
tests/tine20/Calendar/JsonTests.php
tine20/Addressbook/js/Model.js
tine20/Calendar/Controller/Event.php
tine20/Calendar/Convert/Event/Json.php
tine20/Calendar/Model/Event.php
tine20/Calendar/js/Model.js
tine20/Crm/js/Model.js
tine20/Tasks/Model/Task.php
tine20/Tasks/js/Models.js
tine20/Tinebase/Controller/Record/Abstract.php
tine20/Tinebase/Convert/Json.php
tine20/Tinebase/Frontend/Http.php
tine20/Tinebase/Record/RecordSet.php
tine20/Tinebase/Tinebase.jsb2
tine20/Tinebase/User/Sql.php
tine20/Tinebase/css/Tinebase.css
tine20/Tinebase/js/widgets/dialog/EditDialog.js

@@@ -1305,28 -1310,30 +1315,54 @@@ class Calendar_JsonTests extends Calend
              $this->assertEquals(Calendar_Model_Attender::STATUS_TENTATIVE, $attender['status'], 'both attendee status should be TENTATIVE: ' . print_r($attender, TRUE));
          }
      }
 +
 +    /**
 +     * testFreeBusyCheckForExdates
 +     * 
 +     * @see 0008464: freebusy check does not work when creating recur exception
 +     */
 +    public function testFreeBusyCheckForExdates()
 +    {
 +        $events = $this->testCreateRecurException();
 +        $exception = $this->_getException($events, 1);
 +        
 +        $anotherEvent = $this->_getEvent(TRUE);
 +        $anotherEvent = $this->_uit->saveEvent($anotherEvent->toArray());
 +        
 +        $exception['dtstart'] = $anotherEvent['dtstart'];
 +        $exception['dtend'] = $anotherEvent['dtend'];
 +        
 +        try {
 +            $event = $this->_uit->saveEvent($exception, TRUE);
 +            $this->fail('Calendar_Exception_AttendeeBusy expected when saving exception: ' . print_r($exception, TRUE));
 +        } catch (Calendar_Exception_AttendeeBusy $ceab) {
 +            $this->assertEquals('Calendar_Exception_AttendeeBusy', get_class($ceab));
 +        }
 +    }
+     
+     /**
+      * testAddAttachmentToRecurSeries
+      * 
+      * @see 0005024: allow to attach external files to records
+      */
+     public function testAddAttachmentToRecurSeries()
+     {
+         $tempFileBackend = new Tinebase_TempFile();
+         $tempFile = $tempFileBackend->createTempFile(dirname(dirname(__FILE__)) . '/Filemanager/files/test.txt');
+         
+         $recurSet = array_value('results', $this->testSearchRecuringIncludes());
+         // update recurseries 
+         $someRecurInstance = $recurSet[2];
+         $someRecurInstance['attachments'] = array(array('tempFile' => array('id' => $tempFile->getId())));
+         $someRecurInstance['seq'] = 2;
+         $this->_uit->updateRecurSeries($someRecurInstance, FALSE, FALSE);
+         
+         $searchResultData = $this->_searchRecurSeries($recurSet[0]);
+         foreach ($searchResultData['results'] as $recurInstance) {
+             $this->assertTrue(isset($recurInstance['attachments']), 'no attachments found in event: ' . print_r($recurInstance, TRUE));
+             $this->assertEquals(1, count($recurInstance['attachments']));
+             $attachment = $recurInstance['attachments'][0];
+             $this->assertEquals('text/plain', $attachment['contenttype'], print_r($attachment, TRUE));
+         }
+     }
  }
Simple merge
Simple merge
@@@ -68,25 -68,13 +68,15 @@@ class Calendar_Convert_Event_Json exten
      */
      static public function resolveOrganizer($_events)
      {
-         $events = $_events instanceof Tinebase_Record_RecordSet || is_array($_events) ? $_events : array($_events);
-     
-         $organizerIds = array();
-         foreach ($events as $event) {
-             if ($event->organizer) {
-                 $organizerIds[] = $event->organizer;
-             }
-         }
-     
-         $organizers = Addressbook_Controller_Contact::getInstance()->getMultiple(array_unique($organizerIds), TRUE);
-     
-         foreach ($events as $event) {
-             if ($event->organizer && is_scalar($event->organizer)) {
-                 $idx = $organizers->getIndexById($event->organizer);
-                 if ($idx !== FALSE) {
-                     $event->organizer = $organizers[$idx];
-                 }
-             }
-         }
 -        $events = $_events instanceof Tinebase_Record_RecordSet ? $_events : new Tinebase_Record_RecordSet('Calendar_Model_Event', array($_events));
++        $events = $_events instanceof Tinebase_Record_RecordSet
++            ? $_events : new Tinebase_Record_RecordSet('Calendar_Model_Event', array($_events));
++        
+         self::resolveMultipleIdFields($events, array(
+             'Addressbook_Model_Contact' => array(
+                 'options' => array('ignoreAcl' => TRUE),
+                 'fields'  => array('organizer'),
+             )
+         ));
      }
      
      /**
@@@ -90,53 -90,54 +90,55 @@@ class Calendar_Model_Event extends Tine
          ),
          // ical common fields
          'class'                => array(
-             'allowEmpty' => true,
+             Zend_Filter_Input::ALLOW_EMPTY => true,
              array('InArray', array(self::CLASS_PUBLIC, self::CLASS_PRIVATE, /*self::CLASS_CONFIDENTIAL*/))
          ),
-         'description'          => array('allowEmpty' => true          ),
-         'geo'                  => array('allowEmpty' => true, Zend_Filter_Input::DEFAULT_VALUE => NULL),
-         'location'             => array('allowEmpty' => true          ),
-         'organizer'            => array('allowEmpty' => false,         ),
-         'priority'             => array('allowEmpty' => true, 'Int'   ),
+         'description'          => array(Zend_Filter_Input::ALLOW_EMPTY => true          ),
+         'geo'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => NULL),
+         'location'             => array(Zend_Filter_Input::ALLOW_EMPTY => true          ),
 -        'organizer'            => array(Zend_Filter_Input::ALLOW_EMPTY => true,         ),
++        'organizer'            => array(Zend_Filter_Input::ALLOW_EMPTY => false,        ),
+         'priority'             => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'Int'   ),
          'status'            => array(
-             'allowEmpty' => true,
+             Zend_Filter_Input::ALLOW_EMPTY => true,
              array('InArray', array(self::STATUS_CONFIRMED, self::STATUS_TENTATIVE, self::STATUS_CANCELED))
          ),
-         'summary'              => array('allowEmpty' => true          ),
-         'url'                  => array('allowEmpty' => true          ),
-         'uid'                  => array('allowEmpty' => true          ),
+         'summary'              => array(Zend_Filter_Input::ALLOW_EMPTY => true          ),
+         'url'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true          ),
+         'uid'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true          ),
          // ical common fields with multiple appearance
-         //'attach'                => array('allowEmpty' => true         ),
-         'attendee'              => array('allowEmpty' => true         ), // RecordSet of Calendar_Model_Attender
-         'alarms'                => array('allowEmpty' => true         ), // RecordSet of Tinebase_Model_Alarm
-         'tags'                  => array('allowEmpty' => true         ), // originally categories handled by Tinebase_Tags
-         'notes'                 => array('allowEmpty' => true         ), // originally comment handled by Tinebase_Notes
-         'relations'             => array('allowEmpty' => true         ),
-         //'contact'               => array('allowEmpty' => true         ),
-         //'related'               => array('allowEmpty' => true         ),
-         //'resources'             => array('allowEmpty' => true         ),
-         //'rstatus'               => array('allowEmpty' => true         ),
+         //'attach'                => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'attendee'              => array(Zend_Filter_Input::ALLOW_EMPTY => true         ), // RecordSet of Calendar_Model_Attender
+         'alarms'                => array(Zend_Filter_Input::ALLOW_EMPTY => true         ), // RecordSet of Tinebase_Model_Alarm
+         'tags'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ), // originally categories handled by Tinebase_Tags
+         'notes'                 => array(Zend_Filter_Input::ALLOW_EMPTY => true         ), // originally comment handled by Tinebase_Notes
++        'relations'             => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'attachments'           => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         
+         //'contact'               => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         //'related'               => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         //'resources'             => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         //'rstatus'               => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
          // ical scheduleable interface fields
-         'dtstart'               => array('allowEmpty' => true         ),
-         'recurid'               => array('allowEmpty' => true         ),
+         'dtstart'               => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'recurid'               => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
          // ical scheduleable interface fields with multiple appearance
-         'exdate'                => array('allowEmpty' => true         ), //  array of Tinebase_DateTimeTinebase_DateTime's
-         //'exrule'                => array('allowEmpty' => true         ),
-         //'rdate'                 => array('allowEmpty' => true         ),
-         'rrule'                 => array('allowEmpty' => true         ),
+         'exdate'                => array(Zend_Filter_Input::ALLOW_EMPTY => true         ), //  array of Tinebase_DateTimeTinebase_DateTime's
+         //'exrule'                => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         //'rdate'                 => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'rrule'                 => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
          // calendar helper fields
-         'is_all_day_event'      => array('allowEmpty' => true         ),
-         'rrule_until'           => array('allowEmpty' => true         ),
-         'originator_tz'         => array('allowEmpty' => true         ),
+         'is_all_day_event'      => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'rrule_until'           => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'originator_tz'         => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
      
          // grant helper fields
-         Tinebase_Model_Grants::GRANT_FREEBUSY  => array('allowEmpty' => true),
-         Tinebase_Model_Grants::GRANT_READ    => array('allowEmpty' => true),
-         Tinebase_Model_Grants::GRANT_SYNC    => array('allowEmpty' => true),
-         Tinebase_Model_Grants::GRANT_EXPORT  => array('allowEmpty' => true),
-         Tinebase_Model_Grants::GRANT_EDIT    => array('allowEmpty' => true),
-         Tinebase_Model_Grants::GRANT_DELETE  => array('allowEmpty' => true),
-         Tinebase_Model_Grants::GRANT_PRIVATE => array('allowEmpty' => true),
+         Tinebase_Model_Grants::GRANT_FREEBUSY => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         Tinebase_Model_Grants::GRANT_READ     => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         Tinebase_Model_Grants::GRANT_SYNC     => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         Tinebase_Model_Grants::GRANT_EXPORT   => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         Tinebase_Model_Grants::GRANT_EDIT     => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         Tinebase_Model_Grants::GRANT_DELETE   => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+         Tinebase_Model_Grants::GRANT_PRIVATE  => array(Zend_Filter_Input::ALLOW_EMPTY => true),
      );
      
      /**
Simple merge
Simple merge
@@@ -43,56 -58,57 +58,57 @@@ class Tasks_Model_Task extends Tinebase
       */
      protected $_validators = array(
          // tine record fields
-         'container_id'         => array('allowEmpty' => true,  'Int' ),
-         'created_by'           => array('allowEmpty' => true,        ),
-         'creation_time'        => array('allowEmpty' => true         ),
-         'last_modified_by'     => array('allowEmpty' => true         ),
-         'last_modified_time'   => array('allowEmpty' => true         ),
-         'is_deleted'           => array('allowEmpty' => true         ),
-         'deleted_time'         => array('allowEmpty' => true         ),
-         'deleted_by'           => array('allowEmpty' => true         ),
-         'seq'                  => array('allowEmpty' => true         ),
+         'container_id'         => array(Zend_Filter_Input::ALLOW_EMPTY => true,  'Int' ),
+         'created_by'           => array(Zend_Filter_Input::ALLOW_EMPTY => true,        ),
+         'creation_time'        => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'last_modified_by'     => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'last_modified_time'   => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'is_deleted'           => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'deleted_time'         => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'deleted_by'           => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'seq'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
          // task only fields
-         'id'                   => array('allowEmpty' => true, 'Alnum'),
-         'percent'              => array('allowEmpty' => true, 'default' => 0),
-         'completed'            => array('allowEmpty' => true         ),
-         'due'                  => array('allowEmpty' => true         ),
+         'id'                   => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'Alnum'),
+         'percent'              => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'default' => 0),
+         'completed'            => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'due'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
          // ical common fields
          'class'                => array(
-             'allowEmpty' => true,
+             Zend_Filter_Input::ALLOW_EMPTY => true,
              array('InArray', array(self::CLASS_PUBLIC, self::CLASS_PRIVATE, /*self::CLASS_CONFIDENTIAL*/)),
          ),
-         'description'          => array('allowEmpty' => true         ),
-         'geo'                  => array('allowEmpty' => true, Zend_Filter_Input::DEFAULT_VALUE => NULL),
-         'location'             => array('allowEmpty' => true         ),
-         'organizer'            => array('allowEmpty' => true,        ),
-         'originator_tz'        => array('allowEmpty' => true         ),
-         'priority'             => array('allowEmpty' => true, 'default' => 1),
-         'status'               => array('allowEmpty' => false        ),
+         'description'          => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'geo'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => NULL),
+         'location'             => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'organizer'            => array(Zend_Filter_Input::ALLOW_EMPTY => true,        ),
+         'originator_tz'        => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
+         'priority'             => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'default' => 1),
 -        'status'               => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
++        'status'               => array(Zend_Filter_Input::ALLOW_EMPTY => false        ),
          'summary'              => array('presence' => 'required'     ),
-         'url'                  => array('allowEmpty' => true         ),
+         'url'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
          // ical common fields with multiple appearance
-         'attach'                => array('allowEmpty' => true        ),
-         'attendee'              => array('allowEmpty' => true        ),
-         'tags'                  => array('allowEmpty' => true        ), //originally categories
-         'comment'               => array('allowEmpty' => true        ),
-         'contact'               => array('allowEmpty' => true        ),
-         'related'               => array('allowEmpty' => true        ),
-         'resources'             => array('allowEmpty' => true        ),
-         'rstatus'               => array('allowEmpty' => true        ),
+         'attach'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'attendee'             => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'tags'                 => array(Zend_Filter_Input::ALLOW_EMPTY => true        ), //originally categories
+         'comment'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'contact'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'related'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'resources'            => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'rstatus'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
          // scheduleable interface fields
-         'dtstart'               => array('allowEmpty' => true        ),
-         'duration'              => array('allowEmpty' => true        ),
-         'recurid'               => array('allowEmpty' => true        ),
+         'dtstart'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'duration'             => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'recurid'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
          // scheduleable interface fields with multiple appearance
-         'exdate'                => array('allowEmpty' => true        ),
-         'exrule'                => array('allowEmpty' => true        ),
-         'rdate'                 => array('allowEmpty' => true        ),
-         'rrule'                 => array('allowEmpty' => true        ),
+         'exdate'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'exrule'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'rdate'                => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'rrule'                => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
          // tine 2.0 notes, alarms and relations
-         'notes'                 => array('allowEmpty' => true        ),
-         'alarms'                => array('allowEmpty' => true        ), // RecordSet of Tinebase_Model_Alarm
-         'relations'             => array('allowEmpty' => true        ),
+         'notes'                => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'alarms'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ), // RecordSet of Tinebase_Model_Alarm
+         'relations'            => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
+         'attachments'          => array(Zend_Filter_Input::ALLOW_EMPTY => true),
      );
      
      /**
Simple merge
@@@ -142,32 -142,83 +142,91 @@@ class Tinebase_Convert_Json implements 
              return;
          }
          
-         foreach ($resolveFields as $foreignRecordClassName => $fields) {
-             $foreignIds = array();
-             $fields = (array) $fields;
-     
-             foreach ($fields as $field) {
-                 $foreignIds = array_unique(array_merge($foreignIds, $_records->{$field}));
+         $ownRecordClass = $records->getRecordClassName();
+         if ($resolveFields === NULL) {
+             $resolveFields = $ownRecordClass::getResolveForeignIdFields();
+         }
+         
+         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ 
+             . ' Resolving ' . $ownRecordClass . ' fields: ' . print_r($resolveFields, TRUE));
+         
+         foreach ((array) $resolveFields as $foreignRecordClassName => $fields) {
+             if ($foreignRecordClassName === 'recursive') {
+                 foreach ($fields as $field => $model) {
+                     foreach ($records->$field as $subRecords) {
+                         self::resolveMultipleIdFields($subRecords);
+                     }
+                 }
+             } else {
+                 self::_resolveForeignIdFields($records, $foreignRecordClassName, (array) $fields);
              }
+         }
+     }
      
-             if (! Tinebase_Core::getUser()->hasRight(substr($foreignRecordClassName, 0, strpos($foreignRecordClassName, "_")), Tinebase_Acl_Rights_Abstract::RUN))
-                 continue;
-     
+     /**
+      * resolve foreign fields for records
+      * 
+      * @param Tinebase_Record_RecordSet $records
+      * @param string $foreignRecordClassName
+      * @param array $fields
+      */
+     protected static function _resolveForeignIdFields($records, $foreignRecordClassName, $fields)
+     {
+         $options = array_key_exists('options', $fields) ? $fields['options'] : array();
+         $fields = array_key_exists('fields', $fields) ? $fields['fields'] : $fields;
+         
+         $foreignIds = array();
+         foreach ($fields as $field) {
+             $foreignIds = array_unique(array_merge($foreignIds, $records->{$field}));
+         }
+         
+         if (! Tinebase_Core::getUser()->hasRight(substr($foreignRecordClassName, 0, strpos($foreignRecordClassName, "_")), Tinebase_Acl_Rights_Abstract::RUN)) {
+             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
+                 . ' Not resolving ' . $foreignRecordClassName . ' records because user has no right to run app.');
+             return;
+         }
+         
 -        $controller = Tinebase_Core::getApplicationInstance($foreignRecordClassName);
++        try {
 +            $controller = Tinebase_Core::getApplicationInstance($foreignRecordClassName);
-     
-             if (method_exists($controller, 'modlogActive')) {
-                 $modlogActive = $controller->modlogActive(FALSE);
-             }
++        } catch (Tinebase_Exception_AccessDenied $tead) {
++            return;
++        }
++        
++        if (method_exists($controller, 'modlogActive')) {
++            $modlogActive = $controller->modlogActive(FALSE);
++        }
+         
+         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ 
+             . ' Fetching ' . $foreignRecordClassName . ' by id: ' . print_r($foreignIds, TRUE));
+         
+         if (array_key_exists('ignoreAcl', $options) && $options['ignoreAcl']) {
+             // @todo make sure that second param of getMultiple() is $ignoreAcl
+             $foreignRecords = $controller->getMultiple($foreignIds, TRUE);
+         } else {
              $foreignRecords = $controller->getMultiple($foreignIds);
-             $foreignRecords->setTimezone(Tinebase_Core::get(Tinebase_Core::USERTIMEZONE));
-             $foreignRecords->convertDates = true;
-             
-             if ($foreignRecords->count()) {
-                 foreach ($_records as $record) {
-                     foreach ($fields as $field) {
-                         $idx = $foreignRecords->getIndexById($record->{$field});
-                         if (isset($idx) && $idx !== FALSE) {
-                             $record->{$field} = $foreignRecords[$idx];
+         }
+         
+         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ 
+             . ' Foreign records found: ' . print_r($foreignRecords->toArray(), TRUE));
+         
+         if (count($foreignRecords) === 0) {
+             return;
+         }
+         
+         foreach ($records as $record) {
+             foreach ($fields as $field) {
+                 if (is_scalar($record->{$field})) {
+                     $idx = $foreignRecords->getIndexById($record->{$field});
+                     if (isset($idx) && $idx !== FALSE) {
+                         $record->{$field} = $foreignRecords[$idx];
+                     } else {
+                         switch ($foreignRecordClassName) {
+                             case 'Tinebase_Model_User':
+                             case 'Tinebase_Model_FullUser':
+                                 $record->{$field} = Tinebase_User::getInstance()->getNonExistentUser();
+                                 break;
+                             default:
+                                 // skip
                          }
                      }
                  }
Simple merge
Simple merge
Simple merge
@@@ -934,13 -932,11 +934,13 @@@ class Tinebase_User_Sql extends Tinebas
      /**
       * Get multiple users
       *
 -     * @param   string|array $_id Ids
 -     * @param   string  $_accountClass  type of model to return
 +     * fetch FullUser by default
 +     *
-      * @param     string|array $_id Ids
-      * @param   string  $_accountClass  type of model to return
++     * @param  string|array $_id Ids
++     * @param  string  $_accountClass  type of model to return
       * @return Tinebase_Record_RecordSet of 'Tinebase_Model_User' or 'Tinebase_Model_FullUser'
       */
 -    public function getMultiple($_id, $_accountClass = 'Tinebase_Model_User') 
 +    public function getMultiple($_id, $_accountClass = 'Tinebase_Model_FullUser') 
      {
          if (empty($_id)) {
              return new Tinebase_Record_RecordSet($_accountClass);
Simple merge