Merge branch '2013.10' into 2014.11
authorPhilipp Schüle <p.schuele@metaways.de>
Thu, 27 Aug 2015 12:32:25 +0000 (14:32 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 27 Aug 2015 12:32:25 +0000 (14:32 +0200)
Conflicts:
tine20/Tinebase/User.php

Change-Id: I1f2ff4290ef3d027c911348ad24a0cdedff91ac1

1  2 
tine20/Tinebase/Container.php
tine20/Tinebase/User.php

@@@ -383,23 -383,20 +383,23 @@@ class Tinebase_Container extends Tineba
       * used to get a list of all containers accesssible by the current user
       * 
       * @param   string|Tinebase_Model_User          $accountId
 -     * @param   string                              $applicationName
 +     * @param   string|Tinebase_Model_Application   $recordClass
       * @param   array|string                        $grant
       * @param   bool                                $onlyIds return only ids
       * @param   bool                                $ignoreACL
       * @return  Tinebase_Record_RecordSet|array
       * @throws  Tinebase_Exception_NotFound
       */
 -    public function getContainerByACL($accountId, $applicationName, $grant, $onlyIds = FALSE, $ignoreACL = FALSE)
 +    public function getContainerByACL($accountId, $recordClass, $grant, $onlyIds = FALSE, $ignoreACL = FALSE)
      {
 +        // legacy handling 
 +        $meta = $this->_resolveRecordClassArgument($recordClass);
 +        
          if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
 -            . ' app: ' . $applicationName . ' / account: ' . $accountId . ' / grant: ' . implode('/', (array)$grant));
 +            . ' app: ' . $meta['appName'] . ' / account: ' . $accountId . ' / grant:' . implode('/', (array)$grant));
          
          $accountId     = Tinebase_Model_User::convertUserIdToInt($accountId);
 -        $applicationId = Tinebase_Application::getInstance()->getApplicationByName($applicationName)->getId();
 +        $applicationId = Tinebase_Application::getInstance()->getApplicationByName($meta['appName'])->getId();
          $grant         = $ignoreACL ? '*' : $grant;
          
          // always bring values in the same order for $classCacheId 
              sort($grant);
          }
          
 -        $classCacheId = convertCacheId($accountId . $applicationId . implode('', (array)$grant) . (int)$onlyIds . (int)$ignoreACL);
 +        $classCacheId = Tinebase_Helper::convertCacheId($accountId . $applicationId . implode('', (array)$grant) . (int)$onlyIds . (int)$ignoreACL);
          
          try {
              return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
          // any account should have at least one personal folder
          // @todo add test for empty case
          if (empty($result)) {
 -            $personalContainer = $this->getDefaultContainer($applicationName, $accountId);
 +            $personalContainer = $this->getDefaultContainer($meta['appName'], $accountId);
              if ($personalContainer instanceof Tinebase_Model_Container) {
                  $result = ($onlyIds) ? 
                      array($personalContainer->getId()) : 
      /**
       * return a container by container name
       *
 -     * @param   string $appName app name
 -     * @param   int|Tinebase_Model_Container $containerName
 -     * @param   string $type
 -     * @param   string $ownerId
 +     * @param   string|Tinebase_Model_Application  $recordClass app name
 +     * @param   int|Tinebase_Model_Container       $containerName
 +     * @param   string                             $type
 +     * @param   string                             $ownerId
       * @return  Tinebase_Model_Container
       * @throws  Tinebase_Exception_NotFound
       * @throws  Tinebase_Exception_UnexpectedValue
       */
 -    public function getContainerByName($appName, $containerName, $type, $ownerId = NULL)
 +    public function getContainerByName($recordClass, $containerName, $type, $ownerId = NULL)
      {
 +        // legacy handling
 +        $meta = $this->_resolveRecordClassArgument($recordClass);
 +        
          if (! in_array($type, array(Tinebase_Model_Container::TYPE_PERSONAL, Tinebase_Model_Container::TYPE_SHARED))) {
              throw new Tinebase_Exception_UnexpectedValue ("Invalid type $type supplied.");
          }
          
          $ownerId = $ownerId instanceof Tinebase_Model_User ? $ownerId->getId() : $ownerId;
          
 -        $applicationId = Tinebase_Application::getInstance()->getApplicationByName($appName)->getId();
 +        $applicationId = Tinebase_Application::getInstance()->getApplicationByName($meta['appName'])->getId();
  
          $select = $this->_getSelect()
              ->where("{$this->_db->quoteIdentifier('container.application_id')} = ?", $applicationId)
          $grant       = $_ignoreACL ? '*' : $_grant;
          $application = Tinebase_Application::getInstance()->getApplicationByName($meta['appName']);
          
 -        $classCacheId = convertCacheId(
 +        $classCacheId = Tinebase_Helper::convertCacheId(
              $accountId .
              $application->getId() .
              ($meta['recordClass'] ? $meta['recordClass'] : null) .
       * returns the shared container for a given application accessible by the current user
       *
       * @param   string|Tinebase_Model_User          $_accountId
 -     * @param   string|Tinebase_Model_Application   $_application
 +     * @param   string|Tinebase_Model_Application   $recordClass
       * @param   array|string                        $_grant
       * @param   bool                                $_ignoreACL
       * @return  Tinebase_Record_RecordSet set of Tinebase_Model_Container
       * @throws  Tinebase_Exception_NotFound
       */
 -    public function getSharedContainer($_accountId, $_application, $_grant, $_ignoreACL = FALSE)
 +    public function getSharedContainer($_accountId, $recordClass, $_grant, $_ignoreACL = FALSE)
      {
 +        // legacy handling
 +        $meta = $this->_resolveRecordClassArgument($recordClass);
 +        $application = Tinebase_Application::getInstance()->getApplicationByName($meta['appName']);
          $accountId   = Tinebase_Model_User::convertUserIdToInt($_accountId);
 -        $application = Tinebase_Application::getInstance()->getApplicationByName($_application);
          $grant       = $_ignoreACL ? '*' : $_grant;
          
 -        $classCacheId = convertCacheId(
 +        $classCacheId = Tinebase_Helper::convertCacheId(
              $accountId .
              $application->getId() .
              implode('', (array)$grant) .
       * return users which made personal containers accessible to given account
       *
       * @param   string|Tinebase_Model_User          $_accountId
 -     * @param   string|Tinebase_Model_Application   $_application
 +     * @param   string|Tinebase_Model_Application   $recordClass
       * @param   array|string                        $_grant
       * @param   bool                                $_ignoreACL
       * @return  Tinebase_Record_RecordSet set of Tinebase_Model_User
       */
 -    public function getOtherUsers($_accountId, $_application, $_grant, $_ignoreACL = FALSE)
 +    public function getOtherUsers($_accountId, $recordClass, $_grant, $_ignoreACL = FALSE)
      {
 -        $userIds = $this->_getOtherAccountIds($_accountId, $_application, $_grant, $_ignoreACL);
 +        $meta = $this->_resolveRecordClassArgument($recordClass);
 +        $userIds = $this->_getOtherAccountIds($_accountId, $meta['appName'], $_grant, $_ignoreACL);
          
          $users = Tinebase_User::getInstance()->getMultiple($userIds);
          $users->sort('accountDisplayName');
          $application = Tinebase_Application::getInstance()->getApplicationByName($_application);
          $grant       = $_ignoreACL ? '*' : $_grant;
  
 -        $classCacheId = convertCacheId($accountId . $application->getId() . implode('', (array)$grant) .(int)$_ignoreACL);
 +        $classCacheId = Tinebase_Helper::convertCacheId($accountId . $application->getId() . implode('', (array)$grant) .(int)$_ignoreACL);
          try {
              return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
          } catch (Tinebase_Exception_NotFound $tenf) {
       * return set of all personal container of other users made accessible to the given account 
       *
       * @param   string|Tinebase_Model_User          $_accountId
 -     * @param   string|Tinebase_Model_Application   $_application
 +     * @param   string|Tinebase_Model_Application   $recordClass
       * @param   array|string                        $_grant
       * @param   bool                                $_ignoreACL
       * @return  Tinebase_Record_RecordSet set of Tinebase_Model_Container
       */
 -    public function getOtherUsersContainer($_accountId, $_application, $_grant, $_ignoreACL = FALSE)
 +    public function getOtherUsersContainer($_accountId, $recordClass, $_grant, $_ignoreACL = FALSE)
      {
 -        $result = $this->_getOtherUsersContainerData($_accountId, $_application, $_grant, $_ignoreACL);
 -        
 +        // legacy handling
 +        $meta = $this->_resolveRecordClassArgument($recordClass);
 +        $result = $this->_getOtherUsersContainerData($_accountId, $meta['appName'], $_grant, $_ignoreACL);
 +
          return $result;
      }
      
          $application = Tinebase_Application::getInstance()->getApplicationByName($_application);
          $grant       = $_ignoreACL ? '*' : $_grant;
          
 -        $classCacheId = convertCacheId(
 +        $classCacheId = Tinebase_Helper::convertCacheId(
              $accountId .
              $application->getId() .
              implode('', (array)$grant) .
       * @param   boolean $_ignoreAcl
       * @param   boolean $_tryAgain
       * @throws  Tinebase_Exception_AccessDenied
+      * @throws  Tinebase_Exception_Record_SystemContainer
       * @throws  Tinebase_Exception_InvalidArgument
       * 
       * @todo move records in deleted container to personal container?
                      throw new Tinebase_Exception_InvalidArgument('Can delete personal or shared containers only.');
                  }
              }
 -            $this->deleteContainerContents($container);
 +            $this->deleteContainerContents($container, $_ignoreAcl);
              $deletedContainer = $this->_setRecordMetaDataAndUpdate($container, 'delete');
              
          } catch (Exception $e) {
       * 
       * @param Tinebase_Model_Container $container
       */
 -    public function deleteContainerContents($container)
 +    public function deleteContainerContents($container, $_ignoreAcl = FALSE)
      {
          // set records belonging to this container to deleted
          $model = $container->model;
          if ($model) {
              $controller = Tinebase_Core::getApplicationInstance($model);
              $filterName = $model . 'Filter';
 +            if($_ignoreAcl === TRUE && method_exists($controller, 'doContainerACLChecks')) {
 +                $acl = $controller->doContainerACLChecks(FALSE);
 +            }
              if ($controller && class_exists($filterName)) {
                  $filter = new $filterName(array(
                      array(
                      'AND');
                  $controller::getInstance()->deleteByFilter($filter);
              }
 +            if ($_ignoreAcl === TRUE && method_exists($controller, 'doContainerACLChecks')) {
 +                $controller->doContainerACLChecks($acl);
 +            }
          }
      }
      
          if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
              . ' account: ' . $accountId . ' / containerId: ' . $containerId . ' / grant:' . implode('/', (array)$_grant));
          
 -        $classCacheId = convertCacheId($accountId . $containerId);
 -        
 +        $classCacheId = Tinebase_Helper::convertCacheId($accountId . $containerId . implode('', (array)$_grant));
 +
          try {
              $allGrants = $this->loadFromClassCache(__FUNCTION__, $classCacheId);
          } catch (Tinebase_Exception_NotFound $tenf) {
          $containerId        = Tinebase_Model_Container::convertContainerIdToInt($_containerId);
          $container          = ($_containerId instanceof Tinebase_Model_Container) ? $_containerId : $this->getContainerById($_containerId);
          
 -        $cacheKey = convertCacheId('getGrantsOfAccount' . $containerId . $accountId . $container->seq);
 +        $cacheKey = Tinebase_Helper::convertCacheId('getGrantsOfAccount' . $containerId . $accountId . $container->seq);
          $cache = Tinebase_Core::getCache();
          $grants = $cache->load($cacheKey);
          if ($grants === FALSE) {
       * @param string $action
       * @param string $recordId
       * @return integer new content seq
 -     * 
 -     * @todo clear cache? perhaps not, we have getContentSequence() for that
       */
      public function increaseContentSequence($containerId, $action = NULL, $recordId = NULL)
      {
diff --combined tine20/Tinebase/User.php
@@@ -163,8 -163,6 +163,6 @@@ class Tinebase_Use
       */
      public static function getInstance() 
      {
-         $backendType = self::getConfiguredBackend();
-         
          if (self::$_instance === NULL) {
              $backendType = self::getConfiguredBackend();
              if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' accounts backend: ' . $backendType);
      {
          if ($username instanceof Tinebase_Model_FullUser) {
              $username = $username->accountLoginName;
-         } else {
-             $username = $username;
          }
          
          if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . "  sync user data for: " . $username);
          if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' 
              . print_r($user->toArray(), TRUE));
          
-         $group = self::getPrimaryGroupForUser($user);
-         
+         self::getPrimaryGroupForUser($user);
          try {
              $currentUser = $userBackend->getUserByProperty('accountId', $user, 'Tinebase_Model_FullUser');
          
                      self::createContactForSyncedUser($currentUser);
                  }
              }
 -        
 +            
 +            Tinebase_Timemachine_ModificationLog::setRecordMetaData($currentUser, 'update');
              $syncedUser = $userBackend->updateUserInSqlBackend($currentUser);
              if (! empty($user->container_id)) {
                  $syncedUser->container_id = $user->container_id;
              if ($user->visibility !== Tinebase_Model_FullUser::VISIBILITY_HIDDEN) {
                  self::createContactForSyncedUser($user);
              }
 +            Tinebase_Timemachine_ModificationLog::setRecordMetaData($user, 'create');
              $syncedUser = $userBackend->addUserInSqlBackend($user);
              $userBackend->addPluginUser($syncedUser, $user);
          }
          }
          
          $addressbook = Addressbook_Backend_Factory::factory(Addressbook_Backend_Factory::SQL);
-         
          try {
              $contact = $addressbook->getByUserId($syncedUser->getId());
              $originalContact = clone $contact;
-             
              Tinebase_User::getInstance()->updateContactFromSyncBackend($syncedUser, $contact);
              $contact = self::_user2Contact($syncedUser, $contact);
-             
-             // TODO allow to diff jpegphoto, too
+             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__
+                 . print_r($syncedUser->toArray(), true)
+                 . ' new: ' . print_r($contact->toArray(), true)
+                 . ' orig:' . print_r($originalContact->toArray(), true));
+             // TODO allow to diff jpegphoto, too / maybe this should only be done when called via CLI/cronjob
              $diff = $contact->diff($originalContact, array('jpegphoto'));
-             if (! $diff->isEmpty()) {
+             if (! $diff->isEmpty() || ($originalContact->jpegphoto == 0 && ! empty($contact->jpegphoto))) {
                  // add modlog info
                  Tinebase_Timemachine_ModificationLog::setRecordMetaData($contact, 'update');
 -                Tinebase_Container::getInstance()->increaseContentSequence($contact->container_id);
 -
 +                if ($contact->container_id !== null) {
 +                    Tinebase_Container::getInstance()->increaseContentSequence($contact->container_id);
 +                }
 +                
                  if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
                      . ' Updating contact data for user ' . $syncedUser->accountLoginName);
                  if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
                      . ' Diff: ' . print_r($diff->toArray(), true));
-                 
                  $addressbook->update($contact);
              } else {
                  if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
                      throw new Tinebase_Exception('Primary group ' . $user->accountPrimaryGroup . ' not found in sync backend.');
                  }
                  try {
-                     $sqlGgroup = $groupBackend->getGroupByName($group->name);
+                     $groupBackend->getGroupByName($group->name);
                      throw new Tinebase_Exception('Group already exists but it has a different ID: ' . $group->name);
          
                  } catch (Tinebase_Exception_Record_NotDefined $tern) {
          // update or create user in local sql backend
          try {
              $userBackend->getUserByProperty('accountLoginName', $adminLoginName);
 +            Tinebase_Timemachine_ModificationLog::setRecordMetaData($user, 'update');
              $user = $userBackend->updateUserInSqlBackend($user);
          } catch (Tinebase_Exception_NotFound $ten) {
              // call addUser here to make sure, sql user plugins (email, ...) are triggered
 +            Tinebase_Timemachine_ModificationLog::setRecordMetaData($user, 'create');
              $user = $userBackend->addUser($user);
          }
          
          // set the password for the account
 -        Tinebase_User::getInstance()->setPassword($user, $adminPassword);
 +        // empty password triggers password change dialogue during first login
 +        if (!empty($adminPassword)) {
 +            Tinebase_User::getInstance()->setPassword($user, $adminPassword);
 +        }
  
          // add the admin account to all groups
          Tinebase_Group::getInstance()->addGroupMember($adminGroup, $user);