/** * Delete those messages from the database which corresponds to the given condition or to the given ids array * Note: the delete cascade arrays are handled! * * @param string the name of this class * Note: This is required until min phpversion will be 5.3. Since PHP 5.3 we can use static::function_name to achieve late static bindings * @param string where condition * @param array object ids * @return mixed # of rows affected or false if error */ static function db_delete_where($class_name, $sql_where, $object_ids = NULL, $params = NULL) { global $DB; $DB->begin(); if (!empty($sql_where)) { $messages_to_delete = $DB->get_assoc('SELECT msg_ID, msg_thread_ID FROM T_messaging__message WHERE ' . $sql_where); $object_ids = array_keys($messages_to_delete); $thread_ids_to_delete = array_unique($messages_to_delete); } if (!$object_ids) { // There is no comment to delete $DB->commit(); return; } $message_ids_to_delete = implode(', ', $object_ids); if (empty($thread_ids_to_delete)) { // Make sure thread ids of the messages are collected $thread_ids_to_delete = $DB->get_col('SELECT msg_thread_ID FROM T_messaging__message WHERE msg_ID IN ( ' . $message_ids_to_delete . ' )'); } // Update thread statuses first unread message IDs $result = $DB->query('UPDATE T_messaging__threadstatus SET tsta_first_unread_msg_ID = ( SELECT message1.msg_ID FROM T_messaging__message as message1 WHERE message1.msg_thread_ID = tsta_thread_ID AND message1.msg_datetime > ( SELECT MAX( message2.msg_datetime) FROM T_messaging__message as message2 WHERE message2.msg_ID IN ( ' . $message_ids_to_delete . ' ) AND message2.msg_thread_ID = tsta_thread_ID ) ORDER BY message1.msg_datetime ASC LIMIT 1 ) WHERE tsta_first_unread_msg_ID IN ( ' . $message_ids_to_delete . ')') !== false; if ($result) { // Remove messages with all of its delete cascade relations $result = parent::db_delete_where($class_name, $sql_where, $object_ids); } if ($result !== false) { // Delete those threads where all of the messages were deleted load_class('messaging/model/_thread.class.php', 'Thread'); $orphan_thread_ids = $DB->get_col(' SELECT msg_thread_ID FROM T_messaging__message WHERE msg_thread_ID IN ( ' . implode(', ', $thread_ids_to_delete) . ' ) GROUP BY msg_thread_ID HAVING COUNT(*) < 1'); // Delete orphan threads if there are any if (!empty($orphan_thread_ids) && Thread::db_delete_where('Thread', NULL, $orphan_thread_ids) === false) { // Deleting threads was unsuccessful $result = false; } } // Commit or rollback the transaction $result !== false ? $DB->commit() : $DB->rollback(); return $result; }
/** * Delete orphan threads * * @param integer or array of integers - one or multiple user ids - to delete those orphan threads where only the given user(s) was/were involved, leave it to NULL to delete all orphan threads * @return boolean true on success */ function delete_orphan_threads($user_ids = NULL) { global $DB; $DB->begin(); if (is_array($user_ids)) { $users = implode(', ', $user_ids); $in_users_condition = ' OR user_ID IN ( ' . $users . ' )'; $not_in_users_condition = ' AND user_ID NOT IN ( ' . $users . ' )'; } else { $in_users_condition = is_number($user_ids) ? ' OR user_ID = ' . $user_ids : ''; $not_in_users_condition = is_number($user_ids) ? ' AND user_ID != ' . $user_ids : ''; } // Get those thread ids which have already deleted participants or which participants will be deleted now $affected_threads_ids = $DB->get_col('SELECT DISTINCT tsta_thread_ID FROM T_messaging__threadstatus LEFT JOIN T_users ON tsta_user_ID = user_ID WHERE user_ID IS NULL' . $in_users_condition); if (empty($affected_threads_ids)) { // There are no affected thread ids, nothing to delete $DB->commit(); return true; } // Filter previously collected thread ids to get those which have existing users outside of the deleted ones $not_orphan_threads = $DB->get_col('SELECT DISTINCT tsta_thread_ID FROM T_messaging__threadstatus LEFT JOIN T_users ON tsta_user_ID = user_ID WHERE tsta_thread_ID IN ( ' . implode(', ', $affected_threads_ids) . ' ) AND user_ID IS NOT NULL' . $not_in_users_condition); // Orphan thread ids are the affected threads minus the ones with existing users $orphan_thread_ids = array_diff($affected_threads_ids, $not_orphan_threads); if (!empty($orphan_thread_ids)) { // There are orphan threads ( or orphan thread targets ) load_class('messaging/model/_thread.class.php', 'Thread'); // Delete all orphan threads with all cascade relations if (Thread::db_delete_where('Thread', NULL, $orphan_thread_ids, array('use_transaction' => false)) === false) { // Deleting orphan threads failed $DB->rollback(); return false; } } $DB->commit(); return true; }