Index: modules/node/node.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v retrieving revision 1.60 diff -u -p -r1.60 node.admin.inc --- modules/node/node.admin.inc 30 Jul 2009 19:24:21 -0000 1.60 +++ modules/node/node.admin.inc 6 Aug 2009 23:40:54 -0000 @@ -75,6 +75,7 @@ function node_filters() { 'options' => array( 'status-1' => t('published'), 'status-0' => t('not published'), + 'draft-1' => t('pending drafts'), 'promote-1' => t('promoted'), 'promote-0' => t('not promoted'), 'sticky-1' => t('sticky'), @@ -128,6 +129,9 @@ function node_build_filter_query(SelectQ case 'language': $query->condition('n.' . $key, $value); break; + case 'draft': + $query->innerJoin('node_revision', 'v', 'n.nid = v.nid AND n.vid > v.vid'); + break; } } } @@ -599,4 +603,4 @@ function node_multiple_delete_confirm_su function node_modules_installed($modules) { // Clear node type cache for node permissions. node_type_clear(); -} \ No newline at end of file +} Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1092 diff -u -p -r1.1092 node.module --- modules/node/node.module 5 Aug 2009 15:58:34 -0000 1.1092 +++ modules/node/node.module 6 Aug 2009 23:40:56 -0000 @@ -1181,6 +1181,15 @@ function node_show($node, $message = FAL drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp))), PASS_THROUGH); } + // If the user has access to revisions, check if there are any pending and + // display a message if so. + if (user_access('view revisions') && user_access('revert revisions') || user_access('administer nodes')) { + $max_vid = db_query('SELECT MAX(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid)); + if ($max_vid > $node->vid) { + drupal_set_message(t('This content has one or more pending drafts, view revisions to review and publish.', array('@revisions' => url('node/' . $node->nid . '/revisions')))); + } + } + // Update the history table, stating that this user viewed this node. node_tag_new($node->nid); Index: modules/node/node.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v retrieving revision 1.73 diff -u -p -r1.73 node.pages.inc --- modules/node/node.pages.inc 4 Aug 2009 06:44:48 -0000 1.73 +++ modules/node/node.pages.inc 6 Aug 2009 23:40:57 -0000 @@ -232,9 +232,8 @@ function node_form(&$form_state, $node) '#weight' => 95, ); $form['options']['status'] = array( - '#type' => 'checkbox', - '#title' => t('Published'), - '#default_value' => $node->status, + '#type' => 'value', + '#value' => $node->status, ); $form['options']['promote'] = array( '#type' => 'checkbox', @@ -258,12 +257,19 @@ function node_form(&$form_state, $node) // Add the buttons. $form['buttons'] = array(); $form['buttons']['#weight'] = 100; - $form['buttons']['submit'] = array( + $form['buttons']['publish'] = array( '#type' => 'submit', '#access' => variable_get('node_preview_' . $node->type, 1) != DRUPAL_REQUIRED || (!form_get_errors() && isset($form_state['node_preview'])), - '#value' => t('Save'), + '#value' => isset($node->nid) && $node->status ? t('Save') : t('Publish'), '#weight' => 5, - '#submit' => array('node_form_submit'), + '#submit' => array('node_form_publish_submit'), + ); + $form['buttons']['draft'] = array( + '#access' => user_access('access revisions') && user_access('publish revisions') || user_access('administer nodes'), + '#type' => 'submit', + '#value' => t('Save as draft'), + '#weight' => 6, + '#submit' => array('node_form_draft_submit'), ); $form['buttons']['preview'] = array( '#access' => variable_get('node_preview_' . $node->type, 1) != DRUPAL_DISABLED, @@ -272,6 +278,13 @@ function node_form(&$form_state, $node) '#weight' => 10, '#submit' => array('node_form_build_preview'), ); + $form['buttons']['unpublish'] = array( + '#access' => !empty($node->status) && user_access('administer nodes'), + '#type' => 'submit', + '#value' => t('Unpublish'), + '#weight' => 11, + '#submit' => array('node_form_unpublish_submit'), + ); if (!empty($node->nid) && node_access('delete', $node)) { $form['buttons']['delete'] = array( '#type' => 'submit', @@ -395,6 +408,48 @@ function theme_node_preview($node) { return $output; } +/** + * Submit handler for saving as draft. + */ +function node_form_draft_submit($form, &$form_state) { + $node = node_form_submit_build_node($form, $form_state); + + // Always create a new revision if this button is used. + $node->revision = TRUE; + node_save($node); + + // Keep the original revision ID if the node is published, and there is + // already an existing revision. + if ($node->status && $node->old_vid) { + db_update('node') + ->fields(array('vid' => $node->old_vid)) + ->condition('nid', $node->nid) + ->execute(); + } + + if ($node->nid) { + unset($form_state['rebuild']); + $form_state['nid'] = $node->nid; + $form_state['redirect'] = 'node/' . $node->nid; + } +} + +/** + * Submit handler for saving as published. + */ +function node_form_publish_submit($form, &$form_state) { + $form_state['values']['status'] = 1; + node_form_submit($form, $form_state); +} + +/** + * Submit handler for saving as unpublished. + */ +function node_form_unpublish_submit($form, &$form_state) { + $form_state['values']['status'] = 0; + node_form_submit($form, $form_state); +} + function node_form_submit($form, &$form_state) { global $user; @@ -507,7 +562,8 @@ function node_revision_overview($node) { $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision))) . (($revision->log != '') ? '

' . filter_xss($revision->log) . '

' : ''); if ($revert_permission) { - $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert"); + $title = $node->vid > $revision->vid ? t('revert') : t('publish'); + $operations[] = l($title, "node/$node->nid/revisions/$revision->vid/revert"); } if ($delete_permission) { $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete"); @@ -530,7 +586,7 @@ function node_revision_overview($node) { */ function node_revision_revert_confirm($form_state, $node_revision) { $form['#node_revision'] = $node_revision; - return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel')); + return confirm_form($form, t('Are you sure you want to publish the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel')); } function node_revision_revert_confirm_submit($form, &$form_state) { Index: modules/trigger/trigger.test =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.test,v retrieving revision 1.15 diff -u -p -r1.15 trigger.test --- modules/trigger/trigger.test 28 Jul 2009 19:18:08 -0000 1.15 +++ modules/trigger/trigger.test 6 Aug 2009 23:41:07 -0000 @@ -39,8 +39,14 @@ class TriggerContentTestCase extends Dru $edit = array(); $edit['title'] = '!SimpleTest test node! ' . $this->randomName(10); $edit['body[0][value]'] = '!SimpleTest test body! ' . $this->randomName(32) . ' ' . $this->randomName(32); - $edit[$info['property']] = !$info['expected']; - $this->drupalPost('node/add/page', $edit, t('Save')); + if ($action == 'node_publish_action' || $action == 'node_unpublish_action') { + $button = $info['button']; + } + else { + $edit[$info['property']] = !$info['expected']; + } + $button = isset($button) ? $button : t('Save'); + $this->drupalPost('node/add/page', $edit, $button); // Make sure the text we want appears. $this->assertRaw(t('!post %title has been created.', array('!post' => 'Page', '%title' => $edit['title'])), t('Make sure the page has actually been created')); // Action should have been fired. @@ -79,11 +85,13 @@ class TriggerContentTestCase extends Dru 'property' => 'status', 'expected' => 1, 'name' => t('publish post'), + 'button' => t('Publish'), ), 'node_unpublish_action' => array( 'property' => 'status', 'expected' => 0, 'name' => t('unpublish post'), + 'button' => t('Unpublish'), ), 'node_make_sticky_action' => array( 'property' => 'sticky',