Merge branch '2013.10' into 2014.11
authorPhilipp Schüle <p.schuele@metaways.de>
Tue, 30 Dec 2014 11:37:05 +0000 (12:37 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Tue, 30 Dec 2014 11:37:05 +0000 (12:37 +0100)
Conflicts:
tests/tine20/Calendar/JsonTests.php
tine20/Tinebase/Container.php
tine20/Tinebase/Export/Spreadsheet/Ods.php
tine20/Tinebase/Frontend/Json.php
tine20/Tinebase/Record/Abstract.php
tine20/composer.json
tine20/composer.lock

Change-Id: I3d3cf870d6341a33f5262b95a9868c5a9b5ac089

33 files changed:
1  2 
tests/tine20/Calendar/AllTests.php
tests/tine20/Calendar/JsonTests.php
tests/tine20/Calendar/TestCase.php
tests/tine20/Timetracker/AbstractTest.php
tests/tine20/Tinebase/Acl/RolesTest.php
tests/tine20/Tinebase/ContainerTest.php
tine20/Admin/Controller/User.php
tine20/Calendar/Backend/Sql.php
tine20/Calendar/Calendar.jsb2
tine20/Calendar/Model/Attender.php
tine20/Calendar/Model/Event.php
tine20/Calendar/Model/Rrule.php
tine20/Calendar/js/EventEditDialog.js
tine20/Calendar/js/MainScreenCenterPanel.js
tine20/Tinebase/Acl/Roles.php
tine20/Tinebase/Config/Abstract.php
tine20/Tinebase/Container.php
tine20/Tinebase/Convert/Json.php
tine20/Tinebase/DateTime.php
tine20/Tinebase/Db/Table.php
tine20/Tinebase/Export/Abstract.php
tine20/Tinebase/Export/Spreadsheet/Ods.php
tine20/Tinebase/Frontend/Json.php
tine20/Tinebase/Notes.php
tine20/Tinebase/Record/Abstract.php
tine20/Tinebase/Record/RecordSet.php
tine20/Tinebase/Server/Json.php
tine20/Tinebase/Translation.php
tine20/Tinebase/User/Sql.php
tine20/Tinebase/WebDav/Collection/AbstractContainerTree.php
tine20/Tinebase/js/widgets/relation/GenericPickerGridPanel.js
tine20/composer.json
tine20/composer.lock

Simple merge
@@@ -1505,49 -1492,36 +1505,81 @@@ class Calendar_JsonTests extends Calend
          $event = $this->_uit->saveEvent($eventData);
          $this->assertEquals(1, $event['attendee'][1]['quantity'], 'The invalid quantity should be saved as 1');
      }
 +
 +    /**
 +     * trigger caldav import by json frontend
 +     * 
 +     * @todo use mock as fallback (if server can not be reached by curl)
 +     * @todo get servername from unittest config / skip or mock if no servername found
 +     */
 +    public function testCalDAVImport()
 +    {
 +        // Skip if tine20.com.local could not be resolved
 +        if (gethostbyname('tine20.com.local') == 'tine20.com.local') {
 +            $this->markTestSkipped('Can\'t perform test, because instance is not reachable.');
 +        }
 +
 +        $this->_testNeedsTransaction();
 +        
 +        $event = $this->testCreateEvent(/* $now = */ true);
 +        
 +        $fe = new Calendar_Frontend_Json();
 +        $testUserCredentials = TestServer::getInstance()->getTestCredentials();
 +        $fe->importRemoteEvents(
 +            'http://tine20.com.local/calendars/' . Tinebase_Core::getUser()->contact_id . '/' . $event['container_id']['id'],
 +            Tinebase_Model_Import::INTERVAL_DAILY,
 +            array(
 +                'container_id'          => 'remote_caldav_calendar',
 +                'sourceType'            => 'remote_caldav',
 +                'importFileByScheduler' => false,
 +                'allowDuplicateEvents'  => true,
 +                'username'              => $testUserCredentials['username'],
 +                'password'              => $testUserCredentials['password'],
 +            ));
 +
 +        $importScheduler = Tinebase_Controller_ScheduledImport::getInstance();
 +        $record = $importScheduler->runNextScheduledImport();
 +
 +        $container = Tinebase_Container::getInstance()->getContainerByName('Calendar', 'remote_caldav_calendar', Tinebase_Model_Container::TYPE_PERSONAL, Tinebase_Core::getUser()->getId());
 +        $this->_testCalendars[] = $container;
 +        $this->assertTrue($container instanceof Tinebase_Model_Container, 'Container was not created');
 +
 +        $this->assertNotEquals($record, null, 'The import could not start!');
 +        
 +        $filter = $this->_getEventFilterArray($container->getId());
 +        $result = $this->_uit->searchEvents($filter, array());
 +        $this->assertEquals(1, $result['totalcount']);
 +    }
+     
+     /**
+      * testGetRelations
+      * 
+      * @see 0009542: load event relations on demand
+      */
+     public function testGetRelations()
+     {
+         $contact = Addressbook_Controller_Contact::getInstance()->create(new Addressbook_Model_Contact(array(
+             'n_family' => 'Contact for relations test'
+         )));
+         $eventData = $this->_getEvent()->toArray();
+         $eventData['relations'] = array(
+         array(
+             'own_model'              => 'Calendar_Model_Event',
+             'own_backend'            => 'Sql',
+             'own_id'                 => 0,
+             'own_degree'             => Tinebase_Model_Relation::DEGREE_SIBLING,
+             'type'                   => '',
+             'related_backend'        => 'Sql',
+             'related_id'             => $contact->getId(),
+             'related_model'          => 'Addressbook_Model_Contact',
+             'remark'                 => NULL,
+         ));
+         $event = $this->_uit->saveEvent($eventData);
+         
+         $tfj = new Tinebase_Frontend_Json();
+         $relations = $tfj->getRelations('Calendar_Model_Event', $event['id']);
+         
+         $this->assertEquals(1, $relations['totalcount']);
+         $this->assertEquals($contact->n_fn, $relations['results'][0]['related_record']['n_family'], print_r($relations['results'], true));
+     }
  }
Simple merge
@@@ -44,11 -44,9 +44,12 @@@ abstract class Timetracker_AbstractTes
       */
      protected function setUp()
      {
+         Tinebase_Acl_Roles::getInstance()->resetClassCache();
          Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
          $this->_json = new Timetracker_Frontend_Json();
 +        
 +        Sales_Controller_Contract::getInstance()->setNumberPrefix();
 +        Sales_Controller_Contract::getInstance()->setNumberZerofill();
      }
  
      /**
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -318,10 -311,9 +357,10 @@@ Tine.Calendar.MainScreenCenterPanel = E
              }],
              items: [
                  this.showSheetView,
 -                this.showGridView
 +                this.showGridView,
 +                this.action_import
              ]
-         };
+         }];
      },
      
      /**
@@@ -342,21 -355,16 +355,24 @@@ class Tinebase_Acl_Role
          }
          $data['creation_time'] = Tinebase_DateTime::now()->get(Tinebase_Record_Abstract::ISO8601LONG);
          
 -        $newId = $this->_rolesTable->insert($data);
 -        
 -        if ($newId === NULL) {
 -           $newId = $this->_db->lastSequenceId(substr(SQL_TABLE_PREFIX . 'roles', 0,25) . '_s');
 -        }
 +        $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction($this->_db);
 +        try {
 +            $newId = $this->_rolesTable->insert($data);
 +            
 +            if ($newId === NULL) {
 +                $newId = $this->_db->lastSequenceId(substr(SQL_TABLE_PREFIX . 'roles', 0,25) . '_s');
 +            }            
 +            
 +            Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId);
 +        } catch(Exception $e){            
 +            Tinebase_TransactionManager::getInstance()->rollBack();
 +            throw $e;
 +        }        
          
          $role = $this->getRoleById($newId);
+         
+         $this->resetClassCache();
+         
          return $role;
      }
      
@@@ -321,10 -321,10 +321,10 @@@ abstract class Tinebase_Config_Abstrac
             Tinebase_Core::setupCache();
             $cache = Tinebase_Core::getCache();
          }
 -
 +        
          if (Tinebase_Core::get(Tinebase_Core::SHAREDCACHE)) {
-             if ($cache->test('cachedAppConfig_' . $this->_appName)) {
-                 $this->_cachedApplicationConfig = $cache->load('cachedAppConfig_' . $this->_appName);
+             if ($cachedApplicationConfig = $cache->load('cachedAppConfig_' . $this->_appName)) {
+                 $this->_cachedApplicationConfig = $cachedApplicationConfig;
                  return;
              }
          }
@@@ -389,18 -395,26 +396,29 @@@ class Tinebase_Container extends Tineba
       * @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: ' . $meta['appName'] . ' / account: ' . $accountId . ' / grant:' . implode('', (array)$grant));
 -            . ' 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 
+         if (is_array($grant)) {
+             sort($grant);
+         }
+         
+         $classCacheId = convertCacheId($accountId . $applicationId . implode('', (array)$grant) . (int)$onlyIds . (int)$ignoreACL);
+         
+         if (isset($this->_classCache[__FUNCTION__][$classCacheId])) {
+             return $this->_classCache[__FUNCTION__][$classCacheId];
+         }
+         
          $select = $this->_getSelect($onlyIds ? 'id' : '*')
              ->distinct()
              ->join(array(
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -120,18 -120,16 +127,18 @@@ class Tinebase_Export_Spreadsheet_Ods e
          // build export table (use current table if using template)
          Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Creating export for ' . $this->_modelName . ' . ' . $this->_getDataTableName());
          if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($this->_config->toArray(), TRUE));
-         
-         $spreadSheet = $this->_openDocumentObject->getBody();
+         $this->_spreadSheetObject = $this->_openDocumentObject->getBody();
          
          // append / use existing table
-         if ($spreadSheet->tableExists($this->_getDataTableName()) === true) {
-             $this->_activeTable = $spreadSheet->getTable($this->_getDataTableName());
+         if ($this->_spreadSheetObject->tableExists($this->_getDataTableName()) === true) {
+             $this->_activeTable = $this->_spreadSheetObject->getTable($this->_getDataTableName());
          } else {
-             $this->_activeTable = $spreadSheet->appendTable($this->_getDataTableName());
+             $this->_activeTable = $this->_spreadSheetObject->appendTable($this->_getDataTableName());
          }
          
 +        $this->_setColumnStyles();
 +        
          // add header (disabled at the moment)
          if (isset($this->_config->header) && $this->_config->header) {
              $this->_addHead($this->_activeTable);
          // add record rows
          $i = 0;
          foreach ($_records as $record) {
-             
-             $row = $this->_activeTable->appendRow();
+             $this->processRecord($record, $i);
+             $i++;
+         }
+         
+     }
 -
++    
+     /**
+      * add single body row
+      *
+      * @param $record
+      */
+     public function processRecord($record, $idx)
+     {
 -
+         $row = $this->_activeTable->appendRow();
 -
++        
+         foreach ($this->_config->columns->column as $field) {
 -
 -            //$altStyle = 'ceAlternate';
 -
+             // get type and value for cell
+             $cellType = $this->_getCellType($field->type);
+             $cellValue = $this->_getCellValue($field, $record, $cellType);
  
-             foreach ($this->_config->columns->column as $field) {
-                 // get type and value for cell
-                 $cellType = $this->_getCellType($field->type);
-                 $cellValue = $this->_getCellValue($field, $record, $cellType);
-                 
-                 // create cell with type and value and add style
-                 $cell = $row->appendCell($cellValue, $cellType);
-                 
-                 if ($field->columnStyle) {
-                     $cell->setStyle((string) $field->columnStyle);
-                 }
-                 
-                 // add formula
-                 if ($field->formula) {
-                     $cell->setFormula($field->formula);
-                 }
+             // create cell with type and value and add style
+             $cell = $row->appendCell($cellValue, $cellType);
 -
++            
++            if ($field->columnStyle) {
++                $cell->setStyle((string) $field->columnStyle);
++            }
++            
+             // add formula
+             if ($field->formula) {
+                 $cell->setFormula($field->formula);
              }
-             $i++;
 -
 -            /*
 -            if ($i % 2 == 1) {
 -                $cell->setStyle($altStyle);
 -            }
 -            */
 -
 -            //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($field->toArray(), true));
          }
      }
 -
 +    
      /**
       * add style/width to column
       *
@@@ -1092,9 -1010,38 +1092,38 @@@ class Tinebase_Frontend_Json extends Ti
          $result = $this->_search($filter, $paging, Tinebase_Department::getInstance(), 'Tinebase_Model_DepartmentFilter');
          return $result;
      }
 -
 +    
+     /************************* relation functions ***************************/
 -
++    
+     /**
+      * get all relations of a given record
+      *
+      * @param  string       $_model         own model to get relations for
+      * @param  string       $_id            own id to get relations for
+      * @param  string       $_degree        only return relations of given degree
+      * @param  array        $_type          only return relations of given type
+      * @param  string       $_relatedModel  only return relations having this related model
+      * @return array
+      */
+     public function getRelations($model, $id, $degree = NULL, $type = array(), $relatedModel = NULL)
+     {
+         $relations = Tinebase_Relations::getInstance()->getRelations($model, 'Sql', $id, $degree, $type, false, $relatedModel);
+         // @TODO we still have no converter for relations :-(
+         // -> related records returned here are different to the records returned by the apps itself!
+         // -> this problem also applies to to generic json converter!
+         $relations->setTimezone(Tinebase_Core::get(Tinebase_Core::USERTIMEZONE));
+         $relations->bypassFilters = true;
+         $result = $relations->toArray();
+         return array(
+             'results'       => array_values($result),
+             'totalcount'    => count($result),
+         );
+     }
 -
++    
      /************************ config functions ******************************/
 -
 +    
      /**
       * get config settings for application
       *
Simple merge
@@@ -760,58 -742,42 +749,41 @@@ abstract class Tinebase_Record_Abstrac
       */
      protected function _convertISO8601ToDateTime(array &$_data)
      {
-         foreach(array($this->_datetimeFields, $this->_dateFields) as $dtFields) {
-             foreach ($dtFields as $field) {
-                 if (!isset($_data[$field]) || $_data[$field] instanceof DateTime) continue;
-                 
-                 if (! is_array($_data[$field]) && strpos($_data[$field], ',') !== false) {
-                     $_data[$field] = explode(',', $_data[$field]);
-                 }
-                 
-                 try {
-                     if (is_array($_data[$field])) {
-                         foreach($_data[$field] as $dataKey => $dataValue) {
-                             if ($dataValue instanceof DateTime) continue;
-                             $_data[$field][$dataKey] =  (int)$dataValue == 0 ? NULL : new Tinebase_DateTime($dataValue);
-                         }
-                     } else {
-                         $_data[$field] = (int)$_data[$field] == 0 ? NULL : new Tinebase_DateTime($_data[$field]);
-                         
-                     }
-                 } catch (Tinebase_DateTime_Exception $zde) {
-                     Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Error while converting date field "' . $field . '": ' . $zde->getMessage());
-                     $_data[$field] = NULL;
-                 }
-             }
-         }
-     }
-     
-     /**
-      * Converts custom formated dates into Tinebase_DateTime representation
-      *
-      * @param array &$_data
-      * @param string $_format {@see Tinebase_DateTime}
-      * 
-      * @return void
-      */
-     protected function _convertCustomDateToDateTime(array &$_data, $_format)
-     {
          foreach ($this->_datetimeFields as $field) {
-             if (!isset($_data[$field]) || $_data[$field] instanceof DateTime) continue;
+             if (!isset($_data[$field])) {
+                 continue;
+             }
+             
+             $value = $_data[$field];
              
-             if (strpos($_data[$field], ',') !== false) {
-                 $_data[$field] = explode(',', $_data[$field]);
+             if ($value instanceof DateTime) {
+                 continue;
+             }
+             
+             if (! is_array($value) && strpos($value, ',') !== false) {
+                 $value = explode(',', $value);
              }
              
-             if (is_array($_data[$field])) {
-                 foreach($_data[$field] as $dataKey => $dataValue) {
-                     if ($dataValue instanceof DateTime) continue;
-                     $_data[$field][$dataKey] =  (int)$dataValue == 0 ? NULL : new Tinebase_DateTime($dataValue);
+             try {
+                 if (is_array($value)) {
+                     foreach ($value as $dataKey => $dataValue) {
+                         if ($dataValue instanceof DateTime) {
+                             continue;
+                         }
+                         
+                         $value[$dataKey] =  (int)$dataValue == 0 ? NULL : new Tinebase_DateTime($dataValue);
+                     }
+                 } else {
+                     $value = (int)$value == 0 ? NULL : new Tinebase_DateTime($value);
+                     
                  }
-             } else {
-                 $_data[$field] = (int)$_data[$field] == 0 ? NULL : new Tinebase_DateTime($_data[$field]);
+             } catch (Tinebase_DateTime_Exception $zde) {
+                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Error while converting date field "' . $field . '": ' . $zde->getMessage());
+                 $value = NULL;
              }
+             
+             $_data[$field] = $value;
          }
 -        
      }
      
      /**
Simple merge
Simple merge
Simple merge
Simple merge
          "syncroton/syncroton": "1.*",
          "ezyang/htmlpurifier": "v4.6.0",
          "codeplex/phpexcel": "1.7.8",
 +        "phpword/phpword": "dev-master",
          "sabre/dav": "1.8.*",
          "sabre/vobject": "3.1.3 as 2.1.313",
-         "metaways/opendocument": "dev-master",
-         "metaways/timezoneconvert": "dev-master",
+         "metaways/opendocument": "0.2",
 -        "metaways/timezoneconvert": "0.1"
++        "metaways/timezoneconvert": "0.2",
 +        "zendframework/zend-http": "2.2.8-p3 as 2.2.8"
      },
      "require-dev": {
          "phpunit/phpunit": "3.7.*",
@@@ -4,7 -4,7 +4,7 @@@
          "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
          "This file is @generated automatically"
      ],
-     "hash": "12bf5af0b5e9f44868895d30b7624c21",
 -    "hash": "66b54a656036946c932fe960fed5b35d",
++    "hash": "ea2d9f4f8849c7a892cce2141b896dc0",
      "packages": [
          {
              "name": "codeplex/phpexcel",
          },
          {
              "name": "metaways/timezoneconvert",
-             "version": "dev-master",
 -            "version": "0.1",
++            "version": "0.2",
              "source": {
                  "type": "git",
                  "url": "http://git.tine20.org/git/timezoneconvert",
-                 "reference": "c7030f34909e52786259dd6cd425f835d9e5ce9b"
 -                "reference": "c5815ca927826d1cac32bbaaf2830f7188037145"
++                "reference": "1eba807e6104c80c31a2170cf34923610de9ab23"
              },
              "require": {
                  "php": ">=5.3.0"
                  "Timezones",
                  "UTC"
              ],
-             "time": "2014-10-14 12:43:34"
 -            "time": "2013-08-30 08:04:33"
++            "time": "2014-06-02 12:00:27"
 +        },
 +        {
 +            "name": "phpword/phpword",
 +            "version": "dev-master",
 +            "source": {
 +                "type": "git",
 +                "url": "https://bitbucket.org/kkula/phpword.git",
 +                "reference": "4ba9cb7f65618ec6990ecefa5edc6a992db04429"
 +            },
 +            "dist": {
 +                "type": "zip",
 +                "url": "https://bitbucket.org/kkula/phpword/get/4ba9cb7f65618ec6990ecefa5edc6a992db04429.zip",
 +                "reference": "4ba9cb7f65618ec6990ecefa5edc6a992db04429",
 +                "shasum": ""
 +            },
 +            "require": {
 +                "php": ">5.2.0"
 +            },
 +            "type": "library",
 +            "autoload": {
 +                "psr-0": {
 +                    "PHPWord": "Library"
 +                }
 +            },
 +            "notification-url": "https://packagist.org/downloads/",
 +            "license": [
 +                "GNU"
 +            ],
 +            "description": "PHPWord is a library written in PHP that create word documents.",
 +            "homepage": "http://phpword.codeplex.com",
 +            "keywords": [
 +                "doc",
 +                "docx",
 +                "word"
 +            ],
 +            "time": "2012-12-25 21:55:12"
          },
          {
              "name": "sabre/dav",
          }
      ],
      "minimum-stability": "stable",
 -    "stability-flags": [
 -
 -    ],
 +    "stability-flags": {
-         "phpword/phpword": 20,
-         "metaways/opendocument": 20,
-         "metaways/timezoneconvert": 20
++        "phpword/phpword": 20
 +    },
      "prefer-stable": false,
-     "platform": [],
-     "platform-dev": []
+     "platform": [
+     ],
+     "platform-dev": [
+     ]
  }