1

Followup question for the question about "How to access fields from a goal when creating a node with Rules?".

I'm trying to create a rule that finds and uses the fields of the goal that triggered the goal completed event. They can be fetched if you know the goal id (as shown in the answer to the previous question). But creating individual rules for each goal is not viable because there are quite a few of them and I'd like administrators to be able to easily add them without having to write new rules.

So how can I create a rule without specifying a Rules Condition to check the id of the goal that was completed?

1

You could use the Views Rules to get this to work. Read on for more details about how to do so ...

Step 1: Create an appropriate view

Create a view of all goals completed by the current user, sorted (descending) by the date the goal was completed, and a "Rules" display type, in which you use a pager to only show 1 result (i.e. the most recent one ...).

Here is a view (in export format) with (a) a page display (to list all goals completed by the current user) and (b) a Rules display (to only list the most recent completed goal):

$view = new view();
$view->name = 'goals_info_about_completed_goals';
$view->description = 'A list of goals completed by a user.';
$view->tag = 'Goals';
$view->base_table = 'goals';
$view->human_name = 'Goals completed by a user';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Goals completed by a user';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'none';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'none';
$handler->display->display_options['pager']['options']['offset'] = '0';
$handler->display->display_options['style_plugin'] = 'table';
$handler->display->display_options['style_options']['columns'] = array(
  'goal_img' => 'goal_img',
);
$handler->display->display_options['style_options']['default'] = '-1';
$handler->display->display_options['style_options']['info'] = array(
  'goal_img' => array(
    'sortable' => 0,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
    'empty_column' => 0,
  ),
);
/* Relationship: Goal: Goal - completed by users */
$handler->display->display_options['relationships']['goals_completed_goals']['id'] = 'goals_completed_goals';
$handler->display->display_options['relationships']['goals_completed_goals']['table'] = 'goals';
$handler->display->display_options['relationships']['goals_completed_goals']['field'] = 'goals_completed_goals';
$handler->display->display_options['relationships']['goals_completed_goals']['label'] = 'Completed goal';
/* Field: Goal: Goal Image */
$handler->display->display_options['fields']['goal_img']['id'] = 'goal_img';
$handler->display->display_options['fields']['goal_img']['table'] = 'field_data_goal_img';
$handler->display->display_options['fields']['goal_img']['field'] = 'goal_img';
$handler->display->display_options['fields']['goal_img']['label'] = 'Goal image';
$handler->display->display_options['fields']['goal_img']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['goal_img']['click_sort_column'] = 'fid';
$handler->display->display_options['fields']['goal_img']['settings'] = array(
  'image_style' => 'goal_image',
  'image_link' => '',
);
/* Field: Goal: URL */
$handler->display->display_options['fields']['url']['id'] = 'url';
$handler->display->display_options['fields']['url']['table'] = 'views_entity_goal';
$handler->display->display_options['fields']['url']['field'] = 'url';
$handler->display->display_options['fields']['url']['exclude'] = TRUE;
$handler->display->display_options['fields']['url']['link_to_entity'] = 0;
/* Field: Goal: Title */
$handler->display->display_options['fields']['title_1']['id'] = 'title_1';
$handler->display->display_options['fields']['title_1']['table'] = 'goals';
$handler->display->display_options['fields']['title_1']['field'] = 'title';
$handler->display->display_options['fields']['title_1']['alter']['make_link'] = TRUE;
$handler->display->display_options['fields']['title_1']['alter']['path'] = '[url]';
/* Field: Goal: Goal ID */
$handler->display->display_options['fields']['goal_id']['id'] = 'goal_id';
$handler->display->display_options['fields']['goal_id']['table'] = 'goals';
$handler->display->display_options['fields']['goal_id']['field'] = 'goal_id';
/* Field: Goal: User Points */
$handler->display->display_options['fields']['goal_userpoints']['id'] = 'goal_userpoints';
$handler->display->display_options['fields']['goal_userpoints']['table'] = 'field_data_goal_userpoints';
$handler->display->display_options['fields']['goal_userpoints']['field'] = 'goal_userpoints';
$handler->display->display_options['fields']['goal_userpoints']['settings'] = array(
  'thousand_separator' => '',
  'prefix_suffix' => 1,
);
/* Field: Goal: Goal Category */
$handler->display->display_options['fields']['field_goal_category']['id'] = 'field_goal_category';
$handler->display->display_options['fields']['field_goal_category']['table'] = 'field_data_field_goal_category';
$handler->display->display_options['fields']['field_goal_category']['field'] = 'field_goal_category';
/* Field: Goal: Goal Level */
$handler->display->display_options['fields']['field_goal_level']['id'] = 'field_goal_level';
$handler->display->display_options['fields']['field_goal_level']['table'] = 'field_data_field_goal_level';
$handler->display->display_options['fields']['field_goal_level']['field'] = 'field_goal_level';
/* Field: Goal - completed by users: Created */
$handler->display->display_options['fields']['created']['id'] = 'created';
$handler->display->display_options['fields']['created']['table'] = 'goals_completed_goals';
$handler->display->display_options['fields']['created']['field'] = 'created';
$handler->display->display_options['fields']['created']['relationship'] = 'goals_completed_goals';
$handler->display->display_options['fields']['created']['label'] = 'Completion date';
$handler->display->display_options['fields']['created']['date_format'] = 'short';
$handler->display->display_options['fields']['created']['second_date_format'] = 'long';
/* Field: Goal - completed by users: User */
$handler->display->display_options['fields']['uid']['id'] = 'uid';
$handler->display->display_options['fields']['uid']['table'] = 'goals_completed_goals';
$handler->display->display_options['fields']['uid']['field'] = 'uid';
$handler->display->display_options['fields']['uid']['relationship'] = 'goals_completed_goals';
/* Field: Goal - completed by users: Goal */
$handler->display->display_options['fields']['goal_id_1']['id'] = 'goal_id_1';
$handler->display->display_options['fields']['goal_id_1']['table'] = 'goals_completed_goals';
$handler->display->display_options['fields']['goal_id_1']['field'] = 'goal_id';
$handler->display->display_options['fields']['goal_id_1']['relationship'] = 'goals_completed_goals';
/* Field: Goal - completed by users: Goal - completed by users ID */
$handler->display->display_options['fields']['id']['id'] = 'id';
$handler->display->display_options['fields']['id']['table'] = 'goals_completed_goals';
$handler->display->display_options['fields']['id']['field'] = 'id';
$handler->display->display_options['fields']['id']['relationship'] = 'goals_completed_goals';
$handler->display->display_options['fields']['id']['label'] = 'Completed Goal Seqnr';
/* Sort criterion: Goal - completed by users: Created */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'goals_completed_goals';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['relationship'] = 'goals_completed_goals';
$handler->display->display_options['sorts']['created']['order'] = 'DESC';
/* Contextual filter: Goal - completed by users: User */
$handler->display->display_options['arguments']['uid']['id'] = 'uid';
$handler->display->display_options['arguments']['uid']['table'] = 'goals_completed_goals';
$handler->display->display_options['arguments']['uid']['field'] = 'uid';
$handler->display->display_options['arguments']['uid']['relationship'] = 'goals_completed_goals';
$handler->display->display_options['arguments']['uid']['default_action'] = 'default';
$handler->display->display_options['arguments']['uid']['default_argument_type'] = 'current_user';
$handler->display->display_options['arguments']['uid']['summary']['number_of_records'] = '0';
$handler->display->display_options['arguments']['uid']['summary']['format'] = 'default_summary';
$handler->display->display_options['arguments']['uid']['summary_options']['items_per_page'] = '25';

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page_1');
$handler->display->display_options['path'] = 'user/%/completed-goals';

/* Display: RulesList */
$handler = $view->new_display('views_rules', 'RulesList', 'views_rules_1');
$handler->display->display_options['pager']['type'] = 'some';
$handler->display->display_options['pager']['options']['items_per_page'] = '1';
$handler->display->display_options['pager']['options']['offset'] = '0';
$handler->display->display_options['defaults']['fields'] = FALSE;
/* Field: Goal: URL */
$handler->display->display_options['fields']['url']['id'] = 'url';
$handler->display->display_options['fields']['url']['table'] = 'views_entity_goal';
$handler->display->display_options['fields']['url']['field'] = 'url';
$handler->display->display_options['fields']['url']['exclude'] = TRUE;
$handler->display->display_options['fields']['url']['link_to_entity'] = 0;
/* Field: Goal: Title */
$handler->display->display_options['fields']['title_1']['id'] = 'title_1';
$handler->display->display_options['fields']['title_1']['table'] = 'goals';
$handler->display->display_options['fields']['title_1']['field'] = 'title';
$handler->display->display_options['fields']['title_1']['alter']['make_link'] = TRUE;
$handler->display->display_options['fields']['title_1']['alter']['path'] = '[url]';
/* Field: Goal: Goal ID */
$handler->display->display_options['fields']['goal_id']['id'] = 'goal_id';
$handler->display->display_options['fields']['goal_id']['table'] = 'goals';
$handler->display->display_options['fields']['goal_id']['field'] = 'goal_id';
$handler->display->display_options['rules_parameter'] = array(
  'uid' => array(
    'enabled' => 1,
    'type' => 'integer',
    'label' => 'Goal completed by user with id',
    'name' => 'goal_completed_by_uid',
  ),
);
$handler->display->display_options['rules_variables'] = array(
  'url' => array(
    'enabled' => 0,
    'rendered' => 0,
    'type' => '',
    'label' => 'URL',
    'name' => 'url',
  ),
  'title_1' => array(
    'enabled' => 1,
    'rendered' => 0,
    'type' => 'text',
    'label' => 'Title',
    'name' => 'goal_title',
  ),
  'goal_id' => array(
    'enabled' => 1,
    'rendered' => 0,
    'type' => 'integer',
    'label' => 'Goal ID',
    'name' => 'goal_id',
  ),
  'field_goal_category' => array(
    'enabled' => 1,
    'rendered' => 0,
    'type' => 'text',
    'label' => 'Goal Category',
    'name' => 'goal_category',
  ),
  'field_goal_level' => array(
    'enabled' => 1,
    'rendered' => 0,
    'type' => 'text',
    'label' => 'Goal Level',
    'name' => 'goal_level',
  ),
  'goal_userpoints' => array(
    'enabled' => 0,
    'rendered' => 0,
    'type' => '',
    'label' => 'User Points',
    'name' => 'goal_userpoints',
  ),
  'uid' => array(
    'enabled' => 1,
    'rendered' => 0,
    'type' => 'integer',
    'label' => 'Id of User completing goal',
    'name' => 'goal_uid',
  ),
);

Before trying to import the above view in your own site, make sure to define these custom fields for the goals you configured (these fields are select lists with a single value allowed):

  • Goal Category (machine name field_goal_category), eg with values such as "Privilege, Contribution, Participation, Moderation, None".
  • Goal Level (machine name field_goal_level), eg with values such as "Bronze, Silver, Gold, None".

Step 2: Create a rule that contains a Views loop

Create a rule which contains a "Views loop" as a Rules Action, which is similar to a regular Rules loop, but allows looping over rows of view results. Use the Rules Display type of the view created in the previous step. Obviously, because of the number of results we configured in the Rules display of the view, this list consists of only 1 list item (i.e. related to the most recently completed goal).

  • Within that "Views loop", perform a 1st Rules Action to "Fetch an entity by id", and with these additional details:

    • Parameter: Entity type: Goal
    • Identifier: [goal-id]
    • Provides variables: Completed goal (goal_completed)
  • Then add a 2nd Rules Action, within that same "Views loop", something like "Show a message on the site", with a message that looks something like so (note the 2 custom fields included, with machine names field_goal_category and field_goal_level):

    Details about completed goal:

    • Goal ID: [goal-completed:goal-id]
    • Goal Title: [goal-completed:title]
    • Goal Category: [goal-completed:field_goal_category]
    • Goal Level: [goal-completed:field_goal_level]

Here is an export of a rule you can use for this (if you have both custom fields defined, you should be able to import this rule in your own site):

{ "rules_show_details_about_completed_goal" : {
    "LABEL" : "Show details about completed goal",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "TAGS" : [ "goals" ],
    "REQUIRES" : [ "rules", "goals" ],
    "ON" : { "goal_awarded" : [] },
    "DO" : [
      { "VIEW LOOP" : {
          "VIEW" : "goals_info_about_completed_goals",
          "DISPLAY" : "views_rules_1",
          "USING" : { "goal_completed_by_uid" : [ "awarded-user:uid" ] },
          "ROW VARIABLES" : {
            "goal_title" : { "goal_title" : "Title" },
            "goal_id" : { "goal_id" : "Goal ID" }
          },
          "DO" : [
            { "entity_fetch" : {
                "USING" : { "type" : "goal", "id" : [ "goal-id" ] },
                "PROVIDE" : { "entity_fetched" : { "goal_completed" : "Completed goal" } }
              }
            },
            { "drupal_message" : { "message" : "Details about completed goal:\u003Cbr \/\u003E\u003Cbr \/\u003E\r\n- Goal ID: [goal-completed:goal-id]\u003Cbr \/\u003E\r\n- Goal Title: [goal-completed:title]\u003Cbr \/\u003E\r\n- Goal Category: [goal-completed:field_goal_category]\u003Cbr \/\u003E\r\n- Goal Level: [goal-completed:field_goal_level]\u003Cbr \/\u003E" } }
          ]
        }
      }
    ]
  }
}

Here are the "Replacement patterns for Completed goal" that are shown with the Rules Action to Show a message on the site:

[goal-completed:title]                  Title               Goal "title" property.
[goal-completed:created]                Created             The date the goal was created.
[goal-completed:changed]                Changed             The date the goal was changed.
[goal-completed:Goal ID]                Label               The human readable label.
[goal-completed:url]                    URL                 The URL of the entity.
[goal-completed:field-goal-description] Goal Description    Field "field_goal_description".
[goal-completed:goal-userpoints]        User Points         Field "goal_userpoints".
[goal-completed:goal-img]               Goal Image          Field "goal_img". The following properties may be appended to the token: file (The image file.)
[goal-completed:field-goal-category]    Goal Category       Field "field_goal_category".
[goal-completed:field-goal-level]       Goal Level          Field "field_goal_level".
[goal-completed:field_goal_description] Goal Description    Long text field.
[goal-completed:goal_userpoints]        User Points         Integer field.
[goal-completed:goal_img]               Goal Image          Image field.
[goal-completed:field_goal_category]    Goal Category       List (text) field.
[goal-completed:field_goal_level]       Goal Level          List (text) field.

Obviously, these Replacement patterns have been made available via the Rules Action "Fetch entity by Id" that precedes it. And with that, you have anything available to "find and use the fields of the goal that triggered the goal completed event" (as in your question).

Step 3: Demo

Here is an example of a message shown to a user, after the user completes some goal (if the above view and rule is enabled):

Details about completed goal:

  • Goal ID: 11
  • Goal Title: Citizen Patrol
  • Goal Category: Moderation
  • Goal Level: Bronze

Note: For way more details on using Views Rules, refer to ("Option 2" of) my answer to "How to use Rules to send an E-mail after saving a new comment, to users who checked a boolean in their profile?".

PS: this answer applies to D7 ...

  • @zoom-ping merci for the confirmation (may I say "what else did you expect?") ... and the accept, and +1 ...! – Pierre.Vriens Sep 28 '17 at 14:24
  • I expected nothing less, just confirming that I managed to implement it on my site with some edits and without botching it :) – zoom-ping Sep 28 '17 at 14:53
  • @zoom-ping merci for the "confidence" ... So what is it that one cannot implement using the Rules module ? – Pierre.Vriens Sep 28 '17 at 15:10
  • This might be a separate question, but when I'm trying I create a new entity (node) with the same rule, I can't select the fetched goal fields to populate fields of the new created entity. Any tips? – zoom-ping Oct 4 '17 at 16:43
  • @zoom-ping True, it's probably better to create a new question (= followup with link to this one?), in which you add more details also about what you mean by that "I cannot select the fetched goal fields". Unless maybe this tip may help already: be aware that Rules is pretty smart, because it'll typically show you fields to select from that have a valid (matching?) "type". And for fields with a type that does not match, you may have to first perform a Rules Action "convert data type". For a good sample (with user points and integers): look at drupal.stackexchange.com/a/217857/39516 – Pierre.Vriens Oct 4 '17 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.