Add a publish button on node edit forms in Drupal 6 using a custom module

This tutorial assumes you have a reasonable knowledge of Drupal such as being able to create a custom module. It also requires an understanding of PHP and jQuery.

Create a new module, I will call mine node_publish.

The first thing I will do is create a callback function that will be used to publish the node. To do this, I will first create a menu item using hook_menu().

<?php
function node_publish_menu() {
  
$items['node/%/publish'] = array(
    
'title' => 'Node published',
    
'page callback' => 'node_publish_publish',
    
'page arguments' => array(1),
    
'access arguments' => array('administer nodes'),
    
'type' => MENU_CALLBACK,
  );
  return 
$items;
}
?>

This uses the menu path of node/<nid>/publish, much the same way that node/<nid>/delete and node/<nid>/edit work. This will call the function node_publish_publish.

<?php
function node_publish_publish($nid) {
  if (
is_numeric($nid)) {
    
db_query("UPDATE {node} SET status = 1 WHERE nid = %d"$nid);
  }
  if (isset(
$_REQUEST['destination'])) {
    
drupal_goto($_REQUEST['destination']);
  }
  else {
    
drupal_goto('node/'$nid);
  }
}
?>

This function takes the nid out of the path and checks to make sure it is numeric, if it is we set the status to published for that node.

Once the node is published, we will redirect the user to another page. In this case I have looked to see if a destination is already set, if so go to it, otherwise return to the node view.

Now you can create a link to node/<nid>/publish in any of your other modules or views which will publish the node. But this tutorial is going to expand to adding a button on to the node edit form to allow you to publish, rather than having to check the Published box then press Submit.

<?php
function node_publish_form_alter(&$form$form_state$form_id) {
  global 
$user;
  global 
$base_url;
  if (
strstr($form_id'_node_form') && $form['nid']['#value'] != '' && $form['options']['status']['#default_value'] == 0) {
    if (
user_access('administer nodes')) {
      
$form['buttons']['publish'] = array(
        
'#type' => 'button',
        
'#value' => 'Publish',
        
'#submit' => FALSE,
        
'#attributes' => array(
          
'onclick' => 'return false;',
          
'style' => 'display:none;',
        ),
      );
      
drupal_add_js('$(document).ready(function() {
        $("#edit-publish").show();
        $("#edit-publish").click(function() {
          window.location = "'
$base_url .'/node/'arg(1) .'/publish";
          return false;
        });
      });'
'inline''footer');
    }
  }
}
?>

The above should be self explanatory to most people, but for those that it isn't:

First we get the data for the $user object and the $base_url of the site. Then we check to make sure the form_id ends with _node_form as this will cover all nodes. We then make sure that the $form array doesn't have an empty nid value, if it does then the form is for a new node and shouldn't feature the publish button. We then check to make sure that the node isn't already published, if it is there is no point in showing the publish button.

We then perform a check to make sure the user has access to publish nodes. If they have then we add in a simple button with an onclick attribute of return false, which will stop it acting like a submit button for users with javascript. For users without javascript the style attribute will remove the button from view allowing the user to use the checkbox and press submit.

The jQuery that we have firsts shows the button, as it is hidden by default, then set up a click function for the button. We direct the user to the publish page which will then take them to the node view. Alternatively you can modify the jQuery to do a POST action and publish the node in the background and also check the published box allowing further modification of the node.

Comments

Thanks a lot for the code. I thought about the same thing. It will save me some time for the coding!

ty )

update your db_query call as below
db_query("UPDATE {node} SET status = 1 WHERE nid = :nid", array(':nid'=> $nid) );

In D7 you should be using db_update() rather than db_query().

db_update('node')->fields(array('status' => 1))->condition('nid', $nid)->execute();

In my case, it was easier & safer to do a node_load, and node_save operation for cases where there might be data in the node_revision table.
I revised my IF statement as such:
if (is_numeric($nid)) {
$node = node_load($nid);
$node->status = 1;
node_save($node);
}

Yes and the menu item should probably be node/%node/publish rather than node/%/publish

You learn a lot over 3 years.