toolshed-8.x-1.x-dev/modules/toolshed_search/src/Plugin/search_api/processor/EntityPropertiesProcessor.php

modules/toolshed_search/src/Plugin/search_api/processor/EntityPropertiesProcessor.php
<?php

namespace Drupal\toolshed_search\Plugin\search_api\processor;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityChangedInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Plugin\search_api\data_type\value\TextValue;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Processor\ProcessorProperty;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Adds the common entity properties to the indexed data.
 *
 * Doing this allows creating views and filters that can be applied across
 * multiple entity types using singular search fields.
 *
 * @SearchApiProcessor(
 *   id = "toolshed_search_entity_properties",
 *   label = @Translation("Entity properties"),
 *   description = @Translation("Create for common entity properties into the global datasource."),
 *   stages = {
 *     "add_properties" = 0,
 *   },
 *   locked = false,
 *   hidden = false,
 * )
 */
class EntityPropertiesProcessor extends ProcessorPluginBase {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface|null
   */
  protected ?EntityTypeManagerInterface $entityTypeManager;

  /**
   * Mapping Search API property paths to property ID keys for quick lookups.
   *
   * @var mixed[]
   */
  protected array $propMappings = [];

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    $processor = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $processor->setEntityTypeManager($container->get('entity_type.manager'));

    return $processor;
  }

  /**
   * Retrieves the entity type manager.
   *
   * @return \Drupal\Core\Entity\EntityTypeManagerInterface
   *   The entity type manager.
   */
  public function getEntityTypeManager(): EntityTypeManagerInterface {
    return $this->entityTypeManager;
  }

  /**
   * Sets the entity type manager.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   *
   * @return $this
   */
  public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager): self {
    $this->entityTypeManager = $entity_type_manager;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public static function supportsIndex(IndexInterface $index): bool {
    foreach ($index->getDatasources() as $datasource) {
      if ($entityTypeId = $datasource->getEntityTypeId()) {
        $entityType = \Drupal::entityTypeManager()
          ->getDefinition($entityTypeId);

        if ($entityType && $entityType->entityClassImplements(ContentEntityInterface::class)) {
          return TRUE;
        }
      }
    }

    return FALSE;
  }

  /**
   * Get the $item fields relevant to this processor keyed by property path.
   *
   * @param \Drupal\search_api\Item\ItemInterface $item
   *   The Search API item whose fields are being populated.
   *
   * @return \Drupal\search_api\Item\FieldInterface[][]
   *   An array of fields from the Search API $item keyed by the property
   *   paths defined in ::getPropertyDefintions().
   */
  protected function getFieldsByProperty(ItemInterface $item): array {
    $indexId = $item->getIndex()->id();
    $srcFields = $item->getFields();

    // Create a mapping from field IDs to the property path the field has data
    // for supports. This should not change per index, and could speed up
    // successive calls to ::addFieldValues() for this search index.
    if (!isset($this->propMappings[$indexId])) {
      $mapping = [];
      $properties = $this->getPropertyDefinitions();

      foreach ($srcFields as $key => $field) {
        $propPath = $field->getPropertyPath();

        if ($field->getDatasourceId() === NULL && isset($properties[$propPath])) {
          $mapping[$propPath][$key] = $key;
        }
      }

      $this->propMappings[$indexId] = $mapping;
    }

    $fields = [];
    foreach ($this->propMappings[$indexId] as $prop => $keys) {
      foreach ($keys as $key) {
        if (isset($srcFields[$key])) {
          $fields[$prop][$key] = $srcFields[$key];
        }
      }
    }

    return $fields;
  }

  /**
   * Determine the status of a content entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to determine the status of.
   *
   * @return bool|null
   *   Returns the status value of an entity if
   */
  protected function getEntityStatus(ContentEntityInterface $entity): ?bool {
    if ($entity instanceof EntityPublishedInterface) {
      return $entity->isPublished();
    }

    if ($entity instanceof UserInterface) {
      return $entity->isActive();
    }

    $entityType = $entity->getEntityType();
    $statusKey = $entityType->getKey('status');

    if ($statusKey && $entity->hasField($statusKey)) {
      return (bool) $entity->get($statusKey)->value;
    }

    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(?DatasourceInterface $datasource = NULL): array {
    $properties = [];

    // Add the properties only to the global Search API index, so skip adding
    // to any specific datasource (content, taxonomy, etc...).
    if (!$datasource) {
      $properties['entity_label'] = new ProcessorProperty([
        'label' => $this->t('Entity label'),
        'description' => $this->t('The value of the label property of the entity.'),
        'type' => 'search_api_text',
        'is_list' => FALSE,
        'processor_id' => $this->getPluginId(),
      ]);

      $properties['entity_bundle'] = new ProcessorProperty([
        'label' => $this->t('Entity bundle'),
        'description' => $this->t('Canonical entity bundle name that includes the entity type and bundle together with a colon separator.'),
        'type' => 'string',
        'is_list' => FALSE,
        'processor_id' => $this->getPluginId(),
      ]);

      $properties['entity_status'] = new ProcessorProperty([
        'label' => $this->t('Entity status'),
        'description' => $this->t('Exposes a boolean status for entity types that support status. Consider using the "Entity Status" processor if looking to only filter unpublished content.'),
        'type' => 'boolean',
        'is_list' => FALSE,
        'processor_id' => $this->getPluginId(),
      ]);

      $properties['entity_created'] = new ProcessorProperty([
        'label' => $this->t('Entity created date'),
        'description' => $this->t('Entity created date if available from entity.'),
        'type' => 'timestamp',
        'is_list' => FALSE,
        'processor_id' => $this->getPluginId(),
      ]);

      $properties['entity_changed'] = new ProcessorProperty([
        'label' => $this->t('Entity changed'),
        'description' => $this->t('The entity last changed timestamp if supported by the entity type.'),
        'type' => 'timestamp',
        'is_list' => FALSE,
        'processor_id' => $this->getPluginId(),
      ]);
    }

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function addFieldValues(ItemInterface $item): void {
    $entity = $item->getOriginalObject()->getValue();

    // Only add property information for entities.
    if (!($entity instanceof ContentEntityInterface)) {
      return;
    }

    $fields = $this->getFieldsByProperty($item);

    // Add the entity label to the search index.
    if (!empty($fields['entity_label'])) {
      $text = new TextValue($entity->label());
      foreach ($fields['entity_label'] as $field) {
        $field->setValues([$text]);
      }
    }

    // Add the entity type and bundle for single field accross entity types.
    // The bundle is stored as "ENTITY_TYPE:BUNDLE_LABEL".
    if (!empty($fields['entity_bundle'])) {
      foreach ($fields['entity_bundle'] as $field) {
        $field->setValues([$entity->getEntityTypeId() . ':' . $entity->bundle()]);
      }
    }

    if (!empty($fields['entity_status'])) {
      $statusValue = $this->getEntityStatus($entity);
      foreach ($fields['entity_status'] as $field) {
        $field->setValues([$statusValue]);
      }
    }

    if ($entity->hasField('created') && !empty($fields['entity_created'])) {
      $createdField = $entity->get('created');
      $fieldType = $createdField->getFieldDefinition()->getType();

      if (in_array($fieldType, ['timestamp', 'created'])) {
        foreach ($fields['entity_created'] as $field) {
          $field->setValues([$createdField->value]);
        }
      }
    }

    // Only entities that implement the EntityChangedInterface have a
    // consistent way of finding the changed time.
    if ($entity instanceof EntityChangedInterface && !empty($fields['entity_changed'])) {
      foreach ($fields['entity_changed'] as $field) {
        $field->setValues([$entity->getChangedTime()]);
      }
    }
  }

}

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

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