? files
? undo.patch
? modules/devel
? modules/signup
? sites/localhost
Index: database/database.mysql
===================================================================
RCS file: /cvs/drupal/drupal/database/database.mysql,v
retrieving revision 1.204
diff -u -F^function -r1.204 database.mysql
--- database/database.mysql 14 Nov 2005 22:23:11 -0000 1.204
+++ database/database.mysql 15 Nov 2005 16:43:04 -0000
@@ -243,6 +243,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.146
diff -u -F^function -r1.146 database.pgsql
--- database/database.pgsql 14 Nov 2005 22:23:11 -0000 1.146
+++ database/database.pgsql 15 Nov 2005 16:43:05 -0000
@@ -238,6 +238,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.147
diff -u -F^function -r1.147 updates.inc
--- database/updates.inc 14 Nov 2005 22:23:11 -0000 1.147
+++ database/updates.inc 15 Nov 2005 16:43:06 -0000
@@ -104,7 +104,8 @@
"2005-10-23" => "update_151",
"2005-10-28" => "update_152",
"2005-11-03" => "update_153",
- "2005-11-14" => "update_154"
+ "2005-11-14" => "update_154",
+ "2005-11-15" => "update_155"
);
function update_110() {
@@ -1159,6 +1160,43 @@ function update_154() {
return $ret;
}
+function update_155() {
+ $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;
+}
+
/**
Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.59
diff -u -F^function -r1.59 locale.inc
--- includes/locale.inc 13 Nov 2005 02:32:18 -0000 1.59
+++ includes/locale.inc 15 Nov 2005 16:43:08 -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.188
diff -u -F^function -r1.188 block.module
--- modules/block.module 13 Nov 2005 08:26:01 -0000 1.188
+++ modules/block.module 15 Nov 2005 16:43:09 -0000
@@ -421,26 +421,17 @@ function block_box_add_execute($form_id,
}
/**
- * Menu callback; confirm deletion of custom blocks.
+ * Deletion of custom blocks.
*/
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'));
-}
-
-/**
- * Deletion of custom blocks.
- */
-function block_box_delete_confirm_execute($form_id, $form_values) {
- db_query('DELETE FROM {boxes} WHERE bid = %d', $form_values['bid']);
- drupal_set_message(t('The block %name has been removed.', array('%name' => theme('placeholder', $form_values['info']))));
+ $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');
-};
-
+}
function block_box_form($edit = array()) {
$form['title'] = array('#type' => 'textfield', '#title' => t('Block title'), '#default_value' => $edit['title'], '#maxlength' => 64, '#description' => t('The title of the block as shown to the user.'));
Index: modules/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book.module,v
retrieving revision 1.329
diff -u -F^function -r1.329 book.module
--- modules/book.module 12 Nov 2005 11:26:16 -0000 1.329
+++ modules/book.module 15 Nov 2005 16:43:10 -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);
}
/**
@@ -303,8 +303,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.390
diff -u -F^function -r1.390 comment.module
--- modules/comment.module 15 Nov 2005 07:29:47 -0000 1.390
+++ modules/comment.module 15 Nov 2005 16:43:11 -0000
@@ -268,8 +268,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':
@@ -981,12 +987,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);
@@ -998,20 +1002,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;
}
/**
@@ -1361,9 +1355,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.31
diff -u -F^function -r1.31 contact.module
--- modules/contact.module 14 Nov 2005 22:23:11 -0000 1.31
+++ modules/contact.module 15 Nov 2005 16:43:12 -0000
@@ -213,19 +213,12 @@ function contact_admin_edit($cid = NULL)
}
function contact_admin_delete($cid) {
- $info = db_fetch_object(db_query("SELECT cid, category FROM {contact} WHERE cid = %d", $cid));
- 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', $info->category))),
- 'admin/contact',
- t('This action cannot be undone.'),
- t('Delete'),
- t('Cancel'));
- }
- else {
- db_query("DELETE FROM {contact} WHERE cid = %d", $cid);
+ $did = next_delete_id();
+ $info = db_fetch_object(db_query("SELECT cid, category FROM {contact} WHERE cid = %d", $cid));
+ $preview = array('category' => $info->category);
+ drupal_set_message(t('Contact category %category moved to trash', array('%category' => $info->category)));
+ system_trash($did, $category, 'contact', $preview, "DELETE FROM {contact} WHERE cid = %d", $cid);
drupal_goto('admin/contact');
- }
}
Index: modules/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter.module,v
retrieving revision 1.83
diff -u -F^function -r1.83 filter.module
--- modules/filter.module 12 Nov 2005 11:26:16 -0000 1.83
+++ modules/filter.module 15 Nov 2005 16:43:13 -0000
@@ -350,33 +350,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.284
diff -u -F^function -r1.284 forum.module
--- modules/forum.module 12 Nov 2005 11:26:16 -0000 1.284
+++ modules/forum.module 15 Nov 2005 16:43:14 -0000
@@ -154,7 +154,9 @@ function forum_taxonomy($op, $type, $obj
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)) {
- node_delete($node->nid);
+ $node = node_load($node->nid);
+ $node->did = $object->did;
+ node_delete($node);
}
}
elseif ($op == 'delete' && $type == 'vocabulary' && $object->vid == _forum_get_vid()) {
Index: modules/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale.module,v
retrieving revision 1.129
diff -u -F^function -r1.129 locale.module
--- modules/locale.module 1 Nov 2005 10:17:34 -0000 1.129
+++ modules/locale.module 15 Nov 2005 16:43:15 -0000
@@ -301,39 +301,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.548
diff -u -F^function -r1.548 node.module
--- modules/node.module 13 Nov 2005 02:43:33 -0000 1.548
+++ modules/node.module 15 Nov 2005 16:43:17 -0000
@@ -859,6 +859,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'),
@@ -1093,16 +1096,18 @@ 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');
}
}
@@ -1153,7 +1158,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;
@@ -1190,28 +1195,81 @@ 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' => '
', '#tree' => TRUE);
- 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, '#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($nid);
+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.'));
}
@@ -1327,11 +1385,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");
@@ -1849,16 +1910,36 @@ 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' => 'value', '#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['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;
}
/**
@@ -1866,7 +1947,10 @@ function node_delete_confirm() {
*/
function node_delete_confirm_execute($form_id, $form_values) {
if ($form_values['confirm']) {
- node_delete($form_values['nid']);
+ // 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');
}
}
@@ -1874,28 +1958,40 @@ function node_delete_confirm_execute($fo
/**
* Delete a node.
*/
-function node_delete($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);
- $node = node_load($nid);
+ // Call the node-specific callback (if any):
+ node_invoke($node, 'delete');
+ node_invoke_nodeapi($node, 'delete');
- if (node_access('delete', $node)) {
- db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
- db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
+ // Clear the cache so an anonymous poster can see the node being deleted.
+ cache_clear_all();
- // Call the node-specific callback (if any):
- node_invoke($node, 'delete');
- node_invoke_nodeapi($node, 'delete');
-
- // Clear the cache so an anonymous poster can see the node being deleted.
- cache_clear_all();
-
- // Remove this node from the search index if needed.
- if (function_exists('search_wipe')) {
- search_wipe($node->nid, 'node');
- }
- drupal_set_message(t('%title has been deleted.', array('%title' => theme('placeholder', $node->title))));
- watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))));
+ // Remove this node from the search index if needed.
+ 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))));
}
/**
Index: modules/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path.module,v
retrieving revision 1.71
diff -u -F^function -r1.71 path.module
--- modules/path.module 12 Nov 2005 11:26:16 -0000 1.71
+++ modules/path.module 15 Nov 2005 16:43:18 -0000
@@ -99,17 +99,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) {
@@ -216,7 +224,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.179
diff -u -F^function -r1.179 poll.module
--- modules/poll.module 12 Nov 2005 11:26:16 -0000 1.179
+++ modules/poll.module 15 Nov 2005 16:43:18 -0000
@@ -84,9 +84,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.118
diff -u -F^function -r1.118 profile.module
--- modules/profile.module 13 Nov 2005 08:33:44 -0000 1.118
+++ modules/profile.module 15 Nov 2005 16:43:19 -0000
@@ -554,18 +554,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.212
diff -u -F^function -r1.212 statistics.module
--- modules/statistics.module 13 Nov 2005 02:40:18 -0000 1.212
+++ modules/statistics.module 15 Nov 2005 16:43:20 -0000
@@ -477,7 +477,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.255
diff -u -F^function -r1.255 system.module
--- modules/system.module 14 Nov 2005 22:19:14 -0000 1.255
+++ modules/system.module 15 Nov 2005 16:43:22 -0000
@@ -47,7 +47,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');
}
/**
@@ -139,6 +139,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;
@@ -1143,6 +1155,259 @@ function theme_search_box($form) {
return $output;
}
+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');
+}
+
/**
* Output a confirmation form
*
Index: modules/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy.module,v
retrieving revision 1.236
diff -u -F^function -r1.236 taxonomy.module
--- modules/taxonomy.module 12 Nov 2005 11:26:16 -0000 1.236
+++ modules/taxonomy.module 15 Nov 2005 16:43:23 -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);
@@ -327,7 +315,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();
@@ -344,37 +339,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.
*/
@@ -596,7 +591,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.
@@ -657,13 +652,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') {
@@ -1048,7 +1036,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);
@@ -1177,20 +1165,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)) {
@@ -1201,7 +1178,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.59
diff -u -F^function -r1.59 upload.module
--- modules/upload.module 13 Nov 2005 02:00:37 -0000 1.59
+++ modules/upload.module 15 Nov 2005 16:43:24 -0000
@@ -301,7 +301,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;
@@ -392,14 +397,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');
@@ -524,3 +521,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.530
diff -u -F^function -r1.530 user.module
--- modules/user.module 14 Nov 2005 21:49:47 -0000 1.530
+++ modules/user.module 15 Nov 2005 16:43:27 -0000
@@ -1260,18 +1260,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.
@@ -1461,21 +1459,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');
}
@@ -1668,8 +1655,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);
@@ -1680,13 +1670,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')) {