Index: database/database.mysql
===================================================================
RCS file: /cvs/drupal/drupal/database/database.mysql,v
retrieving revision 1.201
diff -u -F^function -r1.201 database.mysql
--- database/database.mysql 18 Oct 2005 14:41:26 -0000 1.201
+++ database/database.mysql 29 Oct 2005 12:51:35 -0000
@@ -239,6 +239,22 @@
) TYPE=MyISAM;
--
+-- Table structure for table 'deleted'
+--
+
+CREATE TABLE deleted (
+ tid int(10) unsigned NOT NULL default '0',
+ did int(10) unsigned NOT NULL default '0',
+ rid varchar(255) NOT NULL default '',
+ uid int(10) unsigned NOT NULL default '0',
+ root_row varchar(255) NOT NULL default '',
+ data longtext NOT NULL,
+ preview longtext NOT NULL,
+ timestamp int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (tid)
+) TYPE=MyISAM;
+
+--
-- Table structure for table 'files'
--
Index: database/database.pgsql
===================================================================
RCS file: /cvs/drupal/drupal/database/database.pgsql,v
retrieving revision 1.140
diff -u -F^function -r1.140 database.pgsql
--- database/database.pgsql 18 Oct 2005 14:41:26 -0000 1.140
+++ database/database.pgsql 29 Oct 2005 12:51:35 -0000
@@ -235,6 +235,22 @@
);
--
+-- Table structure for table 'deleted'
+--
+
+CREATE TABLE deleted (
+ tid integer NOT NULL default '0',
+ did integer NOT NULL default '0',
+ rid text NOT NULL default '',
+ uid integer NOT NULL default '0',
+ root_row text NOT NULL default '',
+ data text NOT NULL default '',
+ preview text NOT NULL default '',
+ timestamp integer NOT NULL default '0',
+ PRIMARY KEY (tid)
+);
+
+--
-- Table structure for table 'files'
--
Index: database/updates.inc
===================================================================
RCS file: /cvs/drupal/drupal/database/updates.inc,v
retrieving revision 1.140
diff -u -F^function -r1.140 updates.inc
--- database/updates.inc 22 Oct 2005 15:14:46 -0000 1.140
+++ database/updates.inc 29 Oct 2005 12:51:36 -0000
@@ -67,7 +67,8 @@
"2005-09-07" => "update_147",
"2005-09-18" => "update_148",
"2005-09-27" => "update_149",
- "2005-10-15" => "update_150"
+ "2005-10-15" => "update_150",
+ "2005-10-27" => "update_151"
);
function update_110() {
@@ -919,6 +920,43 @@ function update_150() {
return $ret;
}
+function update_151() {
+ $ret = array();
+
+ switch ($GLOBALS['db_type']) {
+ case 'mysqli':
+ case 'mysql':
+ $ret[] = update_sql("CREATE TABLE deleted (
+ tid int(10) unsigned NOT NULL default '0',
+ did int(10) unsigned NOT NULL default '0',
+ rid varchar(255) NOT NULL default '',
+ uid int(10) unsigned NOT NULL default '0',
+ root_row varchar(255) NOT NULL default '',
+ data longtext NOT NULL,
+ preview longtext NOT NULL,
+ timestamp int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (tid)
+ )");
+ break;
+ case 'pgsql':
+ $ret[] = update_sql("CREATE TABLE deleted (
+ tid integer NOT NULL default '0',
+ did integer NOT NULL default '0',
+ rid text NOT NULL default '',
+ uid integer NOT NULL default '0',
+ root_row text NOT NULL default '',
+ data text NOT NULL,
+ preview text NOT NULL,
+ timestamp integer NOT NULL default '0',
+ PRIMARY KEY (tid)
+ )");
+ break;
+ default:
+ break;
+ }
+ return $ret;
+}
+
function update_sql($sql) {
$edit = $_POST["edit"];
$result = db_query($sql);
Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.56
diff -u -F^function -r1.56 locale.inc
--- includes/locale.inc 21 Oct 2005 11:14:28 -0000 1.56
+++ includes/locale.inc 29 Oct 2005 12:51:37 -0000
@@ -935,10 +935,14 @@ function _locale_export_remove_plural($e
}
function _locale_string_delete($lid) {
- db_query('DELETE FROM {locales_source} WHERE lid = %d', $lid);
- db_query('DELETE FROM {locales_target} WHERE lid = %d', $lid);
+ $did = next_delete_id();
+ $result = db_fetch_object(db_query('SELECT source, location FROM {locales_source} WHERE lid = %d', $lid));
+ $preview = array('source' => $result->source, 'location' => $result->location);
+ drupal_set_message(t('The string has been moved to trash.'));
+ system_trash($did, $lid, 'locale', $preview, 'DELETE FROM {locales_source} WHERE lid = %d', $lid);
+ system_trash($did, $lid, NULL, NULL, 'DELETE FROM {locales_target} WHERE lid = %d', $lid);
locale_refresh_cache();
- drupal_set_message(t('The string has been removed.'));
+ drupal_goto('admin/locale/string/search');
}
/**
@@ -1166,7 +1170,7 @@ function _locale_prepare_iso_list() {
function _locale_get_iso639_list() {
return array(
"aa" => array("Afar"),
- "ab" => array("Abkhazian", "аҧÑ?уа бызшәа"),
+ "ab" => array("Abkhazian", "аҧÑ?уа бызшәа"),
"ae" => array("Avestan"),
"af" => array("Afrikaans"),
"ak" => array("Akan"),
@@ -1177,8 +1181,8 @@ function _locale_get_iso639_list() {
"ay" => array("Aymara"),
"az" => array("Azerbaijani", "azərbaycan"),
"ba" => array("Bashkir"),
- "be" => array("Belarusian", "БеларуÑ?каÑ?"),
- "bg" => array("Bulgarian", "БългарÑ?ки"),
+ "be" => array("Belarusian", "БеларуÑ?каÑ?"),
+ "bg" => array("Bulgarian", "БългарÑ?ки"),
"bh" => array("Bihari"),
"bi" => array("Bislama"),
"bm" => array("Bambara", "Bamanankan"),
@@ -1199,14 +1203,14 @@ function _locale_get_iso639_list() {
"de" => array("German", "Deutsch"),
"dv" => array("Maldivian"),
"dz" => array("Bhutani"),
- "ee" => array("Ewe", "Æ?Ê‹É›"),
+ "ee" => array("Ewe", "Æ?Ê‹É›"),
"el" => array("Greek", "Ελληνικά"),
"en" => array("English"),
"eo" => array("Esperanto"),
"es" => array("Spanish", "Español"),
"et" => array("Estonian", "Eesti"),
"eu" => array("Basque", "Euskera"),
- "fa" => array("Persian", "Ù?ارسی"),
+ "fa" => array("Persian", "Ù?ارسی"),
"ff" => array("Fulah", "Fulfulde"),
"fi" => array("Finnish", "Suomi"),
"fj" => array("Fiji"),
@@ -1221,7 +1225,7 @@ function _locale_get_iso639_list() {
"gv" => array("Manx"),
"ha" => array("Hausa"),
"he" => array("Hebrew", "עברית"),
- "hi" => array("Hindi", "हिन�दी"),
+ "hi" => array("Hindi", "हिन�दी"),
"ho" => array("Hiri Motu"),
"hr" => array("Croatian", "Hrvatski"),
"hu" => array("Hungarian", "Magyar"),
@@ -1232,7 +1236,7 @@ function _locale_get_iso639_list() {
"ie" => array("Interlingue"),
"ig" => array("Igbo"),
"ik" => array("Inupiak"),
- "is" => array("Icelandic", "Ã?slenska"),
+ "is" => array("Icelandic", "Ã?slenska"),
"it" => array("Italian", "Italiano"),
"iu" => array("Inuktitut"),
"ja" => array("Japanese", "日本語"),
@@ -1244,7 +1248,7 @@ function _locale_get_iso639_list() {
"kk" => array("Kazakh", "Қазақ"),
"kl" => array("Greenlandic"),
"km" => array("Cambodian"),
- "kn" => array("Kannada", "ಕನ�ನಡ"),
+ "kn" => array("Kannada", "ಕನ�ನಡ"),
"ko" => array("Korean", "í•œêµì–´"),
"kr" => array("Kanuri"),
"ks" => array("Kashmiri"),
@@ -1262,7 +1266,7 @@ function _locale_get_iso639_list() {
"mg" => array("Malagasy"),
"mh" => array("Marshallese"),
"mi" => array("Maori"),
- "mk" => array("Macedonian", "МакедонÑ?ки"),
+ "mk" => array("Macedonian", "МакедонÑ?ки"),
"ml" => array("Malayalam", "മലയാളം"),
"mn" => array("Mongolian"),
"mo" => array("Moldavian"),
@@ -1292,7 +1296,7 @@ function _locale_get_iso639_list() {
"rm" => array("Rhaeto-Romance"),
"rn" => array("Kirundi"),
"ro" => array("Romanian", "Română"),
- "ru" => array("Russian", "РуÑ?Ñ?кий"),
+ "ru" => array("Russian", "РуÑ?Ñ?кий"),
"rw" => array("Kinyarwanda"),
"sa" => array("Sanskrit"),
"sc" => array("Sardinian"),
@@ -1301,20 +1305,20 @@ function _locale_get_iso639_list() {
"sg" => array("Sango"),
"sh" => array("Serbo-Croatian"),
"si" => array("Singhalese"),
- "sk" => array("Slovak", "SlovenÄ?ina"),
- "sl" => array("Slovenian", "SlovenÅ¡Ä?ina"),
+ "sk" => array("Slovak", "SlovenÄ?ina"),
+ "sl" => array("Slovenian", "SlovenÅ¡Ä?ina"),
"sm" => array("Samoan"),
"sn" => array("Shona"),
"so" => array("Somali"),
"sq" => array("Albanian", "Shqip"),
- "sr" => array("Serbian", "СрпÑ?ки"),
+ "sr" => array("Serbian", "СрпÑ?ки"),
"ss" => array("Siswati"),
"st" => array("Sesotho"),
"su" => array("Sudanese"),
"sv" => array("Swedish", "Svenska"),
"sw" => array("Swahili", "Kiswahili"),
- "ta" => array("Tamil", "தமிழ�"),
- "te" => array("Telugu", "తెల�గ�"),
+ "ta" => array("Tamil", "தமிழ�"),
+ "te" => array("Telugu", "తెల�గ�"),
"tg" => array("Tajik"),
"th" => array("Thai", "ภาษาไทย"),
"ti" => array("Tigrinya"),
@@ -1328,7 +1332,7 @@ function _locale_get_iso639_list() {
"tw" => array("Twi"),
"ty" => array("Tahitian"),
"ug" => array("Uighur"),
- "uk" => array("Ukrainian", "УкраїнÑ?ька"),
+ "uk" => array("Ukrainian", "УкраїнÑ?ька"),
"ur" => array("Urdu", "اردو"),
"uz" => array("Uzbek", "o'zbek"),
"ve" => array("Venda"),
@@ -1340,7 +1344,7 @@ function _locale_get_iso639_list() {
"yo" => array("Yoruba", "Yorùbá"),
"za" => array("Zhuang"),
"zh-hans" => array("Chinese, Simplified", "简体ä¸æ–‡"),
- "zh-hant" => array("Chinese, Traditional", "ç¹?é«”ä¸æ–‡"),
+ "zh-hant" => array("Chinese, Traditional", "ç¹?é«”ä¸æ–‡"),
"zu" => array("Zulu", "isiZulu"),
);
}
Index: modules/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block.module,v
retrieving revision 1.184
diff -u -F^function -r1.184 block.module
--- modules/block.module 22 Oct 2005 15:14:46 -0000 1.184
+++ modules/block.module 29 Oct 2005 12:51:38 -0000
@@ -408,10 +408,12 @@ function block_box_add() {
*/
function block_box_delete($bid = 0) {
$box = block_box_get($bid);
- $form['info'] = array('#type' => 'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
- $form['bid'] = array('#type' => 'hidden', '#value' => $bid);
-
- return confirm_form('block_box_delete_confirm', $form, t('Are you sure you want to delete the block %name?', array('%name' => theme('placeholder', $info))), 'admin/block', '', t('Delete'), t('Cancel'));
+ $did = next_delete_id();
+ $preview = array('title' => $box['title'], 'info' => $box['info'], 'body' => $box['body']);
+ drupal_set_message(t('The block %name has been moved to trash.', array('%name' => theme('placeholder', $box['info']))));
+ system_trash($did, $bid, 'block', $preview, 'DELETE FROM {boxes} WHERE bid = %d', $bid);
+ cache_clear_all();
+ drupal_goto('admin/block');
}
/**
@@ -419,10 +421,7 @@ function block_box_delete($bid = 0) {
*/
function block_box_delete_confirm_execute($form_id, $edit) {
$form = $GLOBALS['form_values'];
- db_query('DELETE FROM {boxes} WHERE bid = %d', $form['bid']);
- drupal_set_message(t('The block %name has been removed.', array('%name' => theme('placeholder', $form['info']))));
- cache_clear_all();
- drupal_goto('admin/block');
+
};
Index: modules/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book.module,v
retrieving revision 1.326
diff -u -F^function -r1.326 book.module
--- modules/book.module 28 Oct 2005 14:04:20 -0000 1.326
+++ modules/book.module 29 Oct 2005 12:51:40 -0000
@@ -217,7 +217,7 @@ function book_update($node) {
* Implementation of hook_delete().
*/
function book_delete(&$node) {
- db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {book} WHERE nid = %d', $node->nid);
}
/**
@@ -298,8 +298,10 @@ function book_outline() {
break;
case t('Remove from book outline'):
- db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
- drupal_set_message(t('The post has been removed from the book.'));
+ $did = next_delete_id();
+ $preview = array('title' => $node-title, 'body' => $node->body);
+ drupal_set_message(t('The post has been removed from the book and placed in trash.'));
+ system_trash($did, $node->nid, 'book', $preview, 'DELETE FROM {book} WHERE nid = %d', $node->nid);
drupal_goto("node/$node->nid");
break;
Index: modules/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment.module,v
retrieving revision 1.384
diff -u -F^function -r1.384 comment.module
--- modules/comment.module 20 Oct 2005 09:27:36 -0000 1.384
+++ modules/comment.module 29 Oct 2005 12:51:41 -0000
@@ -232,8 +232,14 @@ function comment_nodeapi(&$node, $op, $a
break;
case 'delete':
- db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid);
- db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
+ $result = db_query('SELECT * FROM {comments} WHERE nid = %d', $node->nid);
+ while ($comment = db_fetch_object($result)) {
+ $i++;
+ $preview['subject'. $i] = $comment->subject;
+ $preview['comment'. $i] = $comment->comment;
+ }
+ system_trash($node->did, $node->nid, NULL, $preview, 'DELETE FROM {comments} WHERE nid = %d', $node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
break;
case 'update index':
@@ -909,12 +915,10 @@ function comment_delete($cid) {
$comment = db_fetch_object(db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', $cid));
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
- $output = '';
-
// We'll only delete if the user has confirmed the
// deletion using the form in our else clause below.
- if ($comment->cid && $_POST['edit']['confirm']) {
- drupal_set_message(t('The comment and all its replies have been deleted.'));
+ if ($comment->cid) {
+ drupal_set_message(t('The comment and all its replies have been moved to trash.'));
// Delete comment and its replies.
_comment_delete_thread($comment);
@@ -926,20 +930,10 @@ function comment_delete($cid) {
drupal_goto("node/$comment->nid");
}
- else if ($comment->cid) {
- $output = confirm_form('comment_confirm_delete',
- array(),
- t('Are you sure you want to delete the comment %title?', array('%title' => theme('placeholder', $comment->subject))),
- 'node/'. $comment->nid,
- t('Any replies to this comment will be lost. This action cannot be undone.'),
- t('Delete'),
- t('Cancel'));
- }
else {
drupal_set_message(t('The comment no longer exists.'));
}
- return $output;
}
/**
@@ -1289,9 +1283,19 @@ function theme_comment_post_forbidden()
}
function _comment_delete_thread($comment) {
+ static $did;
+ if ($did) {
+ $root_row = NULL;
+ $preview = NULL;
+ }
+ else {
+ $did = next_delete_id();
+ $root_row = 'comment';
+ $preview = array('subject' => $comment->subject, 'comment' => $comment->comment);
+ }
// Delete the comment:
- db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid);
- watchdog('content', t('Comment: deleted %subject.', array('%subject' => theme('placeholder', $comment->subject))));
+ system_trash($did, $comment->nid, $root_row, $preview, 'DELETE FROM {comments} WHERE cid = %d', $comment->cid);
+ watchdog('content', t('Comment: moved %subject to trash.', array('%subject' => theme('placeholder', $comment->subject))));
comment_invoke_comment($comment, 'delete');
Index: modules/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact.module,v
retrieving revision 1.26
diff -u -F^function -r1.26 contact.module
--- modules/contact.module 11 Oct 2005 19:44:34 -0000 1.26
+++ modules/contact.module 29 Oct 2005 12:51:41 -0000
@@ -197,18 +197,11 @@ function contact_admin_edit($category =
}
function contact_admin_delete($category) {
- if ($_POST['op'] != t('Delete')) {
- return confirm_form('contact_admin_delete', array(),
- t('Are you sure you want to delete %category?', array('%category' => theme('placeholder', $category))),
- 'admin/contact',
- t('This action cannot be undone.'),
- t('Delete'),
- t('Cancel'));
- }
- else {
- db_query("DELETE FROM {contact} WHERE category = '%s'", $category);
+ $did = next_delete_id();
+ $preview = array('category' => $category);
+ drupal_set_message(t('Contact category %category moved to trash', array('%category' => t($category))));
+ system_trash($did, $category, 'contact', $preview, "DELETE FROM {contact} WHERE category = '%s'", $category);
drupal_goto('admin/contact');
- }
}
Index: modules/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter.module,v
retrieving revision 1.77
diff -u -F^function -r1.77 filter.module
--- modules/filter.module 22 Oct 2005 15:14:46 -0000 1.77
+++ modules/filter.module 29 Oct 2005 12:51:43 -0000
@@ -339,33 +339,23 @@ function filter_admin_add() {
* Menu callback; confirm deletion of a format.
*/
function filter_admin_delete() {
- $edit = $_POST['edit'];
- if ($edit['confirm']) {
- if ($edit['format'] != variable_get('filter_default_format', 1)) {
- db_query("DELETE FROM {filter_formats} WHERE format = %d", $edit['format']);
- db_query("DELETE FROM {filters} WHERE format = %d", $edit['format']);
-
- $default = variable_get('filter_default_format', 1);
- db_query("UPDATE {node_revisions} SET format = %d WHERE format = %d", $default, $edit['format']);
- db_query("UPDATE {comments} SET format = %d WHERE format = %d", $default, $edit['format']);
- db_query("UPDATE {boxes} SET format = %d WHERE format = %d", $default, $edit['format']);
-
- cache_clear_all('filter:'. $edit['format'], true);
-
- drupal_set_message(t('Deleted input format %format.', array('%format' => theme('placeholder', $edit['name']))));
- }
- drupal_goto('admin/filters');
- }
-
$format = arg(3);
- $format = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format));
-
- $form['format'] = array('#type' => 'hidden', '#value' => $format->format);
- $form['name'] = array('#type' => 'hidden', '#value' => $format->name);
-
- return confirm_form('filter_admin_delete', $form, t('Are you sure you want to delete the input format %format?', array('%format' => theme('placeholder', $format->name))), 'admin/filters', t('If you have any content left in this input format, it will be switched to the default input format. This action cannot be undone.'), t('Delete'), t('Cancel'));
-
+ if ($format != variable_get('filter_default_format', 1)) {
+ $result = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format));
+ $did = next_delete_id();
+ $preview = array('name' => $result->name);
+ drupal_set_message(t('Input format %format sent to trash.', array('%format' => theme('placeholder', $result->name))));
+ system_trash($did, $format, 'filter', $preview, "DELETE FROM {filters} WHERE format = %d", $format);
+ system_trash($did, $format, NULL, NULL, "DELETE FROM {filter_formats} WHERE format = %d", $format);
+
+ $default = variable_get('filter_default_format', 1);
+ db_query("UPDATE {node_revisions} SET format = %d WHERE format = %d", $default, $format);
+ db_query("UPDATE {comments} SET format = %d WHERE format = %d", $default, $format);
+ db_query("UPDATE {boxes} SET format = %d WHERE format = %d", $default, $format);
+ cache_clear_all('filter:'. $format, true);
+ }
+ drupal_goto('admin/filters');
}
/**
Index: modules/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum.module,v
retrieving revision 1.280
diff -u -F^function -r1.280 forum.module
--- modules/forum.module 28 Oct 2005 13:56:26 -0000 1.280
+++ modules/forum.module 29 Oct 2005 12:51:44 -0000
@@ -86,14 +86,8 @@ function forum_admin() {
}
break;
case t('Delete'):
- if (!$edit['confirm']) {
- $output = _forum_confirm_delete($edit['tid']);
- break;
- }
- else {
$name = $edit['name'];
$edit['name'] = 0;
- }
case t('Submit'):
$status = taxonomy_save_term($edit);
if (arg(3) == 'container') {
@@ -139,10 +133,10 @@ function forum_admin() {
function forum_taxonomy($op, $type, $object = NULL) {
if ($op == 'delete' && $type == 'term' && $object->vid == _forum_get_vid()) {
$results = db_query('SELECT f.nid FROM {forum} f WHERE f.tid = %d', $object->tid);
- while ($node = db_fetch_object($results)) {
- $edit['nid'] = $node->nid;
- $edit['confirm'] = TRUE;
- node_delete($edit);
+ while ($nid = db_fetch_object($results)) {
+ $node = node_load($nid->nid);
+ $node->did = $object->did;
+ node_delete($node);
}
}
elseif ($op == 'delete' && $type == 'vocabulary' && $object->vid == _forum_get_vid()) {
@@ -151,20 +145,6 @@ function forum_taxonomy($op, $type, $obj
}
/**
- * Returns a confirmation page for deleting a forum taxonomy term
- *
- * @param $tid ID of the term to be deleted
- */
-function _forum_confirm_delete($tid) {
- $term = taxonomy_get_term($tid);
-
- $form['tid'] = array('#type' => 'hidden', '#value' => $tid);
-
- return confirm_form('forum_confirm_delete', $form, t('Are you sure you want to delete the forum %name?', array('%name' => theme('placeholder', $term->name))),
- 'admin/forums', t('Deleting a forum or container will delete all sub-forums as well. This action cannot be undone.'), t('Delete'), t('Cancel'));
-}
-
-/**
* Returns a form for adding a container to the forum vocabulary
*
* @param $edit Associative array containing a container term to be added or edited.
@@ -580,7 +560,7 @@ function forum_insert($node) {
* Implementation of hook_delete().
*/
function forum_delete(&$node) {
- db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {forum} WHERE nid = %d', $node->nid);
}
/**
Index: modules/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale.module,v
retrieving revision 1.128
diff -u -F^function -r1.128 locale.module
--- modules/locale.module 13 Oct 2005 10:02:31 -0000 1.128
+++ modules/locale.module 29 Oct 2005 12:51:44 -0000
@@ -294,39 +294,28 @@ function locale_admin_manage() {
function locale_admin_manage_delete_screen() {
include_once './includes/locale.inc';
$langcode = arg(4);
- $edit = $_POST['edit'];
-
- // Check confirmation and if so, delete language
- if ($edit['confirm']) {
- $languages = locale_supported_languages(FALSE, TRUE);
- if (isset($languages['name'][$edit['langcode']])) {
- db_query("DELETE FROM {locales_meta} WHERE locale = '%s'", $edit['langcode']);
- db_query("DELETE FROM {locales_target} WHERE locale = '%s'", $edit['langcode']);
- $message = t('The language %locale has been removed.', array('%locale' => theme('placeholder', t($languages['name'][$edit['langcode']]))));
- drupal_set_message($message);
- watchdog('locale', $message);
- }
-
- // Changing the locale settings impacts the interface:
- cache_clear_all();
- drupal_goto('admin/locale/language/overview');
- }
-
+
// Do not allow deletion of English locale
if ($langcode == 'en') {
drupal_goto('admin/locale/language/overview');
return;
}
- // For other locales, warn user that data loss is ahead
+ // Delete language
$languages = locale_supported_languages(FALSE, TRUE);
+ if (isset($languages['name'][$langcode])) {
+ $did = next_delete_id();
+ $preview = array('language code' => $langcode, 'name' => $languages['name'][$langcode]);
+ $message = t('The language %locale has been sent to trash.', array('%locale' => theme('placeholder', t($languages['name'][$langcode]))));
+ drupal_set_message($message);
+ watchdog('locale', $message);
+ system_trash($did, $langcode, 'locale', $preview, "DELETE FROM {locales_meta} WHERE locale = '%s'", $langcode);
+ system_trash($did, $langcode, NULL, NULL, "DELETE FROM {locales_target} WHERE locale = '%s'", $langcode);
+ }
- $form['langcode'] = array('#type' => 'hidden', '#value' => $langcode);
- return confirm_form('locale_admin_manage_delete_screen', $form,
- t('Are you sure you want to delete the language %name?', array('%name' => theme('placeholder', t($languages['name'][$langcode])))),
- 'admin/locale/language/overview',
- t('Deleting a language will remove all data associated with it. This action cannot be undone.'),
- t('Delete'), t('Cancel'));
+ // Changing the locale settings impacts the interface:
+ cache_clear_all();
+ drupal_goto('admin/locale/language/overview');
}
/**
Index: modules/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node.module,v
retrieving revision 1.543
diff -u -F^function -r1.543 node.module
--- modules/node.module 28 Oct 2005 14:04:20 -0000 1.543
+++ modules/node.module 29 Oct 2005 12:51:47 -0000
@@ -866,6 +866,9 @@ function node_menu($may_cache) {
'access' => user_access('administer nodes'));
$items[] = array('path' => 'admin/node/action', 'title' => t('content'),
'type' => MENU_CALLBACK);
+ $items[] = array('path' => 'admin/node/batch_delete', 'title' => t('content'),
+ 'type' => MENU_CALLBACK, 'access' => user_access('administer nodes'),
+ 'callback' => 'node_multiple_delete_confirm');
$items[] = array('path' => 'admin/node/overview', 'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/settings/node', 'title' => t('posts'),
@@ -907,7 +910,7 @@ function node_menu($may_cache) {
'weight' => 1,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'node/'. arg(1) .'/delete', 'title' => t('delete'),
- 'callback' => 'node_delete_page',
+ 'callback' => 'node_delete_confirm',
'access' => node_access('delete', $node),
'weight' => 1,
'type' => MENU_CALLBACK);
@@ -1100,18 +1103,20 @@ function node_filter_form_execute() {
* Generate the content administration overview.
*/
function node_admin_nodes_execute($form_id, $edit) {
- $operations = node_operations();
- if ($operations[$edit['operation']][1]) {
- // Flag changes
- $operation = $operations[$edit['operation']][1];
- foreach ($edit['nodes'] as $nid => $value) {
- if ($value) {
- db_query($operation, $nid);
+ if ($edit['operation'] != 'delete') {
+ $operations = node_operations();
+ if ($operations[$edit['operation']][1]) {
+ // Flag changes
+ $operation = $operations[$edit['operation']][1];
+ foreach ($edit['nodes'] as $nid => $value) {
+ if ($value) {
+ db_query($operation, $nid);
+ }
}
+ drupal_set_message(t('The update has been performed.'));
}
- drupal_set_message(t('The update has been performed.'));
+ drupal_goto('admin/node');
}
- drupal_goto('admin/node');
}
function node_admin_nodes_validate($form_id, $edit) {
@@ -1160,7 +1165,7 @@ function node_admin_nodes() {
// If you are attempting to delete nodes, display the multiple deletion form.
if ($form_values['operation'] == 'delete') {
- $output = node_multiple_delete_form();
+ $output = node_multiple_delete_confirm();
}
return $output;
@@ -1197,30 +1202,82 @@ function theme_node_admin_nodes($form) {
return $output;
}
-function node_multiple_delete_form() {
+function node_multiple_delete_confirm() {
global $form_values;
- $form['nodes'] = array('#prefix' => '
');
- foreach ($form_values['nodes'] as $nid => $value) {
- if ($value) {
- $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid));
- $form['nodes'][$nid] = array('#type' => 'hidden', '#value' => $nid, '#tree' => TRUE, '#prefix' => '', '#suffix' => check_plain($title) .'');
+ $edit = $_POST['edit'];
+ // Grab nids from url for execute
+ if ($edit['confirm']) {
+ $nids = array_keys($edit['checkboxes']);
+ }
+ else {
+ // Keep only checked nodes' nids
+ $nids = array_keys(array_intersect($form_values['nodes'], array('1')));
+ }
+ foreach ($nids as $nid) {
+ $node = node_load($nid);
+ $extras = node_invoke_nodeapi($node, 'delete pre');
+ // No extras, just delete
+ if (!count($extras)) {
+ node_delete($node);
+ }
+ else {
+ // Add node and extras to the list only if no module has cancelled deletion for this node.
+ if (!in_array(FALSE, $extras)) {
+ $form['nodes'][$node->nid] = array('#type' => 'value', '#value' => 1);
+ $form['title'][$node->nid] = array('#type' => 'markup', '#value' => check_plain($node->title));
+ $form['extras'][$node->nid] = $extras;
+ $options[$node->nid] = '';
+ }
}
}
- $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
-
- return confirm_form('node_multiple_delete_form', $form,
- t('Are you sure you want to delete these items?'),
- 'admin/node', t('This action cannot be undone.'),
- t('Delete all'), t('Cancel'));
+ if ($edit['confirm']) {
+ confirm_form('node_multiple_delete_confirm', $form,
+ t('The following items need to be reviewed'),
+ 'admin/node', t('Selected items will be sent to trash.'),
+ t('Delete selected'), t('Cancel'));
+ }
+ // Back to the admin page if no nodes can be deleted.
+ if (!count($options)) {
+ drupal_goto('admin/node');
+ }
+ else {
+ $form['nodes']['#tree'] = TRUE;
+ $form['title']['#tree'] = TRUE;
+ $form['extras']['#tree'] = TRUE;
+ $form['checkboxes'] = array('#type' => 'checkboxes', '#options' => $options);
+ $form['confirm'] = array('#type' => 'value', '#value' => 1);
+ $form['operation'] = array('#type' => 'value', '#value' => 'delete');
+ $form['#method'] = 'post';
+ $form['#action'] = url('admin/node/batch_delete');
+ return confirm_form('node_multiple_delete_confirm', $form,
+ t('The following items need to be reviewed'),
+ 'admin/node', t('Selected items will be sent to trash.'),
+ t('Delete selected'), t('Cancel'));
+ }
}
+function theme_node_multiple_delete_confirm($form) {
+ $rows = array();
+ $header = array('');
+ $output = '';
+ foreach(element_children($form['nodes']) as $nid) {
+ $rows[] = array(''. ''. form_render($form['title'][$nid]) .''. form_render($form['checkboxes'][$nid]) .'
'. form_render($form['extras'][$nid]) . form_render($form['nodes'][$nid]));
+ $rows[] = array('');
+ }
+ $output .= theme('table', $header, $rows);
+ $output .= form_render($form);
+ return $output;
+}
-function node_multiple_delete_form_execute($form_id, $edit) {
- if ($edit['confirm']) {
- foreach ($edit['nodes'] as $nid => $value) {
- node_delete(array('nid' => $nid, 'confirm' => 1));
+function node_multiple_delete_confirm_execute($form_id, $form_values) {
+ $edit = $_POST['edit'];
+ if ($form_values['confirm']) {
+ foreach ($edit['checkboxes'] as $nid => $value) {
+ // Merge extra confirm data with node
+ $node = object2array(node_load($nid));
+ $node = array2object(array_merge($node, $edit['extras'][$nid]));
+ node_delete($node);
}
- drupal_set_message(t('The items have been deleted.'));
}
drupal_goto('admin/node');
}
@@ -1334,11 +1391,14 @@ function node_revision_delete($nid, $rev
$count_revisions = db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $nid));
// Don't delete the last revision of the node or the current revision
if ($count_revisions > 1) {
- db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision);
- drupal_set_message(t('Deleted revision with the ID %revision.', array('%revision' => theme('placeholder', $revision))));
+ $node = node_load($nid);
+ $did = next_delete_id();
+ $preview = array('title' => $node->title, 'body' => $node->body);
+ drupal_set_message(t('Revision ID %revision moved to trash.', array('%revision' => theme('placeholder', $revision))));
+ system_trash($did, $nid, 'node revision', $preview, "DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision);
}
else {
- drupal_set_message(t('Deletion failed. You tried to delete the current revision.'));
+ drupal_set_message(t('Deletion failed. You tried to move the current revision to trash.'));
}
drupal_goto("node/$nid/revisions");
@@ -1842,29 +1902,73 @@ function node_form_execute($form_id, $ed
/**
* Ask for confirmation, and delete the node.
*/
-function node_delete($edit) {
+function node_delete_confirm() {
+ $edit = $_POST['edit'];
+ $edit['nid'] = $edit['nid'] ? $edit['nid'] : arg(1);
$node = node_load($edit['nid']);
-
if (node_access('delete', $node)) {
- $form['nid'] = array('#type' => 'hidden', '#value' => $node->nid);
- $output = confirm_form('node_delete_confirm', $form,
- t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
- $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action cannot be undone.'),
- t('Delete'), t('Cancel') );
+ $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
+ $form['confirm'] = array('#type' => 'value', '#value' => 1);
+ // Check for extra info from modules
+ $extras = node_invoke_nodeapi($node, 'delete pre');
+ $form['extras'] = $extras;
+ if ($edit['confirm']) {
+ confirm_form('node_delete_confirm', $form,
+ t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
+ $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action will send the
+ item to trash'), t('Delete'), t('Cancel'));
+ }
+ // No extras, just delete the node
+ if (!count($extras)) {
+ node_delete($node);
+ drupal_goto('node');
+ }
+ else {
+ // Cancel deletion if necessary, otherwise display confirm form
+ if (in_array(FALSE, $extras)) {
+ drupal_goto('node/'. $node->nid .'/edit');
+ }
+ else {
+ return confirm_form('node_delete_confirm', $form,
+ t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
+ $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action will send the
+ item to trash'), t('Delete'), t('Cancel'));
+ }
+ }
}
-
- return $output;
}
-function node_delete_confirm_execute() {
- global $form_values;
- $node = node_load($form_values['nid']);
-
- if (node_access('delete', $node)) {
+function node_delete_confirm_execute($form_id, $form_values) {
+ if ($form_values['confirm']) {
+ // Merge extra confirm data with node
+ $node = object2array(node_load($form_values['nid']));
+ $node = array2object(array_merge($node, $form_values));
+ node_delete($node);
+ drupal_goto('node');
+ }
+}
- if ($form_values['confirm']) {
- db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
- db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
+function node_delete($node) {
+ if (is_numeric($node)) {
+ $node = node_load($node);
+ }
+ elseif (is_array($node)) {
+ $node = node_load($node['nid']);
+ }
+ if (!$node->did) {
+ $node->did = next_delete_id();
+ $root_row = 'node';
+ }
+ else {
+ $root_row = NULL;
+ }
+ $preview['title'] = $node->title;
+ if ($node->body) {
+ $preview['body'] = $node->body;
+ }
+ drupal_set_message(t('%title moved to trash.', array('%title' => theme('placeholder', $node->title))));
+ system_trash($node->did, $node->nid, $root_row, $preview, 'DELETE FROM {node} WHERE nid = %d', $node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
// Call the node-specific callback (if any):
node_invoke($node, 'delete');
@@ -1877,11 +1981,7 @@ function node_delete_confirm_execute() {
if (function_exists('search_wipe')) {
search_wipe($node->nid, 'node');
}
-
watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))));
- }
- }
- drupal_goto('node');
}
/**
@@ -2003,20 +2103,6 @@ function node_page() {
}
/**
- * Menu callback; the page for deleting a single node.
- */
-function node_delete_page() {
- $edit = $_POST['edit'];
- $edit['nid'] = $edit['nid'] ? $edit['nid'] : arg(1);
- $node = node_load($edit['nid']);
- if (!($output = node_delete($edit))) {
- drupal_set_message(t('%title has been deleted.', array('%title' => theme('placeholder', $node->title))));
- drupal_goto('');
- }
- return $output;
-}
-
-/**
* Implementation of hook_update_index().
*/
function node_update_index() {
Index: modules/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path.module,v
retrieving revision 1.68
diff -u -F^function -r1.68 path.module
--- modules/path.module 28 Oct 2005 14:04:20 -0000 1.68
+++ modules/path.module 29 Oct 2005 12:51:47 -0000
@@ -105,17 +105,25 @@ function path_admin_edit($pid = 0) {
* Menu callback; handles deletion of an URL alias.
*/
function path_admin_delete($pid = 0) {
- db_query('DELETE FROM {url_alias} WHERE pid = %d', $pid);
- drupal_set_message(t('The alias has been deleted.'));
+ $did = next_delete_id();
+ $result = db_fetch_object(db_query('SELECT src, dst FROM {url_alias} WHERE pid = %d', $pid));
+ $preview = array('source' => $result->src, 'destination' => $result->dst);
+ drupal_set_message(t('The alias has been moved to trash.'));
+ system_trash($did, $pid, 'url alias', $preview, 'DELETE FROM {url_alias} WHERE pid = %d', $pid);
drupal_goto('admin/path');
}
/**
* Set an aliased path for a given Drupal path, preventing duplicates.
*/
-function path_set_alias($path = NULL, $alias = NULL, $pid = NULL) {
+function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $node = NULL) {
if ($path && !$alias) {
- db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
+ if ($node->did) {
+ system_trash($node->did, $node->nid, NULL, NULL, "DELETE FROM {url_alias} WHERE src = '%s'", $path);
+ }
+ else {
+ db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
+ }
drupal_clear_path_cache();
}
else if (!$path && $alias) {
@@ -222,7 +230,7 @@ function path_nodeapi(&$node, $op, $arg)
case 'delete':
$path = "node/$node->nid";
if (drupal_get_path_alias($path) != $path) {
- path_set_alias($path);
+ path_set_alias($path, NULL, NULL, $node);
}
break;
}
Index: modules/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll.module,v
retrieving revision 1.173
diff -u -F^function -r1.173 poll.module
--- modules/poll.module 11 Oct 2005 19:44:35 -0000 1.173
+++ modules/poll.module 29 Oct 2005 12:51:47 -0000
@@ -83,9 +83,16 @@ function poll_cron() {
/**
* Implementation of hook_delete().
*/
-function poll_delete($node) {
- db_query("DELETE FROM {poll} WHERE nid = %d", $node->nid);
- db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
+function poll_delete(&$node) {
+ // Poll trash preview
+ if ($node->choice) {
+ foreach ($node->choice as $key => $array) {
+ $c++;
+ $preview["choice$c"] = $array['chtext'];
+ }
+ }
+ system_trash($node->did, $node->nid, NULL, $preview, "DELETE FROM {poll} WHERE nid = %d", $node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, "DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
}
/**
Index: modules/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile.module,v
retrieving revision 1.115
diff -u -F^function -r1.115 profile.module
--- modules/profile.module 21 Oct 2005 11:14:55 -0000 1.115
+++ modules/profile.module 29 Oct 2005 12:51:48 -0000
@@ -533,18 +533,13 @@ function profile_admin_edit($fid) {
* Menu callback; deletes a field from all user profiles.
*/
function profile_admin_delete($fid) {
- $field = db_fetch_object(db_query("SELECT title FROM {profile_fields} WHERE fid = %d", $fid));
- if ($_POST['edit']['confirm']) {
- db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid);
- cache_clear_all();
- drupal_set_message(t('The field %field has been deleted.', array('%field' => theme('placeholder', $field->title))));
- drupal_goto('admin/settings/profile');
- }
- else {
- return confirm_form('profile_confirm_delete', $form, t('Do you want to remove the field %field?',
- array('%field' => $field->title)),
- 'admin/settings/profile', '', t('Delete'), t('Cancel'));
- }
+ $did = next_delete_id();
+ $result = db_fetch_object(db_query("SELECT title, explanation, category FROM {profile_fields} WHERE fid = %d", $fid));
+ $preview = array('title' => $result->title, 'explanation' => $result->explanation, 'category' => $result->category);
+ drupal_set_message(t('The field %field has been moved to trash.', array('%field' => theme('placeholder', $result->title))));
+ system_trash($did, $fid, 'profile', $preview, 'DELETE FROM {profile_fields} WHERE fid = %d', $fid);
+ cache_clear_all();
+ drupal_goto('admin/settings/profile');
}
function _profile_field_form($type, $edit = array()) {
Index: modules/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics.module,v
retrieving revision 1.210
diff -u -F^function -r1.210 statistics.module
--- modules/statistics.module 12 Oct 2005 01:00:24 -0000 1.210
+++ modules/statistics.module 29 Oct 2005 12:51:49 -0000
@@ -474,7 +474,7 @@ function statistics_nodeapi(&$node, $op,
switch ($op) {
case 'delete':
// clean up statistics table when node is deleted
- db_query('DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
}
}
Index: modules/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system.module,v
retrieving revision 1.247
diff -u -F^function -r1.247 system.module
--- modules/system.module 26 Oct 2005 01:24:09 -0000 1.247
+++ modules/system.module 29 Oct 2005 12:51:50 -0000
@@ -46,7 +46,7 @@ function system_help($section) {
* Implementation of hook_perm().
*/
function system_perm() {
- return array('administer site configuration', 'access administration pages', 'bypass input data check');
+ return array('administer site configuration', 'access administration pages', 'bypass input data check', 'administer trash');
}
/**
@@ -138,6 +138,18 @@ function system_menu($may_cache) {
}
$items[] = array('path' => 'admin/modules', 'title' => t('modules'),
'callback' => 'system_modules', 'access' => $access);
+
+ // Trash
+ $items[] = array('path' => 'admin/trash', 'title' => t('trash'),
+ 'callback' => 'system_admin_trash', 'access' => TRUE);
+ $items[] = array('path' => 'trash/preview', 'title' => t('preview'),
+ 'callback' => 'system_trash_preview', 'access' => TRUE, 'type' => MENU_CALLBACK);
+ $items[] = array('path' => 'trash/recover', 'title' => t('recover'),
+ 'callback' => 'system_trash_recover', 'access' => TRUE, 'type' => MENU_CALLBACK);
+ $items[] = array('path' => 'trash/delete', 'title' => t('delete'),
+ 'callback' => 'system_trash_delete', 'access' => TRUE, 'type' => MENU_CALLBACK);
+ $items[] = array('path' => 'admin/trash/action', 'title' => t('content'),
+ 'type' => MENU_CALLBACK);
}
return $items;
@@ -1231,3 +1243,256 @@ function confirm_form($form_id, $form, $
$form['actions']['cancel'] = array('#value' => l($no ? $no : t('Cancel'), $path));
return drupal_get_form($form_id, $form, 'confirm_form');
}
+
+function system_admin_trash() {
+
+ global $user;
+ global $form_values;
+ $op = $_POST['op'];
+ $form = array();
+ $view_all = user_access('administer trash');
+ if ($view_all) {
+ $result = pager_query("SELECT * FROM {deleted} WHERE root_row != '' ORDER BY timestamp DESC", 25 , 0);
+ }
+ else {
+ $result = pager_query("SELECT * FROM {deleted} WHERE root_row != '' AND uid = %d ORDER BY timestamp DESC", 25 , 0, NULL, $user->uid);
+ }
+ $destination = drupal_get_destination();
+ while ($recover = db_fetch_object($result)) {
+ $preview = unserialize($recover->preview);
+ $title = is_array($preview[0]) ? array_shift($preview[0]) : '[none]';
+ $items[$recover->did] = '';
+ $form['datetime'][$recover->did] = array('#type' => 'markup', '#value' => format_date($recover->timestamp, 'small'));
+ $form['type'][$recover->did] = array('#type' => 'markup', '#value' => t($recover->root_row));
+ $form['title'][$recover->did] = array('#type' => 'markup', '#value' => t($title));
+ $form['preview'][$recover->did] = array('#type' => 'markup', '#value' => l(t('preview'), "trash/preview/$recover->tid", array(), $destination));
+ }
+ $form['did'] = array('#type' => 'checkboxes', '#options' => $items);
+ $form['pager'] = array('#value' => theme('pager', NULL, 25, 0));
+ $form['buttons'] = array('#prefix' => '', '#suffix' => '
');
+ $form['buttons']['recover'] = array('#type' => 'submit', '#value' => t('Recover'));
+ if ($view_all) {
+ $form['buttons']['delete'] = array('#type' => 'button', '#button_type' => 'submit', '#value' => t('Delete selected'));
+ $form['buttons']['delete_all'] = array('#type' => 'button', '#button_type' => 'submit', '#value' => t('Delete all'));
+ }
+ $form['buttons']['all'] = array('#type' => 'hidden', '#value' => 'all');
+ $form['#method'] = 'post';
+ $form['#action'] = url('admin/trash/action');
+
+ if ($op != t('Delete')) {
+ $output .= drupal_get_form('system_admin_trash', $form, 'system_trash_recover_delete');
+ }
+
+ // If you are attempting to delete nodes, display the multiple deletion form.
+ if ($op && ($op != t('Recover'))) {
+ $output = system_trash_multiple_delete_confirm();
+ }
+ return $output;
+}
+
+function theme_system_admin_trash($form) {
+
+ // Overview table:
+ $output = form_render($form['buttons']);
+ $header = array(NULL, t('Title'), t('Type'), t('Trashed'), t('Operations'));
+ if (is_array($form['datetime'])) {
+ foreach (element_children($form['datetime']) as $key) {
+ $row = array();
+ $row[] = form_render($form['did'][$key]);
+ $row[] = form_render($form['title'][$key]);
+ $row[] = form_render($form['type'][$key]);
+ $row[] = form_render($form['datetime'][$key]);
+ $row[] = form_render($form['preview'][$key]);
+ $rows[] = $row;
+ }
+
+ }
+ else {
+ $rows[] = array(array('data' => t('There are no items in your trash'), 'colspan' => '5'));
+ }
+
+ $output .= theme('table', $header, $rows);
+ if ($form['pager']['#value']) {
+ $output .= form_render($form['pager']);
+ }
+
+ return $output;
+}
+
+function system_trash($did, $rid, $root_row, $preview, $query) {
+ global $user;
+ static $same_did;
+ static $summed_preview;
+ // Grab the args for the query
+ $all_args = func_get_args();
+ if (count($all_args) > 5) {
+ $args = array_slice($all_args, 5);
+ }
+ else {
+ $args = array();
+ }
+ // Turn delete into select and get result
+ $delete = preg_replace('/DELETE.*?FROM/i', 'SELECT * FROM', $query);
+ $result = db_query($delete, $args);
+ $rid = $rid ? $rid : '';
+ $root_row = $root_row ? $root_row : '';
+ // Allow modules to add to data storage array
+ $recover = module_invoke_all('system_trash', $did, $rid, $root_row);
+ // Grab table name and store
+ $table = preg_match('/^DELETE FROM \{([^}]+)/', $query, $m);
+ $recover['table'] = $m[1];
+ // Loop through result inserting rows into deleted table
+ while ($recover['data'] = db_fetch_array($result)) {
+ $data = serialize($recover);
+ $tid = db_next_id('{deleted}_tid');
+ db_query("INSERT INTO {deleted} SET tid = %d, did = %d, rid = %d, uid = %d, root_row = '%s', data = '%s', timestamp = %d", $tid, $did, $rid, $user->uid, $root_row, $data, time());
+ $root_row = '';
+ }
+ // Only one message for each did
+ if ($same_did != $did) {
+ drupal_set_message(t('Click %here to recover from %trash.', array('%here' => l(t('here'), "trash/recover/$did"), '%trash' => l(t('trash'), "admin/trash"))));
+ $same_did = $did;
+ $summed_preview = array();
+ }
+ // Insert new preview summary
+ if ($preview) {
+ $summed_preview[] = $preview;
+ }
+ $insert_preview = $summed_preview ? serialize($summed_preview) : '';
+ db_query("UPDATE {deleted} SET preview = '%s' WHERE did = %d AND root_row !=''", $insert_preview, $did);
+ // Delete from original table
+ db_query($query, $args);
+}
+
+function system_trash_preview($tid) {
+ global $user;
+ $op = $_POST['op'];
+ $view_all = user_access('administer trash');
+ $insert = db_fetch_object(db_query('SELECT * FROM {deleted} WHERE tid = %d', $tid));
+ if ($view_all || $insert->uid == $user->uid) {
+ $did = $insert->did;
+ $output = '';
+ $form['buttons'] = array('#prefix' => '', '#suffix' => '
');
+ $form['buttons']['recover'] = array('#type' => 'submit', '#value' => t('Recover'));
+ if ($view_all) {
+ $form['buttons']['delete'] = array('#type' => 'button', '#button_type' => 'submit', '#value' => t('Delete selected'));
+ }
+
+ $form['did']['#tree'] = TRUE;
+ $form['did'][$did] = array('#type' => 'hidden', '#value' => 1);
+
+ if ($op != t('Delete')) {
+ $output .= drupal_get_form('system_trash_preview', $form, 'system_trash_recover_delete');
+ }
+
+ // If you are attempting to delete nodes, display the multiple deletion form.
+ if ($op && ($op != t('Recover'))) {
+ $output = system_trash_multiple_delete_confirm();
+ }
+ // Grab preview data
+ $values = array();
+ $data = unserialize($insert->preview);
+ $header = array();
+ $rows = array();
+ if ($data) {
+ foreach ($data as $preview_section) {
+ foreach ($preview_section as $key => $value) {
+ $rows[] = array(''. t($key) . ': ', t($value));
+ }
+ $rows[] = array(array('data' => '', 'colspan' => 2));
+ }
+ }
+ $output .= '';
+ $output .= '- '. t('Trashed') .': '. format_date($insert->timestamp, 'small');
+ $output .= '
- '. t('Type') .': '. t($insert->root_row);
+ $output .= '
';
+ $output .= ''. t('Data') .':
';
+ $output .= theme('table', $header, $rows);;
+ return $output;
+ }
+ else {
+ drupal_access_denied();
+ }
+}
+
+function system_trash_recover_delete_execute($form_id, $form_values) {
+ $op = $_POST['op'];
+ $form_values['did'] = $form_values['did'] ? $form_values['did'] : array();
+ $dids = array_keys($form_values['did'], 1);
+ if ((count($dids) == 0) && $op != t('Delete all') && $form_values['operation'] != t('Delete all')) {
+ drupal_set_message(t('No items were selected. Select items in order to perform the operation'));
+ drupal_goto('admin/trash');
+ }
+ if ($op == t('Recover')) {
+ foreach ($dids as $did) {
+ $result = db_query('SELECT * FROM {deleted} WHERE did = %d', $did);
+ // Loop through reinserting all rows
+ while ($insert = db_fetch_object($result)) {
+ $values = array();
+ $recover = unserialize($insert->data);
+ foreach ($recover['data'] as $key => $value) {
+ $values[] = is_numeric($value) ? '%d' : '\'%s\'';
+ // Best guess at recovered node if present
+ if ($key == 'nid') {
+ $nid = $value;
+ }
+ }
+ db_query('INSERT INTO {'. $recover['table']. '} VALUES('. implode(', ', $values). ')', $recover['data']);
+ }
+ module_invoke_all('system_trash_recover', $did);
+ db_query('DELETE FROM {deleted} WHERE did = %d', $did);
+ }
+ if ($form_id == 'system_trash_preview') {
+ $message = $nid ? t('The %item has been recovered', array('%item' => l(t('item'), "node/$nid"))) : t('The item has been recovered');
+ }
+ else {
+ $message = t('The items have been recovered');
+ }
+ }
+ if ($form_values['confirm']) {
+ switch ($form_values['operation']) {
+ case t('Delete selected'):
+ foreach ($dids as $did) {
+ module_invoke_all('system_trash_delete', $did);
+ db_query('DELETE FROM {deleted} WHERE did = %d', $did);
+ }
+ $message = t('Permanent delete successful');
+ break;
+ case t('Delete all'):
+ module_invoke_all('system_trash_delete', 'all');
+ db_query('DELETE FROM {deleted}');
+ $message = t('Permanent delete successful');
+ break;
+ }
+ }
+ drupal_set_message($message);
+ drupal_goto('admin/trash');
+}
+
+function system_trash_multiple_delete_confirm() {
+ $op = $_POST['op'];
+ $edit = $_POST['edit'];
+ $edit['did'] = $edit['did'] ? $edit['did'] : array();
+ $dids = array_keys($edit['did'], 1);
+ if ($edit['confirm']) {
+ $form['operation'] = array('#type' => 'hidden', '#value' => $edit['operation']);
+ $_POST['edit']['form_id'] = 'system_trash_recover_delete';
+ }
+ else {
+ $form['operation'] = array('#type' => 'hidden', '#value' => $op);
+ }
+ $form['did']['#tree'] = TRUE;
+ foreach ($dids as $did) {
+ $form['did'][$did] = array('#type' => 'hidden', '#value' => 1);
+ }
+ $item = (count($dids) == 1) ? 'this item' : 'these items';
+ $output = confirm_form('system_trash_recover_delete', $form,
+ t('Are you sure you want to permanently delete %item?', array('%item' => $item)),
+ 'admin/trash', t('This operation cannot be undone.'),
+ t('Delete'), t('Cancel'));
+ return $output;
+}
+
+function next_delete_id() {
+ return db_next_id('{deleted}_did');
+}
Index: modules/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy.module,v
retrieving revision 1.232
diff -u -F^function -r1.232 taxonomy.module
--- modules/taxonomy.module 21 Oct 2005 11:12:46 -0000 1.232
+++ modules/taxonomy.module 29 Oct 2005 12:51:52 -0000
@@ -179,14 +179,16 @@ function taxonomy_save_vocabulary(&$edit
function taxonomy_del_vocabulary($vid) {
$vocabulary = taxonomy_get_vocabulary($vid);
-
- db_query('DELETE FROM {vocabulary} WHERE vid = %d', $vid);
- db_query('DELETE FROM {vocabulary_node_types} WHERE vid = %d', $vid);
+ $did = next_delete_id();
+ $preview = array('name' => $vocabulary->name, 'description' => $vocabulary->description);
+ system_trash($did, $vid, 'vocabulary', $preview, 'DELETE FROM {vocabulary} WHERE vid = %d', $vid);
+ system_trash($did, $vid, NULL, NULL, 'DELETE FROM {vocabulary_node_types} WHERE vid = %d', $vid);
$result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
while ($term = db_fetch_object($result)) {
- taxonomy_del_term($term->tid);
+ taxonomy_del_term($term->tid, $did);
}
+ $vocabulary->did = $did;
module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
cache_clear_all();
@@ -194,20 +196,6 @@ function taxonomy_del_vocabulary($vid) {
return SAVED_DELETED;
}
-function _taxonomy_confirm_del_vocabulary($vid) {
- $vocabulary = taxonomy_get_vocabulary($vid);
-
- $form['type'] = array('#type' => 'hidden', '#value' => 'vocabulary');
- $form['vid'] = array('#type' => 'hidden', '#value' => $vid);
- $form['name'] = array('#type' => 'hidden', '#value' => $vocabulary->name);
- return confirm_form('vocabulary_confirm_delete', $form,
- t('Are you sure you want to delete the vocabulary %title?',
- array('%title' => theme('placeholder', $vocabulary->name))),
- 'admin/taxonomy', t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'),
- t('Delete'),
- t('Cancel'));
-}
-
function taxonomy_form_term($edit = array()) {
$vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4);
$vocabulary = taxonomy_get_vocabulary($vocabulary_id);
@@ -324,7 +312,14 @@ function taxonomy_save_term(&$edit) {
return $status;
}
-function taxonomy_del_term($tid) {
+function taxonomy_del_term($tid, $vocab_did = NULL) {
+ static $count;
+ if ($vocab_did) {
+ $did = $vocab_did;
+ }
+ else {
+ $did = next_delete_id();
+ }
$tids = array($tid);
while ($tids) {
$children_tids = $orphans = array();
@@ -341,37 +336,37 @@ function taxonomy_del_term($tid) {
}
$term = taxonomy_get_term($tid);
-
- db_query('DELETE FROM {term_data} WHERE tid = %d', $tid);
- db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $tid);
- db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid);
- db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid);
- db_query('DELETE FROM {term_node} WHERE tid = %d', $tid);
-
+ if (!$recurse && !$vocab_did) {
+ $root_row = 'taxonomy term';
+ $preview = array('root term' => $term->name, 'description' => $term->description);
+ $recurse = 1;
+ }
+ else {
+ $count++;
+ $root_row = NULL;
+ $preview = array();
+ if ($term->name) {
+ $preview['term'. $count] = $term->name;
+ }
+ if ($term->description) {
+ $preview['description'. $count] = $term->description;
+ }
+ }
+ drupal_set_message(t('Moved term %name to trash.', array('%name' => theme('placeholder', $term->name))));
+ system_trash($did, $term->vid, $root_row, $preview, 'DELETE FROM {term_data} WHERE tid = %d', $tid);
+ system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_hierarchy} WHERE tid = %d', $tid);
+ system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid);
+ system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_synonym} WHERE tid = %d', $tid);
+ system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_node} WHERE tid = %d', $tid);
+ $term->did = $did;
module_invoke_all('taxonomy', 'delete', 'term', $term);
- drupal_set_message(t('Deleted term %name.', array('%name' => theme('placeholder', $term->name))));
}
$tids = $orphans;
}
-
cache_clear_all();
}
-function _taxonomy_confirm_del_term($tid) {
- $term = taxonomy_get_term($tid);
-
- $form['type'] = array('#type' => 'hidden', '#value' => 'term');
- $form['tid'] = array('#type' => 'hidden', '#value' => $tid);
- return confirm_form('term_confirm_delete', $form,
- t('Are you sure you want to delete the term %title?',
- array('%title' => theme('placeholder', $term->name))),
- 'admin/taxonomy',
- t('Deleting a term will delete all its children if there are any. This action cannot be undone.'),
- t('Delete'),
- t('Cancel'));
-}
-
/**
* Generate a tabular listing of administrative functions for vocabularies.
*/
@@ -593,7 +588,7 @@ function taxonomy_node_validate(&$node)
* Save term associations for a given node.
*/
function taxonomy_node_save($nid, $terms) {
- taxonomy_node_delete($nid);
+ db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
// Free tagging vocabularies do not send their tids in the form,
// so we'll detect them here and process them independently.
@@ -654,13 +649,6 @@ function taxonomy_node_save($nid, $terms
}
/**
- * Remove associations of a node to its terms.
- */
-function taxonomy_node_delete($nid) {
- db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
-}
-
-/**
* Find all term objects related to a given term ID.
*/
function taxonomy_get_related($tid, $key = 'tid') {
@@ -1041,7 +1029,7 @@ function taxonomy_nodeapi($node, $op, $a
taxonomy_node_save($node->nid, $node->taxonomy);
break;
case 'delete':
- taxonomy_node_delete($node->nid);
+ system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {term_node} WHERE nid = %d', $node->nid);
break;
case 'validate':
taxonomy_node_validate($node);
@@ -1170,20 +1158,9 @@ function taxonomy_admin() {
}
break;
case t('Delete'):
- if (!$edit['confirm']) {
- if (arg(3) == 'vocabulary') {
- $output = _taxonomy_confirm_del_vocabulary($edit['vid']);
- }
- else {
- $output = _taxonomy_confirm_del_term($edit['tid']);
- }
- break;
- }
- else {
- $deleted_name = $edit['name'];
- $edit['name'] = 0;
- // fall through:
- }
+ $deleted_name = $edit['name'];
+ $edit['name'] = 0;
+ // fall through:
case t('Submit'):
if (arg(3) == 'vocabulary') {
switch (taxonomy_save_vocabulary($edit)) {
@@ -1194,7 +1171,7 @@ function taxonomy_admin() {
drupal_set_message(t('Updated vocabulary %name.', array('%name' => theme('placeholder', $edit['name']))));
break;
case SAVED_DELETED:
- drupal_set_message(t('Deleted vocabulary %name.', array('%name' => theme('placeholder', $deleted_name))));
+ drupal_set_message(t('Moved vocabulary %name to trash.', array('%name' => theme('placeholder', $deleted_name))));
break;
}
}
Index: modules/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload.module,v
retrieving revision 1.56
diff -u -F^function -r1.56 upload.module
--- modules/upload.module 28 Oct 2005 14:04:20 -0000 1.56
+++ modules/upload.module 29 Oct 2005 12:51:53 -0000
@@ -289,7 +289,12 @@ function upload_nodeapi(&$node, $op, $ar
break;
case 'delete':
- upload_delete($node);
+ $file_info = upload_load($node);
+ foreach ($file_info as $file) {
+ $i++;
+ $preview['file'. $i] = $file->filename;
+ }
+ system_trash($node->did, $node->nid, NULL, $preview, "DELETE FROM {files} WHERE nid = %d", $node->nid);
break;
case 'search result':
return $node->files ? format_plural(count($node->files), '1 attachment', '%count attachments') : null;
@@ -380,14 +385,6 @@ function upload_save($node) {
return;
}
-function upload_delete($node) {
- $node->files = upload_load($node);
- foreach ($node->files as $file) {
- file_delete($file->filepath);
- }
- db_query("DELETE FROM {files} WHERE nid = %d", $node->nid);
-}
-
function upload_form($node) {
drupal_add_js('misc/progress.js');
drupal_add_js('misc/upload.js');
@@ -512,3 +509,35 @@ function upload_js() {
print drupal_call_js('window.parent.iframeHandler', $output);
exit;
}
+
+function upload_system_trash($did, $rid, $root_row) {
+ // Store file info in case of later permanent deletion
+ if ($root_row == 'node') {
+ $node = node_load($rid);
+ $file_info = upload_load($node);
+ $files = array();
+ foreach ($file_info as $file) {
+ $filepaths[] = $file->filepath;
+ }
+ $recover['files'] = $filepaths;
+ return $recover;
+ }
+}
+
+function upload_system_trash_delete($did) {
+ // Grab all node deletions and delete associated files
+ if ($did == 'all') {
+ $result = db_query("SELECT * FROM {deleted} WHERE root_row = 'node'");
+ }
+ else {
+ $result = db_query("SELECT * FROM {deleted} WHERE did = %d AND root_row = 'node'", $did);
+ }
+ while ($node = db_fetch_object($result)) {
+ $data = unserialize($node->data);
+ if ($data['files']) {
+ foreach ($data['files'] as $filepath) {
+ file_delete($filepath);
+ }
+ }
+ }
+}
Index: modules/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user.module,v
retrieving revision 1.524
diff -u -F^function -r1.524 user.module
--- modules/user.module 28 Oct 2005 00:37:06 -0000 1.524
+++ modules/user.module 29 Oct 2005 12:51:55 -0000
@@ -1257,18 +1257,16 @@ function user_edit($category = 'account'
}
}
else if (arg(2) == 'delete') {
- if ($edit['confirm']) {
- db_query('DELETE FROM {users} WHERE uid = %d', $account->uid);
- db_query('DELETE FROM {sessions} WHERE uid = %d', $account->uid);
- db_query('DELETE FROM {users_roles} WHERE uid = %d', $account->uid);
- db_query('DELETE FROM {authmap} WHERE uid = %d', $account->uid);
- drupal_set_message(t('The account has been deleted.'));
- module_invoke_all('user', 'delete', $edit, $account);
- drupal_goto('admin/user');
- }
- else {
- return confirm_form('user_confirm_delete', $form, t('Are you sure you want to delete the account %name?', array('%name' => theme('placeholder', $account->name))), 'user/'. $account->uid, t('Deleting a user will remove all their submissions as well. This action cannot be undone.'), t('Delete'));
- }
+ $did = next_delete_id();
+ $preview = array('name' => $account->name, 'email' => $account->mail);
+ system_trash($did, $account->uid, 'user', $preview, 'DELETE FROM {users} WHERE uid = %d', $account->uid);
+ db_query('DELETE FROM {sessions} WHERE uid = %d', $account->uid);
+ drupal_set_message(t('The account has been moved to trash.'));
+ system_trash($did, $account->uid, NULL, NULL, 'DELETE FROM {users_roles} WHERE uid = %d', $account->uid);
+ system_trash($did, $account->uid, NULL, NULL, 'DELETE FROM {authmap} WHERE uid = %d', $account->uid);
+ $account->did = $did;
+ module_invoke_all('user', 'delete', $edit, $account);
+ drupal_goto('admin/user');
}
else if ($_POST['op'] == t('Delete')) {
// Note: we redirect from user/uid/edit to user/uid/delete to make the tabs disappear.
@@ -1458,21 +1456,10 @@ function user_admin_access_add($mask = N
function user_admin_access_delete($aid = 0) {
$access_types = array('user' => t('username'), 'mail' => t('e-mail'));
$edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
-
- $form = array();
- $form['aid'] = array('#type' => 'hidden', '#value' => $aid);
- $output = confirm_form('user_admin_access_delete_confirm', $form,
- t('Are you sure you want to delete the %type rule for %rule?', array('%type' => $access_types[$edit->type], '%rule' => theme('placeholder', $edit->mask))),
- 'admin/access/rules',
- t('This action cannot be undone.'),
- t('Delete'),
- t('Cancel'));
- return $output;
-}
-
-function user_admin_access_delete_confirm_execute($form_id, $edit) {
- db_query('DELETE FROM {access} WHERE aid = %d', $edit['aid']);
+ $did = next_delete_id();
+ $preview = array('type' => $access_types[$edit->type], 'rule' => $edit->mask);
drupal_set_message(t('The access rule has been deleted.'));
+ system_trash($did, $aid, 'access rule', $preview, 'DELETE FROM {access} WHERE aid = %d', $aid);
drupal_goto('admin/access/rules');
}
@@ -1665,8 +1652,11 @@ function user_admin_role() {
}
}
else if ($op == t('Delete role')) {
- db_query('DELETE FROM {role} WHERE rid = %d', $id);
- db_query('DELETE FROM {permission} WHERE rid = %d', $id);
+ $did = next_delete_id();
+ $preview = db_fetch_array(db_query('SELECT name FROM {role} WHERE rid = %d', $id));
+ drupal_set_message(t('The role has been moved to trash. All users with only this role have been moved to the authenticated users pool.'));
+ system_trash($did, $id, 'role', $preview, 'DELETE FROM {role} WHERE rid = %d', $id);
+ system_trash($did, $id, NULL, NULL, 'DELETE FROM {permission} WHERE rid = %d', $id);
// Update the users who have this role set:
$result = db_query('SELECT DISTINCT(ur1.uid) FROM {users_roles} ur1 LEFT JOIN {users_roles} ur2 ON ur2.uid = ur1.uid WHERE ur1.rid = %d AND ur2.rid != ur1.rid', $id);
@@ -1677,13 +1667,12 @@ function user_admin_role() {
}
if ($uid) {
- db_query('DELETE FROM {users_roles} WHERE rid = %d AND uid IN (%s)', $id, implode(', ', $uid));
+ system_trash($did, $id, NULL, NULL, 'DELETE FROM {users_roles} WHERE rid = %d AND uid IN (%s)', $id, implode(', ', $uid));
}
// Users with only the deleted role are put back in the authenticated users pool.
db_query('UPDATE {users_roles} SET rid = %d WHERE rid = %d', _user_authenticated_id(), $id);
- drupal_set_message(t('The role has been deleted.'));
drupal_goto('admin/access/roles');
}
else if ($op == t('Add role')) {