You are here

public function ContentEntityCdfNormalizer::normalize in Acquia Content Hub 8

Normalizes an object into a set of arrays/scalars.

Parameters

object $entity: Object to normalize. Due to the constraints of the class, we know that the object will be of the ContentEntityInterface type.

string $format: The format that the normalization result will be encoded as.

array $context: Context options for the normalizer.

Return value

array|string|bool|int|float|null Return normalized data.

File

src/Normalizer/ContentEntityCdfNormalizer.php, line 228

Class

ContentEntityCdfNormalizer
Converts the Drupal entity object to a Acquia Content Hub CDF array.

Namespace

Drupal\acquia_contenthub\Normalizer

Code

public function normalize($entity, $format = NULL, array $context = []) {

  // Exit if the class does not support normalizing to the given format.
  if (!$this
    ->supportsNormalization($entity, $format)) {
    return NULL;
  }

  // Creating a fake user account to give as context to the normalization.
  $account = new ContentHubUserSession($this->config
    ->get('acquia_contenthub.entity_config')
    ->get('user_role'));
  $context += [
    'account' => $account,
  ];

  // Checking for entity access permission to this particular account.
  $entity_access = $entity
    ->access('view', $account, TRUE);
  if (!$entity_access
    ->isAllowed() && !$entity_access
    ->isNeutral()) {
    return NULL;
  }

  // By executing the rendering here with this cache contexts, we are bubbling
  // it up to the dynamic page cache so that it varies by the query param
  // include_references. Do not remove.
  $cache = [
    '#cache' => [
      'contexts' => [
        'url.query_args:include_references',
      ],
    ],
  ];
  $this->renderer
    ->renderPlain($cache);

  // Add query params to the context.
  $current_uri = \Drupal::request()
    ->getRequestUri();
  $uri = UrlHelper::parse($current_uri);
  $context += [
    'query_params' => $uri['query'],
  ];

  // Set our required CDF properties.
  $entity_type_id = $context['entity_type'] = $entity
    ->getEntityTypeId();
  $entity_uuid = $entity
    ->uuid();
  $origin = $this->config
    ->get('acquia_contenthub.admin_settings')
    ->get('origin');

  // Allow other modules to intercept and do changes to the drupal entity
  // before it is converted to CDF format.
  $this->moduleHandler
    ->alter('acquia_contenthub_drupal_to_cdf', $entity_type_id, $entity);

  // Required Created field.
  if ($entity
    ->hasField('created') && $entity
    ->get('created')) {
    $created = date('c', $entity
      ->get('created')
      ->getValue()[0]['value']);
  }
  else {
    $created = date('c');
  }

  // Modified date in the CDF will correspond to the time when the entity was
  // modified in Content Hub, not in Drupal.
  $modified = date('c');

  // Base Root Path.
  $base_root = $this
    ->getBaseRoot();

  // Initialize Content Hub entity.
  $contenthub_entity = new ContentHubEntity();
  $contenthub_entity
    ->setUuid($entity_uuid)
    ->setType($entity_type_id)
    ->setOrigin($origin)
    ->setCreated($created)
    ->setModified($modified);
  if ($view_modes = $this->contentEntityViewModesNormalizer
    ->getRenderedViewModes($entity)) {
    $contenthub_entity
      ->setMetadata([
      'base_root' => $base_root,
      'view_modes' => $view_modes,
    ]);
  }

  // We have to iterate over the entity translations and add all the
  // translations versions.
  $languages = $entity
    ->getTranslationLanguages();
  foreach ($languages as $language) {
    $langcode = $language
      ->getId();
    $localized_entity = $entity
      ->getTranslation($langcode);

    // If content_translation is enabled, then check whether the current
    // translation revision of the content has been published.
    if (!empty($this->translationManager) && $this->translationManager
      ->isEnabled($entity_type_id, $entity
      ->bundle())) {

      /** @var \Drupal\content_translation\ContentTranslationMetadataWrapperInterface $translation_metadata */
      $translation_metadata = $this->translationManager
        ->getTranslationMetadata($localized_entity);
      if (!$translation_metadata
        ->isPublished()) {
        continue;
      }
    }
    $contenthub_entity = $this
      ->addFieldsToContentHubEntity($contenthub_entity, $localized_entity, $langcode, $context);
  }

  // Allow other modules to intercept and modify the CDF entity after it has
  // been normalized and before it is sent to Content Hub.
  $this->moduleHandler
    ->alter('acquia_contenthub_cdf_from_drupal', $contenthub_entity);

  // Create the array of normalized fields, starting with the URI.
  $normalized = [
    'entities' => [
      $contenthub_entity,
    ],
  ];

  // Add all references to it if the include_references is true.
  if (!empty($context['query_params']['include_references']) && $context['query_params']['include_references'] == 'true') {
    $referenced_entities = [];
    $referenced_entities = $this
      ->getMultilevelReferencedFields($entity, $referenced_entities, $context);

    // Adding path_alias entities to the referenced_entities.
    $path_uuid_attribute = $contenthub_entity
      ->getAttribute('path_uuid');
    if ($path_uuid_attribute) {
      foreach ($path_uuid_attribute
        ->getValues() as $values) {
        foreach ($values as $path_alias_uuid) {
          $path_alias_entity = $this->entityRepository
            ->loadEntityByUuid('path_alias', $path_alias_uuid);
          if ($this->entityManager
            ->isEligibleDependency($path_alias_entity)) {
            $referenced_entities[$path_alias_uuid] = $path_alias_entity;
          }
        }
      }
    }
    $referenced_entities = array_values($referenced_entities);
    foreach ($referenced_entities as $entity) {

      // Only proceed to add the dependency if:
      // - Entity is not a node and it is not translatable.
      // - Entity is a node, its not translatable and it is published.
      // - Entity is translatable and has at least one published translation.
      if (!$this->entityManager
        ->isPublished($entity)) {
        continue;
      }

      // Generate our URL where the isolated rendered view mode lives.
      // This is the best way to really make sure the content in Content Hub
      // and the content shown to any user is 100% the same.
      try {

        // Obtain the Entity CDF by making an hmac-signed internal request.
        $context['query_params']['include_references'] = 'false';
        $referenced_entity_list_cdf = $this
          ->normalize($entity, $format, $context);
        $referenced_entity_list_cdf = array_pop($referenced_entity_list_cdf);
        if (is_array($referenced_entity_list_cdf)) {
          foreach ($referenced_entity_list_cdf as $referenced_entity_cdf) {
            $normalized['entities'][] = $referenced_entity_cdf;
          }
        }
      } catch (\Exception $e) {

        // Do nothing, route does not exist.
      }
    }
  }
  return $normalized;
}