Notify all the concerned users when a content is updated

Events happening in the community are now at Drupal community events on www.drupal.org.
jibize's picture

Hi everyone!

I just can't find the right rules set up for my situation!

I've got a node type called "client account", with a User reference CCK field and a Node reference CCK field (the latest references a node type called "wine"). What I would like to do is when any fileds from the node type "wine" change, notify all the concerned users by email.

I posted already here http://drupal.org/node/765010 with a similar question with no luck.

Thanks for your help...

Comments

Combine with VBO!

itangalo's picture

I would solve your task with the help of Views Bulk Operations. The steps would basically look like this:

  1. Build a view that (a) takes the NID of the wine node as argument and (b) lists all the users that should be notified. Make sure you base this view on the User table, or you'll have problem using it for sending e-mail later on.
  2. Turn the view into a Bulk Operation view. You'll probably want to use the action "send e-mail to user", but there's a slight chance that you want to send the e-mail with Rules rather than directly from Views.
  3. Build a rule that triggers when a wine node is changed, and have it call the VBO programatically.

In the third step you'll have to send the wine NID as argument, and if you send the e-mail with VBO you'll also have to send the proper parameters to Views. This is probably the most tricky part due to a bug in VBO.

Some help on the way can be found here: http://nodeone.se/drupal-planet/make-rules-dance-with-views-bulk-operations

Good luck!
//Johan Falk, NodeOne, Sweden

Thank you so much!

jibize's picture

Hi Itangalo,

Thanks a lot for your help you're a super star!

It sounds like THE solution! but I'm just wondering about something you said: "Make sure you base this view on the User table, or you'll have problem using it for sending e-mail later on." It looks like if I base my view on the user table, I can't use the node ID as argument... Is there a workaround, or can we do it as well with a view based on the node table?

Once again thank you very much for your help!

More tricky than I thought

itangalo's picture

Hey, thanks! Glad to help.

The problem with VBO -> Rules is that Views only sends the kind of object found in the Views base table. It doesn't matter if you can make Views list users – if you started off with nodes, the nodes are the ones that will be passed to Rules. This means that you either will have to find a way to connect NID to User in Views (and base the View on Users), or connect node to user in Rules (and base the View on nodes).

The architecture of your site (and in particular the wine node) will determine which way you want to go. One of the few ways of going from Users to Nodes is Content Profile (which can load a profile as a relationship in Views, which makes it possible to use node fields for arguments and other stuff).

When I read your question more closely I see that this is not the case for your site. The relationships are Client -> Wine and Client -> User, which makes this rather tricky. I was going to say that it is not impossible, but after spending some time on trying a few solutions out I resent to saying that it cannot be done without some PHP coding. :-(

Here's one way of doing it, with small use of PHP code.

  1. Rules is triggered on wine node save (and the content has changed).
  2. It calls a VBO vbo_clients, and sends along the Wine NID as argument.
  3. vbo_clients lists all the affected clients and calls a rule set, rule_set_list_users, for each client listed.
  4. In the rule set you'll have to use "execute custom PHP" to get all the users from the client node. You'll have use of a foreach ($client->field_relevant_user AS $client_user) loop, followed by a do_something_on_user($client_user['uid']); statement.
  5. The loop could call another rule set that you use to send the e-mail, but you'd probably want to use something like system_send_email_action directly. (But with a separate rule set you get a more nice-looking way of configuring the content of the e-mail.)

Three cases can simplify this process:

  • You introduce a new reference Wine -> Client. This makes it possible to skip step 2 and insted to another iteration in step 4 (Wine -> Client -> User). More code, less Views. (Not my way of doing things, but you'll cut one of the steps out.)
  • The Client -> User reference only refers to a single user. This gets you a no-code solution – step 4–5 becomes "load user account" and "send e-mail" in Rules.
  • You use Content Profiles, and have a reference Profile -> Client. Combined with a reference Wine -> Client, you can skip step 3–5 and instead have a user-based View calling the send email action directly.

The way of achieving the VBO in the last point would be to introduce a number of relationships, like so:

  • In VBO: Add relationship User -> Profile
  • In VBO: Add relationship Profile -> Client
  • In Rules: Load the Client that is associated with the wine
  • Rules/VBO: Call the VBO with the client NID as argument, having it show all relevant users

That was a pretty long comment. I hope it can be of some use!
//Johan Falk, NodeOne, Sweden

Hm.

niklp's picture

This is nice, BUT, there's a problem.

You cannot take a nid, pass it views as an argument in a user view and make it list referenced users on the node. It just doesn't work - there's no available argument handler for it. I was pretty surprised to see this actually... seems like an omission in either views or user_reference module. It means I have no idea how to achieve what's being described here though, that's for sure! :)

On another note, the bug that's mentioned above is now fixed in dev and will almost certainly be fixed in versions of VBO above 1.9.

Content profile

itangalo's picture

It is possible to get arguments of node type if you use content profile as a relationship in a view based on users.

I have to admit that I can't really follow what I wrote before, but I hope this might help somehow. (I can't find any place where I refer to User view that takes a nid argument.)

Happy to see that the bug hopefully has been resolved! I did a quick test on the new dev, but without success. I'll make another go with a more clean installation, and hope to make it work. Regardless, infojunkie is a hero. :-)

Cheers!
//Johan Falk, NodeOne, Sweden

Hello, how can you do

mayerwin's picture

Hello, how can you do that:
"The loop could call another rule set that you use to send the e-mail, but you'd probably want to use something like system_send_email_action directly. (But with a separate rule set you get a more nice-looking way of configuring the content of the e-mail.)"

I cannot find the right API reference to call an action defined in rules with some arguments (user and node variables).

Thanks!

UI for calling rule set

itangalo's picture

If you define a rule set, you'll be able to call it as an action from Rules.
When you create the rule set you'll get a chance to define arguments for the rule set. (This is actually the only time you can change these arguments.) When calling the rule as an action, you can set the arguments as you please from existing variables.

Good luck!
//Johan Falk, NodeOne, Sweden

Thanks Itangalo for your

mayerwin's picture

Thanks Itangalo for your quick answer; basically which PHP function am I supposed to call in the "execute PHP custom code" action? In pseudocode, I am expecting to do something like:

for each $user in $users
   rules_evaluate_rule_set('send email with template rule set', $user, $node)
next

But I can't find the proper syntax.

Don't know the function name...

itangalo's picture

I don't know the function name, but I know that you can choose the name of the rule set instead of executing custom PHP. (All rule sets are listed in the action list, under 'Rule Sets'.) However, that doesn't help you very much when you want to call the rule set from within a PHP loop.

My guess is that the proper way of calling a rule set from PHP is to invoke Rules and send along the name of the rule set (along with arguments), but this is just a guess. Sorry. :-(

Some searching ended up at the following:

I hope it might be of help.
//Johan Falk, NodeOne, Sweden

Just to let you know I found

mayerwin's picture

Just to let you know I found how to do it (with a custom field_authorizedusers containing user ids from user reference cck field):
foreach ($node->field_authorizedusers as $r) {
$u = user_load($r['uid']); $m = $u->mail;
rules_invoke_rule_set('rules_send_notification_to_user', array('user' => &$u, 'node' => &$node));
}
rules_send_notification_to_user is the rule set I created and that performs per user actions.
:-)

Great!

itangalo's picture

Great! Thanks for sharing the solution.

//Johan Falk

An other solution...

jibize's picture

Hello there,

Sorry for my very late reply but I've been away for two weeks... First of, a BIG thank you to Itangalo, you're definitely a super super star! Thanks to you I finally set up the user notification properly. That's how I made it:

1) I set up a rule that trigers a VBO on a wine node chages passing the node ID along

2) I set up a VBO, based on a node table (it also works with a user table) with
a) the User reference as Relationships
b) the node ID as argument
the VBO action is "Execute arbitrary PHP script"

3) I set up the "arbitrary PHP script" action as follow

<?php
$to
$context['row']->users_node_data_field_client_username_mail;
$nid$context['view']['arguments']['0'];

$node = node_load($nid);

$clientName = $object->title;
$wineName = $node->title;
$nid = $node->nid;
$siteName = variable_get('site_name', '');
$defaultEmail = variable_get('site_mail', '');
$body =
'Dear ' . $clientName . ',

We would like to inform you that the wine reference '
. $wineName . ' has been updated. For more information, please visit the following link: (the url)/node/' . $nid . ', or log in to your account at (the url)/content/clients-zone.

Thank you,

Regards,

'
. $siteName;

$message = array(
 
'to' => $to,
 
'subject' => t($siteName . ' Wine List update'),
 
'body' => t($body),
 
'headers' => array('From' =>$defaultEmail),
);

drupal_mail_send($message);
?>

What is interesting to mention is that you can basically retrieve any fields that your view display, as it is stored in the $context variable. You just need to use the var_dump() function to find out its name.

That's it!

PS: Itangalo, I first tried your second advice
"The Client -> User reference only refers to a single user. This gets you a no-code solution – step 4–5 becomes "load user account" and "send e-mail" in Rules."
it worked well, but the only thing is that I couldn't pass the wine node ID (that has been updated) to the rule set as it accepts only one argument (in my case the user ID), so I couldn't precise in my email wich wine has been updated.

Thanks again for your help Itangalo, and thanks to NikLP for mentioning the bug fix in VBO.

Retrieve views fileds?

itangalo's picture

What is interesting to mention is that you can basically retrieve any fields that your view display, as it is stored in the $context variable. You just need to use the var_dump() function to find out its name.

This sounds really interesting, but I can't get it to work.
I've tried calling a rules set from a VBO, and I let the rule set var_dump (or dpm) both $context, $contexts and get_defined_vars() -- but I get null back.

Where do you run the var_dump, and where does the context become available?

//Johan Falk, NodeOne, Sweden

Action not a Rule set

jibize's picture

Hi Itangalo,

From VBO I call an Action not a Rule Set, the type of the Action is "Execute arbitrary PHP script". So if you do a var_dump() in the Action, you should get something...

Hope this helps

Awright

itangalo's picture

Then I see.
I guess I could do some PHP stuff and call a rule set if I wanted, and send in information from the View row to the rule set on the way.

Thanks for the tip!
//Johan Falk, NodeOne, Sweden

Code-free solution

niklp's picture

I have made a code-free solution to this problem, but it requires a patch (that is broken) to userreference.module. See this thread: http://drupal.org/node/375337 - "userreference relationship for views with base 'user'"

If we can fix this patch, so that all userreference fields are reflected in the views UI, then it is simply a matter of adding a relationship from the user table to the relevant node/cck table so that the users in the uref field can be selected. I have tried this and gotten it to succeed.

If you have only one uref field in your site setup, this patch will work - otherwise only the last field added will display in the views UI, currently.

The details outlined by Itangalo above do work - the problem is that currently there is no relationship handler in views or userreference to handle a relationship between the user base table and the userreference cck fields. This patch fixes that.

So basically, you can add the rule set, with an email sending rule, add a VBO view to execute the rule set, where the view is set up to get all users that are in the uref field (given a nid argument), then execute the VBO via triggered rules, and hey presto, you're emailing all the relevant users.

Also check out the "reroute_mail" module, as this allows for total redirection of all your drupal system's outgoing mail to one address, for testing purposes :)

Question

jaynhook's picture

Hi all,

I have a VBO and Rule setup that seems to do what I want. However, using the Send e-mail operation in Rules, I am only allowed to input a specific e-mail address as the Recipient. I cannot use tokens. How do I get the e-mail to send to each recipient listed by the view? Thanks for all of your help and time!

Have you tried this module

itserich's picture

Have you tried this module Views Send? http://drupal.org/project/views_send

Not sure if it is what you want.

I have not needed but if you try it please let us know how it goes.

Also possible when a profile field is updated?

guntherdevisch's picture

Hi,

I was wondering if the above is also possible when a profile field is updated? When the user changes the profile field, i want to send an e-mail :)

Anyone?

Thanks,
Gunther

Don't think so

itangalo's picture

I don't think Rules has integration with core Profile module – but if you're interested in coding there are pretty good examples in the Handbooks that you could try and copy from.

In general I would recommend the Content Profile module in front of core Profile, if you're using Drupal 6. (In Drupal 7, this is a non-issue since user accounts are fieldable.)

Best of luck!
//Johan Falk, NodeOne, Sweden
Want to learn more Rules? Check out my latest screen cast series!

Thanks

guntherdevisch's picture

Hi Itangalo,

Thanks for your reply.

I will definitely have a look to try coding it.

How do you mean that user accounts are fieldable in Drupal 7? No need of profile or content profile fields? I'm using Drupal version 6.20 right now.

Thanks,
Gunther

Found a solution for profile fields

guntherdevisch's picture

Hi Itangalo,

I found a solution to send an e-mail if a profile field changes (for Drupal 6). You also need Rules (i have 6.x-1.4) and then a patch to create a 'User profile details have been updated' event: http://drupal.org/node/363682#comment-4097742

If you go 'Add a new rule' under 'Triggerd Rules' you can see the new rule 'User profile details have been updated' under 'User'. Now you can add Conditions like 'User belongs to role..' or something else, as Action you can then choose 'Send a mail to a user'...

I've also added a condition (Custom PHP Code) to check only one profile field update. Check my code below:

$werksituatieOud = '';
$werksituatieNieuw = '';
$werksituatieOud = $account_unchanged->profile_werksituatie;
$werksituatieNieuw = $user->profile_werksituatie;

if (($werksituatieOud == 'Ik zoek een job!') && ($werksituatieOud != 'Ik ben niet (meer) op zoek'))
{
if (($werksituatieNieuw == 'Ik ben niet (meer) op zoek') && ($werksituatieNieuw != 'Ik zoek een job!'))  { return TRUE; }
}
else { return FALSE; }

Greets,
Gunther

Rules

Group organizers

Group categories

Categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: