7

Scenario:

A user can create a node (content type "story"). All story nodes that are created are unpublished by default.

I have a boolean field called "publish my story". Once this has been checked and saved the node is published using rules.

Question:

Is it possible to revoke a users ability to edit published nodes by using rules as I do not want them to change the story afterwards.

7

Yes, you can define dynamic rules in a custom module. See hook_node_access

Here's a sample implementation:

/**
 * Implements hook_node_access().
 */
function MYMODULE_node_access($node, $op, $account) {
  if (
    // The $node argument can be either a $node object or a machine name of
    // node's content type. It is called multiple times during a page load
    // so it is enough if you perform the check once you get the object.
    is_object($node) && $node->type == 'story' &&
    // Operation on which you want to act: "create", "delete", "update", "view".
    $op == 'update'
  ) {
    // Check if the node is published.
    if ($node->field_published[LANGUAGE_NONE][0]['value'] == 1) {
      return NODE_ACCESS_DENY;
    }
  }
}
  • I was hoping to do it using rules, but this works great thanks! – Q10 Oct 22 '12 at 15:46
  • 2
    > if ($node->field_published[LANGUAGE_NONE][0]['value'] == 1) { could be better using field_get_item like > field_get_items('node', $node, 'field_published') to prevent language bugs – Clemens Tolboom Jun 17 '15 at 9:43
1

Here are a complete module to perform the task, plus assigning a role to do that behavior with it:

saidbakr_tools.info:

name = SaidBakr Tools
description = Tools offered by Said Bakr said.fox@gmail.com
core = 7.x 

configure = admin/config/administration/saidbakr_tools

saidbakr_tools.module:

<?php
/**
 * Implements hook_node_access().
 */
function saidbakr_tools_node_access($node, $op, $account) {
   global $user;
  if (
    // The $node argument can be either a $node object or a machine name of
    // node's content type. It is called multiple times during a page load
    // so it is enough if you perform the check once you get the object.
    is_object($node) && $node->type == 'article' &&
    // Operation on which you want to act: "create", "delete", "update", "view".
    $op == 'update'
  ) {
    // Check if the node is published.
  //  var_dump($node);
    if ($node->status == 1 && in_array(variable_get('saidbakr_tools_role','author'), $user->roles)) {
      return NODE_ACCESS_DENY;
    }
  }
}

/**
 * Implements hook_menu().
 */
function saidbakr_tools_menu() {
  $items = array();

  $items['admin/config/administration/saidbakr_tools'] = array(
    'title' => 'SaidBakr Tools',
    'description' => 'Settings for SaidBakr Tools!',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('saidbakr_tools_form'),
    'access arguments' => array('access administration pages'),
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

/**
 * Page callback: Current posts settings
 *
 * @see saidbakr_tools_menu()
 */
function saidbakr_tools_form($form, &$form_state) {
  $form['saidbakr_tools_role'] = array(
    '#type' => 'textfield',
    '#title' => t('The role name'),
    '#default_value' => variable_get('saidbakr_tools_role', 'author'),
    '#size' => 20,
    '#maxlength' => 24,
    '#description' => t('Enter the role name that its users should not be able to edit published contents.'),
    '#required' => TRUE,
  );

  return system_settings_form($form);
}

Create the above two files in a folder, name it saidbakr_tools and then upload it to your Drupal installation at sites/all/modules.

In this solution to test node publish status, I used $node->status

  • 1
    This is a nice clean solution that worked well for me, even in tandem with the 'Save Draft' module. – Danny Browne Dec 6 '18 at 14:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.