Hi,

For the moment I have a rule that has the "After updating an existing user account" event. In the conditions it is going to check if a certain field value is changed (using the account and account-unchanged data values), if so it will send an email and show a message.
But I also update users through cron and I only want to trigger this rule when the user edit form has been submitted.
Is that possible? I couldn't figure out how to do this...

Comments

RedEight’s picture

Version: 7.x-2.2 » 7.x-2.9
Issue summary: View changes

I am also trying to figure this out myself. My current thought is that there might be a way to check the url to determine if it was updated via the user edit page... But I'm at a loss as to how this would be done. Does anyone know of a rule condition that checks that?

saurabh.dhariwal’s picture

Please follow the below steps for your purpose:

Step 1 : Alter user edit with custom module.

function YOURCUSTOMMODULENAME_user_update(&$edit, $account, $category) {
                rules_invoke_event('event name', $user);        
        }

Step 2 : Create custom rule event

function YOURCUSTOMMODULENAME_rules_event_info() {
  return array(
    'event name' => array(
      'label' => t('text'),
      'module' => 'YOURCUSTOMMODULENAME',
      'group' => 'groupname for rule where this event will display' ,
      'variables' => array(
        'current_user' => array('type' => 'user', 'label' => t('The current logged in user.'))
    ),
  );
}        

Step 3 : Your rule conditions and actions set for this custom rule event.

Now, user update his profile your custom rule event will be fire and your action will execute with your rule.

Let me know if you face any query/concern regarding this.

Thanks!

RedEight’s picture

saurabh.dhariwal, unfortunately that won't work for either of our use cases. Mainly because that will fire anytime the user_save() method is called on a user object that already exists. We want this to only occur if the user_save() operation was the result of a user edit form submission. I haven't been able to find a way of checking what called the user_save().

RedEight’s picture

I think I was able to figure this out. I implemented a form alter for the user edit form that adds a submit callback to the front of the submit callback list. I use the callback to check if the form was submitted via the "Save" button and set a 'flag' variable if it was (that way we know they are trying to update an existing user). I then implemented a variation of saurabh.dhariwal's "HOOK_user_update" that triggers our custom rules event if that variable was set.

Here's the code

/**
* @file YOUR_MODULE.module
*/
/**
 * Implements hook_FORM_ID_form_alter()
 */
function YOUR_MODULE_form_user_profile_form_alter(&$form, &$form_state, $form_id) {
  // Ensure that our form submit function triggers before the user save operation kicks off
  array_unshift($form['#submit'], 'YOUR_MODULE_user_profile_form_submit');
}
/**
 * Adds the flag on form submit
 */
function YOUR_MODULE_user_profile_form_submit($form, &$form_state) {
  // Make sure the form submit was a user update
  if ($form_state['values']['op'] == t('Save')) {
    // Since it was, we set the flag
    variable_set('YOUR_MODULE_manual_user_update_flag', TRUE);
  }
}

/**
 * Implements hook_user_update()
 */
function YOUR_MODULE_user_update(&$edit, $account, $category) {
  // Retrieve the flag
  $user_form_was_submitted = variable_get('YOUR_MODULE_manual_user_update_flag');
  // If it was set to TRUE
  if ($user_form_was_submitted) {
    // Clear the flag so it doesn't accidently trigger elsewhere
    variable_set('YOUR_MODULE_manual_user_update_flag', FALSE);
    // Fire the rule event and pass it the account object
    rules_invoke_event('YOUR_MODULE_user_update_by_form', $account);
  }
}

And in YOUR_MODULE.rules.inc

/**
 * @file: YOUR_MODULE.rules.inc
 * YOUR_MODULES rules code: events, conditions, and actions.
 */

/**
 * Implements hook_rules_event_info().
 */
function YOUR_MODULE_rules_event_info() {
  $events = array();

  $event = array();
  $event = array(
    'label' => t('After updating an existing user account via user edit form'),
    'module' => 'YOUR_MODULE',
    'group' => t('User'),
    'variables' => array(
      'account' => array('type' => 'user', 'label' => t('updated user')),
      'account_unchanged' => array('type' => 'user', 'label' => t('unchanged user'), 'handler' => 'rules_events_entity_unchanged'),
    ),
    'access callback' => 'rules_user_integration_access',
  );
  $events['YOUR_MODULE_user_update_by_form'] = $event;

  return $events;
}

Once you have that implemented, a new event will appear in the rules ui. Select that event and it works exactly the same as "After updating an existing user account" but it only fires when the user is manually saved via the form_user_profile form. Calls to user_save() from anywhere else will not fire the event.

Thank you saurabh.dhariwal for starting me on the right path toward a working rule event. =]

jelo’s picture

I linked these issues https://www.drupal.org/node/2780389 because my use case is exactly the same. I do a programmatic update on login which triggers my rule (which it should not). However, I cannot prevent it from happening right now, but hope to stop the condition to fail by introducing a new condition to check if an object exists. That would allow you to not trigger your rule if the account-unchanged object does not exist (which is the case when user_save fires without user edit previously)...

TR’s picture

Status: Active » Fixed

#4 provides a solution to the original question.

The post in #5 has its own open issue, so we don't need to keep this one open as well.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.