/[drupal]/contributions/modules/trash/trash.module
ViewVC logotype

Contents of /contributions/modules/trash/trash.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Thu Feb 21 17:42:15 2008 UTC (21 months, 1 week ago) by roetzi
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.1: +141 -148 lines
File MIME type: text/x-php
Drupal 6 port
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * Provides a trash for nodes.
7 * Nodes in the trash can be restored or deleted.
8 *
9 * This works by adding a new value for the {node}.status flag. This is dangerous as
10 * all other Drupal codes assumes that the status flag can only have the values 0 or 1.
11 * The reason it works (or should work most of the time) is that other code normally
12 * checks for the status to be 1 to show a node or else assumes it is unpublished.
13 *
14 * To disallow access to trashed nodes, all grants are removed for nodes in the trash.
15 * Users with the 'administer nodes' permission can still see trashed nodes.
16 *
17 * This module calls hook_nodeapi with two new operations:
18 * - 'move to trash': The node is being moved to the trash
19 * - 'restore from trash': The node is being restored from the trash
20 */
21
22 /**
23 * Status value used for database field {node}.status
24 */
25 define('STATUS_TRASH', -1);
26
27 /**
28 * Number of items on one page of the trash list.
29 */
30 define('TRASH_LIST_SIZE', 50);
31
32 /**
33 * Implementation of hook_help().
34 */
35 function trash_help($path, $arg) {
36 switch ($path) {
37 case 'admin/help#trash':
38 $output = '<p>' . t('The trash module gives you a node trash. Deleted nodes will be moved into the trash and can be restored or permanently deleted afterwards') . '</p>';
39 return $output;
40 break;
41 }
42 }
43
44 /**
45 * Implementation of hook_perm().
46 */
47 function trash_perm() {
48 return array('view trash', 'restore trash', 'purge trash');
49 }
50
51 /**
52 * Implementation of hook_menu().
53 */
54 function trash_menu() {
55 $items = array();
56 $items['trash'] = array(
57 'title' => t('Trash'),
58 'description' => t('Node trash.'),
59 'page callback' => 'trash_view',
60 'access arguments' => array('view trash'),
61 'type' => MENU_NORMAL_ITEM
62 );
63 $items['trash/empty'] = array(
64 'page callback' => 'drupal_get_form',
65 'page arguments' => array('trash_empty_trash_confirm'),
66 'access arguments' => array('purge trash'),
67 'type' => MENU_CALLBACK
68 );
69 // View node from trash
70 $items['trash/%node'] = array(
71 'title' => t('View'),
72 'page callback' => 'trash_view_node',
73 'page arguments' => array(1),
74 'access arguments' => array('view trash'),
75 'type' => MENU_CALLBACK,
76 );
77 $items['trash/%node/view'] = array(
78 'title' => t('View'),
79 'type' => MENU_DEFAULT_LOCAL_TASK,
80 'weight' => -10,
81 );
82 // Restore node from trash
83 $items['trash/%node/restore'] = array(
84 'title' => t('Restore'),
85 'page callback' => 'drupal_get_form',
86 'page arguments' => array('trash_restore_node_confirm', 1),
87 'access arguments' => array('restore trash'),
88 'type' => MENU_LOCAL_TASK,
89 'weight' => 0,
90 );
91 // Delete node from trash
92 $items['trash/%node/delete'] = array(
93 'title' => t('Delete'),
94 'page callback' => 'drupal_get_form',
95 'page arguments' => array('trash_delete_node_confirm', 1),
96 'access arguments' => array('purge trash'),
97 'type' => MENU_LOCAL_TASK,
98 'weight' => 10,
99 );
100 // Move to trash tab
101 $items['node/%node/trash'] = array(
102 'title' => t('Move to trash'),
103 'page callback' => 'drupal_get_form',
104 'page arguments' => array('node_delete_confirm', 1),
105 'access callback' => '_trash_move_tab_access',
106 'access arguments' => array(1),
107 'weight' => 1,
108 'type' => MENU_LOCAL_TASK,
109 'file' => 'node.pages.inc',
110 'file path' => drupal_get_path('module', 'node')
111 );
112 return $items;
113 }
114
115 /**
116 * Implementation of hook_menu_alter().
117 */
118 function trash_menu_alter(&$callbacks) {
119 $callbacks['node/%node']['page callback'] = '_trash_node_page_view';
120 $callbacks['node/%node/edit']['page callback'] = '_trash_node_page_edit';
121 $callbacks['node/%node/delete']['page callback'] = '_trash_node_page_delete';
122 }
123
124 /**
125 * Access callback for 'Move to trash' tab.
126 */
127 function _trash_move_tab_access($node) {
128 return $node->nid && trash_enabled($node->type) && trash_move_to_trash_tab_enabled($node->type);
129 }
130
131 /**
132 * Overridden page callback for 'node/%node' path.
133 */
134 function _trash_node_page_view($node, $cid = NULL) {
135 if ($node->status == STATUS_TRASH) {
136 return trash_deleted_message($node);
137 }
138 else {
139 return node_page_view($node, $cid);
140 }
141 }
142
143 /**
144 * Overridden page callback for 'node/%node/edit' path.
145 */
146 function _trash_node_page_edit($node) {
147 if ($node->status == STATUS_TRASH) {
148 return trash_deleted_message($node);
149 }
150 else {
151 return node_page_edit($node);
152 }
153 }
154
155 /**
156 * Overridden page callback for 'node/%node/delete' path.
157 */
158 function _trash_node_page_delete($node) {
159 if ($node->status == STATUS_TRASH) {
160 return trash_deleted_message($node);
161 }
162 else {
163 return drupal_get_form('node_delete_confirm', $node);
164 }
165 }
166
167 /**
168 * Implementation of hook_form_alter().
169 */
170 function trash_form_alter(&$form, $form_state, $form_id) {
171 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
172 // Node editing form. Check if it is an affected type.
173 if (trash_enabled($form['type']['#value'])) {
174 if ($form['nid']['#value']) {
175 // Node is edited.
176 // Remove delete button as there is a 'Move to trash' tab now.
177 if (trash_delete_button_removing_enabled($form['type']['#value'])) {
178 unset($form['buttons']['delete']);
179 }
180 else {
181 $form['buttons']['delete']['#value'] = t('Move to trash');
182 }
183 }
184 }
185 }
186 if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
187 // Node type edit form: Add checkbox to activate trash
188 $form['workflow']['trash_settings'] = array(
189 '#type' => 'checkboxes',
190 '#title' => t("Trash"),
191 '#description' => t("If the trash is enabled for this node type, nodes will be moved to trash instead of being deleted. To permanently delete them you need to delete them from the !trash. If you remove the 'Move to trash' button you should activate the 'Move to trash' tab or you won't be able to delete nodes anymore.", array('!trash' => l(t('Trash'), 'trash'))),
192 '#options' => array(
193 'enabled' => t("Enable trash"),
194 'move_to_trash_tab' => t("Add a 'Move to trash' tab to nodes"),
195 'remove_delete_button' => t("Remove 'Move to trash' button from node edit page"),
196 ),
197 '#weight' => 5,
198 '#default_value' => variable_get('trash_settings_'. $form['#node_type']->type, array()),
199 );
200 }
201 if ($form_id == 'node_delete_confirm') {
202 $node = node_load($form['nid']['#value']);
203 if (trash_enabled($node->type)) {
204 drupal_set_title(t('Are you sure you want to move %title to the trash?', array('%title' => $node->title)));
205 $form['log'] = array(
206 '#type' => 'textfield',
207 '#title' => t('Log message'),
208 '#default_value' => t('Moved to trash'),
209 '#weight' => -1,
210 );
211 $form['description']['#value'] = t('The node will be moved to the !trash where it can be restored or permanently deleted.', array('!trash' => l(t('trash'), 'trash')));
212 $form['actions']['submit']['#value'] = t('Move to trash');
213 unset($form['#submit']);
214 $form['#submit'] = array('trash_node_delete_confirm_submit');
215 }
216 }
217 }
218
219 /**
220 * Is the trash activated for the node type?
221 *
222 * @param $node_type
223 * Node type string
224 */
225 function trash_enabled($node_type) {
226 return in_array('enabled', variable_get("trash_settings_$node_type", array()));
227 }
228
229 /**
230 * Is the 'Move to trash' tab enabled for the node type?
231 *
232 * @param $node_type
233 * Node type string
234 */
235 function trash_move_to_trash_tab_enabled($node_type) {
236 return in_array('move_to_trash_tab', variable_get("trash_settings_$node_type", array()));
237 }
238
239 /**
240 * Is the 'Delete' button removed for the node type?
241 *
242 * @param $node_type
243 * Node type string
244 */
245 function trash_delete_button_removing_enabled($node_type) {
246 return in_array('remove_delete_button', variable_get("trash_settings_$node_type", array()));
247 }
248
249 /**
250 * Menu callback to view the page of a node in the trash.
251 */
252 function trash_deleted_message($node) {
253 $output = '';
254 drupal_set_title(t('Trash:') . ' ' . $node->title);
255 if (user_access('view trash')) {
256 $output .= '<p>' . t('This page has been moved to the !trash.', array('!trash' => l(t('trash'), 'trash'))) . '</p>';
257 $output .= '<p>' . t('You can') . '</p><ul>';
258 $output .= '<li>' . t('!view the lastest version', array('!view' => l(t('View'), 'trash/'.$node->nid.'/view'))) . '</li>';
259 if (user_access('restore trash')) {
260 $output .= '<li>' . t('!restore the lastest version', array('!restore' => l(t('Restore'), 'trash/'.$node->nid.'/restore'))) . '</li>';
261 }
262 if (user_access('purge trash')) {
263 $output .= '<li>' . t('Permanently !delete the page', array('!delete' => l(t('delete'), 'trash/'.$node->nid.'/delete'))) . '</li>';
264 }
265 }
266 else {
267 $output .= '<p>' . t('This page has been moved to the trash.') . '</p>';
268 }
269 return $output;
270 }
271
272 /**
273 * Menu callback for 'trash' page.
274 */
275 function trash_view() {
276 $output = '';
277 $header = array(
278 array('data' => NULL, 'colspan' => 2),
279 array('data' => t('Type'), 'field' => 'n.type'),
280 array('data' => t('Title'), 'field' => 'n.title'),
281 array('data' => t('Deleted on'), 'field' => 'n.changed', 'sort' => 'desc'),
282 array('data' => t('Log')),
283 );
284 $count_sql = db_rewrite_sql("SELECT count(n.nid) FROM {node} n WHERE status = " . STATUS_TRASH);
285 $node_sql = db_rewrite_sql("SELECT n.nid,n.type,n.title,n.changed,u.uid,u.name,r.log FROM {node} n JOIN {users} u ON n.uid = u.uid JOIN {node_revisions} r ON n.vid = r.vid WHERE n.status = " . STATUS_TRASH . tablesort_sql($header));
286 $result = pager_query($node_sql, TRASH_LIST_SIZE, 0, $count_sql);
287 $nodes = array();
288 while($node = db_fetch_object($result)) {
289 $nodes[] = $node;
290 }
291 if (count($nodes)) {
292 $node_types = node_get_types('names');
293 $rows = array();
294 foreach($nodes as $node) {
295 $row = array(
296 user_access('restore trash') ? l(t('(restore)'), "trash/$node->nid/restore") : '',
297 user_access('purge trash') ? l(t('(delete)'), "trash/$node->nid/delete") : '',
298 $node_types[$node->type],
299 l($node->title, "trash/$node->nid/view"),
300 t('!date by !username', array(
301 '!date' => format_date($node->changed, 'small'),
302 '!username' => theme('username', $node))),
303 $node->log,
304 );
305 $rows[] = $row;
306 }
307 $output .= theme('table', $header, $rows);
308 $output .= theme('pager', NULL, TRASH_LIST_SIZE, 0);
309 if (user_access('purge trash')) {
310 $output .= '<p>' . l(t('Empty trash'), "trash/empty") . '</p>';
311 }
312 }
313 else {
314 $output .= '<p>' . t('The trash is empty') . '</p>';
315 }
316 return $output;
317 }
318
319 /**
320 * Menu callback for 'trash/%nid/view' page.
321 */
322 function trash_view_node($node) {
323 $output = '';
324 if (node_access('view', $node) && $node->status == STATUS_TRASH) {
325 drupal_set_title(t('Trash:') . ' ' . check_plain($node->title));
326 $output = node_view($node, FALSE, TRUE, TRUE);
327 }
328 else {
329 $output = drupal_access_denied();
330 }
331 return $output;
332 }
333
334 /**
335 * Restore node confirmation form.
336 */
337 function trash_restore_node_confirm(&$form_state, $node) {
338 $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
339 $form['log'] = array(
340 '#type' => 'textfield',
341 '#title' => t('Log message'),
342 '#default_value' => t('Restored from trash'),
343 '#weight' => -1,
344 );
345 return confirm_form($form,
346 t('Are you sure you want to restore %title?', array('%title' => $node->title)),
347 isset($_GET['destination']) ? $_GET['destination'] : 'trash/'. $node->nid,
348 t(''),
349 t('Restore'), t('Cancel'));
350 }
351
352 /**
353 * Restore node confirmation form submit handler.
354 */
355 function trash_restore_node_confirm_submit($form, &$form_state) {
356 if ($form_state['values']['confirm']) {
357 $node = node_load($form_state['values']['nid']);
358 // Save node as a published again.
359 $node->status = 1;
360 $node->revision = TRUE;
361 $node->log = $form_state['values']['log'];
362
363 // Call nodeapi hook
364 node_invoke_nodeapi($node, 'restore from trash');
365
366 // Save node
367 node_save($node);
368
369 // Go to restored node
370 $form_state['redirect'] = 'node/' . $node->nid;
371 }
372 else {
373 // Go to trash list
374 $form_state['redirect'] = 'trash';
375 }
376 }
377
378 /**
379 * Permanently delete node confirmation form.
380 */
381 function trash_delete_node_confirm(&$form_state, $node) {
382 $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
383
384 return confirm_form($form,
385 t('Are you sure you want to permanently delete %title?', array('%title' => $node->title)),
386 isset($_GET['destination']) ? $_GET['destination'] : 'trash/'. $node->nid,
387 t('This action cannot be undone.'),
388 t('Delete'), t('Cancel'));
389 }
390
391 /**
392 * Permanently delete node confirmation form submit handler.
393 */
394 function trash_delete_node_confirm_submit($form, &$form_state) {
395 if ($form_state['values']['confirm']) {
396 // Delete the node.
397 node_delete($form_state['values']['nid']);
398 }
399 // Go to trash list
400 $form_state['redirect'] = 'trash';
401 }
402
403 /**
404 * Submit handler for the 'node_delete_confirm' form of the node module.
405 * This is called instead of the original submit handler if the trash is enabled.
406 */
407 function trash_node_delete_confirm_submit($form, &$form_state) {
408 if ($form_state['values']['confirm']) {
409 $node = node_load($form_state['values']['nid']);
410 if (trash_enabled($node->type)) {
411 // Save node as a new revision with status set to TRASH.
412 $node->status = STATUS_TRASH;
413 $node->revision = TRUE;
414 $node->log = $form_state['values']['log'];
415 // Call nodeapi hook
416 node_invoke_nodeapi($node, 'move to trash');
417 // Save node
418 node_save($node);
419 // Go to trash list
420 $form_state['redirect'] = 'trash';
421 }
422 else {
423 // Call original submit handler
424 node_delete_confirm_submit($form, $form_state);
425 }
426 }
427 }
428
429 /**
430 * Empty trash confirmation form.
431 */
432 function trash_empty_trash_confirm(&$form_state) {
433 return confirm_form($form,
434 t('Are you sure you want to empty the trash?', array('%title' => $node->title)),
435 isset($_GET['destination']) ? $_GET['destination'] : 'trash',
436 t('This action cannot be undone.'),
437 t('Empty trash'), t('Cancel'));
438 }
439
440 /**
441 * Empty trash confirmation form submit handler.
442 */
443 function trash_empty_trash_confirm_submit($form, &$form_state) {
444 if ($form_state['values']['confirm']) {
445 $result = db_query("SELECT n.nid FROM {node} n WHERE n.status = %d", STATUS_TRASH);
446 while ($node = db_fetch_object($result)) {
447 node_delete($node->nid);
448 }
449 }
450 $form_state['redirect'] = 'trash';
451 }

  ViewVC Help
Powered by ViewVC 1.1.2