protected function _removeFixtures() { if ($this->_customerRecords) { Sales_Controller_Customer::getInstance()->delete($this->_customerRecords->getId()); } if ($this->_contactRecords) { $this->_contactController->delete($this->_contactRecords->getId()); } if ($this->_addressRecords) { $this->_addressController->delete($this->_addressRecords->getId()); } if ($this->_contractRecords) { Sales_Controller_Contract::getInstance()->delete($this->_contractRecords->getId()); } $paController = Sales_Controller_ProductAggregate::getInstance(); $paController->deleteByFilter(new Sales_Model_ProductAggregateFilter(array())); $this->_invoiceController = Sales_Controller_Invoice::getInstance(); $this->_invoiceController->deleteByFilter(new Sales_Model_InvoiceFilter(array())); }
/** * 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)))); }
/** * 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; }
/** * merges source contracts into the target contract (relations and products) * * @param Sales_Model_Contract $targetContract * @param Tinebase_Record_RecordSet $sourceContracts */ public function mergeContracts(Sales_Model_Contract $targetContract, Tinebase_Record_RecordSet $sourceContracts) { // handle relations (duplicates get skipped) foreach ($sourceContracts as $sourceContract) { Tinebase_Relations::getInstance()->transferRelations($sourceContract->getId(), $targetContract->getId(), 'Sales_Model_Contract'); } // handle products $filter = new Sales_Model_ProductAggregateFilter(array()); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'in', 'value' => $sourceContracts->getId()))); $products = Sales_Controller_ProductAggregate::getInstance()->search($filter); foreach ($products as $product) { $product->contract_id = $targetContract->getId(); Sales_Controller_ProductAggregate::getInstance()->update($product); } return true; }
/** * 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(); }
/** * Gets the phone id filter for the first record in the given recordset * * @param Tinebase_Record_RecordSet $userPhones * @return Tinebase_Model_Filter_Abstract */ protected function _getDefaultPhoneFilter($userPhones) { if ($userPhones->count()) { $filter = new Phone_Model_CallFilter(array('id' => 'defaultAdded', 'field' => 'phone_id', 'operator' => 'AND', 'value' => array(array('field' => ':id', 'operator' => 'in', 'value' => $userPhones->getId())))); } else { $filter = new Tinebase_Model_Filter_Text(array('id' => 'defaultAdded', 'field' => 'id', 'operator' => 'equals', 'value' => 'notexists')); } return $filter; }
/** * creates an exception instance of a recurring event * * NOTE: deleting persistent exceptions is done via a normal delete action * and handled in the deleteInspection * * @param Calendar_Model_Event $_event * @param bool $_deleteInstance * @param bool $_allFollowing * @param bool $_checkBusyConflicts * @return Calendar_Model_Event exception Event | updated baseEvent * * @todo replace $_allFollowing param with $range * @deprecated replace with create/update/delete */ public function createRecurException($_event, $_deleteInstance = FALSE, $_allFollowing = FALSE, $_checkBusyConflicts = FALSE) { $baseEvent = $this->getRecurBaseEvent($_event); if ($baseEvent->last_modified_time != $_event->last_modified_time) { if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " It is not allowed to create recur instance if it is clone of base event"); } throw new Tinebase_Timemachine_Exception_ConcurrencyConflict('concurrency conflict!'); } // // Maybe Later // // exdates needs to stay in baseEvents container // if ($_event->container_id != $baseEvent->container_id) { // throw new Calendar_Exception_ExdateContainer(); // } // check if this is an exception to the first occurence if ($baseEvent->getId() == $_event->getId()) { if ($_allFollowing) { throw new Exception('please edit or delete complete series!'); } // NOTE: if the baseEvent gets a time change, we can't compute the recurdid w.o. knowing the original dtstart $recurid = $baseEvent->setRecurId($baseEvent->getId()); unset($baseEvent->recurid); $_event->recurid = $recurid; } // just do attender status update if user has no edit grant if ($this->_doContainerACLChecks && !$baseEvent->{Tinebase_Model_Grants::GRANT_EDIT}) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " user has no editGrant for event: '{$baseEvent->getId()}'. Only creating exception for attendee status"); } if ($_event->attendee instanceof Tinebase_Record_RecordSet) { foreach ($_event->attendee as $attender) { if ($attender->status_authkey) { $exceptionAttender = $this->attenderStatusCreateRecurException($_event, $attender, $attender->status_authkey, $_allFollowing); } } } if (!isset($exceptionAttender)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG) && $_event->attendee instanceof Tinebase_Record_RecordSet) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Failed to update attendee: " . print_r($_event->attendee->toArray(), true)); } throw new Tinebase_Exception_AccessDenied('Failed to update attendee, status authkey might be missing'); } return $this->get($exceptionAttender->cal_event_id); } // NOTE: recurid is computed by rrule recur computations and therefore is already part of the event. if (empty($_event->recurid)) { throw new Exception('recurid must be present to create exceptions!'); } // we do notifications ourself $sendNotifications = $this->sendNotifications(FALSE); // EDIT for baseEvent is checked above, CREATE, DELETE for recur exceptions is implied with it $doContainerACLChecks = $this->doContainerACLChecks(FALSE); $db = $this->_backend->getAdapter(); $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction($db); $exdate = new Tinebase_DateTime(substr($_event->recurid, -19)); $exdates = is_array($baseEvent->exdate) ? $baseEvent->exdate : array(); $originalDtstart = $_event->getOriginalDtStart(); $originalEvent = Calendar_Model_Rrule::computeNextOccurrence($baseEvent, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $originalDtstart); if ($_allFollowing != TRUE) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Adding exdate for: '{$_event->recurid}'"); } array_push($exdates, $exdate); $baseEvent->exdate = $exdates; $updatedBaseEvent = $this->update($baseEvent, FALSE); if ($_deleteInstance == FALSE) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Creating persistent exception for: '{$_event->recurid}'"); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " Recur exception: " . print_r($_event->toArray(), TRUE)); } $_event->base_event_id = $baseEvent->getId(); $_event->setId(NULL); unset($_event->rrule); unset($_event->exdate); foreach (array('attendee', 'notes', 'alarms') as $prop) { if ($_event->{$prop} instanceof Tinebase_Record_RecordSet) { $_event->{$prop}->setId(NULL); } } $originalDtstart = $_event->getOriginalDtStart(); $dtStartHasDiff = $originalDtstart->compare($_event->dtstart) != 0; // php52 compat if (!$dtStartHasDiff) { $attendees = $_event->attendee; unset($_event->attendee); } $note = $_event->notes; unset($_event->notes); $persistentExceptionEvent = $this->create($_event, $_checkBusyConflicts); if (!$dtStartHasDiff) { // we save attendee seperatly to preserve their attributes if ($attendees instanceof Tinebase_Record_RecordSet) { $attendees->cal_event_id = $persistentExceptionEvent->getId(); $calendar = Tinebase_Container::getInstance()->getContainerById($_event->container_id); foreach ($attendees as $attendee) { $this->_createAttender($attendee, $_event, TRUE, $calendar); $this->_increaseDisplayContainerContentSequence($attendee, $persistentExceptionEvent, Tinebase_Model_ContainerContent::ACTION_CREATE); } } } // @todo save notes and add a update note -> what was updated? -> modlog is also missing $persistentExceptionEvent = $this->get($persistentExceptionEvent->getId()); } } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " shorten recur series for/to: '{$_event->recurid}'"); } // split past/future exceptions $pastExdates = array(); $futureExdates = array(); foreach ($exdates as $exdate) { $exdate->isLater($_event->dtstart) ? $futureExdates[] = $exdate : ($pastExdates[] = $exdate); } $persistentExceptionEvents = $this->getRecurExceptions($_event); $pastPersistentExceptionEvents = new Tinebase_Record_RecordSet('Calendar_Model_Event'); $futurePersistentExceptionEvents = new Tinebase_Record_RecordSet('Calendar_Model_Event'); foreach ($persistentExceptionEvents as $persistentExceptionEvent) { $persistentExceptionEvent->getOriginalDtStart()->isLater($_event->dtstart) ? $futurePersistentExceptionEvents->addRecord($persistentExceptionEvent) : $pastPersistentExceptionEvents->addRecord($persistentExceptionEvent); } // update baseEvent $rrule = Calendar_Model_Rrule::getRruleFromString($baseEvent->rrule); if (isset($rrule->count)) { // get all occurences and find the split $exdate = $baseEvent->exdate; $baseEvent->exdate = NULL; //$baseCountOccurrence = Calendar_Model_Rrule::computeNextOccurrence($baseEvent, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $baseEvent->rrule_until, $baseCount); $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($baseEvent, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $baseEvent->dtstart, $baseEvent->rrule_until); $baseEvent->exdate = $exdate; $originalDtstart = $_event->getOriginalDtStart(); foreach ($recurSet as $idx => $rInstance) { if ($rInstance->dtstart >= $originalDtstart) { break; } } $rrule->count = $idx + 1; } else { $lastBaseOccurence = Calendar_Model_Rrule::computeNextOccurrence($baseEvent, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $_event->getOriginalDtStart()->subSecond(1), -1); $rrule->until = $lastBaseOccurence ? $lastBaseOccurence->getOriginalDtStart() : $baseEvent->dtstart; } $baseEvent->rrule = (string) $rrule; $baseEvent->exdate = $pastExdates; // NOTE: we don't want implicit attendee updates //$updatedBaseEvent = $this->update($baseEvent, FALSE); $this->_inspectEvent($baseEvent); $updatedBaseEvent = parent::update($baseEvent); if ($_deleteInstance == TRUE) { // delete all future persistent events $this->delete($futurePersistentExceptionEvents->getId()); } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " create new recur series for/at: '{$_event->recurid}'"); } // NOTE: in order to move exceptions correctly in time we need to find out the original dtstart // and create the new baseEvent with this time. A following update also updates its exceptions $originalDtstart = new Tinebase_DateTime(substr($_event->recurid, -19)); $adoptedDtstart = clone $_event->dtstart; $dtStartHasDiff = $adoptedDtstart->compare($originalDtstart) != 0; // php52 compat $eventLength = $_event->dtstart->diff($_event->dtend); $_event->dtstart = clone $originalDtstart; $_event->dtend = clone $originalDtstart; $_event->dtend->add($eventLength); // adopt count if (isset($rrule->count)) { $baseCount = $rrule->count; $rrule = Calendar_Model_Rrule::getRruleFromString($_event->rrule); $rrule->count = $rrule->count - $baseCount; $_event->rrule = (string) $rrule; } $_event->setId(Tinebase_Record_Abstract::generateUID()); $_event->uid = $futurePersistentExceptionEvents->uid = Tinebase_Record_Abstract::generateUID(); $_event->setId(Tinebase_Record_Abstract::generateUID()); $futurePersistentExceptionEvents->setRecurId($_event->getId()); unset($_event->recurid); unset($_event->base_event_id); foreach (array('attendee', 'notes', 'alarms') as $prop) { if ($_event->{$prop} instanceof Tinebase_Record_RecordSet) { $_event->{$prop}->setId(NULL); } } $_event->exdate = $futureExdates; $attendees = $_event->attendee; unset($_event->attendee); $note = $_event->notes; unset($_event->notes); $persistentExceptionEvent = $this->create($_event, $_checkBusyConflicts && $dtStartHasDiff); // we save attendee separately to preserve their attributes if ($attendees instanceof Tinebase_Record_RecordSet) { foreach ($attendees as $attendee) { $this->_createAttender($attendee, $persistentExceptionEvent, true); } } // @todo save notes and add a update note -> what was updated? -> modlog is also missing $persistentExceptionEvent = $this->get($persistentExceptionEvent->getId()); foreach ($futurePersistentExceptionEvents as $futurePersistentExceptionEvent) { $this->update($futurePersistentExceptionEvent, FALSE); } if ($dtStartHasDiff) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " new recur series has adpted dtstart -> update to adopt exceptions'"); } $persistentExceptionEvent->dtstart = clone $adoptedDtstart; $persistentExceptionEvent->dtend = clone $adoptedDtstart; $persistentExceptionEvent->dtend->add($eventLength); $persistentExceptionEvent = $this->update($persistentExceptionEvent, $_checkBusyConflicts); } } } Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId); // restore original notification handling $this->sendNotifications($sendNotifications); $notificationAction = $_deleteInstance ? 'deleted' : 'changed'; $notificationEvent = $_deleteInstance ? $_event : $persistentExceptionEvent; // restore acl $this->doContainerACLChecks($doContainerACLChecks); // send notifications if ($this->_sendNotifications && $_event->mute != 1) { // NOTE: recur exception is a fake event from client. // this might lead to problems, so we wrap the calls try { if (count($_event->attendee) > 0) { $_event->attendee->bypassFilters = TRUE; } $_event->created_by = $baseEvent->created_by; $this->doSendNotifications($notificationEvent, Tinebase_Core::getUser(), $notificationAction, $originalEvent); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getTraceAsString()); } Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " could not send notification {$e->getMessage()}"); } } return $_deleteInstance ? $updatedBaseEvent : $persistentExceptionEvent; }