I am trying to set up a website that will allow users to see nodes that are available but restrict access to view the body (and/or CCK fields). This way I can set up views to show a directory of "premium content" but restrict access to it unless they have a certain role.

Is there a way to achieve this?
Thanks

Comments

modul’s picture

I suppose the most flexible way (maybe not the easiest, but who cares about that :-) ) is to set up some logic in your template.

Let's say you have a content type "my_content_type". The corresponding .tpl file would then be: node-my_content_type.tpl.php . You could start by copying node.tpl.php into that file.

The tricky thing is to find all bits and pieces you want or don't want to show in the $node variable. Best thing to do that would be this little bit of temporary code, in node-my_content_type.tpl.php:

echo "<pre>";
var_dump($node);
echo "</pre>";

That informs you about the many, many parts which are present in the $node variable.

Now, suppose you want to show the title to users of the type "nonpremium" and "title + body" to user type "premium".

First, you'd have to find the user type of your visitor. That's easy. Maybe the best way would be to write a simple function for that:

function ispremium() {
global $user;
   if (in_array("premium", $user->roles)) {
      return true;
   } else {
      return false;
   }
}

And for nonpremium users:

function isnonpremium() {
global $user;
   if (in_array("nonpremium", $user->roles)) {
      return true;
   } else {
      return false;
   }
}

Now we're almost done. In your node-my_content_type.tpl.php, more or less at the place where you see print $content;, you could insert a bit of code like this:

if (ispremium()) {
   echo $node->title . "<br>";
   echo $node->body;
}
if (isnonpremium()) {
  echo $node->title . "<br>";
  echo "If you want to see more, you better become a premium user.";
}

Obviously, this code needs optimizing, probably in a "switch case" construction or something. Anyway, I think the logic is very easy, so it shouldn't be a real problem. Hope you get it working. As I said, it may not be the easiest way, but meddling with the .tpl files is a Very flexible way of showing varying contents.

bsherwood’s picture

I am not a programmer, but I have a question after looking over your code. I don't see in the code where it sets which role can do what. If I have roleA and roleB, where would you set RoleA to see premium content and RoleB to see "If you want to see more, you better become a premium user." All I did see was you calling on $user->roles.

Also I am just learning some PHP but what exactly does -> mean? as in $user->roles?

Thanks

modul’s picture

The "->", as in "$node->title", simply retrieves a certain part, in this case the title, from the $node object.

And the last code snippet is the one which shows something depending on the role (which was retrieved by the ispremium() or isnonpremium() functions): if a user "is premium", he'll see title and body, if he "is non premium", he'll see only the title.

And yes, you can do this with Views too. But I think it causes less overhead to do it the way I described.

bsherwood’s picture

I like the idea of using less overhead.

I have one more (potentially stupid) question, if you don't mind answering.

In your last post you mentioned $user->roles deciding which function to use (ispremium() or isnonpremium()). What permissions in drupal ACL would I have to change in order for those functions to pull the correct permissions? Basically how could I group users into "premium" or "nonpremium"?

Thanks for helping a beginner understand.

modul’s picture

"Premium" and "Notpremium" were just examples. I don't know your user roles, so you'll have to adjust the two (or more) functions accordingly. Just make sure that you use the correct (and case sensitive) names in your functions. You don't have to change any permissions in Drupal. I assume they were set correctly, the way you want them to be. My functions (or functions modeled after them) simply check if a user belongs to usertype X, and if so, return a value of "true". When that is the case, he is entitled to see certain content. If you have, for instance, a user type "Some_user_type", you'd have to check for "Some_user_type" in a function.

Alternatively, you could also use the Hidden Content module (http://drupal.org/project/hidden_content), as someone else already pointed out.

bsherwood’s picture

Aha, I get it now. Sometimes I just need to be hit over the head with a 2X4. I really like your example and I try not to add modules to my site if I can use a few lines of code to do the work.

Thanks for all your help.

nevets’s picture

Set up a view to the premium content, make it a page view of type list and only display the title (field = Node: Title) and set the option to "Without Link". (Under the hood you can get fancier with some programming and have the title linked to the content for people with access to premiium content).

bsherwood’s picture

nevets,
Would you happen to know the code? What you just described is exactly what I need.

hairylunch’s picture

There's no code involved. He's saying to use the views module, and then configure your fields in your view. From my understand, you'd configure the view, enabling a page view, and the view would only contain a field of Node: Title.

Once you've got that, there'll be an option column, and in that column, the default is "As link" - just change that to "Without Link"

bsherwood’s picture

He made the comment " (Under the hood you can get fancier with some programming and have the title linked to the content for people with access to premiium content)."

If I create a page view, allow everyone to see it and set "without link" even people who can access the content can't click on it. I would like to add the code that would make it "without link" for one role and "as link" as another.

hairylunch’s picture

Ah, I missed that. Personally, since I'm not that familiar with coding in drupal, I'd take the alternative approach and create two views, one that has a linked title, and one that doesn't. I'd then change the permissions so that the appropriate ones are accessible to the right users.

Nevets solution is probably more elegant as it wouldn't require different menus/permissions/etc.

nevets’s picture

Here is the code to enable the link for a given role, add it to your view under the 'Arguments' section in the 'Argument Handling Code' textbox. This should work for both table and list views. It assumes that 'Node: Title' is the first field, if not you will need to change the value of $field_index. You will also probably want to change $which_role to reflect the role id of the role you want linked titles enabled for.

// Default to title not being liinked
// We assume there title is the first field under fiields
// Change $field_index if title is not first field
$field_index = 0;
$view->field[$field_index]['options'] = 'nolink';
global $user;
// The role we want to enable linked titles for
$which_role = 2;
if ( isset($user->roles[$which_role]) ) {
$view->field[$field_index]['options'] = 'link';
}
Hetta’s picture

liquidcms’s picture

I have pretty much the same requirements - but from a different angle.

I want std access control modules (such as TAC) to do their thing as far as limiting who can see content (node views) BUT - i want anyone (anon) to be able to see ALL links to content.

Basically i have a view block or view page with a listing of links to content. I want all the links to show as links for any role. But for node view denied roles i want the link to go to my custom access denied page (explaining to them that if they signed up they would get access).

I think this is against the Drupal core access control which doesn't show a link to a node you wouldn't be able to get to - WHERE is this controlled??

Peter Lindstrom
LiquidCMS - Content Management Solution Experts

Hetta’s picture

hidden_content will do exactly what you wish.