// Note the order: We delete the entity before calling _unflag() to
        // delete the {flagging} record.
        $this->_delete_flagging($existing_flagging_id);
        $this->_unflag($entity_id, $uid, $sid);
        module_invoke_all('flag', 'unflag', $this, $entity_id, $account, $existing_flagging_id);

I suspect the core pattern is usually to invoke hooks *before* data is deleted, so implementations can act on the imminently deleted data.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

joachim’s picture

Either way, the order of operations needs to be documented.

joachim’s picture

And if we changed this, the fix at #1719942: RulesEvaluationException with node unflagged event will need to be reverted.

joachim’s picture

Title: should hook_flag() $op unflag be invoke after things have been deleted or not? » hook_flag_unflag() should be invoked before the flagging is deleted
Category: task » bug
joachim’s picture

Issue tags: +Needs change record

Just a note to say that all changes to hook_flag() and its successors should go on the same change notification.

joachim’s picture

The tricky thing here is that hook_flag_unflag() implementors currently have access to the updated flag counts.

If we reverse the order, then the count they have access to is the OLD count from before the unflagging action, which is one out.

We thus probably have to rearrange things like this:

1. decrease the count
2. invoke hook and rules
3. delete the entity

Which then runs us into potential problems of data integrity if something in the hook or rule causes a failure -- hence we need to start a DB transation (like http://api.drupal.org/api/drupal/modules!node!node.module/function/node_... does).

joachim’s picture

Splitting the count change and the entity delete means splitting this:

  function _unflag($entity_id, $flagging_id) {
    db_delete('flagging')->condition('flagging_id', $flagging_id)->execute();
    $this->_decrease_count($entity_id);
  }

I think in the long term we should merge _(un)flag() with the flagging CRUD methods, but in the short term to avoid DX WTF, both _(un)flag() methods should lose the nested call to _(inc|dec)rease_count() and instead require callers to call both sequentially (which is just flag() -- these are all private methods anyway). Filed #1736280: unnest call to _(inc|dec)rease_count() in _(un)flag() as a helper issue.

joachim’s picture

Status: Active » Needs review
FileSize
3.44 KB
joachim’s picture

Status: Needs review » Fixed

Issue #1720180 by joachim: Changed hook_flag_unflag() and Rules event to be invoked before the flagging entity is deleted.

I gave this a new change record since the Rules and Trigger changes impacts site builders too: http://drupal.org/node/1736314

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

Status: Closed (fixed) » Needs review

Status: Needs review » Needs work

The last submitted patch, 7: 1720180.flag_.invoke-hook-flag-unflag-before-deletion.patch, failed testing.

joachim’s picture

Issue summary: View changes
Status: Needs work » Closed (fixed)