I assume you use Drupal 8:
Flag action handled by \Drupal\flag\Controller\ActionLinkController::flag
so i think you should override this to check on your user and prevent to flag bookmarks nodes:
- Override ActionLinkController controller using RouteSubscriber like the following:
Add the following to YOUR_MODULE_NAME.services.yml
services:
YOUR_MODULE_NAME.route_subscriber:
class: Drupal\YOUR_MODULE_NAME\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
Create YOUR_MODULE_NAME/src/Routing/RouteSubscriber.php
<?php
namespace Drupal\YOUR_MODULE_NAME\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
/**
* Listens to the dynamic route events.
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
// Change the route associated with /flag/flag/{flag}/{entity_id}.
if ($route = $collection->get('flag.action_link_flag')) {
$route->setDefault('_controller', '\Drupal\YOUR_MODULE_NAME\Controller\MyCustomActionLinkController::flag');
}
}
}
- Create your new Controller YOUR_MODULE_NAME/src/Controller/MyCustomActionLinkController.php like the following:
namespace Drupal\YOUR_MODULE_NAME\Controller;
use Drupal\Component\Utility\Html;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\EntityInterface;
use Drupal\flag\Ajax\ActionLinkFlashCommand;
use Drupal\flag\Controller\ActionLinkController;
use Drupal\flag\FlagInterface;
class MyCustomActionLinkController extends ActionLinkController {
/**
* Performs a flagging when called via a route.
*
* @param \Drupal\flag\FlagInterface $flag
* The flag entity.
* @param int $entity_id
* The flaggable entity ID.
*
* @return \Drupal\Core\Ajax\AjaxResponse|null
* The response object, only if successful.
*
* @see \Drupal\flag\Plugin\Reload
*/
public function flag(FlagInterface $flag, $entity_id) {
/* @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->flagService->getFlaggableById($flag, $entity_id);
$uid = \Drupal::currentUser()->id();
// Do your check here i just test with the user admin.
if ($uid == 1) {
// Change the message you want to show
$flag->setFlagMessage("Sorry you don't have right to bookmark this");
return $this->generateResponse($flag, $entity, $flag->getMessage('flag'));
}
else {
try {
$this->flagService->flag($flag, $entity);
} catch (\LogicException $e) {
// Fail silently so we return to the entity, which will show an updated
// link for the existing state of the flag.
}
return $this->generateResponse($flag, $entity, $flag->getMessage('flag'));
}
}
/**
* Generates a response after the flag has been updated.
*
* @param \Drupal\flag\FlagInterface $flag
* The flag entity.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
* @param string $message
* (optional) The message to flash.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* The response object.
*/
private function generateResponse(FlagInterface $flag, EntityInterface $entity, $message) {
// Create a new AJAX response.
$response = new AjaxResponse();
// Get the link type plugin.
$link_type = $flag->getLinkTypePlugin();
// Generate the link render array.
$link = $link_type->getAsFlagLink($flag, $entity);
// Generate a CSS selector to use in a JQuery Replace command.
$selector = '.js-flag-' . Html::cleanCssIdentifier($flag->id()) . '-' . $entity->id();
// Create a new JQuery Replace command to update the link display.
$replace = new ReplaceCommand($selector, $this->renderer->renderPlain($link));
$response->addCommand($replace);
// Push a message pulsing command onto the stack.
$pulse = new ActionLinkFlashCommand($selector, $message);
$response->addCommand($pulse);
return $response;
}
}
Notes:
- You may need to do the same the route
flag.action_link_flag_nojs
.
- I reimplement the method generateResponse because it has a private visibility.