Skip to main content

Perform actions on flag/unflag in Drupal 8

Flag in Drupal 8

Flag is a great module, but the documentation for Drupal 8 version of this module is not so great. Recently I had to perform some additional actions when a node is flagged, and I couldn't find anything online about this.

In Drupal 7 things were pretty clear. You can use hook flag like this:

hook_flag_flag($flag, $entity_id, $account, $flagging)

but in Drupal 8 this doesn't work. After wasting some time online trying to find anything useful, I did what any good Drupal developer would do in a similar situation. I dug deep into the module's code and tried to figure out how to do what I need to do.

I suspected that instead of hooks, in Drupal 8 version of the Flag module we have to use Event subscribers, and after looking through the code my suspicions were confirmed. This is a much better solution than writing hooks, and I just had to figure out how to write this Event subscriber.

First you need to create MODULE_NAME.services.yml file. It should look something like this:

services:
  MODULE_NAME.flag_subscriber:
    class: Drupal\MODULE_NAME\EventSubscriber\FlagSubscriber
    tags:
      - { name: event_subscriber }

Now, you need to create FlagSubscriber.php file (you don't have to use this name of course) in the src/EventSubscriber folder. This file will contain our logic. Required method you need to implement is getSubscribedEvents(). Here you need to define events and actions that will fire on these events:

public static function getSubscribedEvents() {
  $events = [];
  $events[FlagEvents::ENTITY_FLAGGED][] = ['onFlag'];
  $events[FlagEvents::ENTITY_UNFLAGGED][] = ['onUnflag'];
  return $events;
}

As you can see we have two events ENTITY_FLAGGED and ENTITY_UNFLAGGED. onFlag and onUnflag are methods which will be called on these events.

Everytime your entity is flagged or unflagged, onFlag and onUnflag methods will be executed, and this is just what I need to implement some custom logic.

The complete example:

<?php

/**
* @file
* Contains \Drupal\MODULE_NAME\EventSubscriber\FlagSubscriber.
*/

namespace Drupal\MODULE_NAME\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\flag\Event\FlagEvents;
use Drupal\flag\Event\FlaggingEvent;
use Drupal\flag\Event\UnflaggingEvent;

class FlagSubscriber implements EventSubscriberInterface {

  public function onFlag(FlaggingEvent $event) {
    $flagging = $event->getFlagging();
    $entity_nid = $flagging->getFlaggable()->id();
    // WRITE SOME CUSTOM LOGIC
  }

  public function onUnflag(UnflaggingEvent $event) {
    $flagging = $event->getFlaggings();
    $flagging = reset($flagging);
    $entity_nid = $flagging->getFlaggable()->id();
    // WRITE SOME CUSTOM LOGIC
  }

  public static function getSubscribedEvents() {
    $events = [];
    $events[FlagEvents::ENTITY_FLAGGED][] = ['onFlag'];
    $events[FlagEvents::ENTITY_UNFLAGGED][] = ['onUnflag'];
    return $events;
  }

}

As you can see from the code above, in the onFlag method you can get the entity ID directly. In the onUnflag method you get array of entities, so you need to iterate over this array or in our case just get the first entity from the array.

Although you need to write a few more lines of code in Drupal 8 to perform actions on flag/unflag, I really like this approach.

Share