/** * record set diff resolving * * @param Tinebase_Record_Interface $newRecord * @param Tinebase_Model_ModificationLog $diff */ protected function _resolveRecordSetMergeUpdate(Tinebase_Record_Interface $newRecord, Tinebase_Model_ModificationLog $diff) { $attribute = $diff->modified_attribute; if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Try to merge record set changes of record attribute " . $attribute); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' New record: ' . print_r($newRecord->toArray(), TRUE)); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Mod log: ' . print_r($diff->toArray(), TRUE)); } $concurrentChangeDiff = new Tinebase_Record_RecordSetDiff(Zend_Json::decode($diff->new_value)); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' RecordSet diff: ' . print_r($concurrentChangeDiff->toArray(), TRUE)); } foreach ($concurrentChangeDiff->added as $added) { $addedRecord = new $concurrentChangeDiff->model($added); if (!$newRecord->{$attribute}->getById($addedRecord->getId())) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Adding recently added record " . $addedRecord->getId()); } $newRecord->{$attribute}->addRecord($addedRecord); } } foreach ($concurrentChangeDiff->removed as $removed) { $removedRecord = new $concurrentChangeDiff->model($removed); $recordToRemove = $newRecord->{$attribute}->getById($removedRecord->getId()); if ($recordToRemove) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Removing record " . $recordToRemove->getId()); } $newRecord->{$attribute}->removeRecord($recordToRemove); } } foreach ($concurrentChangeDiff->modified as $modified) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' modified diff: ' . print_r($modified, TRUE)); } $modifiedRecord = new $concurrentChangeDiff->model(array_merge(array('id' => $modified['id']), $modified['diff']), TRUE); $newRecordsRecord = $newRecord->{$attribute}->getById($modifiedRecord->getId()); if ($newRecordsRecord && ($newRecordsRecord->has('seq') || $newRecordsRecord->has('last_modified_time'))) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Managing updates for ' . get_class($newRecordsRecord) . ' record ' . $newRecordsRecord->getId()); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' new record: ' . print_r($newRecordsRecord->toArray(), TRUE)); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' modified record: ' . print_r($modifiedRecord->toArray(), TRUE)); } if (null === $this->_applicationId) { throw new Tinebase_Exception_UnexpectedValue('application_id needs to be set here'); } $this->manageConcurrentUpdates($this->_applicationId, $newRecordsRecord, $modifiedRecord); } else { throw new Tinebase_Timemachine_Exception_ConcurrencyConflict('concurrency conflict - modified record changes could not be merged!'); } } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' New record after merge: ' . print_r($newRecord->toArray(), TRUE)); } }
/** * testRelatedModlog * * @see 0000996: add changes in relations/linked objects to modlog/history */ public function testRelatedModlog() { // create lead with tag, customfield and related contacts $savedLead = $this->_saveLead(); // change relations, customfields + tags $savedLead['tags'][] = array('name' => 'another tag', 'type' => Tinebase_Model_Tag::TYPE_PERSONAL); foreach ($savedLead['relations'] as $key => $value) { if ($value['type'] == 'PARTNER') { $savedLead['relations'][$key]['type'] = 'CUSTOMER'; } if ($value['type'] == 'TASK') { unset($savedLead['relations'][$key]); } } $savedLead['customfields'][$this->_cfcName] = '5678'; $updatedLead = $this->_instance->saveLead($savedLead); // check modlog + history $modifications = Tinebase_Timemachine_ModificationLog::getInstance()->getModifications('Crm', $updatedLead['id']); //print_r($updatedLead); $this->assertEquals(3, count($modifications), 'expected 3 modifications: ' . print_r($modifications->toArray(), TRUE)); foreach ($modifications as $modification) { switch ($modification->modified_attribute) { case 'customfields': $this->assertEquals('{"' . $this->_cfcName . '":"5678"}', $modification->new_value); break; case 'relations': $diff = new Tinebase_Record_RecordSetDiff(Zend_Json::decode($modification->new_value)); $this->assertEquals(0, count($diff->added)); $this->assertEquals(1, count($diff->removed)); $this->assertEquals(1, count($diff->modified), 'relations modified mismatch: ' . print_r($diff->toArray(), TRUE)); $this->assertTrue(isset($diff->modified[0]['diff']['type'])); $this->assertEquals('CUSTOMER', $diff->modified[0]['diff']['type'], 'type diff is not correct: ' . print_r($diff->toArray(), TRUE)); break; case 'tags': $diff = new Tinebase_Record_RecordSetDiff(Zend_Json::decode($modification->new_value)); $this->assertEquals(1, count($diff->added)); $this->assertEquals(0, count($diff->removed)); $this->assertEquals(0, count($diff->modified), 'tags modified mismatch: ' . print_r($diff->toArray(), TRUE)); break; default: $this->fail('Invalid modification: ' . print_r($modification->toArray(), TRUE)); } } }
/** * get system note change text * * @param Tinebase_Model_ModificationLog $modification * @return string */ protected function _getSystemNoteChangeText(Tinebase_Model_ModificationLog $modification) { // check if $modification->new_value is json string and record set diff // @see 0008546: When edit event, history show "code" ... if (Tinebase_Helper::is_json($modification->new_value)) { $newValueArray = Zend_Json::decode($modification->new_value); if ((isset($newValueArray['model']) || array_key_exists('model', $newValueArray)) && (isset($newValueArray['added']) || array_key_exists('added', $newValueArray))) { $diff = new Tinebase_Record_RecordSetDiff($newValueArray); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' fetching translated text for diff: ' . print_r($diff->toArray(), true)); } return $diff->getTranslatedDiffText(); } } return $modification->old_value . ' -> ' . $modification->new_value; }