5

I know there is Node Limit module, but since it is in alpha stage since a rather long time, I am wondering if there is more elegant way to do so which does not need additional modules?

3 Answers 3

6

FWIW I've been using Node Limit on a dev site for a few weeks now, it's had thorough testing and seems to work perfectly. I'm using the 'Node Limit Type' and 'Node Limit User of Role' sub-modules.

If you want to implement it yourself, you can't really look anywhere better than inside the Node Limit module itself. It implements hook_node_prepare() to deny access to the node add form if the user has exceeded the maximum nodes, based on various rules.

A very simple custom implementation might look like this:

function MYMODULE_node_prepare($node) {
  if (empty($node->nid) && $node->type == 'the_content_type') {
    // Grab the number of nodes of this type the user has already created.
    $args = array(':type' => 'the_content_type', ':uid' => $GLOBALS['user']->uid);
    $node_count = db_query('SELECT COUNT(nid) FROM {node} WHERE type = :type AND uid = :uid', $args)->fetchField();

    // Get the max allowed number of nodes
    $limit = function_to_get_limit();

    // If the user is at/has exceeded the limit, set a message and send the user
    // off somewhere else.
    if ($limit >= $node_count) {
      drupal_set_message(t('Node limit exceeded'));

      drupal_goto('somewhere');
    }
  }
}

You could obviously add further checks in there to make sure the user has a certain role, etc. I'd advise having a flick through the code in the Node Limit module to see how the above could be improved upon.

The above is a 'friendly' way to perform the check (i.e. one that doesn't just throw out a 403 page). If you want to be more militant, you could put roughly the same code in a hook_node_access() implementation instead:

function MYMODULE_node_access($node, $op, $account) {
  if ($op == 'create' && $node->type == 'the_content_type') {
    // Grab the number of nodes of this type the user has already created.
    $args = array(':type' => 'the_content_type', ':uid' => $account->uid);
    $node_count = db_query('SELECT COUNT(nid) FROM {node} WHERE type = :type AND uid = :uid', $args)->fetchField();

    // Get the max allowed number of nodes
    $limit = function_to_get_limit();

    // If the user us at/has exceeded the limit, set a message and send the user
    // off somewhere else.
    if ($limit >= $node_count) {
      return NODE_ACCESS_DENY;
    }

    return NODE_ACCESS_ALLOW;
  }

  return NODE_ACCESS_IGNORE;
}
3

I only wanted users to be able to create a single node of a content type on my site. In my use case, every user needed to have a node (basically using nodes as profiles), so I used the Rules module to automatically create the node and a relation (with the Relation module) to the user upon account validation (though the relation might not be necessary in your case).

Then, I gave users permission to edit their own nodes of the content type, but not create them.

1

If you want you can study the code of the Only One module to see a simple way to accomplish this.

The Only One module allows the creation of Only One node per language in the selected content types for this configuration.

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function onlyone_form_node_form_alter(&$form, &$form_state, $form_id) {
  $onlyone_content_types = variable_get('onlyone_node_types');
  // Getting the name of the node type.
  $node_type = $form['type']['#value'];
  // Verifying if the new node should by onlyone.
  if (isset($onlyone_content_types) && in_array($node_type, $onlyone_content_types, TRUE)) {
    $node = $form_state['node'];
    // If we are trying to create a new node.
    if (!isset($node->nid) || isset($node->is_new)) {
      $query = new EntityFieldQuery();
      $query->entityCondition('entity_type', 'node')
        ->entityCondition('bundle', $node_type);
      // The site is multilingual?
      if (drupal_multilingual()) {
        global $language;
        $query->propertyCondition('language', $language->language);
      }
      // Executing the query.
      $result = $query->execute();
      // If we have one node, then redirect to the edit page.
      if (isset($result['node'])) {
        $nid = array_keys($result['node']);
        $nid = $nid[0];
        drupal_goto('node/' . $nid . '/edit');
      }
    }
  }
}

Disclosure: I'm the maintainer of the module Only One.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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