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

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) {
safe_require('search', 'elasticsearch');
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;
......
......@@ -132,10 +132,11 @@ function column_collation_is_default($table, $column) {
* @uses $db
* @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 string $use_trigger Allow the sql query to do fall through to pseudo_trigger
* @return boolean
* @throws SQLException
*/
function execute_sql($command, array $values=null) {
function execute_sql($command, array $values=null, $use_trigger=true) {
global $db;
if (!is_a($db, 'ADOConnection')) {
......@@ -145,7 +146,7 @@ function execute_sql($command, array $values=null) {
$command = db_quote_table_placeholders($command);
list($sqltype, $table, $idsql, $bindoffset) = get_table_from_query($command);
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
if (!empty($values) && is_array($values) && count($values) > 0) {
$bindvals = array_slice($values, $bindoffset);
......@@ -961,6 +962,7 @@ function set_field_select($table, $newfield, $newvalue, $select, array $values)
$select = db_quote_table_placeholders($select);
$calllocal = false;
if ($type = table_need_trigger($table)) {
// Need to find the ids
$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)
safe_require('search', 'elasticsearch');
ElasticsearchIndexing::bulk_add_to_queue($ids);
}
else if ($type == 'local') {
$calllocal = true;
}
}
$values = array_merge(array($newvalue), $values);
$sql = 'UPDATE '. db_table_name($table) .' SET '. db_quote_identifier($newfield) .' = ? ' . $select;
try {
$stmt = $db->Prepare($sql);
return $db->Execute($stmt, $values);
$dbex = $db->Execute($stmt, $values);
}
catch (ADODB_Exception $e) {
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)
}
function table_need_trigger($table) {
if ($dbprefix = get_config('dbprefix')) {
$table = preg_replace('/' . $dbprefix . '/', '', $table);
}
if (defined('SKIP_TRIGGER') && SKIP_TRIGGER === true) {
return false;
}
......@@ -1256,6 +1279,10 @@ function table_need_trigger($table) {
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;
}
......@@ -1266,6 +1293,17 @@ function pseudo_trigger($table, $data, $id, $savetype = 'insert') {
safe_require('search', 'elasticsearch');
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
// Run the query
$sql = 'UPDATE '. db_table_name($table) .' SET '. $setclause . ' WHERE ' . $whereclause;
$calllocal = false;
// Work out table name and get ids
list($sqltype, $table, $idsql, $bindoffset) = get_table_from_query($sql);
if ($sqltype == 'update' && !is_null($table) && !is_null($idsql)) {
......@@ -1464,22 +1503,41 @@ function update_record($table, $dataobject, $where=null, $primarykey=false, $ret
safe_require('search', 'elasticsearch');
ElasticsearchIndexing::bulk_add_to_queue($ids);
}
else if ($type == 'local') {
$calllocal = true;
}
}
}
$dbex = false;
try {
$stmt = $db->Prepare($sql);
$rs = $db->Execute($stmt, array_merge($setclausevalues, $wherevalues));
if ($returnpk) {
$primarykey = $primarykey ? $primarykey : 'id';
$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) {
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() {
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) {
return 'ArtefactType' . ucfirst($type);
}
......
......@@ -119,34 +119,27 @@ class PluginModuleMultirecipientnotification extends PluginModule {
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) {
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 {
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) {
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() {
......
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