/** * Get a log change. * * @param array $params * * @return array * API Success Array * @throws \API_Exception * @throws \Civi\API\Exception\UnauthorizedException */ function civicrm_api3_logging_get($params) { $schema = new CRM_Logging_Schema(); $interval = empty($params['log_date']) ? NULL : $params['interval']; $differ = new CRM_Logging_Differ($params['log_conn_id'], CRM_Utils_Array::value('log_date', $params), $interval); return civicrm_api3_create_success($differ->getAllChangesForConnection($schema->getLogTablesForContact())); }
/** * Class constructor. */ public function __construct() { // don’t display the ‘Add these Contacts to Group’ button $this->_add2groupSupported = FALSE; $dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN); $this->loggingDB = $dsn['database']; // used for redirect back to contact summary $this->cid = CRM_Utils_Request::retrieve('cid', 'Integer', CRM_Core_DAO::$_nullObject); $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name'); $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts); $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts); $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts); $this->_logTables = array('log_civicrm_contact' => array('fk' => 'id'), 'log_civicrm_email' => array('fk' => 'contact_id', 'log_type' => 'Contact'), 'log_civicrm_phone' => array('fk' => 'contact_id', 'log_type' => 'Contact'), 'log_civicrm_address' => array('fk' => 'contact_id', 'log_type' => 'Contact'), 'log_civicrm_note' => array('fk' => 'entity_id', 'entity_table' => TRUE, 'bracket_info' => array('table' => 'log_civicrm_note', 'column' => 'subject')), 'log_civicrm_note_comment' => array('fk' => 'entity_id', 'table_name' => 'log_civicrm_note', 'joins' => array('table' => 'log_civicrm_note', 'join' => "entity_log_civireport.entity_id = fk_table.id AND entity_log_civireport.entity_table = 'civicrm_note'"), 'entity_table' => TRUE, 'bracket_info' => array('table' => 'log_civicrm_note', 'column' => 'subject')), 'log_civicrm_group_contact' => array('fk' => 'contact_id', 'bracket_info' => array('entity_column' => 'group_id', 'table' => 'log_civicrm_group', 'column' => 'title'), 'action_column' => 'status', 'log_type' => 'Group'), 'log_civicrm_entity_tag' => array('fk' => 'entity_id', 'bracket_info' => array('entity_column' => 'tag_id', 'table' => 'log_civicrm_tag', 'column' => 'name'), 'entity_table' => TRUE), 'log_civicrm_relationship' => array('fk' => 'contact_id_a', 'bracket_info' => array('entity_column' => 'relationship_type_id', 'table' => 'log_civicrm_relationship_type', 'column' => 'label_a_b')), 'log_civicrm_activity_for_target' => array('fk' => 'contact_id', 'table_name' => 'log_civicrm_activity', 'joins' => array('table' => 'log_civicrm_activity_contact', 'join' => "(entity_log_civireport.id = fk_table.activity_id AND fk_table.record_type_id = {$targetID})"), 'bracket_info' => array('entity_column' => 'activity_type_id', 'options' => CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE)), 'log_type' => 'Activity'), 'log_civicrm_activity_for_assignee' => array('fk' => 'contact_id', 'table_name' => 'log_civicrm_activity', 'joins' => array('table' => 'log_civicrm_activity_contact', 'join' => "entity_log_civireport.id = fk_table.activity_id AND fk_table.record_type_id = {$assigneeID}"), 'bracket_info' => array('entity_column' => 'activity_type_id', 'options' => CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE)), 'log_type' => 'Activity'), 'log_civicrm_activity_for_source' => array('fk' => 'contact_id', 'table_name' => 'log_civicrm_activity', 'joins' => array('table' => 'log_civicrm_activity_contact', 'join' => "entity_log_civireport.id = fk_table.activity_id AND fk_table.record_type_id = {$sourceID}"), 'bracket_info' => array('entity_column' => 'activity_type_id', 'options' => CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE)), 'log_type' => 'Activity'), 'log_civicrm_case' => array('fk' => 'contact_id', 'joins' => array('table' => 'log_civicrm_case_contact', 'join' => 'entity_log_civireport.id = fk_table.case_id'), 'bracket_info' => array('entity_column' => 'case_type_id', 'options' => CRM_Case_PseudoConstant::caseType('title', FALSE)))); $logging = new CRM_Logging_Schema(); // build _logTables for contact custom tables $customTables = $logging->entityCustomDataLogTables('Contact'); foreach ($customTables as $table) { $this->_logTables[$table] = array('fk' => 'entity_id', 'log_type' => 'Contact'); } // build _logTables for address custom tables $customTables = $logging->entityCustomDataLogTables('Address'); foreach ($customTables as $table) { $this->_logTables[$table] = array('fk' => 'contact_id', 'joins' => array('table' => 'log_civicrm_address', 'join' => 'entity_log_civireport.entity_id = fk_table.id'), 'log_type' => 'Contact'); } // Allow log tables to be extended via report hooks. CRM_Report_BAO_Hook::singleton()->alterLogTables($this, $this->_logTables); parent::__construct(); }
/** * @param $table * @param int $contactID * * @return array */ public function diffsInTable($table, $contactID = NULL) { $diffs = array(); $params = array(1 => array($this->log_conn_id, 'Integer'), 2 => array($this->log_date, 'String')); $logging = new CRM_Logging_Schema(); $addressCustomTables = $logging->entityCustomDataLogTables('Address'); $contactIdClause = $join = ''; if ($contactID) { $params[3] = array($contactID, 'Integer'); switch ($table) { case 'civicrm_contact': $contactIdClause = "AND id = %3"; break; case 'civicrm_note': $contactIdClause = "AND (( entity_id = %3 AND entity_table = 'civicrm_contact' ) OR (entity_id IN (SELECT note.id FROM `{$this->db}`.log_civicrm_note note WHERE note.entity_id = %3 AND note.entity_table = 'civicrm_contact') AND entity_table = 'civicrm_note'))"; break; case 'civicrm_entity_tag': $contactIdClause = "AND entity_id = %3 AND entity_table = 'civicrm_contact'"; break; case 'civicrm_relationship': $contactIdClause = "AND (contact_id_a = %3 OR contact_id_b = %3)"; break; case 'civicrm_activity': $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name'); $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts); $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts); $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts); $join = "\nLEFT JOIN civicrm_activity_contact at ON at.activity_id = lt.id AND at.contact_id = %3 AND at.record_type_id = {$targetID}\nLEFT JOIN civicrm_activity_contact aa ON aa.activity_id = lt.id AND aa.contact_id = %3 AND aa.record_type_id = {$assigneeID}\nLEFT JOIN civicrm_activity_contact source ON source.activity_id = lt.id AND source.contact_id = %3 AND source.record_type_id = {$sourceID} "; $contactIdClause = "AND (at.id IS NOT NULL OR aa.id IS NOT NULL OR source.id IS NOT NULL)"; break; case 'civicrm_case': $contactIdClause = "AND id = (select case_id FROM civicrm_case_contact WHERE contact_id = %3 LIMIT 1)"; break; default: if (array_key_exists($table, $addressCustomTables)) { $join = "INNER JOIN `{$this->db}`.`log_civicrm_address` et ON et.id = lt.entity_id"; $contactIdClause = "AND contact_id = %3"; break; } // allow tables to be extended by report hook query objects list($contactIdClause, $join) = CRM_Report_BAO_Hook::singleton()->logDiffClause($this, $table); if (empty($contactIdClause)) { $contactIdClause = "AND contact_id = %3"; } if (strpos($table, 'civicrm_value') !== FALSE) { $contactIdClause = "AND entity_id = %3"; } } } // find ids in this table that were affected in the given connection (based on connection id and a ±10 s time period around the date) $sql = "\nSELECT DISTINCT lt.id FROM `{$this->db}`.`log_{$table}` lt\n{$join}\nWHERE lt.log_conn_id = %1 AND\n lt.log_date BETWEEN DATE_SUB(%2, INTERVAL {$this->interval}) AND DATE_ADD(%2, INTERVAL {$this->interval})\n {$contactIdClause}"; $dao = CRM_Core_DAO::executeQuery($sql, $params); while ($dao->fetch()) { $diffs = array_merge($diffs, $this->diffsInTableForId($table, $dao->id)); } return $diffs; }
function __construct() { $logging = new CRM_Logging_Schema(); $this->tables[] = 'civicrm_contribution'; $this->tables = array_merge($this->tables, array_keys($logging->customDataLogTables())); $this->detail = 'logging/contribute/detail'; $this->summary = 'logging/contribute/summary'; parent::__construct(); }
public function postProcess() { parent::postProcess(); // handle logging // FIXME: do it only if the setting changed require_once 'CRM/Logging/Schema.php'; $values = $this->exportValues(); $logging = new CRM_Logging_Schema(); $values['logging'] ? $logging->enableLogging() : $logging->disableLogging(); }
/** * Setting Callback - On Change. * * Respond to changes in the "logging" setting. Set up or destroy * triggers, etal. * * @param array $oldValue * List of component names. * @param array $newValue * List of component names. * @param array $metadata * Specification of the setting (per *.settings.php). */ public static function onToggle($oldValue, $newValue, $metadata) { if ($oldValue == $newValue) { return; } $logging = new CRM_Logging_Schema(); if ($newValue) { $logging->enableLogging(); } else { $logging->disableLogging(); } }
function __construct() { $logging = new CRM_Logging_Schema(); $this->tables[] = 'civicrm_contact'; $this->tables = array_merge($this->tables, array_keys($logging->customDataLogTables())); $this->tables[] = 'civicrm_email'; $this->tables[] = 'civicrm_phone'; $this->tables[] = 'civicrm_im'; $this->tables[] = 'civicrm_openid'; $this->tables[] = 'civicrm_website'; $this->tables[] = 'civicrm_address'; $this->tables[] = 'civicrm_note'; $this->tables[] = 'civicrm_relationship'; $this->detail = 'logging/contact/detail'; $this->summary = 'logging/contact/summary'; parent::__construct(); }
/** * Test creating logging schema when database is in multilingual mode. * Also test altering a multilingual table. */ public function testMultilingualAlterSchemaLogging() { CRM_Core_I18n_Schema::makeMultilingual('en_US'); $logging = new CRM_Logging_Schema(); $logging->enableLogging(); $value = CRM_Core_DAO::singleValueQuery("SELECT id FROM log_civicrm_contact LIMIT 1", array(), FALSE, FALSE); $this->assertNotNull($value, 'Logging not enabled successfully'); $logging->disableLogging(); CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_option_value` ADD COLUMN `logging_test` INT DEFAULT NULL", array(), FALSE, NULL, FALSE, TRUE); CRM_Core_I18n_Schema::rebuildMultilingualSchema(array('en_US')); $logging->enableLogging(); $query = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE `log_civicrm_option_value`", array(), TRUE, NULL, FALSE, FALSE); $query->fetch(); $create = explode("\n", $query->Create_Table); CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_option_value` DROP COLUMN `logging_test`", array(), FALSE, NULL, FALSE, TRUE); $this->assertTrue(in_array(" `logging_test` int(11) DEFAULT NULL", $create)); $logging->disableLogging(); }
function __construct() { $logging = new CRM_Logging_Schema(); $this->tables[] = 'civicrm_contact'; $this->tables = array_merge($this->tables, array_keys($logging->customDataLogTables())); $this->tables[] = 'civicrm_email'; $this->tables[] = 'civicrm_phone'; $this->tables[] = 'civicrm_im'; $this->tables[] = 'civicrm_openid'; $this->tables[] = 'civicrm_website'; $this->tables[] = 'civicrm_address'; $this->tables[] = 'civicrm_note'; $this->tables[] = 'civicrm_relationship'; $this->tables[] = 'civicrm_activity'; $this->tables[] = 'civicrm_case'; // allow tables to be extended by report hook query objects CRM_Report_BAO_Hook::singleton()->alterLogTables($this, $this->tables); $this->detail = 'logging/contact/detail'; $this->summary = 'logging/contact/summary'; parent::__construct(); }
static function alterFieldSQL(&$params, $indexExist = FALSE) { $sql = str_repeat(' ', 8); $sql .= "ALTER TABLE {$params['table_name']}"; // lets suppress the required flag, since that can cause sql issue $params['required'] = FALSE; switch ($params['operation']) { case 'add': $separator = "\n"; $prefix = "ADD "; $sql .= self::buildFieldSQL($params, $separator, "ADD COLUMN "); $separator = ",\n"; $sql .= self::buildPrimaryKeySQL($params, $separator, "ADD PRIMARY KEY "); $sql .= self::buildSearchIndexSQL($params, $separator, "ADD INDEX "); $sql .= self::buildForeignKeySQL($params, $separator, "ADD ", $params['table_name']); break; case 'modify': $separator = "\n"; $prefix = "MODIFY "; $sql .= self::buildFieldSQL($params, $separator, $prefix); $separator = ",\n"; $sql .= self::buildSearchIndexSQL($params, $separator, "ADD INDEX ", $indexExist); break; case 'delete': $sql .= " DROP COLUMN `{$params['name']}`"; if (CRM_Utils_Array::value('primary', $params)) { $sql .= ", DROP PRIMARY KEY"; } if (CRM_Utils_Array::value('fk_table_name', $params)) { $sql .= ", DROP FOREIGN KEY FK_{$params['fkName']}"; } break; } // CRM-7007: do not i18n-rewrite this query $dao = CRM_Core_DAO::executeQuery($sql, array(), TRUE, NULL, FALSE, FALSE); $dao->free(); $config = CRM_Core_Config::singleton(); if ($config->logging) { // logging support: if we’re adding a column (but only then!) make sure the potential relevant log table gets a column as well if ($params['operation'] == 'add') { $logging = new CRM_Logging_Schema(); $logging->fixSchemaDifferencesFor($params['table_name'], array($params['name'])); } elseif ($params['operation'] == 'delete') { // CRM-7293: if we’re dropping a column – rebuild triggers CRM_Core_DAO::triggerRebuild($params['table_name']); } } return TRUE; }
/** * Add records of the extension to the database -- and enable it * * @param array $keys * List of extension keys. * @throws CRM_Extension_Exception */ public function install($keys) { $origStatuses = $this->getStatuses(); // TODO: to mitigate the risk of crashing during installation, scan // keys/statuses/types before doing anything foreach ($keys as $key) { list($info, $typeManager) = $this->_getInfoTypeHandler($key); // throws Exception switch ($origStatuses[$key]) { case self::STATUS_INSTALLED: // ok, nothing to do break; case self::STATUS_DISABLED: // re-enable it $typeManager->onPreEnable($info); $this->_setExtensionActive($info, 1); $typeManager->onPostEnable($info); break; case self::STATUS_UNINSTALLED: // install anew $typeManager->onPreInstall($info); $this->_createExtensionEntry($info); $typeManager->onPostInstall($info); break; case self::STATUS_UNKNOWN: default: throw new CRM_Extension_Exception("Cannot install or enable extension: {$key}"); } } $this->statuses = NULL; $this->mapper->refresh(); CRM_Core_Invoke::rebuildMenuAndCaches(TRUE); $schema = new CRM_Logging_Schema(); $schema->fixSchemaDifferences(); foreach ($keys as $key) { list($info, $typeManager) = $this->_getInfoTypeHandler($key); // throws Exception switch ($origStatuses[$key]) { case self::STATUS_INSTALLED: // ok, nothing to do break; case self::STATUS_DISABLED: // re-enable it break; case self::STATUS_UNINSTALLED: // install anew $typeManager->onPostPostInstall($info); break; case self::STATUS_UNKNOWN: default: throw new CRM_Extension_Exception("Cannot install or enable extension: {$key}"); } } }
/** * Set this tables to reflect tables changed in a merge. */ protected function setTablesToContactRelatedTables() { $schema = new CRM_Logging_Schema(); $this->tables = $schema->getLogTablesForContact(); // allow tables to be extended by report hook query objects. // This is a report specific hook. It's unclear how it interacts to / overlaps the main one. // It probably precedes the main one and was never reconciled with it.... CRM_Report_BAO_Hook::singleton()->alterLogTables($this, $this->tables); }
/** * @param array $params * @param bool $indexExist * @param bool $triggerRebuild * * @return bool */ public static function alterFieldSQL(&$params, $indexExist = FALSE, $triggerRebuild = TRUE) { $sql = str_repeat(' ', 8); $sql .= "ALTER TABLE {$params['table_name']}"; // lets suppress the required flag, since that can cause sql issue $params['required'] = FALSE; switch ($params['operation']) { case 'add': $separator = "\n"; $prefix = "ADD "; $sql .= self::buildFieldSQL($params, $separator, "ADD COLUMN "); $separator = ",\n"; $sql .= self::buildPrimaryKeySQL($params, $separator, "ADD PRIMARY KEY "); $sql .= self::buildSearchIndexSQL($params, $separator, "ADD INDEX "); $sql .= self::buildForeignKeySQL($params, $separator, "ADD ", $params['table_name']); break; case 'modify': $separator = "\n"; $prefix = "MODIFY "; $sql .= self::buildFieldSQL($params, $separator, $prefix); $separator = ",\n"; $sql .= self::buildSearchIndexSQL($params, $separator, "ADD INDEX ", $indexExist); break; case 'delete': $sql .= " DROP COLUMN `{$params['name']}`"; if (!empty($params['primary'])) { $sql .= ", DROP PRIMARY KEY"; } if (!empty($params['fk_table_name'])) { $sql .= ", DROP FOREIGN KEY FK_{$params['fkName']}"; } break; } // CRM-7007: do not i18n-rewrite this query $dao = CRM_Core_DAO::executeQuery($sql, array(), TRUE, NULL, FALSE, FALSE); $dao->free(); $config = CRM_Core_Config::singleton(); if ($config->logging) { // CRM-16717 not sure why this was originally limited to add. // For example custom tables can have field length changes - which need to flow through to logging. // Are there any modifies we DON'T was to call this function for (& shouldn't it be clever enough to cope?) if ($params['operation'] == 'add' || $params['operation'] == 'modify') { $logging = new CRM_Logging_Schema(); $logging->fixSchemaDifferencesFor($params['table_name'], array(trim($prefix) => array($params['name'])), FALSE); } } if ($triggerRebuild) { CRM_Core_DAO::triggerRebuild($params['table_name']); } return TRUE; }
public static function doFinish() { $upgrade = new CRM_Upgrade_Form(); list($ignore, $latestVer) = $upgrade->getUpgradeVersions(); // Seems extraneous in context, but we'll preserve old behavior $upgrade->setVersion($latestVer); // Clear cached metadata. Civi::service('settings_manager')->flush(); // cleanup caches CRM-8739 $config = CRM_Core_Config::singleton(); $config->cleanupCaches(1); // Rebuild all triggers and re-enable logging if needed $logging = new CRM_Logging_Schema(); $logging->fixSchemaDifferences(); //CRM-16257 update Config.IDS.ini might be an old copy CRM_Core_IDS::createConfigFile(TRUE); }
public function postProcess() { // store the submitted values in an array $config = CRM_Core_Config::singleton(); $params = $this->controller->exportValues($this->_name); // update upload max size in DB $params['maxImportFileSize'] = CRM_Core_Config_Defaults::formatUnitSize(ini_get('upload_max_filesize')); CRM_Core_BAO_ConfigSetting::create($params); // get current logging status $values = $this->exportValues(); parent::postProcess(); if ($config->logging != $values['logging']) { $logging = new CRM_Logging_Schema(); if ($values['logging']) { $logging->enableLogging(); } else { $logging->disableLogging(); } } }
/** * Function for find out whether to use logging schema entries for contact * summary, instead of normal log entries. * * @return int report id of Contact Logging Report (Summary) / false * @access public * @static */ static function useLoggingReport() { // first check if logging is enabled $config = CRM_Core_Config::singleton(); if (!$config->logging) { return FALSE; } $loggingSchema = new CRM_Logging_Schema(); if ($loggingSchema->isEnabled()) { $params = array('report_id' => 'logging/contact/summary'); $instance = array(); CRM_Report_BAO_ReportInstance::retrieve($params, $instance); if (!empty($instance) && (empty($instance['permission']) || !empty($instance['permission']) && CRM_Core_Permission::check($instance['permission']))) { return $instance['id']; } } return FALSE; }
public function postProcess() { // store the submitted values in an array $config = CRM_Core_Config::singleton(); $params = $this->controller->exportValues($this->_name); // get current logging status $values = $this->exportValues(); parent::postProcess(); if ($config->logging != $values['logging']) { $logging = new CRM_Logging_Schema(); if ($values['logging']) { $logging->enableLogging(); } else { $logging->disableLogging(); } } }
/** * Wrapper function to drop triggers. * * @param string $tableName * the specific table requiring a rebuild; or NULL to rebuild all tables. */ public static function dropTriggers($tableName = NULL) { $info = array(); $logging = new CRM_Logging_Schema(); $logging->triggerInfo($info, $tableName); // drop all existing triggers on all tables $logging->dropTriggers($tableName); }
/** * Implements hook_civicrm_uninstall(). * * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall */ function mosaico_civicrm_uninstall() { _mosaico_civix_civicrm_uninstall(); $schema = new CRM_Logging_Schema(); $schema->fixSchemaDifferences(); }
public static function doFinish() { $upgrade = new CRM_Upgrade_Form(); list($ignore, $latestVer) = $upgrade->getUpgradeVersions(); // Seems extraneous in context, but we'll preserve old behavior $upgrade->setVersion($latestVer); // lets rebuild the config array in case we've made a few changes in the // code base // this also helps us always store the latest version of civi in the DB $params = array(); CRM_Core_BAO_ConfigSetting::add($params); // CRM-12804 comment-51411 : add any missing settings // at the end of upgrade CRM_Core_BAO_Setting::updateSettingsFromMetaData(); // cleanup caches CRM-8739 $config = CRM_Core_Config::singleton(); $config->cleanupCaches(1); // Rebuild all triggers and re-enable logging if needed $logging = new CRM_Logging_Schema(); $logging->fixSchemaDifferences(); //CRM-16257 update Config.IDS.ini might be an old copy CRM_Core_IDS::createConfigFile(TRUE); }
static function triggerRebuild($tableName = NULL) { $info = array(); $logging = new CRM_Logging_Schema(); $logging->triggerInfo($info, $tableName); CRM_Core_I18n_Schema::triggerInfo($info, $tableName); CRM_Utils_Hook::triggerInfo($info, $tableName); // drop all existing triggers on all tables $logging->dropTriggers($tableName); // now create the set of new triggers self::createTriggers($info); }
/** * Switch database from multi-lang back to single (by dropping * additional columns and views and retaining only the selected locale). * * @param $retain string the locale to retain * * @return void */ static function makeSinglelingual($retain) { $domain = new CRM_Core_DAO_Domain(); $domain->find(TRUE); $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales); // break early if the db is already single-lang if (!$locales) { return; } // lets drop all triggers first $logging = new CRM_Logging_Schema(); $logging->dropTriggers(); // turn subsequent tables singlelingual $tables = CRM_Core_I18n_SchemaStructure::tables(); foreach ($tables as $table) { self::makeSinglelingualTable($retain, $table); } // update civicrm_domain.locales $domain->locales = 'NULL'; $domain->save(); //CRM-6963 -fair assumption. global $dbLocale; $dbLocale = ''; // now lets rebuild all triggers CRM_Core_DAO::triggerRebuild(); }
/** * Assert logging is enabled or disabled as per input parameter. * * @param bool $expected * Do we expect it to be enabled. */ protected function assertLoggingEnabled($expected) { $schema = new CRM_Logging_Schema(); $this->assertTrue($schema->isEnabled() === $expected); }