Flags: flagging unflagging rules, how to check if an user has already flagged a node? I'm using Drupal 7 and I created 3 flags for article content type; these flags are global flags: bad, nice and cool. Now, I want create a rule in order to check if an user has already flagged an article.

For example: a user flags article as bad.
Now the user wants to flag the same article as nice.
Theoretically, the user must unflag bad and flag nice.

I want a rule that check if the user has already flagged a node; if yes, the previous flag must unflagged.

In Rules there are Rules Conditions that can execute php code, but flag api, has a $flag-is_flagged function that checks if an user flagged a node only if the flag is non-global flag.

Any idea?
What you're trying to achieve (= allow users to flag nodes by one out of 3 flags), is by design NOT something you can implement by using a global flag. Because global flags cannot be used by individual users. So I suggest you rethink/rework the design of those flags, so that they are NOT defined as global anymore. After you do so, you should be able to implement what you're trying to do, by using the Rules module, and with no need for PHP code. Read on for more details on how to do so.

Have a look at this rule (in Rules export format):

{ "rules_unflag_related_flags" : {
    "LABEL" : "Unflag related flags",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "flag" ],
    "ON" : { "flag_flagged_this_is_nice" : [] },
    "IF" : [
      { "flag_flagged_node" : {
          "flag" : "this_is_bad",
          "node" : [ "flagged-node" ],
          "flagging_user" : [ "flagging_user" ]
        }
      }
    ],
    "DO" : [
      { "flag_unflagnode" : {
          "flag" : "this_is_bad",
          "node" : [ "flagged-node" ],
          "flagging_user" : [ "flagging_user" ],
          "permission_check" : "1"
        }
      }
    ]
  }
}


Some details about the above rule:


Rules Event: A node has been flagged, under "Nice".
Rules Condition: The flagged node is flagged with flag "Bad", by the flagging user.
Rules Action: Unflag the flagged node, for flag "Bad", by the flagging user.


You should be able to import the above rule in your own site, provided you first adapt the machine names of both flags (this_is_nice and this_is_bad) to fit your own machine names.

If nice is not sufficient (and it should be cool also ...)

If you want to implement similar logic for the "cool" flag, you can rework the Rules Condition and Rules Action in the sample rule above towards a Rules Component (say you name it "Disallow BAD flag"), and remove them from the rule shown above. Then clone this Rules Component towards a similar one for the "Cool" flag  (say you name it "Disallow COOL flag"), in which you change all "bad" to "cool". And finally invoke both Rules Components via an extra Rules Action (1 for each) in the sample rule above.

Or you can use the Conditional Rules module to consolidate both rules in a single rule. Here is a variation of the above rule (using flags with machine names this_is_nice, this_is_bad and this_is_cool), to illustrate how such rule would look like:

{ "rules_unflag_related_flags" : {
    "LABEL" : "Unflag related flags",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules_conditional", "flag" ],
    "ON" : { "flag_flagged_this_is_nice" : [] },
    "DO" : [
      { "CONDITIONAL" : [
          {
            "IF" : { "flag_flagged_node" : {
                "flag" : "this_is_bad",
                "node" : [ "flagged-node" ],
                "flagging_user" : [ "flagging_user" ]
              }
            },
            "DO" : [
              { "flag_unflagnode" : {
                  "flag" : "this_is_bad",
                  "node" : [ "flagged-node" ],
                  "flagging_user" : [ "flagging_user" ],
                  "permission_check" : "1"
                }
              }
            ]
          },
          {
            "ELSE IF" : { "flag_flagged_node" : {
                "flag" : "this_is_cool",
                "node" : [ "flagged-node" ],
                "flagging_user" : [ "flagging_user" ]
              }
            },
            "DO" : [
              { "flag_unflagnode" : {
                  "flag" : "this_is_cool",
                  "node" : [ "flagged-node" ],
                  "flagging_user" : [ "flagging_user" ],
                  "permission_check" : "1"
                }
              }
            ]
          }
        ]
      }
    ]
  }
}


Easy, no?