Question:

How to loop over OG group members from comment

Mason: 5 days ago

I'm trying to set up a Rule to send a privatemsg to all group members when someone posts a comment on the group node itself.

One approach I've tried using existing options provided by the OG module:

**Events**
After saving a new comment

**Conditions**
Entity is a group
  Parameter: Entity: [comment:node]

**Actions** 
Get group members from group audience
  Parameter: Group content: [comment:node]
  Provides variables: List of group members (group_members)
Loop
  Parameter: List: [group_members]
  List item: Current member (member)
    **Loop actions**

This method fails to find any members. I'm guessing this is because the "Get group members from group audience" function expects its parameter to be a node posted on the group rather than the node representing the group itself.

Another method I've tried is to define a new Rules action in a custom module:


/**
 * Implements hook_rules_action_info
 */
function mymodule_rules_action_info()
{
    return array(
        'mymodule_get_og_members' => array(
            'label' => t( 'Get OG members from group node' ),
            'group' => t( 'Custom' ),
            'parameter' => array(
                'nid' => array(
                    'label' => t( 'Group node NID' ),
                    'type' => 'integer',
                ),
            ),
            'provides' => array(
                'group_members' => array(
                    'label' => 'List of group members',
                    'type' => 'list',
                ),
            ),
        ),
    );
}

/**
 *
 */
function mymodule_get_og_members( $nid )
{
    $node = node_load( $nid );
    $uids = og_get_group_members_properties( $node, array(), 'members__' . OG_STATE_ACTIVE, 'node' );
    $members = user_load_multiple( $uids );
    // user_load_multiple indexes by UID which might be confusing the Rules loop. Reindex!
    $members = array_values( $members );
    dpm( $members ); // This works!
    return $members;
}

In Rules UI I've added this custom action followed by a loop. The loop suggests the provided members-list variable to iterate over and everything looks fine, yet when the Rule is run I get errors like this:

Unable to get variable group_members, it is not defined.

Unable to evaluate loop.

I've asked an overlapping question here: https://www.drupal.org/node/905632#comment-10893894

Similar posts that I've read:

How to loop over a list of Organic Group users using Rules (https://drupal.stackexchange.com/questions/152085/how-to-loop-over-a-list-of-organic-group-users-using-rules)

I can't access a provided variable in rule action (https://drupal.stackexchange.com/questions/25690/i-cant-access-a-provided-variable-in-rule-action?rq=1)

https://drupal.stackexchange.com/a/170922/58279

Answer:
Aiden: 5 days ago

I found a work-around by implementing all of the desired functions in the custom action provided by my custom module:


/**
 * Implements hook_rules_action_info
 */
function mymodule_rules_action_info()
{
    return array(
        'mymodule_comment_notify_og_members' => array(
            'label' => t( 'Notify OG members of comment' ),
            'group' => t( 'Custom' ),
            'parameter' => array(
                'comment' => array(
                    'label' => t( 'Comment entity' ),
                    'type'  => 'entity',
                ),
            ),
        ),
    );
}

/**
 * Notify relevant OG group members of a new group comment
 *
 * @param   object (entity metadata wrapper)    $comment
 */
function mymodule_comment_notify_og_members( $comment )
{
    //~ dpm( $comment->getPropertyInfo() );

    // Get the nodes we need from the comment entity metadata wrapper
    $node = $comment->node->value();
    $author = $comment->author->value();

    // Get all active group members
    $uids = og_get_group_members_properties( $node, array(), 'members__' . OG_STATE_ACTIVE, 'node' );
    $members = user_load_multiple( $uids );
    foreach( $members as $member )
    {
        if( $member->uid !== $author->uid )
        {
            // We're not notifying the author of his own comment

            $subject = format_username( $author ) . ' commented on ' . check_plain( $node->title );
            $body = '';
            $body .= '

Hi ' . format_username( $member ) . ',

'; $body .= '

' . l( format_username( $author ), 'user/' . $author->uid ) . ' just commented on the ' . l( $node->title, 'node/' . $node->nid ) . ' group.

'; $body .= '

' . l( 'View the comment', 'node/' . $node->nid, array( 'fragment' => 'comment-' . $comment->cid->value() ) ) ; privatemsg_new_thread( array( $member ), $subject, $body, array( 'author' => $author ) ); } } }