gotem_content_moderation-1.1.6-alpha1/src/EventSubscriber/ContentModerationSubscriber.php

src/EventSubscriber/ContentModerationSubscriber.php
<?php

namespace Drupal\gotem\EventSubscriber;

use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\TranslationManager;
use Drupal\gotem\Event\ContentModerationEvent;
use Drupal\gotem\Moderation\ModerationInterface;
use Drupal\gotem\Service\ThresholdService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\node\NodeInterface;
use Drupal\node\Entity\Node;

/**
 * Class ContentModerationSubscriber.
 * Handles content moderation events.
 */
class ContentModerationSubscriber implements EventSubscriberInterface {

  /**
   * The moderation service.
   *
   * @var \Drupal\gotem\Moderation\ModerationInterface
   */
  protected $moderationService;

  /**
   * The threshold service.
   *
   * @var \Drupal\gotem\Service\ThresholdService
   */
  protected $thresholdService;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * The messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * The logger channel.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected $logger;

  /**
   * The state service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * The string translation service.
   *
   * @var \Drupal\Core\StringTranslation\TranslationManager
   */
  protected $stringTranslation;

  /**
   * Static flag to track if moderation is in progress.
   *
   * @var bool
   */
  protected static $moderationInProgress = FALSE;

  /**
   * Constructs a new ContentModerationSubscriber.
   *
   * @param \Drupal\gotem\Moderation\ModerationInterface $moderation_service
   *   The moderation service.
   * @param \Drupal\gotem\Service\ThresholdService $threshold_service
   *   The threshold service.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger
   *   The logger service.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state service.
   * @param \Drupal\Core\StringTranslation\TranslationManager $string_translation
   *   The string translation service.
   */
  public function __construct(
    ModerationInterface $moderation_service,
    ThresholdService $threshold_service,
    AccountProxyInterface $current_user,
    MessengerInterface $messenger,
    LoggerChannelFactoryInterface $logger,
    StateInterface $state,
    TranslationManager $string_translation
  ) {
    $this->moderationService = $moderation_service;
    $this->thresholdService = $threshold_service;
    $this->currentUser = $current_user;
    $this->messenger = $messenger;
    $this->logger = $logger->get('gotem');
    $this->state = $state;
    $this->stringTranslation = $string_translation;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      ContentModerationEvent::EVENT_NAME => 'onContentModeration',
    ];
  }

  /**
   * Responds to content moderation event.
   *
   * @param \Drupal\gotem\Event\ContentModerationEvent $event
   *   The content moderation event.
   */
  public function onContentModeration(ContentModerationEvent $event) {
    // Exit if moderation is already in progress to prevent loops.
    if (self::$moderationInProgress) {
      $this->logger->info('Moderation already in progress, skipping for this request.');
      return;
    }

    $entity = $event->getEntity();

    // Check if moderation is enabled.
    if (!$this->state->get('gotem.settings.moderation_enabled', TRUE)) {
      $this->logger->info('Moderation is disabled for node ID @id.', ['@id' => $entity->id()]);
      return;
    }

    // Only moderate if the node is published.
    if ($entity instanceof NodeInterface && $entity->isPublished()) {
      $text_to_check = $this->extractTextFromFields($entity, ['title', 'body']);
      if (empty(trim($text_to_check))) {
        return;
      }

      // Mark moderation as in progress to prevent re-triggering.
      self::$moderationInProgress = TRUE;

      // Perform the moderation.
      $result = $this->moderationService->moderateText($text_to_check);

      if ($result && !empty($result['flagged'])) {
        // Process moderation result.
        $this->processModerationResult($entity, $result);
      }

      // Reset the flag after processing is done.
      self::$moderationInProgress = FALSE;
    }
  }

  /**
   * Processes the moderation result.
   *
   * @param \Drupal\node\NodeInterface $entity
   *   The node entity.
   * @param array $result
   *   The moderation result.
   */
  protected function processModerationResult(NodeInterface $entity, array $result) {
    $categories = ['hate', 'violence', 'sexual', 'self-harm'];

    // Check moderation score for each category.
    foreach ($categories as $category) {
      $moderation_score = $result['category_scores'][$category] ?? 0;

      // Flag content if it exceeds the threshold for any category.
      if ($this->thresholdService->shouldFlagContent($moderation_score, $category)) {
        $this->handleFlaggedContent($entity, $result, $category);
        break;
      }
    }
  }

  /**
   * Handles flagged content.
   *
   * @param \Drupal\node\NodeInterface $entity
   *   The node entity that was flagged.
   * @param array $result
   *   The moderation result.
   * @param string $category
   *   The category that triggered the flag.
   */
  protected function handleFlaggedContent(NodeInterface $entity, array $result, string $category) {
    // Check if the node is already unpublished to prevent looping.
    if (!$entity->isPublished()) {
      $this->logger->info('Node ID @id is already unpublished, skipping moderation.', ['@id' => $entity->id()]);
      return;
    }

    // Create a moderation flag node.
    $moderation_flag = Node::create([
      'type' => 'moderation_flag',
      'title' => 'Flagged content: ' . $entity->id(),
    ]);
    $moderation_flag->save();

    // Store the node ID in the State API for redirection after save.
    $this->state->set('gotem_flagged_node_id', $entity->id());

    // Add warnings to the user.
    $this->messenger->addWarning($this->stringTranslation->translate('This content has been flagged for %category and is under review.', ['%category' => ucfirst($category)]));
  }

  /**
   * Extracts text from the given fields of the entity.
   *
   * @param \Drupal\node\NodeInterface $entity
   *   The node entity.
   * @param array $fields
   *   The fields to extract text from.
   *
   * @return string
   *   The extracted text.
   */
  protected function extractTextFromFields(NodeInterface $entity, array $fields) {
    $text = '';
    foreach ($fields as $field) {
      if ($entity->hasField($field) && !$entity->get($field)->isEmpty()) {
        $text .= $entity->get($field)->value . ' ';
      }
    }
    return trim($text);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc