public function testGetModifications() { $testBase = array('record_id' => '5dea69be9c72ea3d263613277c3b02d529fbd8bc', 'type' => 'TestType', 'backend' => 'TestBackend'); $firstModificationTime = $this->_persistantLogEntries[0]->modification_time; $lastModificationTime = $this->_persistantLogEntries[count($this->_persistantLogEntries) - 1]->modification_time; $toTest[] = $testBase + array('from_add' => 'addDay,-3', 'until_add' => 'addDay,1', 'nums' => 6); $toTest[] = $testBase + array('nums' => 4); $toTest[] = $testBase + array('account' => 999, 'nums' => 0); foreach ($toTest as $params) { $from = clone $firstModificationTime; $until = clone $lastModificationTime; if (isset($params['from_add'])) { list($fn, $p) = explode(',', $params['from_add']); $from->{$fn}($p); } if (isset($params['until_add'])) { list($fn, $p) = explode(',', $params['until_add']); $until->{$fn}($p); } $account = isset($params['account']) ? $params['account'] : NULL; $diffs = $this->_modLogClass->getModifications('Tinebase', $params['record_id'], $params['type'], $params['backend'], $from, $until, $account); $count = 0; foreach ($diffs as $diff) { if ($diff->record_id == $params['record_id']) { $count++; } } $this->assertEquals($params['nums'], $count); } }
/** * testDateTimeModlog * * @see 0000996: add changes in relations/linked objects to modlog/history */ public function testDateTimeModlog() { $task = Tasks_Controller_Task::getInstance()->create(new Tasks_Model_Task(array('summary' => 'test task'))); $task->due = Tinebase_DateTime::now(); $updatedTask = Tasks_Controller_Task::getInstance()->update($task); $task->seq = 1; $modlog = $this->_modLogClass->getModificationsBySeq($task, 2); $this->assertEquals(1, count($modlog)); $this->assertEquals((string) $task->due, (string) $modlog->getFirstRecord()->new_value, 'new value mismatch: ' . print_r($modlog->toArray(), TRUE)); }
/** * @see Tinebase_Setup_DemoData_Abstract */ protected function _beforeCreate() { $be = new Addressbook_Backend_Sql(); foreach ($this->_personas as $login => $fullName) { try { $user = Tinebase_User::getInstance()->getFullUserByLoginName($login); $contact = Addressbook_Controller_Contact::getInstance()->get($user->contact_id); } catch (Tinebase_Exception_NotFound $e) { list($given, $last) = explode(' ', $fullName); $group = Tinebase_Group::getInstance()->getGroupByName('Users'); $groupId = $group->getId(); $emailDomain = $this->_getMailDomain(); $user = new Tinebase_Model_FullUser(array('accountLoginName' => $login, 'accountPrimaryGroup' => $groupId, 'accountDisplayName' => $fullName, 'accountLastName' => $last, 'accountFirstName' => $given, 'accountFullName' => $fullName, 'accountEmailAddress' => $login . '@' . $emailDomain)); if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) { $internalAddressbook = Tinebase_Container::getInstance()->getContainerByName('Addressbook', 'Internal Contacts', Tinebase_Model_Container::TYPE_SHARED); $user->container_id = $internalAddressbook->getId(); $contact = Admin_Controller_User::getInstance()->createOrUpdateContact($user); $user->contact_id = $contact->getId(); } Tinebase_Timemachine_ModificationLog::setRecordMetaData($user, 'create'); $user = Tinebase_User::getInstance()->addUser($user); Tinebase_Group::getInstance()->addGroupMember($groupId, $user); if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) { $listBackend = new Addressbook_Backend_List(); $listBackend->addListMember($group->list_id, $user->contact_id); } $this->_setUserPassword($user); } if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) { $ar = array_merge($this->_dataMapping[$login], $this->_dataMapping['default']); $filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'DemoData' . DIRECTORY_SEPARATOR . 'persona_' . $login . '.jpg'; if (file_exists($filename)) { $handle = fopen($filename, "r"); $content = fread($handle, filesize($filename)); fclose($handle); $be->_saveImage($contact->getId(), $content); } foreach ($ar as $property => $value) { $contact->{$property} = $value; } Addressbook_Controller_Contact::getInstance()->update($contact); } $this->_personas[$login] = $user; } $this->_createGroups(); $this->_createRoles(); $this->_createSharedTags(); }
/** * create contact in addressbook * * @param Tinebase_Model_FullUser $user */ public static function syncContact($user) { if (!Tinebase_Application::getInstance()->isInstalled('Addressbook')) { return; } $addressbook = Addressbook_Backend_Factory::factory(Addressbook_Backend_Factory::SQL); $internalAddressbook = Tinebase_Container::getInstance()->getContainerByName('Addressbook', 'Internal Contacts', Tinebase_Model_Container::TYPE_SHARED); $contact = new Addressbook_Model_Contact(array('n_family' => $user->accountLastName, 'n_given' => $user->accountFirstName, 'n_fn' => $user->accountFullName, 'n_fileas' => $user->accountDisplayName, 'email' => $user->accountEmailAddress, 'type' => Addressbook_Model_Contact::CONTACTTYPE_USER, 'container_id' => $internalAddressbook->getId())); // add modlog info Tinebase_Timemachine_ModificationLog::setRecordMetaData($contact, 'create'); $contact = $addressbook->create($contact); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Added contact " . $contact->n_given); } $user->contact_id = $contact->getId(); }
/** * creates a common modlog record * * @param string $_model * @param string $_backend * @param array $_updateMetaData * @param string $_recordId * @return Tinebase_Model_ModificationLog */ protected function _getCommonModlog($_model, $_backend, $_updateMetaData = array(), $_recordId = NULL) { if (empty($_updateMetaData)) { list($currentAccountId, $currentTime) = Tinebase_Timemachine_ModificationLog::getCurrentAccountIdAndTime(); } else { $currentAccountId = $_updateMetaData['last_modified_by']; $currentTime = $_updateMetaData['last_modified_time']; } list($appName, $i, $modelName) = explode('_', $_model); $commonModLogEntry = new Tinebase_Model_ModificationLog(array('application_id' => Tinebase_Application::getInstance()->getApplicationByName($appName)->getId(), 'record_id' => $_recordId, 'record_type' => $_model, 'record_backend' => $_backend, 'modification_time' => $currentTime, 'modification_account' => $currentAccountId), TRUE); return $commonModLogEntry; }
/** * create new list by group * * @param Tinebase_Model_Group $group * @return Addressbook_Model_List */ public function createByGroup($group) { $list = new Addressbook_Model_List(array('name' => $group->name, 'description' => $group->description, 'email' => $group->email, 'type' => Addressbook_Model_List::LISTTYPE_GROUP, 'container_id' => empty($group->container_id) ? $this->_getDefaultInternalAddressbook() : $group->container_id, 'members' => isset($group->members) ? $this->_getContactIds($group->members) : array())); // add modlog info Tinebase_Timemachine_ModificationLog::setRecordMetaData($list, 'create'); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Add new list ' . $group->name); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($list->toArray(), TRUE)); } $list = $this->_backend->create($list); return $list; }
/** * 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)); } } }
/** * add system account with tine user credentials (from config.inc.php or config db) * * @param Tinebase_Record_RecordSet $_accounts of Felamimail_Model_Account */ protected function _addSystemAccount(Tinebase_Record_RecordSet $_accounts) { $userId = $this->_currentAccount->getId(); $fullUser = Tinebase_User::getInstance()->getFullUserById($userId); $email = $this->_getAccountEmail($fullUser); // only create account if email address is set if ($email) { $systemAccount = new Felamimail_Model_Account(NULL, TRUE); $this->_addSystemAccountConfigValues($systemAccount); $systemAccount->type = Felamimail_Model_Account::TYPE_SYSTEM; $systemAccount->user_id = $userId; $this->_addUserValues($systemAccount, $fullUser, $email); $this->_addFolderDefaults($systemAccount, TRUE); // create new account and update capabilities Tinebase_Timemachine_ModificationLog::setRecordMetaData($systemAccount, 'create'); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($systemAccount->toArray(), TRUE)); } $systemAccount = $this->_backend->create($systemAccount); $_accounts->addRecord($systemAccount); $this->_addedDefaultAccount = TRUE; // set as default account preference Tinebase_Core::getPreference($this->_applicationName)->{Felamimail_Preference::DEFAULTACCOUNT} = $systemAccount->getId(); Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Created new system account "' . $systemAccount->name . '".'); } else { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Could not create system account for user ' . $fullUser->accountLoginName . '. No email address given.'); } }
/** * create initial admin account * * Method is called during Setup Initialization * * $_options may contain the following keys: * <code> * $options = array( * 'adminLoginName' => 'admin', * 'adminPassword' => 'lars', * 'adminFirstName' => 'Tine 2.0', * 'adminLastName' => 'Admin Account', * 'adminEmailAddress' => '*****@*****.**', * 'expires' => Tinebase_DateTime object * ); * </code> * * @param array $_options [hash that may contain override values for admin user name and password] * @return void * @throws Tinebase_Exception_InvalidArgument */ public static function createInitialAccounts($_options) { if (!isset($_options['adminPassword']) || !isset($_options['adminLoginName'])) { throw new Tinebase_Exception_InvalidArgument('Admin password and login name have to be set when creating initial account.', 503); } $adminLoginName = $_options['adminLoginName']; $adminPassword = $_options['adminPassword']; $adminFirstName = isset($_options['adminFirstName']) ? $_options['adminFirstName'] : 'Tine 2.0'; $adminLastName = isset($_options['adminLastName']) ? $_options['adminLastName'] : 'Admin Account'; $adminEmailAddress = isset($_options['adminEmailAddress']) || array_key_exists('adminEmailAddress', $_options) ? $_options['adminEmailAddress'] : NULL; // get admin & user groups $userBackend = Tinebase_User::getInstance(); $groupsBackend = Tinebase_Group::getInstance(); $adminGroup = $groupsBackend->getDefaultAdminGroup(); $userGroup = $groupsBackend->getDefaultGroup(); Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Creating initial admin user (login: '******' / email: ' . $adminEmailAddress . ')'); $user = new Tinebase_Model_FullUser(array('accountLoginName' => $adminLoginName, 'accountStatus' => 'enabled', 'accountPrimaryGroup' => $userGroup->getId(), 'accountLastName' => $adminLastName, 'accountDisplayName' => $adminLastName . ', ' . $adminFirstName, 'accountFirstName' => $adminFirstName, 'accountExpires' => isset($_options['expires']) ? $_options['expires'] : NULL, 'accountEmailAddress' => $adminEmailAddress)); if ($adminEmailAddress !== NULL) { $user->imapUser = new Tinebase_Model_EmailUser(array('emailPassword' => $adminPassword)); $user->smtpUser = new Tinebase_Model_EmailUser(array('emailPassword' => $adminPassword)); } // update or create user in local sql backend try { $userBackend->getUserByProperty('accountLoginName', $adminLoginName); Tinebase_Timemachine_ModificationLog::setRecordMetaData($user, 'update'); $user = $userBackend->updateUserInSqlBackend($user); } catch (Tinebase_Exception_NotFound $ten) { // call addUser here to make sure, sql user plugins (email, ...) are triggered Tinebase_Timemachine_ModificationLog::setRecordMetaData($user, 'create'); $user = $userBackend->addUser($user); } // set the password for the account // empty password triggers password change dialogue during first login if (!empty($adminPassword)) { Tinebase_User::getInstance()->setPassword($user, $adminPassword); } // add the admin account to all groups Tinebase_Group::getInstance()->addGroupMember($adminGroup, $user); Tinebase_Group::getInstance()->addGroupMember($userGroup, $user); }
/** * delete one record * * @param Tinebase_Record_Interface $_record * @throws Tinebase_Exception_AccessDenied */ protected function _deleteRecord(Tinebase_Record_Interface $_record) { $this->_checkGrant($_record, 'delete'); $this->_deleteLinkedObjects($_record); if (!$this->_purgeRecords && $_record->has('created_by')) { Tinebase_Timemachine_ModificationLog::setRecordMetaData($_record, 'delete', $_record); $this->_backend->update($_record); } else { $this->_backend->delete($_record); } $this->_increaseContainerContentSequence($_record, Tinebase_Model_ContainerContent::ACTION_DELETE); }
/** * uninstall app * * @param Tinebase_Model_Application $_application * @throws Setup_Exception */ protected function _uninstallApplication(Tinebase_Model_Application $_application, $uninstallAll = false) { if ($this->_backend === null) { throw new Setup_Exception('No setup backend available'); } Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Uninstall ' . $_application); try { $applicationTables = Tinebase_Application::getInstance()->getApplicationTables($_application); } catch (Zend_Db_Statement_Exception $zdse) { Setup_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . " " . $zdse); throw new Setup_Exception('Could not uninstall ' . $_application . ' (you might need to remove the tables by yourself): ' . $zdse->getMessage()); } $disabledFK = FALSE; $db = Tinebase_Core::getDb(); do { $oldCount = count($applicationTables); if ($_application->name == 'Tinebase') { $installedApplications = Tinebase_Application::getInstance()->getApplications(NULL, 'id'); if (count($installedApplications) !== 1) { throw new Setup_Exception_Dependency('Failed to uninstall application "Tinebase" because of dependencies to other installed applications.'); } } foreach ($applicationTables as $key => $table) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Remove table: {$table}"); try { // drop foreign keys which point to current table first $foreignKeys = $this->_backend->getExistingForeignKeys($table); foreach ($foreignKeys as $foreignKey) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Drop index: " . $foreignKey['table_name'] . ' => ' . $foreignKey['constraint_name']); $this->_backend->dropForeignKey($foreignKey['table_name'], $foreignKey['constraint_name']); } // drop table $this->_backend->dropTable($table); if ($_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); } unset($applicationTables[$key]); } catch (Zend_Db_Statement_Exception $e) { // we need to catch exceptions here, as we don't want to break here, as a table // might still have some foreign keys // this works with mysql only $message = $e->getMessage(); Setup_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " Could not drop table {$table} - " . $message); // remove app table if table not found in db if (preg_match('/SQLSTATE\\[42S02\\]: Base table or view not found/', $message) && $_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); unset($applicationTables[$key]); } else { Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Disabling foreign key checks ... "); if ($db instanceof Zend_Db_Adapter_Pdo_Mysql) { $db->query("SET FOREIGN_KEY_CHECKS=0"); } $disabledFK = TRUE; } } } if ($oldCount > 0 && count($applicationTables) == $oldCount) { throw new Setup_Exception('dead lock detected oldCount: ' . $oldCount); } } while (count($applicationTables) > 0); if ($disabledFK) { if ($db instanceof Zend_Db_Adapter_Pdo_Mysql) { Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Enabling foreign key checks again... "); $db->query("SET FOREIGN_KEY_CHECKS=1"); } } if ($_application->name != 'Tinebase') { if (!$uninstallAll) { Tinebase_Relations::getInstance()->removeApplication($_application->name); Tinebase_Timemachine_ModificationLog::getInstance()->removeApplication($_application); // delete containers, config options and other data for app Tinebase_Application::getInstance()->removeApplicationData($_application); } // remove application from table of installed applications Tinebase_Application::getInstance()->deleteApplication($_application); } Setup_Uninitialize::uninitialize($_application); Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Removed app: " . $_application->name); }
/** * testConcurrentAttendeeChangeUpdate * * @see 0008078: concurrent attendee change should be merged */ public function testConcurrentAttendeeChangeUpdate() { $eventData = $this->testCreateEvent(); $currentAttendee = $eventData['attendee']; $adminIndex = $eventData['attendee'][0]['user_id']['n_fn'] === 'Susan Clever' ? 1 : 0; $eventData['attendee'][$adminIndex]['status'] = Calendar_Model_Attender::STATUS_TENTATIVE; $event = $this->_uit->saveEvent($eventData); $loggedMods = Tinebase_Timemachine_ModificationLog::getInstance()->getModificationsBySeq(Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(), new Calendar_Model_Attender($eventData['attendee'][$adminIndex]), 2); $this->assertEquals(1, count($loggedMods), 'attender modification has not been logged'); $eventData['attendee'] = $currentAttendee; $scleverIndex = $adminIndex === 1 ? 0 : 1; $attendeeBackend = new Calendar_Backend_Sql_Attendee(); $eventData['attendee'][$scleverIndex]['status_authkey'] = $attendeeBackend->get($eventData['attendee'][$scleverIndex]['id'])->status_authkey; $eventData['attendee'][$scleverIndex]['status'] = Calendar_Model_Attender::STATUS_TENTATIVE; $event = $this->_uit->saveEvent($eventData); foreach ($event['attendee'] as $attender) { $this->assertEquals(Calendar_Model_Attender::STATUS_TENTATIVE, $attender['status'], 'both attendee status should be TENTATIVE: ' . print_r($attender, TRUE)); } }
/** * testConcurrencyLinebreakMismatch * * @see 0007140: normalize linebreaks in concurrency check */ public function testConcurrencyLinebreakMismatch() { $utask = $this->_persistantTestTask1; $utask->description = 'description' . "\n"; $utask = $this->_controller->update($utask); // change linebreak in db to \r\n $loggedMods = Tinebase_Timemachine_ModificationLog::getInstance()->getModifications('Tasks', $utask->getId(), 'Tasks_Model_Task', 'Sql', Tinebase_DateTime::now()->subMinute(5), $utask->last_modified_time); $this->assertEquals(1, count($loggedMods)); $mod = $loggedMods[0]->toArray(); $this->assertEquals('description', $mod['modified_attribute']); $mod['new_value'] = 'description' . "\r\n"; $modlog = new Tinebase_Db_Table(array('name' => SQL_TABLE_PREFIX . 'timemachine_modlog')); $modlog->update($mod, Tinebase_Core::getDb()->quoteInto('id = ?', $mod['id'])); // this should still work as we normalize linebreaks in concurrency check $resolvableConcurrencyTask = clone $utask; $resolvableConcurrencyTask->last_modified_time = Tinebase_DateTime::now()->addHour(-1); $resolvableConcurrencyTask->description = 'description' . "\n"; $task = $this->_controller->update($resolvableConcurrencyTask); $this->assertEquals('description' . "\n", $task->description); }
/** * create initial groups * * Method is called during Setup Initialization */ public static function createInitialGroups() { $defaultAdminGroupName = Tinebase_User::getBackendConfiguration(Tinebase_User::DEFAULT_ADMIN_GROUP_NAME_KEY) ? Tinebase_User::getBackendConfiguration(Tinebase_User::DEFAULT_ADMIN_GROUP_NAME_KEY) : self::DEFAULT_ADMIN_GROUP; $adminGroup = new Tinebase_Model_Group(array('name' => $defaultAdminGroupName, 'description' => 'Group of administrative accounts')); Tinebase_Timemachine_ModificationLog::setRecordMetaData($adminGroup, 'create'); Tinebase_Group::getInstance()->addGroup($adminGroup); $defaultUserGroupName = Tinebase_User::getBackendConfiguration(Tinebase_User::DEFAULT_USER_GROUP_NAME_KEY) ? Tinebase_User::getBackendConfiguration(Tinebase_User::DEFAULT_USER_GROUP_NAME_KEY) : self::DEFAULT_USER_GROUP; $userGroup = new Tinebase_Model_Group(array('name' => $defaultUserGroupName, 'description' => 'Group of user accounts')); Tinebase_Timemachine_ModificationLog::setRecordMetaData($userGroup, 'create'); Tinebase_Group::getInstance()->addGroup($userGroup); }
/** * add new note * * @param Tinebase_Model_Note $_note */ public function addNote(Tinebase_Model_Note $_note) { if (!$_note->getId()) { $id = $_note->generateUID(); $_note->setId($id); } Tinebase_Timemachine_ModificationLog::getInstance()->setRecordMetaData($_note, 'create'); $data = $_note->toArray(FALSE, FALSE); $this->_notesTable->insert($data); }
/** * delete notes * * @param Tinebase_Record_RecordSet $notes */ public function deleteNotes(Tinebase_Record_RecordSet $notes) { $sqlBackend = new Tinebase_Backend_Sql(array('tableName' => $this->getTableName(), 'modelName' => 'Tinebase_Model_Note'), $this->getAdapter()); foreach ($notes as $note) { Tinebase_Timemachine_ModificationLog::setRecordMetaData($note, 'delete', $note); $sqlBackend->update($note); } }
/** * get email addresses this attendee had in the past * * @return array */ public function getEmailsFromHistory() { $emails = array(); $typeMap = array(self::USERTYPE_USER => 'Addressbook_Model_Contact', self::USERTYPE_GROUPMEMBER => 'Addressbook_Model_Contact', self::USERTYPE_RESOURCE => 'Calendar_Model_Resource'); if (isset($typeMap[$this->user_type])) { $type = $typeMap[$this->user_type]; $id = $this->user_id instanceof Tinebase_Record_Abstract ? $this->user_id->getId() : $this->user_id; $modifications = Tinebase_Timemachine_ModificationLog::getInstance()->getModifications(Tinebase_Helper::array_value(0, explode('_', $type)), $this->user_id instanceof Tinebase_Record_Abstract ? $this->user_id->getId() : $this->user_id, $type, 'Sql', $this->creation_time); foreach ($modifications as $modification) { if (in_array($modification->modified_attribute, array('email', 'email_home'))) { if ($modification->old_value) { $emails[] = $modification->old_value; } } } } return $emails; }
/** * add new note * * @param Tinebase_Model_Note $_note */ public function addNote(Tinebase_Model_Note $_note) { if (!$_note->getId()) { $id = $_note->generateUID(); $_note->setId($id); } Tinebase_Timemachine_ModificationLog::getInstance()->setRecordMetaData($_note, 'create'); $data = $_note->toArray(FALSE, FALSE); //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($data, TRUE)); $this->_notesTable->insert($data); }
/** * create or update contact in addressbook backend * * @param Tinebase_Model_FullUser $_user * @return Addressbook_Model_Contact */ public function createOrUpdateContact(Tinebase_Model_FullUser $_user) { $contactsBackend = Addressbook_Backend_Factory::factory(Addressbook_Backend_Factory::SQL); $contactsBackend->setGetDisabledContacts(true); if (empty($_user->container_id)) { $_user->container_id = $this->getDefaultInternalAddressbook(); } try { if (empty($_user->contact_id)) { // jump to catch block throw new Tinebase_Exception_NotFound('contact_id is empty'); } $contact = $contactsBackend->get($_user->contact_id); // update exisiting contact $contact->n_family = $_user->accountLastName; $contact->n_given = $_user->accountFirstName; $contact->n_fn = $_user->accountFullName; $contact->n_fileas = $_user->accountDisplayName; $contact->email = $_user->accountEmailAddress; $contact->type = Addressbook_Model_Contact::CONTACTTYPE_USER; $contact->container_id = $_user->container_id; // add modlog info Tinebase_Timemachine_ModificationLog::setRecordMetaData($contact, 'update'); $contact = $contactsBackend->update($contact); } catch (Tinebase_Exception_NotFound $tenf) { // add new contact $contact = new Addressbook_Model_Contact(array('n_family' => $_user->accountLastName, 'n_given' => $_user->accountFirstName, 'n_fn' => $_user->accountFullName, 'n_fileas' => $_user->accountDisplayName, 'email' => $_user->accountEmailAddress, 'type' => Addressbook_Model_Contact::CONTACTTYPE_USER, 'container_id' => $_user->container_id)); // add modlog info Tinebase_Timemachine_ModificationLog::setRecordMetaData($contact, 'create'); $contact = $contactsBackend->create($contact); } return $contact; }
/** * add one record * * @param Tinebase_Record_Interface $_record * @return Tinebase_Record_Interface */ public function create(Tinebase_Record_Interface $_record) { $this->_checkRight('create'); $_record->account_grants = $this->_convertGrantsToRecordSet($_record->account_grants); Tinebase_Container::getInstance()->checkContainerOwner($_record); Tinebase_Timemachine_ModificationLog::setRecordMetaData($_record, 'create'); $container = $this->_containerController->addContainer($_record, $_record->account_grants, TRUE); $container->account_grants = $this->_containerController->getGrantsOfContainer($container, TRUE); return $container; }
/** * update node * * @param Tinebase_Model_Tree_Node $_node * @return Tinebase_Model_Tree_Node */ public function update(Tinebase_Model_Tree_Node $_node) { $currentNodeObject = $this->get($_node->getId()); $fileObject = $this->_fileObjectBackend->get($currentNodeObject->object_id); Tinebase_Timemachine_ModificationLog::setRecordMetaData($_node, 'update', $currentNodeObject); Tinebase_Timemachine_ModificationLog::setRecordMetaData($fileObject, 'update', $fileObject); // quick hack for 2014.11 - will be resolved correctly in 2015.11-develop if (isset($_SERVER['HTTP_X_OC_MTIME'])) { $fileObject->last_modified_time = new Tinebase_DateTime($_SERVER['HTTP_X_OC_MTIME']); Tinebase_Server_WebDAV::getResponse()->setHeader('X-OC-MTime', 'accepted'); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " using X-OC-MTIME: {$fileObject->last_modified_time->format(Tinebase_Record_Abstract::ISO8601LONG)} for {$_node->name}"); } } // update file object $fileObject->description = $_node->description; $this->_updateFileObject($fileObject, $_node->hash); return $this->_treeNodeBackend->update($_node); }
/** * update existing group * * @param Tinebase_Model_Group $_group * @return Tinebase_Model_Group */ public function update(Tinebase_Model_Group $_group) { $this->checkRight('MANAGE_ACCOUNTS'); // update default user group if name has changed $oldGroup = Tinebase_Group::getInstance()->getGroupById($_group->getId()); $defaultGroupName = Tinebase_User::getBackendConfiguration(Tinebase_User::DEFAULT_USER_GROUP_NAME_KEY); if ($oldGroup->name == $defaultGroupName && $oldGroup->name != $_group->name) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Updated default group name: ' . $oldGroup->name . ' -> ' . $_group->name); Tinebase_User::setBackendConfiguration($_group->name, Tinebase_User::DEFAULT_USER_GROUP_NAME_KEY); Tinebase_User::saveBackendConfiguration(); } $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb()); if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) { $_group->list_id = $oldGroup->list_id; $list = $this->createOrUpdateList($_group); $_group->list_id = $list->getId(); } Tinebase_Timemachine_ModificationLog::setRecordMetaData($_group, 'update', $oldGroup); $group = Tinebase_Group::getInstance()->updateGroup($_group); Tinebase_Group::getInstance()->setGroupMembers($group->getId(), $_group->members); Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId); $event = new Admin_Event_UpdateGroup(); $event->group = $group; Tinebase_Event::fireEvent($event); return $group; }
/** * update node * * @param Tinebase_Model_Tree_Node $_node * @return Tinebase_Model_Tree_Node */ public function updateNode(Tinebase_Model_Tree_Node $_node) { $currentNodeObject = $this->_treeNodeBackend->get($_node->getId()); $modLog = Tinebase_Timemachine_ModificationLog::getInstance(); $modLog->setRecordMetaData($_node, 'update', $currentNodeObject); return $this->_treeNodeBackend->update($_node); }
/** * Returns instance of Tinebase_Timemachine_ModificationLog * (only create instace on demand) * * @return Tinebase_Timemachine_ModificationLog */ protected function getModificationLog() { if (!$this->_modificationLog) { $this->_modificationLog = Tinebase_Timemachine_ModificationLog::getInstance(); } return $this->_modificationLog; }
/** * updates an attender * * @param Calendar_Model_Attender $attender * @param Calendar_Model_Attender $currentAttender * @param Calendar_Model_Event $event * @param bool $isRescheduled event got rescheduled reset all attendee status * @param Tinebase_Model_Container $calendar */ protected function _updateAttender($attender, $currentAttender, $event, $isRescheduled, $calendar = NULL) { $userAccountId = $currentAttender->getUserAccountId(); // update display calendar if attender has/is a useraccount if ($userAccountId) { if ($calendar->type == Tinebase_Model_Container::TYPE_PERSONAL && Tinebase_Container::getInstance()->hasGrant($userAccountId, $calendar, Tinebase_Model_Grants::GRANT_ADMIN)) { // if attender has admin grant to personal physical container, this phys. cal also gets displ. cal $attender->displaycontainer_id = $calendar->getId(); } else { if ($userAccountId == Tinebase_Core::getUser()->getId() && Tinebase_Container::getInstance()->hasGrant($userAccountId, $attender->displaycontainer_id, Tinebase_Model_Grants::GRANT_ADMIN)) { // allow user to set his own displ. cal $attender->displaycontainer_id = $attender->displaycontainer_id; } else { $attender->displaycontainer_id = $currentAttender->displaycontainer_id; } } } // reset status if user has no right and authkey is wrong if ($attender->displaycontainer_id) { if (!Tinebase_Core::getUser()->hasGrant($attender->displaycontainer_id, Tinebase_Model_Grants::GRANT_EDIT) && $attender->status_authkey != $currentAttender->status_authkey) { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Wrong authkey, resetting status (' . $attender->status . ' -> ' . $currentAttender->status . ')'); } $attender->status = $currentAttender->status; } } // reset all status but calUser on reschedule except resources (Resources might have a configured default value) if ($isRescheduled && !$attender->isSame($this->getCalendarUser())) { if ($attender->user_type === Calendar_Model_Attender::USERTYPE_RESOURCE) { //If resource has a default status reset to this $resource = Calendar_Controller_Resource::getInstance()->get($attender->user_id); $attender->status = isset($resource->status) ? $resource->status : Calendar_Model_Attender::STATUS_NEEDSACTION; } else { $attender->status = Calendar_Model_Attender::STATUS_NEEDSACTION; } $attender->transp = null; } // preserve old authkey $attender->status_authkey = $currentAttender->status_authkey; if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " Updating attender: " . print_r($attender->toArray(), TRUE)); } Tinebase_Timemachine_ModificationLog::getInstance()->setRecordMetaData($attender, 'update', $currentAttender); Tinebase_Timemachine_ModificationLog::getInstance()->writeModLog($attender, $currentAttender, get_class($attender), $this->_getBackendType(), $attender->getId()); $this->_backend->updateAttendee($attender); if ($attender->displaycontainer_id !== $currentAttender->displaycontainer_id) { $this->_increaseDisplayContainerContentSequence($currentAttender, $event, Tinebase_Model_ContainerContent::ACTION_DELETE); $this->_increaseDisplayContainerContentSequence($attender, $event, Tinebase_Model_ContainerContent::ACTION_CREATE); } else { $this->_increaseDisplayContainerContentSequence($attender, $event); } }
/** * delete container if user has the required right * * @param int|Tinebase_Model_Container $_containerId * @param boolean $_ignoreAcl * @param boolean $_tryAgain * @throws Tinebase_Exception_AccessDenied * @throws Tinebase_Exception_InvalidArgument * * @todo move records in deleted container to personal container? */ public function deleteContainer($_containerId, $_ignoreAcl = FALSE, $_tryAgain = TRUE) { $containerId = Tinebase_Model_Container::convertContainerIdToInt($_containerId); $container = $_containerId instanceof Tinebase_Model_Container ? $_containerId : $this->getContainerById($containerId); if ($_ignoreAcl !== TRUE) { if (!$this->hasGrant(Tinebase_Core::getUser(), $containerId, Tinebase_Model_Grants::GRANT_ADMIN)) { throw new Tinebase_Exception_AccessDenied('Permission to delete container denied.'); } if ($container->type !== Tinebase_Model_Container::TYPE_PERSONAL and $container->type !== Tinebase_Model_Container::TYPE_SHARED) { throw new Tinebase_Exception_InvalidArgument('Can delete personal or shared containers only.'); } } //$this->delete($containerId); Tinebase_Timemachine_ModificationLog::setRecordMetaData($container, 'delete', $container); $this->update($container); $this->_clearCache(); /* // move all contained objects to next available personal container and try again to delete container $app = Tinebase_Application::getApplicationById($container->application_id); // get personal containers $personalContainers = $this->getPersonalContainer( Tinebase_Core::getUser(), $app->name, $container->owner, Tinebase_Model_Grants::GRANT_ADD ); //-- determine first matching personal container (or create new one) // $personalContainer = //-- move all records to personal container Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Moving all records from container ' . $containerId . ' to personal container ' . $personalContainer->getId() ); */ }
/** * undo changes to records defined by certain criteria (user, date, fields, ...) * * example: $ php tine20.php --username pschuele --method Tinebase.undo -d * -- record_type=Addressbook_Model_Contact modification_time=2013-05-08 modification_account=3263 * * @param Zend_Console_Getopt $opts */ public function undo(Zend_Console_Getopt $opts) { if (!$this->_checkAdminRight()) { return FALSE; } $data = $this->_parseArgs($opts, array('modification_time')); // build filter from params $filterData = array(); $allowedFilters = array('record_type', 'modification_time', 'modification_account', 'record_id', 'modified_attribute'); foreach ($data as $key => $value) { if (in_array($key, $allowedFilters)) { $operator = $key === 'modification_time' ? 'within' : 'equals'; $filterData[] = array('field' => $key, 'operator' => $operator, 'value' => $value); } } $filter = new Tinebase_Model_ModificationLogFilter($filterData); $dryrun = $opts->d; $overwrite = isset($data['overwrite']) && $data['overwrite'] ? TRUE : FALSE; $result = Tinebase_Timemachine_ModificationLog::getInstance()->undo($filter, $overwrite, $dryrun); if (!$dryrun) { echo 'Reverted ' . $result['totalcount'] . " change(s)\n"; } else { echo "Dry run\n"; echo 'Would revert ' . $result['totalcount'] . " change(s):\n"; foreach ($result['undoneModlogs'] as $modlog) { echo 'id ' . $modlog->record_id . ' [' . $modlog->modified_attribute . ']: ' . $modlog->new_value . ' -> ' . $modlog->old_value . "\n"; } } echo 'Failcount: ' . $result['failcount'] . "\n"; return 0; }
/** * set modified timestamp for container * * @param int|Tinebase_Model_Container $container * @param string $action one of {create|update|delete} * @return Tinebase_Model_Container */ protected function _setRecordMetaDataAndUpdate($container, $action) { if (!$container instanceof Tinebase_Model_Container) { $container = $this->getContainerById($container); } Tinebase_Timemachine_ModificationLog::getInstance()->setRecordMetaData($container, $action, $container); $this->_clearCache($container); return $this->update($container); }
/** * updates a single role * * @param Tinebase_Model_Role $role * @return Tinebase_Model_Role */ public function updateRole(Tinebase_Model_Role $role) { Tinebase_Timemachine_ModificationLog::setRecordMetaData($role, 'update', $this->getRoleById($role->getId())); $role = $this->_getRolesBackend()->update($role); $this->resetClassCache(); return $role; }
/** * update node * * @param Tinebase_Model_Tree_Node $_node * @return Tinebase_Model_Tree_Node */ public function update(Tinebase_Model_Tree_Node $_node) { $currentNodeObject = $this->get($_node->getId()); Tinebase_Timemachine_ModificationLog::setRecordMetaData($_node, 'update', $currentNodeObject); // update file object $fileObject = $this->_fileObjectBackend->get($currentNodeObject->object_id); $fileObject->description = $_node->description; $this->_updateFileObject($fileObject, $_node->hash); return $this->_treeNodeBackend->update($_node); }