bibcite-8.x-1.x-dev/modules/bibcite_entity/src/Normalizer/ReferenceNormalizerBase.php

modules/bibcite_entity/src/Normalizer/ReferenceNormalizerBase.php
<?php

namespace Drupal\bibcite_entity\Normalizer;

use Drupal\bibcite_entity\Entity\Contributor;
use Drupal\bibcite_entity\Entity\Keyword;
use Drupal\bibcite_entity\Entity\ReferenceInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Url;
use Drupal\serialization\Normalizer\EntityNormalizer;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;

/**
 * Base normalizer class for bibcite formats.
 */
abstract class ReferenceNormalizerBase extends EntityNormalizer {

  /**
   * Default reference type. Will be assigned for types without mapping.
   *
   * @var string
   */
  const DEFAULT_REF_TYPE = 'miscellaneous';

  /**
   * The format that this Normalizer supports.
   *
   * @var string
   *
   * @todo Remove as it's defined in the base class.
   */
  protected $format;

  /**
   * Format setter for DI calls.
   *
   * @param string|array $format
   *   Normalizer format.
   */
  public function setFormat($format) {
    $this->format = $format;

    foreach ((array) $this->format as $format) {
      $config_name = sprintf('bibcite_entity.mapping.%s', $format);
      $config = $this->configFactory->get($config_name);

      $this->fieldsMapping[$format] = $config->get('fields');
      $this->typesMapping[$format] = $config->get('types');
    }
  }

  /**
   * Default publication type. Will be assigned for types without mapping.
   *
   * @var string
   */
  public $defaultType;

  /**
   * Mapping between bibcite_entity and format publication types.
   *
   * @var array
   */
  protected $typesMapping;

  /**
   * Mapping between bibcite_entity and format fields.
   *
   * @var array
   */
  protected $fieldsMapping;

  /**
   * The interface or class that this Normalizer supports.
   *
   * @var array
   */
  protected $supportedInterfaceOrClass = ['Drupal\bibcite_entity\Entity\ReferenceInterface'];

  /**
   * Configuration factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * Format contributor key.
   *
   * @var string|null
   */
  public $contributorKey = NULL;

  /**
   * Format keyword key.
   *
   * @var null|string
   */
  public $keywordKey = NULL;

  /**
   * Format type key.
   *
   * Default value is 'type'.
   *
   * @var null|string
   */
  public $typeKey = 'type';

  /**
   * Construct new BibliographyNormalizer object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
   *   The entity manager.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Config factory.
   * @param \Drupal\Core\Entity\EntityTypeRepositoryInterface $entity_type_repository
   *   The entity type repository.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   The entity field manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, EntityTypeRepositoryInterface $entity_type_repository, EntityFieldManagerInterface $entity_field_manager) {
    parent::__construct($entity_manager, $entity_type_repository, $entity_field_manager);

    $this->configFactory = $config_factory;
  }

  /**
   * Get format contributor key.
   *
   * @return string|null
   *   Contributor key.
   */
  protected function getContributorKey() {
    return $this->contributorKey;
  }

  /**
   * Get format keyword key.
   *
   * @return string|null
   *   Keyword key.
   */
  protected function getKeywordKey() {
    return $this->keywordKey;
  }

  /**
   * Get format type key.
   *
   * @return string|null
   *   Type key.
   */
  protected function getTypeKey() {
    return $this->typeKey;
  }

  /**
   * Get Drupal denormalizer.
   *
   * @return Drupal\serialization\Normalizer\EntityNormalizer
   *   Denormalized entity.
   */
  public function getDrupalDenormalizer($data, $class, $format = NULL, array $context = []): mixed {
    return parent::denormalize($data, $class, $format, $context);
  }

  /**
   * {@inheritdoc}
   */
  public function denormalize($data, $class, $format = NULL, array $context = []): mixed {
    $contributor_key = $this->getContributorKey();
    if (!empty($data[$contributor_key])) {
      $contributors = (array) $data[$contributor_key];
      unset($data[$contributor_key]);
    }

    $keyword_key = $this->getKeywordKey();
    if (!empty($data[$keyword_key])) {
      $keywords = (array) $data[$keyword_key];
      unset($data[$keyword_key]);
    }

    $type_key = $this->getTypeKey();
    if (empty($data[$type_key])) {
      throw new UnexpectedValueException("Reference type is incorrect or not set.");
    }
    $reference_type = $data[$type_key];
    $converted_type = $this->convertFormatType($reference_type, $format);
    // @todo Review logic of this exception because of $this->convertFormatType() always returns value.
    if (!$converted_type) {
      $url = Url::fromRoute('bibcite_entity.mapping', ['bibcite_format' => $format])
        ->toString();
      throw new UnexpectedValueException("'{$reference_type}' type is not mapped to reference type. <a href='{$url}'>Check mapping configuration</a>.");
    }
    unset($data[$type_key]);
    $data = $this->convertKeys($data, $format);
    $data['type'] = $converted_type;
    /** @var \Drupal\bibcite_entity\Entity\Reference $entity */
    $entity = parent::denormalize($data, $class, $format, $context);

    if (!empty($contributors)) {
      $author_field = $entity->get('author');
      foreach ($contributors as $name) {
        $author_field->appendItem(parent::denormalize(['name' => [['value' => $name]]], Contributor::class, $format, $context));
      }
    }
    if (!empty($keywords)) {
      $keyword_field = $entity->get('keywords');
      foreach ($keywords as $keyword) {
        $keyword_field->appendItem(parent::denormalize(['name' => [['value' => $keyword]]], Keyword::class, $format, $context));
      }
    }
    return $entity;
  }

  /**
   * Convert publication type to format type.
   *
   * @param string $type
   *   Bibcite entity publication type.
   * @param string $format
   *   Serializer format.
   *
   * @return string
   *   Format publication type.
   */
  protected function convertEntityType($type, $format) {
    $types_mapping = array_flip(array_filter($this->typesMapping[$format]));
    return isset($types_mapping[$type]) ? $types_mapping[$type] : $this->defaultType;
  }

  /**
   * Convert format type to publication type.
   *
   * @param string $type
   *   Format publication type.
   * @param string $format
   *   Serializer format.
   *
   * @return null|string
   *   Bibcite entity publication type.
   */
  protected function convertFormatType($type, $format) {
    if (isset($this->typesMapping[$format][$type])) {
      return $this->typesMapping[$format][$type];
    }
    elseif (isset($this->typesMapping[$format][$this->defaultType])) {
      return $this->typesMapping[$format][$this->defaultType];
    }
    return self::DEFAULT_REF_TYPE;
  }

  /**
   * Extract fields values from reference entity.
   *
   * @param \Drupal\bibcite_entity\Entity\ReferenceInterface $reference
   *   Reference entity object.
   * @param string $format
   *   Serializer format.
   *
   * @return array
   *   Array of entity values.
   */
  protected function extractFields(ReferenceInterface $reference, $format) {
    $attributes = [];

    foreach ($this->fieldsMapping[$format] as $format_field => $entity_field) {
      if ($entity_field && $reference->hasField($entity_field) && ($field = $reference->get($entity_field)) && !$field->isEmpty()) {
        $attributes[$format_field] = $this->extractScalar($field);
      }
    }

    return $attributes;
  }

  /**
   * Extract keywords labels from field.
   *
   * @param \Drupal\Core\Field\FieldItemListInterface $field_item_list
   *   List of field items.
   *
   * @return array
   *   Keywords labels.
   */
  protected function extractKeywords(FieldItemListInterface $field_item_list) {
    $keywords = [];

    foreach ($field_item_list as $field) {
      $keywords[] = $field->entity ? $field->entity ->label() : NULL;
    }

    return $keywords;
  }

  /**
   * Extract authors values from field.
   *
   * @param \Drupal\Core\Field\FieldItemListInterface $field_item_list
   *   List of field items.
   *
   * @return array
   *   Authors in BibTeX format.
   */
  protected function extractAuthors(FieldItemListInterface $field_item_list) {
    $authors = [];

    foreach ($field_item_list as $field) {
        $authors[] = $field->entity ? $field->entity->getName() : NULL;
    }

    return $authors;
  }

  /**
   * Extract scalar value.
   *
   * @param \Drupal\Core\Field\FieldItemListInterface $scalar_field
   *   Scalar items list.
   *
   * @return mixed
   *   Scalar value.
   */
  protected function extractScalar(FieldItemListInterface $scalar_field) {
    return $scalar_field->value;
  }

  /**
   * Convert format keys to Bibcite entity keys and filter non-mapped.
   *
   * @param array $data
   *   Array of decoded values.
   * @param string $format
   *   Serializer format.
   *
   * @return array
   *   Array of decoded values with converted keys.
   */
  protected function convertKeys(array $data, $format) {
    $converted = [];

    foreach ($data as $key => $field) {
      if (!empty($this->fieldsMapping[$format][$key])) {
        $converted_key = empty($this->fieldsMapping[$format][$key]) ? $key : $this->fieldsMapping[$format][$key];
        $converted[$converted_key] = [$field];
      }
    }

    return $converted;
  }

  /**
   * {@inheritdoc}
   */
  public function normalize($object, $format = NULL, array $context = []): array|string|int|float|bool|\ArrayObject|NULL {
    /** @var \Drupal\bibcite_entity\Entity\ReferenceInterface $object */

    $attributes = [];
    $attributes[$this->typeKey] = $this->convertEntityType($object->bundle(), $format);

    if ($keywords = $this->extractKeywords($object->get('keywords'))) {
      $attributes[$this->keywordKey] = $keywords;
    }

    if ($authors = $this->extractAuthors($object->get('author'))) {
      $attributes[$this->contributorKey] = $authors;
    }

    $attributes += $this->extractFields($object, $format);

    return $attributes;
  }

}

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

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