Commit 68b57508 authored by Robert Lyon's avatar Robert Lyon Committed by Cecilia Vela Gurovic
Browse files

Bug 1785985: Remove notification triggers



- building a php based way to update notification read count

behatnotneeded

Change-Id: Ibfdb79e36460a327372b1c9da3f624d7c8210d0c
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent 00d43725
...@@ -1490,6 +1490,13 @@ function xmldb_core_upgrade($oldversion=0) { ...@@ -1490,6 +1490,13 @@ function xmldb_core_upgrade($oldversion=0) {
safe_require('search', 'elasticsearch'); safe_require('search', 'elasticsearch');
ElasticSearchIndexing::drop_trigger_functions(); ElasticSearchIndexing::drop_trigger_functions();
} }
log_debug('Remove triggers for notifications');
db_drop_trigger('update_unread_insert', 'notification_internal_activity');
db_drop_trigger('update_unread_update', 'notification_internal_activity');
db_drop_trigger('update_unread_delete', 'notification_internal_activity');
db_drop_trigger('update_unread_insert2', 'module_multirecipient_userrelation');
db_drop_trigger('update_unread_update2', 'module_multirecipient_userrelation');
db_drop_trigger('update_unread_delete2', 'module_multirecipient_userrelation');
} }
return $status; return $status;
......
...@@ -132,10 +132,11 @@ function column_collation_is_default($table, $column) { ...@@ -132,10 +132,11 @@ function column_collation_is_default($table, $column) {
* @uses $db * @uses $db
* @param string $command The sql string you wish to be executed. * @param string $command The sql string you wish to be executed.
* @param array $values When using prepared statements, this is the value array (optional). * @param array $values When using prepared statements, this is the value array (optional).
* @param string $use_trigger Allow the sql query to do fall through to pseudo_trigger
* @return boolean * @return boolean
* @throws SQLException * @throws SQLException
*/ */
function execute_sql($command, array $values=null) { function execute_sql($command, array $values=null, $use_trigger=true) {
global $db; global $db;
if (!is_a($db, 'ADOConnection')) { if (!is_a($db, 'ADOConnection')) {
...@@ -145,7 +146,7 @@ function execute_sql($command, array $values=null) { ...@@ -145,7 +146,7 @@ function execute_sql($command, array $values=null) {
$command = db_quote_table_placeholders($command); $command = db_quote_table_placeholders($command);
list($sqltype, $table, $idsql, $bindoffset) = get_table_from_query($command); list($sqltype, $table, $idsql, $bindoffset) = get_table_from_query($command);
if (!is_null($sqltype) && !is_null($table) && !is_null($idsql)) { if (!is_null($sqltype) && !is_null($table) && !is_null($idsql)) {
if ($type = table_need_trigger($table)) { if ($use_trigger && $type = table_need_trigger($table)) {
// Need to find the ids // Need to find the ids
if (!empty($values) && is_array($values) && count($values) > 0) { if (!empty($values) && is_array($values) && count($values) > 0) {
$bindvals = array_slice($values, $bindoffset); $bindvals = array_slice($values, $bindoffset);
...@@ -961,6 +962,7 @@ function set_field_select($table, $newfield, $newvalue, $select, array $values) ...@@ -961,6 +962,7 @@ function set_field_select($table, $newfield, $newvalue, $select, array $values)
$select = db_quote_table_placeholders($select); $select = db_quote_table_placeholders($select);
$calllocal = false;
if ($type = table_need_trigger($table)) { if ($type = table_need_trigger($table)) {
// Need to find the ids // Need to find the ids
$sql = "SELECT *, '" . $table . "' AS " . db_quote_identifier('table') . " FROM " . db_table_name($table) . ' ' . $select; $sql = "SELECT *, '" . $table . "' AS " . db_quote_identifier('table') . " FROM " . db_table_name($table) . ' ' . $select;
...@@ -969,17 +971,35 @@ function set_field_select($table, $newfield, $newvalue, $select, array $values) ...@@ -969,17 +971,35 @@ function set_field_select($table, $newfield, $newvalue, $select, array $values)
safe_require('search', 'elasticsearch'); safe_require('search', 'elasticsearch');
ElasticsearchIndexing::bulk_add_to_queue($ids); ElasticsearchIndexing::bulk_add_to_queue($ids);
} }
else if ($type == 'local') {
$calllocal = true;
}
} }
$values = array_merge(array($newvalue), $values); $values = array_merge(array($newvalue), $values);
$sql = 'UPDATE '. db_table_name($table) .' SET '. db_quote_identifier($newfield) .' = ? ' . $select; $sql = 'UPDATE '. db_table_name($table) .' SET '. db_quote_identifier($newfield) .' = ? ' . $select;
try { try {
$stmt = $db->Prepare($sql); $stmt = $db->Prepare($sql);
return $db->Execute($stmt, $values); $dbex = $db->Execute($stmt, $values);
} }
catch (ADODB_Exception $e) { catch (ADODB_Exception $e) {
throw new SQLException(create_sql_exception_message($e, $sql, $values)); throw new SQLException(create_sql_exception_message($e, $sql, $values));
} }
if ($calllocal) {
// Call the correct function / savetype
$classname = generate_class_name_from_table($table);
list($plugintype, $pluginname) = generate_plugin_type_from_table($table);
if ($plugintype && $pluginname) {
safe_require($plugintype, $pluginname);
if (method_exists($classname, 'pseudo_trigger')) {
foreach ($ids as $id) {
call_static_method($classname, 'pseudo_trigger', $id->id, 'update');
}
}
}
}
return $dbex;
} }
...@@ -1240,6 +1260,9 @@ function insert_record($table, $dataobject, $primarykey=false, $returnpk=false) ...@@ -1240,6 +1260,9 @@ function insert_record($table, $dataobject, $primarykey=false, $returnpk=false)
} }
function table_need_trigger($table) { function table_need_trigger($table) {
if ($dbprefix = get_config('dbprefix')) {
$table = preg_replace('/' . $dbprefix . '/', '', $table);
}
if (defined('SKIP_TRIGGER') && SKIP_TRIGGER === true) { if (defined('SKIP_TRIGGER') && SKIP_TRIGGER === true) {
return false; return false;
} }
...@@ -1256,6 +1279,10 @@ function table_need_trigger($table) { ...@@ -1256,6 +1279,10 @@ function table_need_trigger($table) {
return 'es'; return 'es';
} }
} }
$localtables = array('notification_internal_activity', 'module_multirecipient_userrelation'); // @TODO have the working out of local tables be a function call
if (isset($localtables) && in_array($table, $localtables)) {
return 'local';
}
return false; return false;
} }
...@@ -1266,6 +1293,17 @@ function pseudo_trigger($table, $data, $id, $savetype = 'insert') { ...@@ -1266,6 +1293,17 @@ function pseudo_trigger($table, $data, $id, $savetype = 'insert') {
safe_require('search', 'elasticsearch'); safe_require('search', 'elasticsearch');
ElasticsearchIndexing::add_to_queue($id, $table, $artefacttype); ElasticsearchIndexing::add_to_queue($id, $table, $artefacttype);
} }
else if ($type == 'local') {
// Call the correct function / savetype
$classname = generate_class_name_from_table($table);
list($plugintype, $pluginname) = generate_plugin_type_from_table($table);
if ($plugintype && $pluginname) {
safe_require($plugintype, $pluginname);
if (method_exists($classname, 'pseudo_trigger')) {
call_static_method($classname, 'pseudo_trigger', $id, $savetype);
}
}
}
} }
} }
...@@ -1444,6 +1482,7 @@ function update_record($table, $dataobject, $where=null, $primarykey=false, $ret ...@@ -1444,6 +1482,7 @@ function update_record($table, $dataobject, $where=null, $primarykey=false, $ret
// Run the query // Run the query
$sql = 'UPDATE '. db_table_name($table) .' SET '. $setclause . ' WHERE ' . $whereclause; $sql = 'UPDATE '. db_table_name($table) .' SET '. $setclause . ' WHERE ' . $whereclause;
$calllocal = false;
// Work out table name and get ids // Work out table name and get ids
list($sqltype, $table, $idsql, $bindoffset) = get_table_from_query($sql); list($sqltype, $table, $idsql, $bindoffset) = get_table_from_query($sql);
if ($sqltype == 'update' && !is_null($table) && !is_null($idsql)) { if ($sqltype == 'update' && !is_null($table) && !is_null($idsql)) {
...@@ -1464,22 +1503,41 @@ function update_record($table, $dataobject, $where=null, $primarykey=false, $ret ...@@ -1464,22 +1503,41 @@ function update_record($table, $dataobject, $where=null, $primarykey=false, $ret
safe_require('search', 'elasticsearch'); safe_require('search', 'elasticsearch');
ElasticsearchIndexing::bulk_add_to_queue($ids); ElasticsearchIndexing::bulk_add_to_queue($ids);
} }
else if ($type == 'local') {
$calllocal = true;
}
} }
} }
$dbex = false;
try { try {
$stmt = $db->Prepare($sql); $stmt = $db->Prepare($sql);
$rs = $db->Execute($stmt, array_merge($setclausevalues, $wherevalues)); $rs = $db->Execute($stmt, array_merge($setclausevalues, $wherevalues));
if ($returnpk) { if ($returnpk) {
$primarykey = $primarykey ? $primarykey : 'id'; $primarykey = $primarykey ? $primarykey : 'id';
$returnsql = 'SELECT ' . $primarykey . ' FROM ' . db_table_name($table) . ' WHERE ' . $whereclause; $returnsql = 'SELECT ' . $primarykey . ' FROM ' . db_table_name($table) . ' WHERE ' . $whereclause;
return get_field_sql($returnsql, $wherevalues); $dbex = get_field_sql($returnsql, $wherevalues);
} }
return true; $dbex = true;
} }
catch (ADODB_Exception $e) { catch (ADODB_Exception $e) {
throw new SQLException(create_sql_exception_message($e, $sql, array_merge($setclausevalues, $wherevalues))); throw new SQLException(create_sql_exception_message($e, $sql, array_merge($setclausevalues, $wherevalues)));
} }
if ($calllocal && !empty($ids)) {
// Call the correct function / savetype
$classname = generate_class_name_from_table($table);
list($plugintype, $pluginname) = generate_plugin_type_from_table($table);
if ($plugintype && $pluginname) {
safe_require($plugintype, $pluginname);
if (method_exists($classname, 'pseudo_trigger')) {
foreach ($ids as $id) {
call_static_method($classname, 'pseudo_trigger', $id->id, 'update');
}
}
}
}
return $dbex;
} }
......
...@@ -1825,6 +1825,31 @@ function generate_class_name() { ...@@ -1825,6 +1825,31 @@ function generate_class_name() {
return 'Plugin' . implode('', array_map('ucfirst', $args)); return 'Plugin' . implode('', array_map('ucfirst', $args));
} }
function generate_class_name_from_table() {
$tableargs = func_get_args();
$args = generate_plugin_type_from_table($tableargs[0]);
return 'Plugin' . implode('', array_map('ucfirst', $args));
}
function generate_plugin_type_from_table() {
$tableargs = func_get_args();
$table = $tableargs[0];
if ($prefix = get_config('dbprefix')) {
$table = preg_replace('/' . $prefix . '/', '', $table);
}
$tableargs = explode('_', $table);
if (count($tableargs) > 2) {
$args = array_slice($tableargs, 0, 2);
// Fix for multirecipientnotifications where table name doesn't follow convention
if (isset($args[1]) && $args[1] == 'multirecipient') {
$args[1] = 'multirecipientnotification';
}
}
return array((isset($args[0]) ? $args[0] : null), (isset($args[1]) ? $args[1] : null));
}
function generate_artefact_class_name($type) { function generate_artefact_class_name($type) {
return 'ArtefactType' . ucfirst($type); return 'ArtefactType' . ucfirst($type);
} }
......
...@@ -119,34 +119,27 @@ class PluginModuleMultirecipientnotification extends PluginModule { ...@@ -119,34 +119,27 @@ class PluginModuleMultirecipientnotification extends PluginModule {
return $tabs; return $tabs;
} }
/**
* The pseudo trigger function that should work like how triggers worked before
* But instead of things happening automatically at db level
* we call the command at the dml.php level to have some control over it
* @param string $id The id of the user to update
* @param string $savetype Whether we are doing an insert / update / or delete
* - Note: in this instance of the pseudo_trigger() we don't care about the $savetype
* as we can work out the current state via an SQL query
*/
public static function pseudo_trigger($id, $savetype = 'insert') {
$usr = get_field('module_multirecipient_userrelation', 'usr', 'id', $id);
execute_sql("UPDATE {usr} SET unread = (
SELECT SUM(counts) FROM (
SELECT COUNT(*) AS counts FROM {module_multirecipient_userrelation} WHERE \"role\" = 'recipient' AND \"read\" = ? AND usr = ?
UNION
SELECT COUNT(*) AS counts FROM {notification_internal_activity} WHERE \"read\" = ? AND usr = ?
) AS countsum
) WHERE id = ?", array('0', $usr, 0, $usr, $usr), false);
}
public static function postinst($prevversion) { public static function postinst($prevversion) {
if ($prevversion < 20131010) {
// Add triggers to update user unread message count when updating
// module_multirecipient_userrelation
db_create_trigger(
'update_unread_insert2',
'AFTER', 'INSERT', 'module_multirecipient_userrelation', '
IF NEW.role = \'recipient\' AND NEW.read = \'0\' THEN
UPDATE {usr} SET unread = unread + 1 WHERE id = NEW.usr;
END IF;'
);
db_create_trigger(
'update_unread_update2',
'AFTER', 'UPDATE', 'module_multirecipient_userrelation', '
IF OLD.read = \'0\' AND NEW.read = \'1\' AND NEW.role = \'recipient\' THEN
UPDATE {usr} SET unread = unread - 1 WHERE id = NEW.usr;
ELSEIF OLD.read = \'1\' AND NEW.read = \'0\' AND NEW.role = \'recipient\' THEN
UPDATE {usr} SET unread = unread + 1 WHERE id = NEW.usr;
END IF;'
);
db_create_trigger(
'update_unread_delete2',
'AFTER', 'DELETE', 'module_multirecipient_userrelation', '
IF OLD.read = \'0\' AND OLD.role = \'recipient\' THEN
UPDATE {usr} SET unread = unread - 1 WHERE id = OLD.usr;
END IF;'
);
}
} }
/** /**
......
...@@ -66,34 +66,27 @@ class PluginNotificationInternal extends PluginNotification { ...@@ -66,34 +66,27 @@ class PluginNotificationInternal extends PluginNotification {
return $messageid; return $messageid;
} }
/**
* The pseudo trigger function that should work like how triggers worked before
* But instead of things happening automatically at db level
* we call the command at the dml.php level to have some control over it
* @param string $id The id of the user to update
* @param string $savetype Whether we are doing an insert / update / or delete
* - Note: in this instance of the pseudo_trigger() we don't care about the $savetype
* as we can work out the current state via an SQL query
*/
public static function pseudo_trigger($id, $savetype = 'insert') {
$usr = get_field('notification_internal_activity', 'usr', 'id', $id);
execute_sql("UPDATE {usr} SET unread = (
SELECT SUM(counts) FROM (
SELECT COUNT(*) AS counts FROM {module_multirecipient_userrelation} WHERE \"role\" = 'recipient' AND \"read\" = ? AND usr = ?
UNION
SELECT COUNT(*) AS counts FROM {notification_internal_activity} WHERE \"read\" = ? AND usr = ?
) AS countsum
) WHERE id = ?", array(0, $usr, 0, $usr, $usr), false);
}
public static function postinst($prevversion) { public static function postinst($prevversion) {
if ($prevversion == 0) {
// Add triggers to update user unread message count when updating
// notification_internal_activity
db_create_trigger(
'update_unread_insert',
'AFTER', 'INSERT', 'notification_internal_activity', '
IF NEW.read = 0 THEN
UPDATE {usr} SET unread = unread + 1 WHERE id = NEW.usr;
END IF;'
);
db_create_trigger(
'update_unread_update',
'AFTER', 'UPDATE', 'notification_internal_activity', '
IF OLD.read = 0 AND NEW.read = 1 THEN
UPDATE {usr} SET unread = unread - 1 WHERE id = NEW.usr;
ELSEIF OLD.read = 1 AND NEW.read = 0 THEN
UPDATE {usr} SET unread = unread + 1 WHERE id = NEW.usr;
END IF;'
);
db_create_trigger(
'update_unread_delete',
'AFTER', 'DELETE', 'notification_internal_activity', '
IF OLD.read = 0 THEN
UPDATE {usr} SET unread = unread - 1 WHERE id = OLD.usr;
END IF;'
);
}
} }
public static function get_event_subscriptions() { public static function get_event_subscriptions() {
......
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