You are here

public function ContentEntityHandler::onParseCdf in Acquia Content Hub 8.2

Parses the CDF representation of Content Entities.

Parameters

\Drupal\acquia_contenthub\Event\ParseCdfEntityEvent $event: Event.

Throws

\Exception

File

src/EventSubscriber/Cdf/ContentEntityHandler.php, line 152

Class

ContentEntityHandler
The Content entity CDF creator.

Namespace

Drupal\acquia_contenthub\EventSubscriber\Cdf

Code

public function onParseCdf(ParseCdfEntityEvent $event) {
  $cdf = $event
    ->getCdf();
  if ($cdf
    ->getType() !== 'drupal8_content_entity') {

    // Bail early if this isn't a content entity.
    return;
  }
  $default_language = $cdf
    ->getMetadata()['default_language'];

  // If entity doesn't have any language available, throw an error.
  if (empty($default_language)) {
    throw new \Exception(sprintf("No language available for entity with UUID %s.", $cdf
      ->getUuid()));
  }
  $langcodes = $cdf
    ->getMetadata()['languages'];
  $entity_values = [];
  $entity_type_id = $cdf
    ->getAttribute('entity_type')
    ->getValue()['und'];
  $entity_type = $this
    ->getEntityTypeManager()
    ->getDefinition($entity_type_id);
  $langcode_key = $entity_type
    ->hasKey('langcode') ? $entity_type
    ->getKey('langcode') : 'langcode';
  $bundle_id = $cdf
    ->getAttribute('bundle')
    ->getValue()['und'];
  foreach (json_decode(base64_decode($cdf
    ->getMetadata()['data']), TRUE) as $field_name => $field) {
    if ($field_name === 'uuid' && $event
      ->hasEntity() && $cdf
      ->getUuid() !== $event
      ->getEntity()
      ->uuid()) {

      // Make sure we do not override the uuid of an existing local entity.
      continue;
    }
    $unserialize_event = new UnserializeCdfEntityFieldEvent($entity_type, $bundle_id, $field_name, $field, $cdf
      ->getMetadata()['field'][$field_name], $event
      ->getStack());
    $this->dispatcher
      ->dispatch(AcquiaContentHubEvents::UNSERIALIZE_CONTENT_ENTITY_FIELD, $unserialize_event);
    $value = $unserialize_event
      ->getValue();
    $entity_values = NestedArray::mergeDeep($entity_values, $value);
  }
  if (!$event
    ->isMutable()) {
    return;
  }
  if (!$event
    ->hasEntity()) {

    // Entities like redirect don't have default_language field
    // which makes the langcode field missing in the actual values
    // for entity creation leading to incorrect default language.
    if (!array_key_exists($langcode_key, $entity_values[$default_language])) {
      $entity_values[$default_language][$langcode_key] = $default_language;
    }

    // If formatted language is different from default language, change it.
    $formatted_default_language = $this
      ->removeChannelId($default_language);
    if ($formatted_default_language !== $default_language) {
      $entity_values[$formatted_default_language] = $entity_values[$default_language];
      $entity_values[$formatted_default_language][$langcode_key] = $formatted_default_language;
      unset($entity_values[$default_language]);
    }

    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
    $entity = $this
      ->getEntityTypeManager()
      ->getStorage($entity_type_id)
      ->create($entity_values[$formatted_default_language]);
    unset($entity_values[$formatted_default_language]);
  }
  else {
    $entity = $event
      ->getEntity();
  }
  foreach ($entity_values as $langcode => $values) {
    if (!in_array($langcode, $langcodes)) {
      continue;
    }
    $langcode = $this
      ->removeChannelId($langcode);
    $values[$langcode_key] = $langcode;
    if (isset($values['content_translation_source'])) {
      $values['content_translation_source'] = $this
        ->removeChannelId($values['content_translation_source']);
    }
    if (!$entity
      ->hasTranslation($langcode)) {
      try {
        $entity
          ->addTranslation($langcode, $values);
      } catch (\InvalidArgumentException $ex) {

        // Still fail but provide information to locate the failing entity.
        throw new \Exception(sprintf("Cannot add translation '%s' for Entity (%s, %s): %s.", $langcode, $entity
          ->getEntityTypeId(), $entity
          ->uuid(), $ex
          ->getMessage()));
      }
    }
    else {

      /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
      $entity = $entity
        ->getTranslation($langcode);
      foreach ($entity as $field_name => $field) {
        if (isset($values[$field_name])) {
          $entity
            ->set($field_name, $values[$field_name]);
        }
      }
    }
  }

  // Dispatch an event for final alteration
  // if we want to add additional data from the CDF to the entity.
  $unserialize_additional_metadata_event = new UnserializeAdditionalMetadataEvent($entity, $cdf);
  $this->dispatcher
    ->dispatch(AcquiaContentHubEvents::UNSERIALIZE_ADDITIONAL_METADATA, $unserialize_additional_metadata_event);
  $entity = $unserialize_additional_metadata_event
    ->getEntity();
  $event
    ->setEntity($entity);
}