This quick tutorial will let you limit the creation of a certain number of nodes for any user with a specific role. For every content type and/or role you want to limit, (Eg.: Contributors limited to 4 posts, Admins are limited to 10 posts), you will need to create a separate rule for each.

Assumptions:

  1. Are a familiar with Drupal 7.x and Rules 7.x
  2. You are familiar with PHP enough to read it.

Basics:

  1. A Content Type that you want to apply a limit to. Eg: "News Post"
  2. A Role that will be limited. Eg: "Contributor"
  3. A User with appropriate permissions to create "News Post", and has the role of "Contributor".

Modules:

  1. Rules (plus all dependancies)
  2. Rules Forms Support ( http://drupal.org/project/rules_forms)

Setup Rules Forms:

  1. Configure Rules Forms (Configuration -> Rules -> Form Events)
  2. Check ON:
    • Enable event activation messages on forms
    • Enable form element inspection tool
  3. Navigate to the node add form for your content type. Eg.: /node/add/news-post
  4. Click the link at the top of the form to enable the form events. Eg.: "Activate events for rules_forms_news_post"
  5. Refresh the node add page after it loads back

Create the Limiting Rule:

  1. Create a new Rule (Configuration -> Rules -> Add new rule)
  2. Name: "Contributor News Post Limit"
  3. React on event: "Rules Forms" -> "News Post node form is being built" -- where "News Post" is the name of the content type that you want limited, as mentioned in the above steps.
  4. Conditions:
    • "User has role(s)" <- and add the role(s) that you want limited. Eg.: "Contributor"
    • "Execute custom PHP code":
      
      // Configure your settings: Node limit/quota & Content Type
      $nodelimit = 10;
      $content_type = 'news_post';
      
      // Check it we are just editing an existing node, and quit if so
      if(arg(0) == 'node' && arg(2) == 'edit'){
      	return FALSE;
      }
      
      // Load the active user account
      global $user;
      
      // Drupal has a security feature called the Database Abstraction Layer. 
      // You have to build DB queries with variables that are defined in an array.
      // Define the query string, where ":drupaluid" etc. are arbitrary placeholders
      $query = 'SELECT * FROM {node} WHERE uid=:drupaluid AND type=:drupaltype';
      
      // Define each placeholder
      $variables = array(':drupaluid' => $user->uid, ':drupaltype' => $content_type);
      
      // Query the Drupal database
      $result = db_query($query, $variables);
      
      // Count the number of rows returned from the Drupal database
      // From: http://api.drupal.org/api/drupal/includes%21database%21database.inc/function/db_query/7
      $nodecount = $result->rowCount();
      
      // Set the flag as to whether this Rule is effective or not
      if ( $nodecount >= $nodelimit) {
      	return TRUE; // You will be over the accepted quota
      } else {
      	return FALSE; // Still got room. Allow the new node.
      }
      
      
  1. Actions:
    • Show a message on the site: Warning: "You have reached your allotted limit of posts. Please delete old posts to make room, and try again".
    • Page Redirect: ** Redirect to wherever you need, if you need **

Done. Feedback/improvements welcome!

Comments

Anonymous’s picture

I'm trying out your method and receive an error. The error occurs when I switch to a user with the role I'm targeting and I add in content. I receive 12 of these error message on lines 313,313, 317,320, then that pattern repeats 2 more times :

Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).

As a side note I had to implement the patch as noted here: http://drupal.org/node/1542280 comment #5 since I was getting that error on line 399. The patch added 3 lines to the rules_forms.module .

I also am using OG, not sure if that matters for D7.20. In this case the user I ran it for had no nodes for the content type and the node_limit was set to 2.

Any ideas? thank you, mark

wOOge’s picture

Hey Mark — looks like an issue with rules_forms — At the time I wrote this, I don't believe I had to patch rules_forms.

--
wOOge | adrianjean.ca

Anonymous’s picture

OK. The patch however did the trick and let me enable the form events. So that was solved. Now with this new error it is specifically happening when I attempt to add new content thus triggering your rule logic.

So are you saying I need to open an issue with rules_forms? If so should I add anything more than I've already specified? I'm new to this and want to make sure they have all the needed info.

thank you, mark

wOOge’s picture

Try disabling the rule and see if the error still happens. If it goes away, then the issue is definitely with Rules_forms.
If it still throws an error, can you copy and paste the error, and the rule PHP code you have used?

--
wOOge | adrianjean.ca

Anonymous’s picture

Since the error didn't go away you asked for the php code and the error. I would've thought that since the error still occurs with the rule disabled then it can't be the code and must be something else. Regardless, here are the errors and then the php code I used afterwards:

ERRORS

Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 317 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 320 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 317 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 320 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 313 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 317 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).
Notice: Undefined index: #type in rules_forms_add_popups() (line 320 of C:\wamp\www\oldpair\sites\all\modules\rules_forms\rules_forms.module).

<strong>PHP CODE USED</strong>

// Configure your settings: Node limit/quota & Content Type
$nodelimit = 3;
$content_type = 'sermon';

// Check it we are just editing an existing node, and quit if so
if(arg(0) == 'node' && arg(2) == 'edit'){
	return FALSE;
}

// Load the active user account
global $user;

// Drupal has a security feature called the Database Abstraction Layer. 
// You have to build DB queries with variables that are defined in an array.
// Define the query string, where ":drupaluid" etc. are arbitrary placeholders
$query = 'SELECT * FROM node WHERE uid=:drupaluid AND type=:drupaltype';

// Define each placeholder
$variables = array(':drupaluid' => $user->uid, ':drupaltype' => $content_type);

// Query the Drupal database
$result = db_query($query, $variables);

// Count the number of rows returned from the Drupal database
// From: http://api.drupal.org/api/drupal/includes%21database%21database.inc/function/db_query/7
$nodecount = $result->rowCount();

// Set the flag as to whether this Rule is effective or not
if ( $nodecount >= $nodelimit) {
	return TRUE; // You will be over the accepted quota
} else {
	return FALSE; // Still got room. Allow the new node.
}
wOOge’s picture

Just a follow up — On a new website I too had to apply the patch in #5 of this issue post:

http://drupal.org/node/1542280

But after doing so, it all works out with these instructions.

--
wOOge | adrianjean.ca

Anonymous’s picture

Well, I turned off the rule and the issue still occurs. So I'm really stumped. I removed the module, patch and all and restarted from scratch and error still occurred. I disabled some modules OG and custom pub options but again to no avail. Searched on google and no one else appears to be having this issue so it seems that it's something I've done.

I then added the rules_forms and applied your technique to a very simple site and it worked fine. So, I'm now trying to look for the needle in the haystack. I guess I'll have to keep disabling modules till I find what's causing the problem. Or do you have other ideas on how to trouble shoot this?

Thank you, I appreciate your help.

Anonymous’s picture

Problem solved. I scrapped my test environment and started new. What I did differently is I applied the patch first. Then I configured per the instructions above. Not sure what specifically caused the errors.

sashi.kiran’s picture

Thanks for sharing this code along with the procedure.
Initially i got an error something like this:

"Recoverable fatal error: Object of class stdClass could not be converted to string in _rules_forms_display_info() (line 399 of /home/nithin/public_html/drupaltest/sites/all/modules/rules_forms/rules_forms.module)."

Then i applied the patch:

http://drupal.org/node/1542280#comment-6249538

and everything went cool....

It worked for me exactly the same as it needed to be..

Thanks again

abutze’s picture

Will this work with multiple content types as well?

dvende’s picture

the message appear, correctly, but after that user still can create a node, even if the limit has been reached.
This without redirection after the message. If I put a redirection, this is triggered immediately and I have no time to see the message. I think that show a message immediately, when the form has been built, is a good idea, so I can realize I can't continue before to fill every mandatory field and so lose my time, but if I can continue after that message... there is no limit at all, in fact.

However, many thanks for the very good example!

Northern_Girl’s picture

Hi.

I would like to know if there is another way of using the Rules module to limit the number of nodes a user can post. I'm asking because 1) the future of most node limit seems to be uncertain; 2) the future of Rules Forms Support seems also uncertain.

Thanks.

Drupal in the snow

kopeboy’s picture

I am checking this right now: Entity Rules (https://www.drupal.org/project/entity_rules)
May be what we are looking for.
It can fire rules components from a content type action like create/edit/delete..

That would be easy. The hard part which I am thinking about would be to set the limit to be time based (like role A can create max 2 nodes of type B in the last X months/days/etc)

delacosta456’s picture

Hi
i would like to know if it is possible to use this method to limit node per vocabulary

wOOge’s picture

@delacosta456 I would imagine so, adding that as one of the rule conditions — but I have not personally tested that.

--
wOOge | adrianjean.ca

carsoncho’s picture

Thank you for the tutorial, this is exactly what I was looking for! One thing I did notice was that the page redirect would cause the message on the site to not show up. I fixed this by using the "Set the redirect target of the form" action instead of the "Page Redirect" action. Doing that seemed to fix my issue of the message not showing up. I don't see any adverse side effects from this, but I'm fairly new to Drupal so maybe someone can help set me straight =]

nyumbani_yangu’s picture

Hi

This looks like what I will need on a site to limit number of Question nodes that a particular Role can post.

My only concern is, what if I remove the role from a user and then reassign again? Will the post limit be reset to the initial limit?

For example - say I have a role "member" that can post 5 questions. He posts 3 questions, and has two left. Lets now suppose admin revokes his role and after a few days reassigns it. Will he get back 5 questions? Will he get 7? Will he remain with 2?

I am actually using commerce license to sell roles on a site for premium content. These roles should have the ability to post a limited numbers of questions (nodes) in their limited time of membership (for example 1 month). After this time they should not be allowed to post questions any more, unless they renew their license and hence get a new set of questions that they can post.

Will your strategy work in this scenario?

Simplicity is the ultimate sophistication, Leonardo da Vinci

wOOge’s picture

Unfortunately no.

In the OP, the code checks how many nodes of a particular type each user has ever posted.

So in your case, if they posted 3 of their 5 limit, then loose, and then regain the role — they will still have their 2 postings left.

--
wOOge | adrianjean.ca

marcel.jtf’s picture

Just tested this on a new Drupal 7.56 site and it works perfect. Except you get the same when trying to edit an existing node.

sibany’s picture

got here by mistake ~ here's a fix for anyone need this :)

just change this ...
// Check it we are just editing an existing node, and quit if so
if(arg(0) == 'node' && arg(1) == 'edit'){
	return FALSE;
}

To

// Check it we are just editing an existing node, and quit if so
if(arg(0) == 'node' && arg(1) && arg(2) == 'edit'){
	return FALSE;
}

Cheers, :)