You are here

function _content_sync_entity_to_db in Content Synchronization 8

Process a content entity YAML and store to the db IMPORT Content.

Parameters

$data: Content entity data from YAML.

$file: file path.

array $context: The batch context.

2 calls to _content_sync_entity_to_db()
processContentBatch in ./content_sync.batch.inc
Processes the content single import batch
processContentDirectoryBatch in ./content_sync.batch.inc
Processes the content sync import batch

File

./content_sync.batch.inc, line 156

Code

function _content_sync_entity_to_db($data, $file, &$context) {

  // Entity Type and Field Manager
  $entityTypeManager = \Drupal::entityTypeManager();
  $entityFieldManager = \Drupal::service('entity_field.manager');
  $entityBundles = \Drupal::service("entity_type.bundle.info");
  $entityRepository = \Drupal::service('entity.repository');

  // Process data only if there is a valid entity type and bundle flag
  $valid_entity_type = TRUE;

  // Get entity type
  if (isset($data['entity_type'])) {
    $entity_type = $data['entity_type'];
  }

  // Get entity bundle
  if (isset($data['bundle'])) {
    $entity_bundle = $data['bundle'];
  }

  // Validate entity_type and bundle
  if (empty($entity_type) || empty($entity_bundle)) {
    $context['results']['errors'][] = t('Entity Type and Bundle are required.') . $file;

    //$context['sandbox']['max'] = $context['sandbox']['progress'];
    $context['sandbox']['progress']++;
    $valid_entity_type = FALSE;
  }
  elseif (!empty($entity_type) && !empty($entity_bundle)) {

    // Check that entity type exists and it is a content instance
    $instances = $entityTypeManager
      ->getDefinitions();
    if (!(isset($instances[$entity_type]) && $instances[$entity_type] instanceof ContentEntityType)) {
      $context['results']['errors'][] = t('Entity type does not exist or it is not a content instance.') . $file;
      $context['sandbox']['progress']++;
      $valid_entity_type = FALSE;
    }
    else {

      // Verify that bundle exists
      if (!isset($entityBundles
        ->getBundleInfo($entity_type)[$entity_bundle])) {
        $context['results']['errors'][] = t('Bundle does not exist, please review the site configuration.') . $file;
        $context['sandbox']['progress']++;
        $valid_entity_type = FALSE;
      }
      else {

        // Check if there are data to be inserted.
        if (!isset($data['values'])) {
          $context['results']['errors'][] = t('Values to be imported not found, check the YAML file.') . $file;
          $context['sandbox']['progress']++;
          $valid_entity_type = FALSE;
        }
      }
    }
  }

  //Process data
  if ($valid_entity_type) {

    // Initialize array of elements to save.
    $entity_elements = [];

    // Get Entity Fields.
    $fields = array_filter($entityFieldManager
      ->getFieldDefinitions($entity_type, $entity_bundle), function ($field_definition) {
      return $field_definition;
    });
    foreach ($fields as $fieldID => $field) {
      $entity_elements[$field
        ->getName()] = $field
        ->getName();
    }

    // Get Entity Properties - to know the id and bundle fields.
    $properties = $entityTypeManager
      ->getDefinitions()[$entity_type]
      ->getKeys();

    // Remove property ID as we are gonna use UUID to avoid conflicts.
    unset($entity_elements[$properties['id']]);
    $entity_elements = array_filter($entity_elements);

    // Get arrays of content to be inserted.
    $data_value = $data['values'][0];

    // Remove vid to avoid conflicts w/revisions.
    unset($data_value['vid']);

    // Gather Content to import
    $record = [];

    // Content
    $data_value[$properties['bundle']] = $entity_bundle;
    foreach ($entity_elements as $elementID => $element) {

      // Set value for entity fields -  from import or default.
      if (isset($data_value[$element])) {
        $record['values'][$element] = $data_value[$element];

        // If it is entity reference get the id from the uuid
        $element_type = $fields[$element]
          ->getType();
        if ($element_type == "entity_reference" || $element_type == "image" || $element_type == "file") {

          // Get entity type
          $reference_type = $fields[$element]
            ->getSettings()['target_type'];

          // Loop all the values
          if (is_array($data_value[$element])) {
            foreach ($data_value[$element] as $er_key => $er_val) {
              $entity = $entityRepository
                ->loadEntityByUuid($reference_type, $er_val['target_id']);
              unset($record['values'][$element][$er_key]['target_id']);
              if (!empty($entity)) {
                $record['values'][$element][$er_key]['target_id'] = $entity
                  ->id();
              }
            }
          }
        }
      }
    }

    //$record['values']['path']['pathauto'] = TRUE;

    // Translations
    if (isset($data_value['translations']) && is_array($data_value['translations'])) {
      foreach ($data_value['translations'] as $translations) {
        $langcode = $translations['langcode'][0]['value'];

        // TODO --- verify if langcode is available in the site
        $translations[$properties['bundle']] = $entity_bundle;
        foreach ($entity_elements as $elementID => $element) {
          if (isset($translations[$element])) {

            // Only translatable elements for translations
            if ($fields[$elementID]
              ->isTranslatable() == TRUE) {
              $record['translations'][$langcode][$element] = $translations[$element];

              // If it is entity reference get the id from the uuid
              $element_type = $fields[$element]
                ->getType();
              if ($element_type == "entity_reference" || $element_type == "image" || $element_type == "file") {

                // Get entity type
                $reference_type = $fields[$element]
                  ->getSettings()['target_type'];

                // Loop all the values
                if (is_array($translations[$element])) {
                  foreach ($translations[$element] as $er_key => $er_val) {
                    $entity = $entityRepository
                      ->loadEntityByUuid($reference_type, $er_val['target_id']);
                    unset($record['translations'][$langcode][$element][$er_key]['target_id']);
                    if (!empty($entity)) {
                      $record['translations'][$langcode][$element][$er_key]['target_id'] = $entity
                        ->id();
                    }
                  }
                }
              }
            }

            // TODO --- Warning about untranslatable fields set on translations.
          }
        }

        //$record['translations'][$langcode]['path']['pathauto'] = TRUE;
      }
    }

    // Flag to detect if the entity exist or is a new one.
    $new_entity = TRUE;

    // Get the id of the the parent uuid.
    if (isset($record['values']['parent'])) {

      // Load the entity from the UUID
      $parent_uuid = $record['values']['parent'];
      $entity = $entityRepository
        ->loadEntityByUuid($entity_type, $parent_uuid);

      // Set parent only if the parent UUID exist.
      unset($record['values']['parent']);
      if (!empty($entity)) {

        // Get the  parent entity id and exchange it for the uuid.
        $record['values']['parent'] = $entity
          ->id();
      }
    }

    // Password exception for users
    if ($entity_type == 'user') {
      if (isset($record['values']['pass'][0]['value'])) {
        $user_password = $record['values']['pass'][0]['value'];
      }
      unset($record['values']['pass']);
    }

    // Check the UUID of the entity being imported.
    if (isset($record['values']['uuid'][0]['value'])) {

      // Load the entity from the UUID
      $uuid = $record['values']['uuid'][0]['value'];
      $entity = $entityRepository
        ->loadEntityByUuid($entity_type, $uuid);

      // If the entity exist then update it.
      if (!empty($entity)) {

        // Set the new entity flag as false.
        $new_entity = FALSE;
        foreach ($entity_elements as $elementID => $element) {
          if (isset($record['values'][$elementID])) {
            $entity
              ->set($elementID, $record['values'][$elementID]);
          }
          else {

            // Get default value.
            $default_value = $fields[$elementID]
              ->getDefaultValue($entity);
            $entity
              ->set($elementID, $default_value);
          }
        }
        $entity
          ->Save();
      }
    }

    //  Entity is new, add it.
    if ($new_entity) {
      $entity = $entityTypeManager
        ->getStorage($entity_type)
        ->create($record['values']);
      $entity
        ->Save();
    }

    // Password exception for users II
    if ($entity_type == 'user' && isset($user_password)) {
      $query = \Drupal::database()
        ->update('users_field_data');
      $query
        ->fields([
        'pass' => $user_password,
      ]);
      $query
        ->condition('uid', $entity
        ->id());
      $query
        ->execute();

      // Store the data for diff
      $new_entity = _content_sync_db_to_entity($entity_type, $entity_bundle, $entity
        ->id());

      // Create the name
      $name = $entity_type . "." . $entity_bundle . "." . $entity
        ->uuid();
      $new_entity['values'][0]['pass'][0]['value'] = $user_password;

      //Insert/Update Data
      $query = \Drupal::database()
        ->delete('cs_db_snapshot');
      $query
        ->condition('name', $name);
      $query
        ->execute();
      $query = \Drupal::database()
        ->insert('cs_db_snapshot');
      $query
        ->fields([
        'collection',
        'name',
        'data',
      ]);
      $query
        ->values([
        '',
        $name,
        serialize($new_entity),
      ]);
      $query
        ->execute();
    }

    // Include Translations
    $lang_default = $entity->langcode->value;

    // Remove translations if they are in the import data the they would be inserted.
    foreach ($entity
      ->getTranslationLanguages() as $langcode => $language) {

      // Verify that it is not the default langcode.
      if ($langcode != $lang_default) {
        $entity
          ->removeTranslation($langcode);
      }
    }
    if (isset($record['translations']) && is_array($record['translations'])) {

      // Commented because automatically pathauto has been set.
      // \Drupal::service('path.alias_storage')->save("/taxonomy/term/" . $term->id(), "/".$entity_bundle."/".$term->id(), $lancode_original);
      foreach ($record['translations'] as $langcode => $translation) {

        // Add Translation if it is not the default language
        if ($langcode != $lang_default) {
          $term_translation = $entity
            ->addTranslation($langcode);
          foreach ($translation as $itemID => $item) {
            $term_translation->{$itemID}
              ->setValue($item);
          }
          $term_translation
            ->save();

          // Commented because automatically pathauto has been set.
          // \Drupal::service('path.alias_storage')->save("/taxonomy/term/" . $term->id(), "/".$entity_bundle."/".$langcode.$term->id(), $langcode);
        }
      }
    }

    // Batch Context status.
    $context['results'][] = $entity
      ->uuid();
    $context['message'] = 'UUID - ' . $entity
      ->uuid();
    $context['sandbox']['progress']++;
  }
}