/**
  * updates dependent records on update the parent record
  *
  * @param Tinebase_Record_Interface $_record
  * @param Tinebase_Record_Interface $_oldRecord
  * @param string $_property
  * @param array $_fieldConfig
  */
 protected function _updateDependentRecords(Tinebase_Record_Interface $_record, Tinebase_Record_Interface $_oldRecord, $_property, $_fieldConfig)
 {
     if (!(isset($_fieldConfig['dependentRecords']) || array_key_exists('dependentRecords', $_fieldConfig)) || !$_fieldConfig['dependentRecords']) {
         return;
     }
     if (!isset($_fieldConfig['refIdField'])) {
         throw new Tinebase_Exception_Record_DefinitionFailure('If a record is dependent, a refIdField has to be defined!');
     }
     // don't handle dependent records on property if it is set to null or doesn't exist.
     if ($_record->{$_property} === NULL || !$_record->has($_property)) {
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Skip updating dependent records (got NULL) on property ' . $_property . ' for ' . $this->_applicationName . ' ' . $this->_modelName . ' with id = "' . $_record->getId() . '"');
         }
         return;
     }
     $ccn = $_fieldConfig['controllerClassName'];
     $controller = $ccn::getInstance();
     $recordClassName = $_fieldConfig['recordClassName'];
     $filterClassName = $_fieldConfig['filterClassName'];
     $existing = new Tinebase_Record_RecordSet($recordClassName);
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_record->{$_property}, TRUE));
     }
     if (!empty($_record->{$_property}) && $_record->{$_property}) {
         // legacy - should be already done in frontend json - remove if all record properties are record sets before getting to controller
         if (is_array($_record->{$_property})) {
             $rs = new Tinebase_Record_RecordSet($recordClassName);
             foreach ($_record->{$_property} as $recordArray) {
                 $rec = new $recordClassName(array(), true);
                 $rec->setFromJsonInUsersTimezone($recordArray);
                 $rs->addRecord($rec);
             }
             $_record->{$_property} = $rs;
         }
         $idProperty = $_record->{$_property}->getFirstRecord()->getIdProperty();
         // legacy end
         $oldFilter = new $filterClassName(array(array('field' => $idProperty, 'operator' => 'in', 'value' => $_record->{$_property}->getId())));
         $oldRecords = $controller->search($oldFilter);
         foreach ($_record->{$_property} as $record) {
             $record->{$_fieldConfig['refIdField']} = $_record->getId();
             // update record if ID exists and has a length of 40 (it has a length of 10 if it is a timestamp)
             if ($record->getId() && strlen($record->getId()) == 40) {
                 // do not try to update if the record hasn't changed
                 $oldRecord = $oldRecords->getById($record->getId());
                 if ($oldRecord && !empty($oldRecord->diff($record)->diff)) {
                     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Updating dependent record with id = "' . $record->getId() . '" on property ' . $_property . ' for ' . $this->_applicationName . ' ' . $this->_modelName);
                     }
                     $existing->addRecord($controller->update($record));
                 } else {
                     $existing->addRecord($record);
                 }
                 // create if is not existing already
             } else {
                 // try to find if it already exists (with corrupted id)
                 if ($record->getId() == NULL) {
                     $crc = $controller->create($record);
                     $existing->addRecord($crc);
                     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Creating dependent record with id = "' . $crc->getId() . '" on property ' . $_property . ' for ' . $this->_applicationName . ' ' . $this->_modelName);
                     }
                 } else {
                     try {
                         $prevRecord = $controller->get($record->getId());
                         if (!empty($prevRecord->diff($record)->diff)) {
                             $existing->addRecord($controller->update($record));
                         } else {
                             $existing->addRecord($record);
                         }
                     } catch (Tinebase_Exception_NotFound $e) {
                         $record->id = NULL;
                         $crc = $controller->create($record);
                         $existing->addRecord($crc);
                         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Creating dependent record with id = "' . $crc->getId() . '" on property ' . $_property . ' for ' . $this->_applicationName . ' ' . $this->_modelName);
                         }
                     }
                 }
             }
         }
     }
     $filter = new $filterClassName(isset($_fieldConfig['addFilters']) ? $_fieldConfig['addFilters'] : array(), 'AND');
     $filter->addFilter(new Tinebase_Model_Filter_Text($_fieldConfig['refIdField'], 'equals', $_record->getId()));
     // an empty array will remove all records on this property
     if (!empty($_record->{$_property})) {
         $filter->addFilter(new Tinebase_Model_Filter_Id('id', 'notin', $existing->getId()));
     }
     $deleteIds = $controller->search($filter, NULL, FALSE, TRUE);
     if (!empty($deleteIds)) {
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Deleting dependent records with id = "' . print_r($deleteIds, 1) . '" on property ' . $_property . ' for ' . $this->_applicationName . ' ' . $this->_modelName);
         }
         $controller->delete($deleteIds);
     }
     $_record->{$_property} = $existing->toArray();
 }
 /**
  * delete linked objects (notes, relations, ...) of record
  *
  * @param Tinebase_Record_Interface $_record
  */
 protected function _deleteLinkedObjects(Tinebase_Record_Interface $_record)
 {
     // use textfilter for employee_id
     $eFilter = new Tinebase_Model_Filter_Text(array('field' => 'employee_id', 'operator' => 'equals', 'value' => $_record->getId()));
     // delete free times
     $filter = new HumanResources_Model_FreeTimeFilter(array(), 'AND');
     $filter->addFilter($eFilter);
     HumanResources_Controller_FreeTime::getInstance()->deleteByFilter($filter);
     // delete contracts
     $filter = new HumanResources_Model_ContractFilter(array(), 'AND');
     $filter->addFilter($eFilter);
     HumanResources_Controller_Contract::getInstance()->deleteByFilter($filter);
     // delete costcenters
     if ($_record->has('costcenters')) {
         $filter = new HumanResources_Model_CostCenterFilter(array(), 'AND');
         $filter->addFilter($eFilter);
         HumanResources_Controller_CostCenter::getInstance()->deleteByFilter($filter);
     }
     // delete accounts
     $filter = new HumanResources_Model_AccountFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'employee_id', 'operator' => 'equals', 'value' => $_record->getId())));
     HumanResources_Controller_Account::getInstance()->deleteByFilter($filter);
     parent::_deleteLinkedObjects($_record);
 }
 /**
  * update one phone
  *
  * @param Voipmanager_Model_Snom_Phone $_phone
  * @return Voipmanager_Model_Snom_Phone
  * @throws Voipmanager_Exception_Validation
  * 
  * @todo do not overwrite update() -> use inspectBefore/After functions
  */
 public function update(Tinebase_Record_Interface $_phone)
 {
     // check first if mac address is already used
     if ($_phone->has('macaddress')) {
         try {
             $phoneWithMac = $this->getByMacAddress($_phone->macaddress);
             if ($phoneWithMac->getId() !== $_phone->getId()) {
                 throw new Voipmanager_Exception_Validation('A phone with this mac address already exists.');
             }
         } catch (Voipmanager_Exception_NotFound $venf) {
             // everything ok
         }
     }
     try {
         $db = $this->_backend->getAdapter();
         $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction($db);
         $phone = $this->_backend->update($_phone);
         $_phoneSettings = $_phone->settings;
         if ($_phoneSettings instanceof Voipmanager_Model_Snom_PhoneSettings) {
             // force the right phone_id
             $_phoneSettings->setId($phone->getId());
             // set all settings which are equal to the default settings to NULL
             $template = Voipmanager_Controller_Snom_Template::getInstance()->get($phone->template_id);
             $settingDefaults = Voipmanager_Controller_Snom_Setting::getInstance()->get($template->setting_id);
             foreach ($_phoneSettings->toArray() as $key => $value) {
                 if ($key == 'phone_id') {
                     continue;
                 }
                 if ($settingDefaults->{$key} == $value) {
                     $_phoneSettings->{$key} = NULL;
                 }
             }
             if (Voipmanager_Controller_Snom_PhoneSettings::getInstance()->get($phone->getId())) {
                 $phoneSettings = Voipmanager_Controller_Snom_PhoneSettings::getInstance()->update($_phoneSettings);
             } else {
                 $phoneSettings = Voipmanager_Controller_Snom_PhoneSettings::getInstance()->create($_phoneSettings);
             }
         }
         Voipmanager_Controller_Snom_Line::getInstance()->deletePhoneLines($phone->getId());
         $this->_createLines($phone, $_phone->lines);
         // save phone rights
         if (isset($_phone->rights)) {
             $this->_backend->setPhoneRights($_phone);
         }
         Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId);
     } catch (Exception $e) {
         $this->_handleRecordCreateOrUpdateException($e);
     }
     return $this->get($phone->getId());
 }
Exemple #4
0
 /**
  * check grant for action (CRUD)
  *
  * @param Tinebase_Record_Interface $_record
  * @param string $_action
  * @param boolean $_throw
  * @param string $_errorMessage
  * @param Tinebase_Record_Interface $_oldRecord
  * @return boolean
  * @throws Tinebase_Exception_AccessDenied
  *
  * @todo use this function in other create + update functions
  * @todo invent concept for simple adding of grants (plugins?)
  */
 protected function _checkGrant($_record, $_action, $_throw = TRUE, $_errorMessage = 'No Permission.', $_oldRecord = NULL)
 {
     if (!$this->_doContainerACLChecks || !$_record->has('container_id') || $this->_currentAccount->hasGrant($_record->container_id, Tinebase_Model_Grants::GRANT_ADMIN)) {
         return TRUE;
     }
     $hasGrant = FALSE;
     switch ($_action) {
         case 'get':
             $hasGrant = $this->_currentAccount->hasGrant($_record->container_id, Tinebase_Model_Grants::GRANT_READ);
             break;
         case 'create':
             $hasGrant = $this->_currentAccount->hasGrant($_record->container_id, Tinebase_Model_Grants::GRANT_ADD);
             break;
         case 'update':
             $hasGrant = $this->_currentAccount->hasGrant($_record->container_id, Tinebase_Model_Grants::GRANT_EDIT);
             break;
         case 'delete':
             $container = Tinebase_Container::getInstance()->getContainerById($_record->container_id);
             $hasGrant = $this->_currentAccount->hasGrant($_record->container_id, Tinebase_Model_Grants::GRANT_DELETE);
             break;
     }
     if (!$hasGrant) {
         if ($_throw) {
             throw new Tinebase_Exception_AccessDenied($_errorMessage);
         } else {
             Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' No permissions to ' . $_action . ' in container ' . $_record->container_id);
         }
     }
     return $hasGrant;
 }
Exemple #5
0
 /**
  * update one phone
  *
  * @param Voipmanager_Model_Snom_Phone $_phone
  * @param Voipmanager_Model_Snom_PhoneSettings|optional $_phoneSettings
  * @return Voipmanager_Model_Snom_Phone
  * @throws Voipmanager_Exception_Validation
  */
 public function update(Tinebase_Record_Interface $_phone)
 {
     //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_phone->toArray(), true));
     // check first if mac address is already used
     if ($_phone->has('macaddress')) {
         try {
             $phoneWithMac = $this->getByMacAddress($_phone->macaddress);
             if ($phoneWithMac->getId() !== $_phone->getId()) {
                 throw new Voipmanager_Exception_Validation('A phone with this mac address already exists.');
             }
         } catch (Voipmanager_Exception_NotFound $venf) {
             // everything ok
         }
     }
     $phone = $this->_backend->update($_phone);
     $_phoneSettings = $_phone->settings;
     if ($_phoneSettings instanceof Voipmanager_Model_Snom_PhoneSettings) {
         // force the right phone_id
         $_phoneSettings->setId($phone->getId());
         // set all settings which are equal to the default settings to NULL
         $template = Voipmanager_Controller_Snom_Template::getInstance()->get($phone->template_id);
         $settingDefaults = Voipmanager_Controller_Snom_Setting::getInstance()->get($template->setting_id);
         foreach ($_phoneSettings->toArray() as $key => $value) {
             if ($key == 'phone_id') {
                 continue;
             }
             if ($settingDefaults->{$key} == $value) {
                 $_phoneSettings->{$key} = NULL;
             }
         }
         if (Voipmanager_Controller_Snom_PhoneSettings::getInstance()->get($phone->getId())) {
             //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_phoneSettings->toArray(), true));
             $phoneSettings = Voipmanager_Controller_Snom_PhoneSettings::getInstance()->update($_phoneSettings);
         } else {
             $phoneSettings = Voipmanager_Controller_Snom_PhoneSettings::getInstance()->create($_phoneSettings);
         }
     }
     Voipmanager_Controller_Snom_Line::getInstance()->deletePhoneLines($phone->getId());
     $this->_createLines($phone, $_phone->lines);
     // save phone rights
     if (isset($_phone->rights)) {
         $this->_backend->setPhoneRights($_phone);
     }
     return $this->get($phone->getId());
 }
 /**
  * sets record modification data and protects it from spoofing
  * 
  * @param   Tinebase_Record_Interface $_newRecord record from user data
  * @param   string                    $_action    one of {create|update|delete}
  * @param   Tinebase_Record_Interface $_curRecord record from storage
  * @throws  Tinebase_Exception_InvalidArgument
  */
 public static function setRecordMetaData($_newRecord, $_action, $_curRecord = NULL)
 {
     // disable validation as this is slow and we are setting valid data here
     $bypassFilters = $_newRecord->bypassFilters;
     $_newRecord->bypassFilters = TRUE;
     list($currentAccountId, $currentTime) = self::getCurrentAccountIdAndTime();
     // spoofing protection
     $_newRecord->created_by = $_curRecord ? $_curRecord->created_by : NULL;
     $_newRecord->creation_time = $_curRecord ? $_curRecord->creation_time : NULL;
     $_newRecord->last_modified_by = $_curRecord ? $_curRecord->last_modified_by : NULL;
     $_newRecord->last_modified_time = $_curRecord ? $_curRecord->last_modified_time : NULL;
     if ($_newRecord->has('is_deleted')) {
         $_newRecord->is_deleted = $_curRecord ? $_curRecord->is_deleted : 0;
         $_newRecord->deleted_time = $_curRecord ? $_curRecord->deleted_time : NULL;
         $_newRecord->deleted_by = $_curRecord ? $_curRecord->deleted_by : NULL;
     }
     switch ($_action) {
         case 'create':
             $_newRecord->created_by = $currentAccountId;
             $_newRecord->creation_time = $currentTime;
             if ($_newRecord->has('seq')) {
                 $_newRecord->seq = 1;
             }
             break;
         case 'update':
             $_newRecord->last_modified_by = $currentAccountId;
             $_newRecord->last_modified_time = $currentTime;
             self::increaseRecordSequence($_newRecord, $_curRecord);
             break;
         case 'delete':
             $_newRecord->deleted_by = $currentAccountId;
             $_newRecord->deleted_time = $currentTime;
             $_newRecord->is_deleted = true;
             self::increaseRecordSequence($_newRecord, $_curRecord);
             break;
         default:
             throw new Tinebase_Exception_InvalidArgument('Action must be one of {create|update|delete}.');
             break;
     }
     $_newRecord->bypassFilters = $bypassFilters;
 }
 /**
  * merges changes made to local storage on concurrent updates into the new record 
  *
  * @param string $applicationId
  * @param  Tinebase_Record_Interface $newRecord record from user data
  * @param  Tinebase_Record_Interface $curRecord record from storage
  * @return Tinebase_Record_RecordSet with resolved concurrent updates (Tinebase_Model_ModificationLog records)
  * @throws Tinebase_Timemachine_Exception_ConcurrencyConflict
  */
 public function manageConcurrentUpdates($applicationId, Tinebase_Record_Interface $newRecord, Tinebase_Record_Interface $curRecord)
 {
     if (!$newRecord->has('seq')) {
         return $this->manageConcurrentUpdatesByTimestamp($newRecord, $curRecord, get_class($newRecord), 'Sql', $newRecord->getId());
     }
     $this->_applicationId = $applicationId;
     $resolved = new Tinebase_Record_RecordSet('Tinebase_Model_ModificationLog');
     if ($curRecord->seq != $newRecord->seq) {
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Concurrent updates: current record last updated '" . ($curRecord->last_modified_time instanceof DateTime ? $curRecord->last_modified_time : 'unknown') . "' where record to be updated was last updated '" . ($newRecord->last_modified_time instanceof DateTime ? $newRecord->last_modified_time : ($curRecord->creation_time instanceof DateTime ? $curRecord->creation_time : 'unknown')) . "' / current sequence: " . $curRecord->seq . " - new record sequence: " . $newRecord->seq);
         }
         $loggedMods = $this->getModificationsBySeq($applicationId, $newRecord, $curRecord->seq);
         // effective modifications made to the record after current user got his record
         $diffs = $this->computeDiff($loggedMods);
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " During the concurrent update, the following changes have been made: " . print_r($diffs->toArray(), true));
         }
         $this->_resolveDiffs($resolved, $diffs, $newRecord);
     } else {
         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
             Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " No concurrent updates.");
         }
     }
     return $resolved;
 }