/** * 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) { $oldRecord = $this->get($_phone->getId()); $rights = $this->_backend->getPhoneRights($_phone->getId()); $currentAccountId = Tinebase_Core::getUser()->getId(); $hasRight = false; foreach ($rights as $right) { if ($right->account_id == $currentAccountId) { // if user has the right to dial and read the phone, he or she may edit the lines if ($right->dial_right && $right->read_right) { $hasRight = true; } } } if (!$hasRight) { throw new Tinebase_Exception_AccessDenied('You are not allowed to edit this phone!'); } // user is not allowed to add or remove lines $diff = $oldRecord->lines->diff($_phone->lines); if (count($diff->added) > 0 || count($diff->removed) > 0) { throw new Tinebase_Exception_AccessDenied('You are not allowed to add or remove lines of this phone!'); } // user may just edit the lines and settings of the phone $oldRecord->lines = $_phone->lines; $oldRecord->settings = $_phone->settings; return parent::update($oldRecord); }
/** * Checks if number is unique if manual generated * * @param Tinebase_Record_Interface $record * @param Boolean $update true if called un update * @throws Tinebase_Exception_Duplicate * @return boolean */ protected function _checkNumberUniquity($record, $update = FALSE) { $filterArray = array(array('field' => 'number', 'operator' => 'equals', 'value' => $record->{$this->_numberProperty})); if ($update) { $filterArray[] = array('field' => 'id', 'operator' => 'notin', 'value' => $record->getId()); } $filterName = $this->_modelName . 'Filter'; $filter = new $filterName($filterArray); $existing = $this->search($filter); if (count($existing->toArray()) > 0) { $e = new Tinebase_Exception_Duplicate(_('The number you have tried to set is already in use!')); $e->setData($existing); $e->setClientRecord($record); throw $e; } return true; }
/** * @param Tinebase_Record_Interface $record * @param $relation * @return string * * TODO use decorators */ protected function _getShadowPathPart(Tinebase_Record_Interface $record, $relation = null) { $type = $this->_getTypeForPathPart($relation); return $type . '/' . $record->getId(); }
/** * delete linked objects / timesheets * * @param Tinebase_Record_Interface $_record */ protected function _deleteLinkedObjects(Tinebase_Record_Interface $_record) { // delete linked timesheets $timesheets = Timetracker_Controller_Timesheet::getInstance()->getTimesheetsByTimeaccountId($_record->getId()); Timetracker_Controller_Timesheet::getInstance()->delete($timesheets->getArrayOfIds()); // delete other linked objects parent::_deleteLinkedObjects($_record); }
/** * inspect creation of one record (after create) * * @param Tinebase_Record_Interface $_createdRecord * @param Tinebase_Record_Interface $_record * @return void */ protected function _inspectAfterCreate($_createdRecord, Tinebase_Record_Interface $_record) { $this->_setTagRights($_record, $_createdRecord->getId()); Tinebase_Tags::getInstance()->setContexts($_record->contexts, $_createdRecord->getId()); }
/** * get all alarms of given record(s) / adds record_id index to result set * * @param string $_model model to get alarms for * @param string|array|Tinebase_Record_Interface|Tinebase_Record_RecordSet $_recordId record id(s) to get alarms for * @param boolean $_onlyIds * @return Tinebase_Record_RecordSet|array of ids */ public function getAlarmsOfRecord($_model, $_recordId, $_onlyIds = FALSE) { if ($_recordId instanceof Tinebase_Record_RecordSet) { $recordId = $_recordId->getArrayOfIds(); } else { if ($_recordId instanceof Tinebase_Record_Interface) { $recordId = $_recordId->getId(); } else { $recordId = $_recordId; } } //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " model: '$_model' id:" . print_r((array)$recordId, true)); $filter = new Tinebase_Model_AlarmFilter(array(array('field' => 'model', 'operator' => 'equals', 'value' => $_model), array('field' => 'record_id', 'operator' => 'in', 'value' => (array) $recordId))); $result = $this->_backend->search($filter, NULL, $_onlyIds); // NOTE: Adding indices to empty recordsets breaks empty tests if (count($result) > 0 && $result instanceof Tinebase_Record_RecordSet) { $result->addIndices(array('record_id')); } return $result; }
/** * update one record * * NOTE: clients might send their original (creation) data w.o. our adoptions for update * therefore we need reapply them * * @param Calendar_Model_Event $_event * @param bool $_checkBusyConflicts * @return Calendar_Model_Event * @throws Tinebase_Exception_AccessDenied * @throws Tinebase_Exception_Record_Validation */ public function update(Tinebase_Record_Interface $_event, $_checkBusyConflicts = FALSE) { if ($_event->recurid) { throw new Tinebase_Exception_UnexpectedValue('recur event instances must be saved as part of the base event'); } $currentOriginEvent = $this->_eventController->get($_event->getId()); $this->_fromiTIP($_event, $currentOriginEvent); // NOTE: create an update must be handled equally as apple devices do not fetch events after creation. // an update from the creating device would change defaults otherwise // NOTE2: Being organizer without attending is not possible when sync is in use as every update // from a sync device of the organizer adds the organizer as attendee :-( // -> in the sync world this is scenario is called delegation and handled differently // -> it might be consequent to have the same behavior (organizer is always attendee with role chair) // in tine20 in general. This is how Thunderbird handles it as well $_event->assertAttendee($this->getCalendarUser()); $exceptions = $_event->exdate instanceof Tinebase_Record_RecordSet ? $_event->exdate : new Tinebase_Record_RecordSet('Calendar_Model_Event'); $exceptions->addIndices(array('is_deleted')); $currentPersistentExceptions = $_event->rrule ? $this->_eventController->getRecurExceptions($_event, FALSE) : new Tinebase_Record_RecordSet('Calendar_Model_Event'); $newPersistentExceptions = $exceptions->filter('is_deleted', 0); $migration = $this->_getExceptionsMigration($currentPersistentExceptions, $newPersistentExceptions); $this->_eventController->delete($migration['toDelete']->getId()); // NOTE: we need to exclude the toCreate exdates here to not confuse computations in createRecurException! $_event->exdate = array_diff($exceptions->getOriginalDtStart(), $migration['toCreate']->getOriginalDtStart()); $updatedBaseEvent = $this->_eventController->update($_event, $_checkBusyConflicts); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Found ' . count($migration['toCreate']) . ' exceptions to create and ' . count($migration['toUpdate']) . ' to update.'); } foreach ($migration['toCreate'] as $exception) { $exception->assertAttendee($this->getCalendarUser()); $this->_prepareException($updatedBaseEvent, $exception); $this->_eventController->createRecurException($exception, !!$exception->is_deleted); } $updatedExceptions = array(); foreach ($migration['toUpdate'] as $exception) { if (in_array($exception->getId(), $updatedExceptions)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . ' Exdate ' . $exception->getId() . ' already updated'); } continue; } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . ' Update exdate ' . $exception->getId() . ' at ' . $exception->dtstart->toString()); } $exception->assertAttendee($this->getCalendarUser()); $this->_prepareException($updatedBaseEvent, $exception); $this->_addStatusAuthkeyForOwnAttender($exception); // skip concurrency check here by setting the seq of the current record $currentException = $currentPersistentExceptions->getById($exception->getId()); $exception->seq = $currentException->seq; if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Updating exception: ' . print_r($exception->toArray(), TRUE)); } $this->_eventController->update($exception, $_checkBusyConflicts); $updatedExceptions[] = $exception->getId(); } // NOTE: we need to refetch here, otherwise eTag fail's as exception updates change baseEvents seq return $this->get($updatedBaseEvent->getId()); }
/** * inspect creation of one record (after create) * * @param Tinebase_Record_Interface $_createdRecord * @param Tinebase_Record_Interface $_record * @return void * * @todo $_record->contracts should be a Tinebase_Record_RecordSet */ protected function _inspectAfterCreate($_createdRecord, Tinebase_Record_Interface $_record) { if (!$_createdRecord->start_date) { return; } // find contract before, set end_date one day before the new contracts' start_date, if needed $filter = new HumanResources_Model_ContractFilter(array(array('field' => 'start_date', 'operator' => 'before', 'value' => $_createdRecord->start_date))); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'end_date', 'operator' => 'isnull', 'value' => TRUE))); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'id', 'operator' => 'not', 'value' => $_createdRecord->getId()))); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'employee_id', 'operator' => 'equals', 'value' => $_createdRecord->employee_id))); $contracts = $this->search($filter); if ($contracts->count() > 1) { throw new Tinebase_Exception_Data('There are more than 1 contracts before the new one without an end_date. Please terminate them before!'); } // if a contract was found, terminate it if ($contracts->count()) { $contract = $contracts->getFirstRecord(); $endDate = clone $_createdRecord->start_date; $endDate->subDay(1); $contract->end_date = $endDate; $this->update($contract); } }
/** * delete linked objects (notes, relations, ...) of record * * @param Tinebase_Record_Interface $_record */ protected function _deleteLinkedObjects(Tinebase_Record_Interface $_record) { // use textfilter for contract_id $filter = new Sales_Model_ProductAggregateFilter(array()); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $_record->getId()))); Sales_Controller_ProductAggregate::getInstance()->deleteByFilter($filter); parent::_deleteLinkedObjects($_record); }
/** * add default grants * * @param Tinebase_Record_Interface $record * @param $boolean $addDuringSetup -> let admin group have all rights instead of user */ protected function _setDefaultGrants($record, $addDuringSetup = false) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Setting default grants ...'); } $record->grants = new Tinebase_Record_RecordSet($this->_grantsModel); $grant = new $this->_grantsModel(array('account_type' => $addDuringSetup ? Tinebase_Acl_Rights::ACCOUNT_TYPE_GROUP : Tinebase_Acl_Rights::ACCOUNT_TYPE_USER, 'record_id' => $record->getId())); $grant->sanitizeAccountIdAndFillWithAllGrants(); $record->grants->addRecord($grant); }
/** * update one record * * @param Tinebase_Record_Interface $_record * @param bool $_checkBusyConflicts * @param string $range * @return Tinebase_Record_Interface * @throws Tinebase_Exception_AccessDenied * @throws Tinebase_Exception_Record_Validation */ public function update(Tinebase_Record_Interface $_record, $_checkBusyConflicts = FALSE, $range = Calendar_Model_Event::RANGE_THIS) { try { $db = $this->_backend->getAdapter(); $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction($db); $sendNotifications = $this->sendNotifications(FALSE); $event = $this->get($_record->getId()); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Going to update the following event. rawdata: ' . print_r($event->toArray(), true)); } //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} (range: {$range})"); // we need to resolve groupmembers before free/busy checking Calendar_Model_Attender::resolveGroupMembers($_record->attendee); $this->_inspectEvent($_record); if ($_checkBusyConflicts) { if ($event->isRescheduled($_record) || count(array_diff($_record->attendee->user_id, $event->attendee->user_id)) > 0) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Ensure that all attendee are free with free/busy check ... "); } $this->checkBusyConflicts($_record); } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skipping free/busy check because event has not been rescheduled and no new attender has been added"); } } } parent::update($_record); } else { if ($_record->attendee instanceof Tinebase_Record_RecordSet) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " user has no editGrant for event: {$_record->id}, updating attendee status with valid authKey only"); } foreach ($_record->attendee as $attender) { if ($attender->status_authkey) { $this->attenderStatusUpdate($_record, $attender, $attender->status_authkey); } } } } if ($_record->isRecurException() && in_array($range, array(Calendar_Model_Event::RANGE_ALL, Calendar_Model_Event::RANGE_THISANDFUTURE))) { $this->_updateExdateRange($_record, $range, $event); } Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Rolling back because: ' . $e); } Tinebase_TransactionManager::getInstance()->rollBack(); $this->sendNotifications($sendNotifications); throw $e; } $updatedEvent = $this->get($event->getId()); // send notifications $this->sendNotifications($sendNotifications); if ($this->_sendNotifications && $_record->mute != 1) { $this->doSendNotifications($updatedEvent, Tinebase_Core::getUser(), 'changed', $event); } return $updatedEvent; }
/** * 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()); }
/** * get custom fields and add them to $_record->customfields arraay * * @param Tinebase_Record_Interface $_record * @param Tinebase_Record_RecordSet $_customFields * @param Tinebase_Record_RecordSet $_configs */ public function resolveRecordCustomFields(Tinebase_Record_Interface $_record, $_customFields = NULL, $_configs = NULL) { $customFields = $_customFields === NULL ? $this->_getCustomFields($_record->getId()) : $_customFields; if (count($customFields) == 0) { return; } if ($_configs === NULL) { $_configs = $this->getCustomFieldsForApplication(Tinebase_Application::getInstance()->getApplicationByName($_record->getApplication())); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Adding ' . count($customFields) . ' custom fields to record ' . $_record->getId()); } $result = array(); foreach ($customFields as $customField) { $idx = $_configs->getIndexById($customField->customfield_id); if ($idx !== FALSE) { $config = $_configs[$idx]; if (strtolower($config->definition['type']) == 'record') { try { $modelParts = explode('.', $config->definition['recordConfig']['value']['records']); // get model parts from saved record class e.g. Tine.Admin.Model.Group $controllerName = $modelParts[1] . '_Controller_' . $modelParts[3]; $controller = call_user_func(array($controllerName, 'getInstance')); $result[$config->name] = $controller->get($customField->value)->toArray(); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::ERR)) { Tinebase_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . ' Error resolving custom field record: ' . $e->getMessage()); } $result[$config->name] = $customField->value; } } else { $result[$config->name] = $customField->value; } } } $_record->customfields = $result; }
/** * finds overwritten by sickness days overwritten vacation days. * deletes the overwritten vacation day and the vacation itself if days_count = 0 * * @param Tinebase_Record_Interface $_record */ protected function _handleOverwrittenVacation($_record) { $fdController = HumanResources_Controller_FreeDay::getInstance(); $changedFreeTimes = array(); foreach ($_record->freedays as $freeday) { $vacationTimeFilter = new HumanResources_Model_FreeTimeFilter(array(array('field' => 'type', 'operator' => 'equals', 'value' => 'vacation'))); $vacationTimeFilter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'employee_id', 'operator' => 'equals', 'value' => $_record->employee_id))); $vacationTimes = $this->search($vacationTimeFilter); $filter = new HumanResources_Model_FreeDayFilter(array(array('field' => 'date', 'operator' => 'equals', 'value' => $freeday['date']))); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'freetime_id', 'operator' => 'not', 'value' => $_record->getId()))); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'freetime_id', 'operator' => 'in', 'value' => $vacationTimes->id))); $vacationDay = $fdController->search($filter)->getFirstRecord(); if ($vacationDay) { $fdController->delete($vacationDay->getId()); $freeTime = $this->get($vacationDay->freetime_id); if (!isset($changedFreeTimes[$vacationDay->freetime_id])) { $changedFreeTimes[$vacationDay->freetime_id] = $freeTime; } $count = (int) $changedFreeTimes[$vacationDay->freetime_id]->days_count - 1; $changedFreeTimes[$vacationDay->freetime_id]->days_count = $count; } } foreach ($changedFreeTimes as $freeTimeId => $freetime) { if ($freetime->days_count == 0) { $this->delete($freetime->getId()); } else { $freeTime->days_count = $count; $this->update($freetime); } } }
/** * get custom fields and add them to $_record->customfields arraay * * @param Tinebase_Record_Interface $_record * @param Tinebase_Record_RecordSet $_customFields * @param Tinebase_Record_RecordSet $_configs */ public function resolveRecordCustomFields(Tinebase_Record_Interface $_record, $_customFields = NULL, $_configs = NULL) { $customFields = $_customFields === NULL ? $this->_getCustomFields($_record->getId()) : $_customFields; if (count($customFields) == 0) { return; } if ($_configs === NULL) { $_configs = $this->getCustomFieldsForApplication(Tinebase_Application::getInstance()->getApplicationByName($_record->getApplication())); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Adding ' . count($customFields) . ' customfields to record ' . $_record->getId()); } $result = array(); foreach ($customFields as $customField) { $this->_setCfValueInRecord($_record, $customField, $_configs); } }
/** * 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); }
/** * returns an array with differences to the given record * * @param Tinebase_Record_Interface $_record record for comparison * @return array with differences field => different value */ public function diff($_record) { if (!$_record instanceof Tinebase_Record_Abstract) { return $_record; } $diff = array(); foreach (array_keys($this->_validators) as $fieldName) { $ownField = $this->__get($fieldName); $recordField = $_record->{$fieldName}; if (in_array($fieldName, $this->_datetimeFields)) { if ($ownField instanceof DateTime && $recordField instanceof DateTime) { if ($ownField->compare($recordField) === 0) { continue; } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' datetime for field ' . $fieldName . ' is not equal: ' . $ownField->getIso() . ' != ' . $recordField->getIso()); } } } else { if (!$recordField instanceof DateTime && $ownField == $recordField) { continue; } } } else { if ($fieldName == $this->_identifier && $this->getId() == $_record->getId()) { continue; } else { if ($recordField instanceof Tinebase_Record_Abstract || $recordField instanceof Tinebase_Record_RecordSet) { $subdiv = $recordField->diff($ownField); if (!empty($subdiv)) { $diff[$fieldName] = $subdiv; } continue; } else { if ($ownField == $recordField) { continue; } else { if (empty($ownField) && empty($recordField)) { continue; } } } } } $diff[$fieldName] = $recordField; } return $diff; }
/** * inspect creation of one record (after create) * * @param Tinebase_Record_Interface $_createdRecord * @param Tinebase_Record_Interface $_record * @return void */ protected function _inspectAfterCreate($_createdRecord, Tinebase_Record_Interface $_record) { // set as default account if it is the only account $accountCount = $this->searchCount(new Felamimail_Model_AccountFilter(array())); if ($accountCount == 1) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Set account ' . $_createdRecord->name . ' as new default email account.'); } Tinebase_Core::getPreference($this->_applicationName)->{Felamimail_Preference::DEFAULTACCOUNT} = $_createdRecord->getId(); } }
/** * merge given record into $this * * @param Tinebase_Record_Interface $record * @param Tinebase_Record_Diff $diff * @return Tinebase_Record_Interface */ public function merge($record, $diff = null) { if (!$this->getId()) { $this->setId($record->getId()); } if ($diff === null) { $diff = $this->diff($record); } if ($diff === null || empty($diff->diff)) { return $this; } foreach ($diff->diff as $field => $value) { if (empty($this->{$field})) { $this->{$field} = $value; } } return $this; }
/** * update foreign key values * * @param string $_mode create|update * @param Tinebase_Record_Interface $_record */ protected function _updateForeignKeys($_mode, Tinebase_Record_Interface $_record) { if (!empty($this->_foreignTables)) { foreach ($this->_foreignTables as $modelName => $join) { if (!(isset($join['field']) || array_key_exists('field', $join))) { continue; } $idsToAdd = array(); $idsToRemove = array(); if (!empty($_record->{$modelName})) { $idsToAdd = Tinebase_Record_RecordSet::getIdsFromMixed($_record->{$modelName}); } $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb()); if ($_mode == 'update') { $select = $this->_db->select(); $select->from(array($join['table'] => $this->_tablePrefix . $join['table']), array($join['field']))->where($this->_db->quoteIdentifier($join['table'] . '.' . $join['joinOn']) . ' = ?', $_record->getId()); Tinebase_Backend_Sql_Abstract::traitGroup($select); $stmt = $this->_db->query($select); $currentIds = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); $stmt->closeCursor(); $idsToRemove = array_diff($currentIds, $idsToAdd); $idsToAdd = array_diff($idsToAdd, $currentIds); } if (!empty($idsToRemove)) { $where = '(' . $this->_db->quoteInto($this->_db->quoteIdentifier($this->_tablePrefix . $join['table'] . '.' . $join['joinOn']) . ' = ?', $_record->getId()) . ' AND ' . $this->_db->quoteInto($this->_db->quoteIdentifier($this->_tablePrefix . $join['table'] . '.' . $join['field']) . ' IN (?)', $idsToRemove) . ')'; $this->_db->delete($this->_tablePrefix . $join['table'], $where); } foreach ($idsToAdd as $id) { $recordArray = array($join['joinOn'] => $_record->getId(), $join['field'] => $id); $this->_db->insert($this->_tablePrefix . $join['table'], $recordArray); } Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId); } } }
/** * delete linked objects (notes, relations, ...) of record * * @param Tinebase_Record_Interface $_record */ protected function _deleteLinkedObjects(Tinebase_Record_Interface $_record) { // delete notes & relations if ($_record->has('notes')) { Tinebase_Notes::getInstance()->deleteNotesOfRecord($this->_modelName, $this->_backend->getType(), $_record->getId()); } if ($_record->has('relations')) { $relations = Tinebase_Relations::getInstance()->getRelations($this->_modelName, $this->_backend->getType(), $_record->getId()); if (!empty($relations)) { // remove relations Tinebase_Relations::getInstance()->setRelations($this->_modelName, $this->_backend->getType(), $_record->getId(), array()); // remove related objects if (!empty($this->_relatedObjectsToDelete)) { foreach ($relations as $relation) { if (in_array($relation->related_model, $this->_relatedObjectsToDelete)) { list($appName, $i, $itemName) = explode('_', $relation->related_model); $appController = Tinebase_Core::getApplicationInstance($appName, $itemName); $appController->delete($relation->related_id); } } } } } }
/** * returns all observers of a given observable and event * * @param Tinebase_Record_Interface $_observable * @param string _event * @return Tinebase_Record_RecordSet */ protected function getObserversByEvent($_observable, $_event) { if (!$_observer->getApplication() || !$_observer->getId()) { throw new Tinebase_Exception_Record_DefinitionFailure(); } $where = array($this->_db->quoteIdentifier('observable_application') . ' =' . $_observable->getApplication(), $this->_db->quoteIdentifier('observable_identifier') . ' =' . $_observable->getId(), $this->_db->quoteIdentifier('observed_event') . ' =' . $this->_db->getAdapter()->quote($_event)); return new Tinebase_Record_RecordSet('Tinebase_Model_PersistentObserver', $this->_db->fetchAll($where), true); }
/** * returns the value of a matrix field * * @param Zend_Config $field * @param Tinebase_Record_Interface $record * @throws Tinebase_Exception_Data * @return number */ protected function _getMatrixCellValue($field, $record) { $result = 0; switch ($field->type) { case 'tags': if (!isset($this->_matrixCache[$field->identifier])) { $this->_matrixCache[$field->identifier] = array(); } if (!isset($this->_matrixCache[$field->identifier][$record->getId()])) { // clear cache, its not needed anymore (could have been filled by the previous record) $this->_matrixCache[$field->identifier] = array(); $this->_matrixCache[$field->identifier][$record->getId()] = Tinebase_Tags::getInstance()->getTagsOfRecord($record); } $result = $this->_matrixCache[$field->identifier][$record->getId()]->filter('name', $field->identifier)->count(); break; default: throw new Tinebase_Exception_Data('Other types than tags are not supported at the moment.'); } return $result; }
/** * (non-PHPdoc) * @see Tinebase_Controller_Record_Abstract::update() */ public function update(Tinebase_Record_Interface $_record) { if (!$this->_checkACLContainer($this->_backend->getNodeContainer($_record->getId()), 'update')) { throw new Tinebase_Exception_AccessDenied('No permission to update nodes.'); } return parent::update($_record); }
/** * inspect update of one record * * @param Tinebase_Record_Interface $_record the update record * @param Tinebase_Record_Interface $_oldRecord the current persistent record * @return void */ protected function _inspectUpdate($_record, $_oldRecord) { if ($_record->__get('order_id')) { $order = $_record->getForeignRecord('order_id', Billing_Controller_Order::getInstance()); if ($order->__get('payment_state') != $_record->__get('payment_state')) { $order->__set('payment_state', $_record->__get('payment_state')); Billing_Controller_Order::getInstance()->update($order); } } $openItem = null; if ($_record->__get('payment_state') == 'PAYED') { try { $openItem = Billing_Controller_OpenItem::getInstance()->getByReceiptId($_record->getId()); if ($openItem->__get('state') != 'DONE') { $openItem->__set('state', 'DONE'); $openItem->__set('open_sum', 0); $openItem->__set('payed_sum', $_record->__get('total_brutto')); $openItem->__set('payment_method_id', $_record->getForeignId('payment_method_id')); } } catch (Exception $e) { // silent failure, as open item might not exist already } } if ($_record->isCancelled()) { if (is_null($openItem)) { $openItem = Billing_Controller_OpenItem::getInstance()->getByReceiptId($_record->getId()); } $openItem->__set('is_cancelled', true); $reversionReceiptId = $_record->getForeignId('reversion_record_id'); try { $reversionOpenItem = Billing_Controller_OpenItem::getInstance()->getByReceiptId($reversionReceiptId); $openItem->__set('open_sum', $openItem->__get('total_brutto') + $reversionOpenItem->__get('total_brutto')); $openItem->__set('payed_sum', -1 * $reversionOpenItem->__get('payed_sum')); $openItem->__set('reversion_record_id', $reversionOpenItem->getId()); } catch (Exception $e) { //failure OK: open item for reversion record might not already exist // will be set in on of the next update calls, as soon, the open item exists. } } if (!$_record->getForeignIdBreakNull('payment_method_id')) { $_record->__set('payment_method_id', 'BANKTRANSFER'); } if ($openItem) { if (!$openItem->getForeignIdBreakNull('payment_method_id')) { $openItem->__set('payment_method_id', 'BANKTRANSFER'); } Billing_Controller_OpenItem::getInstance()->update($openItem); } }
/** * get special field value * * @param Tinebase_Record_Interface $_record * @param array $_param * @param string $_key * @param string $_cellType * @return string */ protected function _getSpecialFieldValue(Tinebase_Record_Interface $_record, $_param, $_key = NULL, &$_cellType = NULL) { $customerId = $_record->getId(); if (!isset($this->_customerAddresses[$customerId])) { $all = $this->_addresses->filter('customer_id', $customerId); $this->_addresses->removeRecords($all); $this->_customerAddresses[$customerId] = array('postal' => $all->filter('type', 'postal')->getFirstRecord(), 'billing' => array('records' => $all->filter('type', 'billing'), 'index' => 0), 'delivery' => array('records' => $all->filter('type', 'delivery'), 'index' => 0)); } switch ($_param['type']) { case 'postal': $address = $this->_customerAddresses[$customerId]['postal']; break; case 'address': return $this->_contacts->filter('id', $_record->{$_param['identifier']})->getFirstRecord()->n_fn; default: if (isset($this->_customerAddresses[$customerId][$_param['type']]['records'])) { $address = $this->_customerAddresses[$customerId][$_param['type']]['records']->getByIndex($this->_customerAddresses[$customerId][$_param['type']]['index']); $this->_customerAddresses[$customerId][$_param['type']]['index']++; } } return $address ? $this->_renderAddress($address, $_param['type']) : ''; }
/** * set relations / tags / alarms * * @param Tinebase_Record_Interface $updatedRecord the just updated record * @param Tinebase_Record_Interface $record the update record * @param Tinebase_Record_Interface $currentRecord the original record if one exists * @param boolean $returnUpdatedRelatedData * @return Tinebase_Record_Interface */ protected function _setRelatedData(Tinebase_Record_Interface $updatedRecord, Tinebase_Record_Interface $record, Tinebase_Record_Interface $currentRecord = null, $returnUpdatedRelatedData = FALSE) { /** @var Addressbook_Model_List $record */ if (isset($record->memberroles)) { // get migration // TODO add generic helper fn for this? $memberrolesToSet = !$record->memberroles instanceof Tinebase_Record_RecordSet ? new Tinebase_Record_RecordSet('Addressbook_Model_ListMemberRole', $record->memberroles, true) : $record->memberroles; foreach ($memberrolesToSet as $memberrole) { foreach (array('contact_id', 'list_role_id', 'list_id') as $field) { if (isset($memberrole[$field]['id'])) { $memberrole[$field] = $memberrole[$field]['id']; } } } $currentMemberroles = $this->_getMemberRoles($record); $diff = $currentMemberroles->diff($memberrolesToSet); if (count($diff['added']) > 0) { $diff['added']->list_id = $updatedRecord->getId(); foreach ($diff['added'] as $memberrole) { $this->_getMemberRolesBackend()->create($memberrole); } } if (count($diff['removed']) > 0) { $this->_getMemberRolesBackend()->delete($diff['removed']->getArrayOfIds()); } } $result = parent::_setRelatedData($updatedRecord, $record, $currentRecord, $returnUpdatedRelatedData); return $result; }
/** * getPathsForRecords * * @param Tinebase_Record_Interface|Tinebase_Record_RecordSet $records * @return Tinebase_Record_RecordSet * @throws Tinebase_Exception_NotFound */ public function getPathsForRecords($records) { $ids = $records instanceof Tinebase_Record_Interface ? array($records->getId()) : $records->getArrayOfIds(); return $this->search(new Tinebase_Model_PathFilter(array(array('field' => 'record_id', 'operator' => 'in', 'value' => $ids)))); }
/** * 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()); }