entity_mesh-1.1.1/entity_mesh.module

entity_mesh.module
<?php

/**
 * @file
 * Primary module hooks for Entity Mesh module.
 */

use Drupal\Core\Entity\ContentEntityDeleteForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\entity_mesh\TrackerInterface;
use Drupal\node\NodeInterface;

/**
 * Implements hook_entity_insert().
 */
function entity_mesh_entity_insert(EntityInterface $entity) {
  entity_mesh_process_entity($entity, 'process');
}

/**
 * Implements hook_entity_update().
 */
function entity_mesh_entity_update(EntityInterface $entity) {
  entity_mesh_process_entity($entity, 'process');
}

/**
 * Implements hook_entity_delete().
 */
function entity_mesh_entity_delete(EntityInterface $entity) {
  entity_mesh_process_entity($entity, 'delete');
}

/**
 * Check if the entity can be process by render_entity.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity to check.
 *
 * @return bool
 *   TRUE if the entity is a render entity, FALSE otherwise.
 */
function entity_mesh_is_render_entity(EntityInterface $entity) {
  return $entity instanceof NodeInterface;
}

/**
 * Process entity.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity to process.
 * @param string $operation
 *   The operation to perform.
 */
function entity_mesh_process_entity(EntityInterface $entity, $operation) {
  // Check it the entity has to be precessed.
  if (!entity_mesh_is_render_entity($entity)) {
    return;
  }

  $service = 'entity_mesh.entity_render';
  $config = \Drupal::config('entity_mesh.settings');
  $processing_mode = $config->get('processing_mode') ?: 'asynchronous';
  $entity_mesh = \Drupal::service($service);

  /** @var Drupal\entity_mesh\TrackerManagerInterface $tracker_manager */
  $tracker_manager = \Drupal::service('entity_mesh.tracker_manager');

  // Create or update the entity in the entity mesh.
  if ($operation === 'process') {
    if ($processing_mode === 'asynchronous') {
      // Tracker the entity.
      $tracker_manager->addTrackedEntity($entity);
      return;
    }

    // Synchronous mode with limit.
    $synchronous_limit = $config->get('synchronous_limit') ?: 25;

    // Count the number of links in the entity.
    $link_count = $entity_mesh->countEntityLinks($entity);

    // If link count is within the limit, process synchronously.
    if ($link_count <= $synchronous_limit) {
      $entity_mesh->processEntity($entity);
    }
    else {
      $tracker_manager->addTrackedEntity($entity);
    }
    return;
  }

  // Remove the entity from the mesh.
  if ($operation === 'delete') {
    if ($processing_mode === 'asynchronous') {
      $tracker_manager->deleteTrackedEntity($entity);
      return;
    }
    $entity_mesh->deleteItem($entity->getEntityTypeId(), $entity->id());
  }

}

/**
 * Implements hook_form_alter().
 *
 * It informs the editor that the node that is deleting is referenced
 * in other places.
 */
function entity_mesh_form_alter(&$form, $form_state, $form_id) {
  if (!\Drupal::currentUser()->hasPermission('access entity_mesh report')) {
    return;
  }

  if (!str_ends_with($form_id, '_delete_form')) {
    return;
  }

  $form_object = $form_state->getFormObject();
  if (!$form_object instanceof ContentEntityDeleteForm) {
    return;
  }

  $node = $form_object->getEntity();
  if (!$node instanceof NodeInterface) {
    return;
  }
  entity_mesh_alter_node_delete_form($form, $node);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function entity_mesh_form_node_delete_multiple_confirm_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (!\Drupal::currentUser()->hasPermission('access entity_mesh report')) {
    return;
  }

  $storage = \Drupal::service('entity_type.manager')->getStorage('node');

  foreach (array_keys($form["entities"]["#items"]) as $key) {
    $keys = explode(':', $key);
    $node_id = array_shift($keys);
    $node = $storage->load($node_id);
    entity_mesh_alter_node_delete_form($form, $node);
  }
}

/**
 * Helper function to alter the node delete form.
 *
 * @param array $form
 *   Form array to be altered.
 * @param \Drupal\node\NodeInterface $node
 *   The node entity being deleted.
 */
function entity_mesh_alter_node_delete_form(&$form, NodeInterface $node) {
  $database = \Drupal::service('database');
  $node_id = $node->id();
  $label = $node->label();

  $language_to_show = 'undefined';
  $languages = [];
  if (\Drupal::hasService('language_manager')) {

    $languages = array_map(function ($language) {
      // Example: Add a suffix to each language name.
      return $language->getName();
    }, \Drupal::languageManager()->getLanguages());

    $default_lang_id = \Drupal::languageManager()->getDefaultLanguage()->getId();
    $node_lang = $node->language()->getId();
    $language_to_show = $node_lang !== $default_lang_id ? $node_lang : 'all';
  }

  // Define the basic query.
  $query = $database->select('entity_mesh')
    ->fields('entity_mesh', [
      'source_title',
      'source_entity_id',
      'source_entity_type',
      'source_entity_langcode',
      'target_entity_type',
      'target_entity_id',
    ])
    ->condition('target_entity_type', 'node')
    ->condition('target_entity_id', $node_id);

  // Get the number of elements.
  $count_query = clone $query;
  $count = $count_query->countQuery()->execute()->fetchField();

  // If there are no references, we do not need to show anything.
  if ($count == 0) {
    return;
  }

  $items = [];
  $execution = $query->execute();
  $execution = $execution->fetchAll();

  // When there are two translation of the same node,
  // only expose the link to the current language.
  foreach ($execution as $record) {
    $index = $record->source_entity_type . '-' . $record->source_entity_id;
    $language = $record->source_entity_langcode ?? 'undefined';

    if (isset($items[$language])) {
      $items[$language] = [];
    }

    $items[$language][$index] = Link::fromTextAndUrl(
      $record->source_title,
      Url::fromRoute('entity.node.canonical', ['node' => $record->source_entity_id])
    );
  }

  $form[$node_id]['title'] = [
    '#type' => 'html_tag',
    '#tag' => 'p',
    '#value' => t('Warning: "@label" is linked from other content listed below. Deleting it may result in broken references that should be updated', ['@label' => $label]),
  ];

  if ($language_to_show !== 'all') {
    $item_list = $items[$language_to_show] ?? [];
    if (count($item_list) === 0) {
      unset($form[$node_id]);
      return;
    }
    $form[$node_id]['items'] = [
      '#theme' => 'item_list',
      '#items' => $item_list,
    ];
    return;
  }

  foreach ($items as $lang => $item_list) {
    $lang_label = $languages[$lang] ?? '';
    $form[$node_id][$lang]['text'] = [
      '#type' => 'html_tag',
      '#tag' => 'p',
      '#value' => t('@lang', ['@lang' => $lang_label]),
    ];
    $form[$node_id][$lang]['items'] = [
      '#theme' => 'item_list',
      '#items' => $item_list,
    ];
  }

}

/**
 * Implements hook_cron().
 *
 * Processes pending entities from the tracker queue during cron runs.
 */
function entity_mesh_cron() {
  $config = \Drupal::config('entity_mesh.settings');
  $cron_enabled = $config->get('cron_enabled') ?? TRUE;

  // If cron processing is disabled, skip.
  if (!$cron_enabled) {
    return;
  }

  $cron_limit = $config->get('cron_limit') ?? 50;
  $tracker = \Drupal::service('entity_mesh.tracker');
  $entity_type_manager = \Drupal::entityTypeManager();
  $entity_render = \Drupal::service('entity_mesh.entity_render');
  $logger = \Drupal::logger('entity_mesh');

  // Get pending entities from tracker.
  $pending_entities = $tracker->getPendingEntities($cron_limit, 'node');

  if (empty($pending_entities)) {
    return;
  }

  $logger->info('Processing @count entities from tracker during cron run.', [
    '@count' => count($pending_entities),
  ]);

  $processed = 0;
  $failed = 0;

  foreach ($pending_entities as $tracker_item) {
    $tracker_id = (int) $tracker_item['id'];
    $entity_id = $tracker_item['entity_id'];
    $entity_type = $tracker_item['entity_type'];
    $operation = (int) $tracker_item['operation'];

    try {
      // Check operation type.
      if ($operation === TrackerInterface::OPERATION_PROCESS) {
        // Load the entity.
        $entity = $entity_type_manager->getStorage($entity_type)->load($entity_id);

        if ($entity instanceof NodeInterface) {
          // Process the entity.
          $entity_render->processEntity($entity);
          // Mark as processed.
          $tracker->markAsProcessed($tracker_id);
          $processed++;
        }
        else {
          // Entity not found, mark as failed.
          $tracker->markAsFailed($tracker_id);
          $failed++;
          $logger->warning('Entity @type:@id not found during cron processing.', [
            '@type' => $entity_type,
            '@id' => $entity_id,
          ]);
        }
      }
      elseif ($operation === TrackerInterface::OPERATION_DELETE) {
        // Delete entity mesh records.
        $entity_render->deleteItem($entity_type, $entity_id);
        // Mark as processed.
        $tracker->markAsProcessed($tracker_id);
        $processed++;
      }
    }
    catch (\Exception $e) {
      // Mark as failed on exception.
      $tracker->markAsFailed($tracker_id);
      $failed++;
      $logger->error('Error processing entity @type:@id during cron: @message', [
        '@type' => $entity_type,
        '@id' => $entity_id,
        '@message' => $e->getMessage(),
      ]);
    }
  }

  if ($processed > 0 || $failed > 0) {
    $logger->info('Cron processing completed: @processed processed, @failed failed.', [
      '@processed' => $processed,
      '@failed' => $failed,
    ]);
  }
}

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

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