#923826 by catch, carlos8f, moshe weitzman: Fixed entity delete operations should use transactions.
parent
8049f94756
commit
8dd7376d5a
|
@ -1583,20 +1583,27 @@ function comment_delete($cid) {
|
||||||
function comment_delete_multiple($cids) {
|
function comment_delete_multiple($cids) {
|
||||||
$comments = comment_load_multiple($cids);
|
$comments = comment_load_multiple($cids);
|
||||||
if ($comments) {
|
if ($comments) {
|
||||||
|
$transaction = db_transaction();
|
||||||
|
try {
|
||||||
|
// Delete the comments.
|
||||||
|
db_delete('comment')
|
||||||
|
->condition('cid', array_keys($comments), 'IN')
|
||||||
|
->execute();
|
||||||
|
foreach ($comments as $comment) {
|
||||||
|
field_attach_delete('comment', $comment);
|
||||||
|
module_invoke_all('comment_delete', $comment);
|
||||||
|
module_invoke_all('entity_delete', $comment, 'comment');
|
||||||
|
|
||||||
// Delete the comments.
|
// Delete the comment's replies.
|
||||||
db_delete('comment')
|
$child_cids = db_query('SELECT cid FROM {comment} WHERE pid = :cid', array(':cid' => $comment->cid))->fetchCol();
|
||||||
->condition('cid', array_keys($comments), 'IN')
|
comment_delete_multiple($child_cids);
|
||||||
->execute();
|
_comment_update_node_statistics($comment->nid);
|
||||||
foreach ($comments as $comment) {
|
}
|
||||||
field_attach_delete('comment', $comment);
|
}
|
||||||
module_invoke_all('comment_delete', $comment);
|
catch (Exception $e) {
|
||||||
module_invoke_all('entity_delete', $comment, 'comment');
|
$transaction->rollback();
|
||||||
|
watchdog_exception('comment', $e);
|
||||||
// Delete the comment's replies.
|
throw $e;
|
||||||
$child_cids = db_query('SELECT cid FROM {comment} WHERE pid = :cid', array(':cid' => $comment->cid))->fetchCol();
|
|
||||||
comment_delete_multiple($child_cids);
|
|
||||||
_comment_update_node_statistics($comment->nid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1123,7 +1123,7 @@ function node_save($node) {
|
||||||
db_ignore_slave();
|
db_ignore_slave();
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
$transaction->rollback('node');
|
$transaction->rollback();
|
||||||
watchdog_exception('node', $e);
|
watchdog_exception('node', $e);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
@ -1164,41 +1164,48 @@ function node_delete($nid) {
|
||||||
* An array of node IDs.
|
* An array of node IDs.
|
||||||
*/
|
*/
|
||||||
function node_delete_multiple($nids) {
|
function node_delete_multiple($nids) {
|
||||||
|
$transaction = db_transaction();
|
||||||
if (!empty($nids)) {
|
if (!empty($nids)) {
|
||||||
$nodes = node_load_multiple($nids, array());
|
$nodes = node_load_multiple($nids, array());
|
||||||
|
|
||||||
foreach ($nodes as $nid => $node) {
|
try {
|
||||||
// Call the node-specific callback (if any):
|
foreach ($nodes as $nid => $node) {
|
||||||
node_invoke($node, 'delete');
|
// Call the node-specific callback (if any):
|
||||||
module_invoke_all('node_delete', $node);
|
node_invoke($node, 'delete');
|
||||||
module_invoke_all('entity_delete', $node, 'node');
|
module_invoke_all('node_delete', $node);
|
||||||
field_attach_delete('node', $node);
|
module_invoke_all('entity_delete', $node, 'node');
|
||||||
|
field_attach_delete('node', $node);
|
||||||
|
|
||||||
// Remove this node from the search index if needed.
|
// Remove this node from the search index if needed.
|
||||||
// This code is implemented in node module rather than in search module,
|
// This code is implemented in node module rather than in search module,
|
||||||
// because node module is implementing search module's API, not the other
|
// because node module is implementing search module's API, not the other
|
||||||
// way around.
|
// way around.
|
||||||
if (module_exists('search')) {
|
if (module_exists('search')) {
|
||||||
search_reindex($nid, 'node');
|
search_reindex($nid, 'node');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete after calling hooks so that they can query node tables as needed.
|
||||||
|
db_delete('node')
|
||||||
|
->condition('nid', $nids, 'IN')
|
||||||
|
->execute();
|
||||||
|
db_delete('node_revision')
|
||||||
|
->condition('nid', $nids, 'IN')
|
||||||
|
->execute();
|
||||||
|
db_delete('history')
|
||||||
|
->condition('nid', $nids, 'IN')
|
||||||
|
->execute();
|
||||||
|
db_delete('node_access')
|
||||||
|
->condition('nid', $nids, 'IN')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
$transaction->rollback();
|
||||||
|
watchdog_exception('node', $e);
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete after calling hooks so that they can query node tables as needed.
|
|
||||||
db_delete('node')
|
|
||||||
->condition('nid', $nids, 'IN')
|
|
||||||
->execute();
|
|
||||||
db_delete('node_revision')
|
|
||||||
->condition('nid', $nids, 'IN')
|
|
||||||
->execute();
|
|
||||||
db_delete('history')
|
|
||||||
->condition('nid', $nids, 'IN')
|
|
||||||
->execute();
|
|
||||||
db_delete('node_access')
|
|
||||||
->condition('nid', $nids, 'IN')
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
// Clear the page and block and node_load_multiple caches.
|
// Clear the page and block and node_load_multiple caches.
|
||||||
cache_clear_all();
|
|
||||||
entity_get_controller('node')->resetCache();
|
entity_get_controller('node')->resetCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -902,6 +902,7 @@ function taxonomy_term_confirm_delete_submit($form, &$form_state) {
|
||||||
drupal_set_message(t('Deleted term %name.', array('%name' => $form_state['values']['name'])));
|
drupal_set_message(t('Deleted term %name.', array('%name' => $form_state['values']['name'])));
|
||||||
watchdog('taxonomy', 'Deleted term %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE);
|
watchdog('taxonomy', 'Deleted term %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE);
|
||||||
$form_state['redirect'] = 'admin/structure/taxonomy';
|
$form_state['redirect'] = 'admin/structure/taxonomy';
|
||||||
|
cache_clear_all();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,6 +942,7 @@ function taxonomy_vocabulary_confirm_delete_submit($form, &$form_state) {
|
||||||
drupal_set_message(t('Deleted vocabulary %name.', array('%name' => $form_state['values']['name'])));
|
drupal_set_message(t('Deleted vocabulary %name.', array('%name' => $form_state['values']['name'])));
|
||||||
watchdog('taxonomy', 'Deleted vocabulary %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE);
|
watchdog('taxonomy', 'Deleted vocabulary %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE);
|
||||||
$form_state['redirect'] = 'admin/structure/taxonomy';
|
$form_state['redirect'] = 'admin/structure/taxonomy';
|
||||||
|
cache_clear_all();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -421,23 +421,31 @@ function taxonomy_vocabulary_save($vocabulary) {
|
||||||
function taxonomy_vocabulary_delete($vid) {
|
function taxonomy_vocabulary_delete($vid) {
|
||||||
$vocabulary = taxonomy_vocabulary_load($vid);
|
$vocabulary = taxonomy_vocabulary_load($vid);
|
||||||
|
|
||||||
// Only load terms without a parent, child terms will get deleted too.
|
$transaction = db_transaction();
|
||||||
$result = db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid = :vid AND th.parent = 0', array(':vid' => $vid))->fetchCol();
|
try {
|
||||||
foreach ($result as $tid) {
|
// Only load terms without a parent, child terms will get deleted too.
|
||||||
taxonomy_term_delete($tid);
|
$result = db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid = :vid AND th.parent = 0', array(':vid' => $vid))->fetchCol();
|
||||||
|
foreach ($result as $tid) {
|
||||||
|
taxonomy_term_delete($tid);
|
||||||
|
}
|
||||||
|
db_delete('taxonomy_vocabulary')
|
||||||
|
->condition('vid', $vid)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
field_attach_delete_bundle('taxonomy_term', $vocabulary->machine_name);
|
||||||
|
module_invoke_all('taxonomy_vocabulary_delete', $vocabulary);
|
||||||
|
module_invoke_all('entity_delete', $vocabulary, 'taxonomy_vocabulary');
|
||||||
|
|
||||||
|
cache_clear_all();
|
||||||
|
entity_get_controller('taxonomy_vocabulary')->resetCache();
|
||||||
|
|
||||||
|
return SAVED_DELETED;
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
$transaction->rollback();
|
||||||
|
watchdog_exception('taxonomy', $e);
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
db_delete('taxonomy_vocabulary')
|
|
||||||
->condition('vid', $vid)
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
field_attach_delete_bundle('taxonomy_term', $vocabulary->machine_name);
|
|
||||||
module_invoke_all('taxonomy_vocabulary_delete', $vocabulary);
|
|
||||||
module_invoke_all('entity_delete', $vocabulary, 'taxonomy_vocabulary');
|
|
||||||
|
|
||||||
cache_clear_all();
|
|
||||||
entity_get_controller('taxonomy_vocabulary')->resetCache();
|
|
||||||
|
|
||||||
return SAVED_DELETED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -588,41 +596,47 @@ function taxonomy_term_save($term) {
|
||||||
* Status constant indicating deletion.
|
* Status constant indicating deletion.
|
||||||
*/
|
*/
|
||||||
function taxonomy_term_delete($tid) {
|
function taxonomy_term_delete($tid) {
|
||||||
$tids = array($tid);
|
$transaction = db_transaction();
|
||||||
while ($tids) {
|
try {
|
||||||
$children_tids = $orphans = array();
|
$tids = array($tid);
|
||||||
foreach ($tids as $tid) {
|
while ($tids) {
|
||||||
// See if any of the term's children are about to be become orphans:
|
$children_tids = $orphans = array();
|
||||||
if ($children = taxonomy_get_children($tid)) {
|
foreach ($tids as $tid) {
|
||||||
foreach ($children as $child) {
|
// See if any of the term's children are about to be become orphans:
|
||||||
// If the term has multiple parents, we don't delete it.
|
if ($children = taxonomy_get_children($tid)) {
|
||||||
$parents = taxonomy_get_parents($child->tid);
|
foreach ($children as $child) {
|
||||||
if (count($parents) == 1) {
|
// If the term has multiple parents, we don't delete it.
|
||||||
$orphans[] = $child->tid;
|
$parents = taxonomy_get_parents($child->tid);
|
||||||
|
if (count($parents) == 1) {
|
||||||
|
$orphans[] = $child->tid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($term = taxonomy_term_load($tid)) {
|
||||||
|
db_delete('taxonomy_term_data')
|
||||||
|
->condition('tid', $tid)
|
||||||
|
->execute();
|
||||||
|
db_delete('taxonomy_term_hierarchy')
|
||||||
|
->condition('tid', $tid)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
field_attach_delete('taxonomy_term', $term);
|
||||||
|
module_invoke_all('taxonomy_term_delete', $term);
|
||||||
|
module_invoke_all('entity_delete', $term, 'taxonomy_term');
|
||||||
|
taxonomy_terms_static_reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($term = taxonomy_term_load($tid)) {
|
$tids = $orphans;
|
||||||
db_delete('taxonomy_term_data')
|
|
||||||
->condition('tid', $tid)
|
|
||||||
->execute();
|
|
||||||
db_delete('taxonomy_term_hierarchy')
|
|
||||||
->condition('tid', $tid)
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
field_attach_delete('taxonomy_term', $term);
|
|
||||||
module_invoke_all('taxonomy_term_delete', $term);
|
|
||||||
module_invoke_all('entity_delete', $term, 'taxonomy_term');
|
|
||||||
taxonomy_terms_static_reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return SAVED_DELETED;
|
||||||
$tids = $orphans;
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
$transaction->rollback();
|
||||||
|
watchdog_exception('taxonomy', $e);
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_clear_all();
|
|
||||||
return SAVED_DELETED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2361,23 +2361,30 @@ function user_delete_multiple(array $uids) {
|
||||||
if (!empty($uids)) {
|
if (!empty($uids)) {
|
||||||
$accounts = user_load_multiple($uids, array());
|
$accounts = user_load_multiple($uids, array());
|
||||||
|
|
||||||
foreach ($accounts as $uid => $account) {
|
$transaction = db_transaction();
|
||||||
module_invoke_all('user_delete', $account);
|
try {
|
||||||
module_invoke_all('entity_delete', $account, 'user');
|
foreach ($accounts as $uid => $account) {
|
||||||
field_attach_delete('user', $account);
|
module_invoke_all('user_delete', $account);
|
||||||
drupal_session_destroy_uid($account->uid);
|
module_invoke_all('entity_delete', $account, 'user');
|
||||||
|
field_attach_delete('user', $account);
|
||||||
|
drupal_session_destroy_uid($account->uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
db_delete('users')
|
||||||
|
->condition('uid', $uids, 'IN')
|
||||||
|
->execute();
|
||||||
|
db_delete('users_roles')
|
||||||
|
->condition('uid', $uids, 'IN')
|
||||||
|
->execute();
|
||||||
|
db_delete('authmap')
|
||||||
|
->condition('uid', $uids, 'IN')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
$transaction->rollback();
|
||||||
|
watchdog_exception('user', $e);
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
db_delete('users')
|
|
||||||
->condition('uid', $uids, 'IN')
|
|
||||||
->execute();
|
|
||||||
db_delete('users_roles')
|
|
||||||
->condition('uid', $uids, 'IN')
|
|
||||||
->execute();
|
|
||||||
db_delete('authmap')
|
|
||||||
->condition('uid', $uids, 'IN')
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
entity_get_controller('user')->resetCache();
|
entity_get_controller('user')->resetCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue