How to send an email using Rules to everyone in an Organic Group based upon a date field?

drupal.stackexchange https://drupal.stackexchange.com/questions/250998

  •  11-01-2021
  •  | 
  •  

سؤال

I have an OG content type with a date field. When the date in the field comes up, I want to use Rules to send an email to everyone in the group using the other fields (title/body/og name) in the node.

(Edit) My OG is "Teams" and the OG Content node type is "Events" with the date field. So when field_date in Events is within 24 hours Rules will send out an email to all the OG Members of Teams.

I'm having a hard time wrapping my head around triggering the event based upon the date field and then send the node information to all the different users in the different groups.

هل كانت مفيدة؟

المحلول

To do what you're asking for, I would only use the Rules module, and the Rules Scheduler (a submodule of it), as further explained below.

Step 1 - Create a Rules Component

Create a Rules Component which looks like so (in Rules export format):

{ "rules_send_notification_to_og_members" : {
    "LABEL" : "Send notification to OG members",
    "PLUGIN" : "rule",
    "REQUIRES" : [ "rules", "og" ],
    "USES VARIABLES" : { "current_node" : { "label" : "Current node", "type" : "node" } },
    "IF" : [
      { "node_is_of_type" : {
          "node" : [ "current-node" ],
          "type" : { "value" : { "book" : "book" } }
        }
      }
    ],
    "DO" : [
      { "og_get_members" : {
          "USING" : { "group_content" : [ "current-node" ] },
          "PROVIDE" : { "group_members" : { "group_members" : "List of group members" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "group-members" ] },
          "ITEM" : { "group_member" : "Current group member" },
          "DO" : [
            { "mail" : {
                "to" : [ "group-member:mail" ],
                "subject" : "Friendly reminder about some post in group",
                "message" : "Hello [group-member:name],\r\n\r\nThere is a reminder about a post with title [current-node:title] (located at [current-node:url]) which belongs to one of the groups you are subscribed to.\r\n\r\nSome more details about this node:\r\n\r\n- Price: [current-node:field-book-price]\r\n- Release Date: [current-node:field-book-release-date]",
                "language" : [ "" ]
              }
            }
          ]
        }
      }
    ]
  }
}

Some details about the above Rules Component:

  • Component Variables: only a "node" (of type "node"), of type "parameter", labeled "Current node", and machine name current_node.
  • Rules Condition: use whatever extra condition you need/want, but actually you may not need any at all. As a sample, I just used "Content is of type" (with actual type = book).
  • Rules Actions:
    • Get group members from group audience, for current_node, and store the result in a list with machine name group_members.
    • Perform a Rules Loop, for each item in the group_members list, whereas the item is named group_member. And for each iteration of this loop, send an eMail to the group member being processed, with all sorts of data about the node included in the eMail title and/or eMail body (use your own imagination to make it fit your needs).

Step 2 - Create a Rules which schedules the Rules Component

Create a Rule which looks like so (in Rules export format):

{ "rules_remind_og_members_about_node_content" : {
    "LABEL" : "Remind OG members about node content",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "og", "rules", "rules_scheduler" ],
    "ON" : [ "node_insert", "node_update" ],
    "IF" : [
      { "og_entity_is_group_content" : { "entity" : [ "node" ] } },
      { "entity_has_field" : { "entity" : [ "node" ], "field" : "field_book_release_date" } }
    ],
    "DO" : [
      { "schedule_delete" : {
          "component" : "rules_send_notification_to_og_members",
          "task" : "Notify-OG-members-for-node-[node:nid]"
        }
      },
      { "schedule" : {
          "component" : "rules_send_notification_to_og_members",
          "date" : {
            "select" : "node:field-book-release-date",
            "date_offset" : { "value" : -259200 }
          },
          "identifier" : "Notify-OG-members-for-node-[node:nid]",
          "param_current_node" : [ "node" ]
        }
      }
    ]
  }
}

Some details about the above Rule:

  • Rules Events (either of both):
    • After saving new content.
    • After updating existing content.
  • Rules Conditions (all conditions must be true):
    • Entity group content, for entity = node.
    • Entity has field for field field_book_release_date, which is defined as a date field, and which you could consider as something like the release data of a book. Note: for nodes which don't have that field, or for which it is empty, this Rules Condition is false (so no Rules Actions will be performed).
  • Rules Actions:
    • Delete scheduled task, with Notify-OG-members-for-node-[node:nid] as the "Task identifier", whereas the task refers to the Rules Component created in Step 1.
    • Schedule component evaluation, with Notify-OG-members-for-node-[node:nid] as the "Task identifier", whereas the task refers to the Rules Component created in Step 1. And the actual date to schedule the execution of this Rules Component, is the date indicated in the node's field field_book_release_date, but with an offset of -3 days (pick whatever value for this offset the fits your needs), so 3 days before the date indicated in that field, the Rules Component is executed.

To be complete: the first Rules Action (to delete the previously scheduled task with the very same Task identifier), is to ensure that the Rules Component is only executed once. The typical scenario is that first the node gets created (and the Rules Component is scheduled accordingly). But later on the node is updated. In that case, the request to execute the previously scheduled Rules Component is deleted, and a new request is scheduled again. And if the date itself was not updated, it will be scheduled for execution at the very same moment. But if the date was updated also, only the date of the most recent update will be taken into account. For this mechanism to work, it's important to use a unique Task Identifier, to be used in both Rules Actions. That's why I added the token [node:nid] to it (with a prefix like Notify-OG-members-for-node- so that it can be recognized by somebody looking at the currently scheduled Rules Components also).

Bonus tip - Resolving potential access issues

By using the Rules Scheduler, in the end the Rules Component will be executed when cron is running (the very first time after the date/time the Rules Component was asked to be scheduled). But cron jobs always run with user Anonymous.

So the question that remains is: "How will the eMail content look like if you're processing a node for which an anonymous user has no access?". If you run in any such access issues, the easiest workaround I can think of is that you improve the Rules Component by adding additional variables (used as "Parameter"), and so that these variables contain the values of the relevant node's fields that you want to be able to refer to in the eMail to be created. Since the user who triggers the Rule from Step 2 (due to a create or update of a node) should have (read) access, for sure these values will be passed to the Rules Component at the time of scheduling the Rules Component.

PS: I'm assuming this question is about D7.

نصائح أخرى

For this you should use VBO to provide a list of nodes to your rule. Here is an answer of mine that gives some detail for this.

When you get the list of nodes, you should be loop them, fetch the users for each, and send the email.

You should probably also add an email sent boolean field to the content type, set it to TRUE in the rule and then use that to filter out nodes in your view so emails don't get sent twice.

More Detail:

For this, you probably need to use the latest Dev release which fixes an issue with VBO not supplying data to Rules.

Views

View 1: List of groups. You would add an extra filter here to get OG groups based on time.

View 1

View 2: List of users of a group. Note the contextual filter and the second image showing its settings.

View 2

View 3

Rules

Rule: This rule runs on Cron, grabs the Groups from View 1 and sends each group to a rule component.

{ "rules_test_og_2" : {
    "LABEL" : "Test OG",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "views_bulk_operations", "rules" ],
    "ON" : { "cron" : [] },
    "DO" : [
      { "views_bulk_operations_action_load_list" : {
          "USING" : { "view" : "vbo_all_groups|block_1" },
          "PROVIDE" : { "entity_list" : { "entity_list" : "A list of entities" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "entity-list" ] },
          "ITEM" : { "current_group" : "Current Group" },
          "DO" : [ { "component_rules_og_helper" : { "node" : [ "current-group" ] } } ]
        }
      }
    ]
  }
}

Or in picture format.

Rule1

Rule Component: This sends each group to View 2 and returns a list of users. The "body" condition and drupal message is to show how to use the group's fields in an email.

{ "rules_og_helper" : {
    "LABEL" : "OG Helper",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "views_bulk_operations" ],
    "USES VARIABLES" : { "node" : { "label" : "node", "type" : "node" } },
    "IF" : [ { "entity_has_field" : { "entity" : [ "node" ], "field" : "body" } } ],
    "DO" : [
      { "views_bulk_operations_action_load_list" : {
          "USING" : { "view" : "my_og_members_view|block_1", "args" : [ "node:nid" ] },
          "PROVIDE" : { "entity_list" : { "users_list" : "List of Users" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "users-list" ] },
          "ITEM" : { "current_user" : "Current User" },
          "DO" : [
            { "drupal_message" : { "message" : [ "current-user:mail" ] } },
            { "drupal_message" : { "message" : [ "node:body:value" ] } }
          ]
        }
      }
    ]
  }
}

Or in picture format.

Rule2

I tested external cron with creating some nodes with user details and it worked fine. It looks complicated but is pretty easy, even with having to apply the patch.

What I haven't included here is an extra field on your content type that you would use as a filter in View 1 and change in your Rule so that emails only get sent once.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى drupal.stackexchange
scroll top