Commit cf24b4fe authored by Mathieu Lutfy's avatar Mathieu Lutfy Committed by Aegir user
Browse files

infrastructure/ops#874 Add civiext nz.co.fuzion.innodbtriggers

parent d2341829
This diff is collapsed.
# INNODB logging
Makes CiviCRM use the INNODB, rather than Archive table format for detailed logging.
The INNODB format is arguablly a better format for CiviCRM logging. Although INNODB tables take more space, they can be queried much more effectively, which is useful when you want to consult the logs. Consulting the change log for ARCHIVE tables is phohibitivley slow once your logging has been running a while.
## See also
* https://civicrm.org/blog/eileen/who-did-what-when - a blog post explaining the motivations behind this extension in more detail
* https://docs.civicrm.org/sysadmin/en/latest/setup/logging/ for more information on logging
<?xml version="1.0"?>
<extension key="nz.co.fuzion.innodbtriggers" type="module">
<file>innodbtriggers</file>
<name>INNODB triggers</name>
<description>Converts the files managed by triggers to INNODB and indexes them</description>
<license>AGPL-3.0</license>
<maintainer>
<author>FIXME</author>
<email>FIXME</email>
</maintainer>
<urls>
<url desc="Main Extension Page">http://FIXME</url>
<url desc="Documentation">http://FIXME</url>
<url desc="Support">http://FIXME</url>
<url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2016-03-17</releaseDate>
<version>1.0</version>
<develStage>alpha</develStage>
<compatibility>
<ver>4.7</ver>
</compatibility>
<comments>Requires logging pages currently targetted at 4.7.5. If log tables already exist run civicrm-api setting.updatelogtables</comments>
<civix>
<namespace>CRM/Innodbtriggers</namespace>
</civix>
</extension>
<?php
// AUTO-GENERATED FILE -- Civix may overwrite any changes made to this file
/**
* (Delegated) Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
*/
function _innodbtriggers_civix_civicrm_config(&$config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$template =& CRM_Core_Smarty::singleton();
$extRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR;
$extDir = $extRoot . 'templates';
if ( is_array( $template->template_dir ) ) {
array_unshift( $template->template_dir, $extDir );
}
else {
$template->template_dir = array( $extDir, $template->template_dir );
}
$include_path = $extRoot . PATH_SEPARATOR . get_include_path( );
set_include_path($include_path);
}
/**
* (Delegated) Implements hook_civicrm_xmlMenu().
*
* @param $files array(string)
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
*/
function _innodbtriggers_civix_civicrm_xmlMenu(&$files) {
foreach (_innodbtriggers_civix_glob(__DIR__ . '/xml/Menu/*.xml') as $file) {
$files[] = $file;
}
}
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
*/
function _innodbtriggers_civix_civicrm_install() {
_innodbtriggers_civix_civicrm_config();
if ($upgrader = _innodbtriggers_civix_upgrader()) {
$upgrader->onInstall();
}
}
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
*/
function _innodbtriggers_civix_civicrm_uninstall() {
_innodbtriggers_civix_civicrm_config();
if ($upgrader = _innodbtriggers_civix_upgrader()) {
$upgrader->onUninstall();
}
}
/**
* (Delegated) Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
*/
function _innodbtriggers_civix_civicrm_enable() {
_innodbtriggers_civix_civicrm_config();
if ($upgrader = _innodbtriggers_civix_upgrader()) {
if (is_callable(array($upgrader, 'onEnable'))) {
$upgrader->onEnable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
* @return mixed
*/
function _innodbtriggers_civix_civicrm_disable() {
_innodbtriggers_civix_civicrm_config();
if ($upgrader = _innodbtriggers_civix_upgrader()) {
if (is_callable(array($upgrader, 'onDisable'))) {
$upgrader->onDisable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_upgrade().
*
* @param $op string, the type of operation being performed; 'check' or 'enqueue'
* @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
*
* @return mixed based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
*/
function _innodbtriggers_civix_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
if ($upgrader = _innodbtriggers_civix_upgrader()) {
return $upgrader->onUpgrade($op, $queue);
}
}
/**
* @return CRM_Innodbtriggers_Upgrader
*/
function _innodbtriggers_civix_upgrader() {
if (!file_exists(__DIR__.'/CRM/Innodbtriggers/Upgrader.php')) {
return NULL;
}
else {
return CRM_Innodbtriggers_Upgrader_Base::instance();
}
}
/**
* Search directory tree for files which match a glob pattern
*
* Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
* Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles()
*
* @param $dir string, base dir
* @param $pattern string, glob pattern, eg "*.txt"
* @return array(string)
*/
function _innodbtriggers_civix_find_files($dir, $pattern) {
if (is_callable(array('CRM_Utils_File', 'findFiles'))) {
return CRM_Utils_File::findFiles($dir, $pattern);
}
$todos = array($dir);
$result = array();
while (!empty($todos)) {
$subdir = array_shift($todos);
foreach (_innodbtriggers_civix_glob("$subdir/$pattern") as $match) {
if (!is_dir($match)) {
$result[] = $match;
}
}
if ($dh = opendir($subdir)) {
while (FALSE !== ($entry = readdir($dh))) {
$path = $subdir . DIRECTORY_SEPARATOR . $entry;
if ($entry{0} == '.') {
} elseif (is_dir($path)) {
$todos[] = $path;
}
}
closedir($dh);
}
}
return $result;
}
/**
* (Delegated) Implements hook_civicrm_managed().
*
* Find any *.mgd.php files, merge their content, and return.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
*/
function _innodbtriggers_civix_civicrm_managed(&$entities) {
$mgdFiles = _innodbtriggers_civix_find_files(__DIR__, '*.mgd.php');
foreach ($mgdFiles as $file) {
$es = include $file;
foreach ($es as $e) {
if (empty($e['module'])) {
$e['module'] = 'nz.co.fuzion.innodbtriggers';
}
$entities[] = $e;
}
}
}
/**
* (Delegated) Implements hook_civicrm_caseTypes().
*
* Find any and return any files matching "xml/case/*.xml"
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function _innodbtriggers_civix_civicrm_caseTypes(&$caseTypes) {
if (!is_dir(__DIR__ . '/xml/case')) {
return;
}
foreach (_innodbtriggers_civix_glob(__DIR__ . '/xml/case/*.xml') as $file) {
$name = preg_replace('/\.xml$/', '', basename($file));
if ($name != CRM_Case_XMLProcessor::mungeCaseType($name)) {
$errorMessage = sprintf("Case-type file name is malformed (%s vs %s)", $name, CRM_Case_XMLProcessor::mungeCaseType($name));
CRM_Core_Error::fatal($errorMessage);
// throw new CRM_Core_Exception($errorMessage);
}
$caseTypes[$name] = array(
'module' => 'nz.co.fuzion.innodbtriggers',
'name' => $name,
'file' => $file,
);
}
}
/**
* (Delegated) Implements hook_civicrm_angularModules().
*
* Find any and return any files matching "ang/*.ang.php"
*
* Note: This hook only runs in CiviCRM 4.5+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules
*/
function _innodbtriggers_civix_civicrm_angularModules(&$angularModules) {
if (!is_dir(__DIR__ . '/ang')) {
return;
}
$files = _innodbtriggers_civix_glob(__DIR__ . '/ang/*.ang.php');
foreach ($files as $file) {
$name = preg_replace(':\.ang\.php$:', '', basename($file));
$module = include $file;
if (empty($module['ext'])) {
$module['ext'] = 'nz.co.fuzion.innodbtriggers';
}
$angularModules[$name] = $module;
}
}
/**
* Glob wrapper which is guaranteed to return an array.
*
* The documentation for glob() says, "On some systems it is impossible to
* distinguish between empty match and an error." Anecdotally, the return
* result for an empty match is sometimes array() and sometimes FALSE.
* This wrapper provides consistency.
*
* @link http://php.net/glob
* @param string $pattern
* @return array, possibly empty
*/
function _innodbtriggers_civix_glob($pattern) {
$result = glob($pattern);
return is_array($result) ? $result : array();
}
/**
* Inserts a navigation menu item at a given place in the hierarchy.
*
* @param array $menu - menu hierarchy
* @param string $path - path where insertion should happen (ie. Administer/System Settings)
* @param array $item - menu you need to insert (parent/child attributes will be filled for you)
*/
function _innodbtriggers_civix_insert_navigation_menu(&$menu, $path, $item) {
// If we are done going down the path, insert menu
if (empty($path)) {
$menu[] = array(
'attributes' => array_merge(array(
'label' => CRM_Utils_Array::value('name', $item),
'active' => 1,
), $item),
);
return TRUE;
}
else {
// Find an recurse into the next level down
$found = false;
$path = explode('/', $path);
$first = array_shift($path);
foreach ($menu as $key => &$entry) {
if ($entry['attributes']['name'] == $first) {
if (!$entry['child']) $entry['child'] = array();
$found = _innodbtriggers_civix_insert_navigation_menu($entry['child'], implode('/', $path), $item, $key);
}
}
return $found;
}
}
/**
* (Delegated) Implements hook_civicrm_navigationMenu().
*/
function _innodbtriggers_civix_navigationMenu(&$nodes) {
if (!is_callable(array('CRM_Core_BAO_Navigation', 'fixNavigationMenu'))) {
_innodbtriggers_civix_fixNavigationMenu($nodes);
}
}
/**
* Given a navigation menu, generate navIDs for any items which are
* missing them.
*/
function _innodbtriggers_civix_fixNavigationMenu(&$nodes) {
$maxNavID = 1;
array_walk_recursive($nodes, function($item, $key) use (&$maxNavID) {
if ($key === 'navID') {
$maxNavID = max($maxNavID, $item);
}
});
_innodbtriggers_civix_fixNavigationMenuItems($nodes, $maxNavID, NULL);
}
function _innodbtriggers_civix_fixNavigationMenuItems(&$nodes, &$maxNavID, $parentID) {
$origKeys = array_keys($nodes);
foreach ($origKeys as $origKey) {
if (!isset($nodes[$origKey]['attributes']['parentID']) && $parentID !== NULL) {
$nodes[$origKey]['attributes']['parentID'] = $parentID;
}
// If no navID, then assign navID and fix key.
if (!isset($nodes[$origKey]['attributes']['navID'])) {
$newKey = ++$maxNavID;
$nodes[$origKey]['attributes']['navID'] = $newKey;
$nodes[$newKey] = $nodes[$origKey];
unset($nodes[$origKey]);
$origKey = $newKey;
}
if (isset($nodes[$origKey]['child']) && is_array($nodes[$origKey]['child'])) {
_innodbtriggers_civix_fixNavigationMenuItems($nodes[$origKey]['child'], $maxNavID, $nodes[$origKey]['attributes']['navID']);
}
}
}
/**
* (Delegated) Implements hook_civicrm_alterSettingsFolders().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_alterSettingsFolders
*/
function _innodbtriggers_civix_civicrm_alterSettingsFolders(&$metaDataFolders = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$settingsDir = __DIR__ . DIRECTORY_SEPARATOR . 'settings';
if(is_dir($settingsDir) && !in_array($settingsDir, $metaDataFolders)) {
$metaDataFolders[] = $settingsDir;
}
}
<?php
require_once 'innodbtriggers.civix.php';
/**
* Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
*/
function innodbtriggers_civicrm_config(&$config) {
_innodbtriggers_civix_civicrm_config($config);
}
/**
* Implements hook_civicrm_xmlMenu().
*
* @param array $files
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
*/
function innodbtriggers_civicrm_xmlMenu(&$files) {
_innodbtriggers_civix_civicrm_xmlMenu($files);
}
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
*/
function innodbtriggers_civicrm_install() {
_innodbtriggers_civix_civicrm_install();
}
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
*/
function innodbtriggers_civicrm_uninstall() {
_innodbtriggers_civix_civicrm_uninstall();
}
/**
* Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
*/
function innodbtriggers_civicrm_enable() {
_innodbtriggers_civix_civicrm_enable();
}
/**
* Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
*/
function innodbtriggers_civicrm_disable() {
_innodbtriggers_civix_civicrm_disable();
}
/**
* Implements hook_civicrm_upgrade().
*
* @param $op string, the type of operation being performed; 'check' or 'enqueue'
* @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
*
* @return mixed
* Based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
*/
function innodbtriggers_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
return _innodbtriggers_civix_civicrm_upgrade($op, $queue);
}
/**
* Implements hook_civicrm_managed().
*
* Generate a list of entities to create/deactivate/delete when this module
* is installed, disabled, uninstalled.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
*/
function innodbtriggers_civicrm_managed(&$entities) {
_innodbtriggers_civix_civicrm_managed($entities);
}
/**
* Implements hook_civicrm_caseTypes().
*
* Generate a list of case-types.
*
* @param array $caseTypes
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function innodbtriggers_civicrm_caseTypes(&$caseTypes) {
_innodbtriggers_civix_civicrm_caseTypes($caseTypes);
}
/**
* Implements hook_civicrm_angularModules().
*
* Generate a list of Angular modules.
*
* Note: This hook only runs in CiviCRM 4.5+. It may
* use features only available in v4.6+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function innodbtriggers_civicrm_angularModules(&$angularModules) {
_innodbtriggers_civix_civicrm_angularModules($angularModules);
}
/**
* Implements hook_civicrm_alterSettingsFolders().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_alterSettingsFolders
*/
function innodbtriggers_civicrm_alterSettingsFolders(&$metaDataFolders = NULL) {
_innodbtriggers_civix_civicrm_alterSettingsFolders($metaDataFolders);
}
/**
* Implements hook_alterLogTables().
*
* @param array $logTableSpec
*/
function innodbtriggers_civicrm_alterLogTables(&$logTableSpec) {
$contactReferences = CRM_Dedupe_Merger::cidRefs();
foreach (array_keys($logTableSpec) as $tableName) {
$contactIndexes = array();
$logTableSpec[$tableName]['engine'] = 'INNODB';
$logTableSpec[$tableName]['engine_config'] = 'ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4';
$contactRefsForTable = CRM_Utils_Array::value($tableName, $contactReferences, array());
foreach ($contactRefsForTable as $fieldName) {
$contactIndexes['index_' . $fieldName] = $fieldName;
}
$indexArray = array(
'index_log_conn_id' => 'log_conn_id',
'index_log_date' => 'log_date',
);
// Check if current table has an "id" column. If so, index it too
$dsn = DB::parseDSN(CIVICRM_DSN);
$dbName = $dsn['database'];
$dao = CRM_Core_DAO::executeQuery("
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = '{$dbName}'
AND TABLE_NAME = '{$tableName}'
AND COLUMN_NAME = 'id'
");
if ($dao->fetch()){
$indexArray['index_id'] = 'id';
}
$logTableSpec[$tableName]['indexes'] = array_merge($indexArray, $contactIndexes);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment