blacksmith-8.x-1.x-dev/src/Blacksmith/EntityImporter/EntityImporter.php

src/Blacksmith/EntityImporter/EntityImporter.php
<?php

namespace Drupal\blacksmith\Blacksmith\EntityImporter;

use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Logger\LoggerChannelTrait;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\blacksmith\Exception\BlacksmithImportSkip;
use Drupal\blacksmith\Blacksmith\EntityImporter\FieldFormatter\FieldFormatterFactory;
use Drupal\blacksmith\BlacksmithItem;
use Drupal\blacksmith\BlacksmithTranslation;

/**
 * Class EntityImporter.
 *
 * @package Drupal\blacksmith\Blacksmith\EntityImporter
 */
abstract class EntityImporter implements EntityImporterInterface {
  use LoggerChannelTrait;
  use MessengerTrait;

  /**
   * Entity storage used to create the entities.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $entityStorage;

  /**
   * Entity field manager service.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * Field formatter factory service.
   *
   * @var \Drupal\blacksmith\Blacksmith\EntityImporter\FieldFormatter\FieldFormatterFactory
   */
  protected $fieldFormatterFactory;

  /**
   * Entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Entity importer factory service.
   *
   * @var \Drupal\blacksmith\Blacksmith\EntityImporter\EntityImporterFactory
   */
  protected $entityImporterFactory;

  /**
   * NodeEntityImporter constructor.
   *
   * @param \Drupal\Core\Entity\EntityStorageInterface $entityStorage
   *   Node entity storage.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   Entity type manager service.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
   *   Entity field manager service.
   * @param \Drupal\blacksmith\Blacksmith\EntityImporter\EntityImporterFactory $entityImporterFactory
   *   Entity importer factory service.
   */
  public function __construct(EntityStorageInterface $entityStorage, EntityTypeManagerInterface $entityTypeManager, EntityFieldManagerInterface $entityFieldManager, EntityImporterFactory $entityImporterFactory) {
    $this->entityStorage = $entityStorage;
    $this->entityTypeManager = $entityTypeManager;
    $this->entityFieldManager = $entityFieldManager;
    $this->entityImporterFactory = $entityImporterFactory;
    $this->fieldFormatterFactory = new FieldFormatterFactory($entityTypeManager);
  }

  /**
   * {@inheritdoc}
   */
  public function import(BlacksmithItem $item) : EntityInterface {
    $values = $this->presetValues($item);

    foreach ($this->getFieldDefinitions($item) as $fieldDefinition) {
      $fieldName = $fieldDefinition->getName();

      // Properly format the value from the Yaml file.
      if ($item->hadField($fieldName)) {
        $fieldFormatter = $this->fieldFormatterFactory->create($fieldDefinition);
        $values[$fieldName] = $fieldFormatter->format($item->get($fieldName));
      }
      // Get the default value.
      elseif ($defaults = $this->getDefaultValues($fieldDefinition)) {
        $values[$fieldName] = $defaults;
      }
      // Throw an error if the field is supposed to have a value.
      elseif (!array_key_exists($fieldName, $values) && $fieldDefinition->isRequired()) {
        $entityTypeName = $this->entityStorage->getEntityType()->getLabel();
        throw new BlacksmithImportSkip("The entity type '$entityTypeName' needs the field : '$fieldName'.", $item);
      }
    }

    // Create the entity and save it to the database.
    $entity = $this->createEntity($values);
    $entity = $this->addEntityTranslations($entity, $item);

    return $entity;
  }

  /**
   * Generates an new entity and saves it in the database.
   *
   * @param array $values
   *   Keyed array of values used to generated an entity.
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *   The created entity.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function createEntity(array $values) : EntityInterface {
    $entity = $this->entityStorage->create($values);
    $entity->save();

    return $entity;
  }

  /**
   * Generates all translations of the entity based on the Blacksmith item.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to which we add translations.
   * @param \Drupal\blacksmith\BlacksmithItem $item
   *   The Blacksmith item used to generate the translations.
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *   The entity with additional translations.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function addEntityTranslations(EntityInterface $entity, BlacksmithItem $item) : EntityInterface {
    if ($entity instanceof ContentEntityBase && $entity->isTranslatable()) {

      foreach ($item->getTranslations() as $langcode => $translation) {
        $translationValues = $this->presentTranslationValues($translation);

        foreach ($this->getFieldDefinitions($item) as $fieldDefinition) {
          $fieldName = $fieldDefinition->getName();

          if (!$fieldDefinition->isTranslatable()) {
            if ($translation->get($fieldName)) {
              $this->messenger()->addWarning("$fieldName is not translatable");
            }
            continue;
          }

          // Properly format the value from the Yaml file.
          if ($fieldValue = $translation->get($fieldName)) {
            $fieldFormatter = $this->fieldFormatterFactory->create($fieldDefinition);
            $translationValues[$fieldName] = $fieldFormatter->format($translation->get($fieldName));
          }
        }

        // Create the translation if any.
        $entity->addTranslation($langcode, $translationValues);
        $entity->save();
      }
    }

    return $entity;
  }

  /**
   * Prepares some values that have a specific key and/or value.
   *
   * @param \Drupal\blacksmith\BlacksmithItem $item
   *   Blacksmith item used to build the entity.
   *
   * @return array
   *   The keyed values that will be set in the entity.
   */
  protected function presetValues(BlacksmithItem $item) : array {
    return [
      $this->entityStorage->getEntityType()->getKey('label') => $item->label(),
      $this->entityStorage->getEntityType()->getKey('bundle') => $item->bundle(),
    ];
  }

  /**
   * Prepares some values that have a specific key and/or value.
   *
   * @param \Drupal\blacksmith\BlacksmithTranslation $translations
   *   Blacksmith translation used to build the entity translation.
   *
   * @return array
   *   The keyed values that will be set in the entity.
   */
  protected function presentTranslationValues(BlacksmithTranslation $translations) : array {
    return [
      $this->entityStorage->getEntityType()->getKey('label') => $translations->label(),
    ];
  }

  /**
   * Get all fields of a specific entity type with bundle.
   *
   * @param \Drupal\blacksmith\BlacksmithItem $item
   *   The Blacksmith item about to be imported.
   *
   * @return \Drupal\Core\Field\FieldDefinitionInterface[]
   *   The list of fields.
   */
  protected function getFieldDefinitions(BlacksmithItem $item) : array {
    return $this->entityFieldManager->getFieldDefinitions($this->entityStorage->getEntityTypeId(), $item->bundle());
  }

  /**
   * Finds the default values of a field.
   *
   * @param \Drupal\Core\Field\FieldDefinitionInterface $fieldDefinition
   *   The field that is about to be saved in the entity.
   *
   * @return array
   *   Raw default values.
   */
  protected function getDefaultValues(FieldDefinitionInterface $fieldDefinition) : array {
    $defaultValues = [];
    foreach ($fieldDefinition->getDefaultValueLiteral() as $value) {
      $defaultValues[] = $value['value'];
    }

    return $defaultValues;
  }

}

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

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