View source
<?php
use Drupal\Core\Entity\ContentEntityType;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Archiver\ArchiveTar;
function processContentBatch($data, &$context) {
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_number'] = 0;
if (isset($data['values'])) {
$context['sandbox']['max'] = (int) count($data['values']);
}
else {
$context['sandbox']['max'] = 1;
}
}
$data_entity = $data;
if (isset($data['values'])) {
$data_entity['values'][0] = $data['values'][$context['sandbox']['progress']];
}
_content_sync_entity_to_db($data_entity, '', $context);
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function processContentDirectoryBatch($files, $collection, $operation, &$context) {
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_number'] = 0;
$context['sandbox']['max'] = (int) count($files);
}
$file = $files[$context['sandbox']['progress']];
if ($file == "site.uuid") {
$context['results']['errors'][] = t('File Skipped ') . $file . t(' - site uuid should not be changed');
$context['message'] = "File Skipped: " . $file;
$context['sandbox']['progress']++;
$operation = Null;
}
$directory = content_sync_get_content_directory('sync');
if (!empty($collection)) {
$file_path = $directory . "/" . str_replace(".", "/", $collection) . "/" . $file . ".yml";
}
else {
$file_path = $directory . "/" . $file . ".yml";
}
$info = pathinfo($file_path);
if (strtolower($info["extension"]) != "yml") {
$context['results']['errors'][] = t("File Skipped: ") . $file;
$context['message'] = "File Skipped: " . $file;
$context['sandbox']['progress']++;
}
else {
list($entity_type, $entity_bundle, $entity_uuid) = explode('.', $file);
$current_user_uuid = \Drupal\user\Entity\User::load(\Drupal::currentUser()
->id())
->uuid();
if ($current_user_uuid == $entity_uuid) {
$context['results'][] = t('File Skipped ') . $file . t(' - current user info should not be updated');
$context['message'] = "File Skipped: " . $file;
$context['sandbox']['progress']++;
}
else {
$superadmin_user_uuid = \Drupal\user\Entity\User::load(1)
->uuid();
if ($superadmin_user_uuid == $entity_uuid) {
$context['results'][] = t('File Skipped ') . $file . t(' - super admin user info should not be updated');
$context['message'] = "File Skipped: " . $file;
$context['sandbox']['progress']++;
}
else {
if ($operation == "create" || $operation == "update") {
try {
$file_data = file_get_contents($file_path);
$data = Yaml::decode($file_data);
} catch (\Exception $e) {
$context['results']['errors'][] = t('Error: %message.', [
'%message' => $e
->getMessage(),
]);
$data = "";
}
if ($entity_uuid != $data['values'][0]['uuid'][0]['value'] || $entity_type != $data['entity_type'] || $entity_bundle != $data['bundle']) {
$context['results']['errors'][] = t('File Skipped ') . $file . t(" - Malformed file");
$context['message'] = "File Skipped: " . $file;
$context['sandbox']['progress']++;
}
else {
_content_sync_entity_to_db($data, $file, $context);
}
}
elseif ($operation == "delete") {
$context['results'][] = t("Content Entity Deleted: ") . $file;
$entityRepository = \Drupal::service('entity.repository');
$entity = $entityRepository
->loadEntityByUuid($entity_type, $entity_uuid);
if (!empty($entity)) {
$entity
->delete();
}
$context['message'] = "Entity Deleted: " . $file;
$context['sandbox']['progress']++;
}
}
}
}
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function _content_sync_entity_to_db($data, $file, &$context) {
$entityTypeManager = \Drupal::entityTypeManager();
$entityFieldManager = \Drupal::service('entity_field.manager');
$entityBundles = \Drupal::service("entity_type.bundle.info");
$entityRepository = \Drupal::service('entity.repository');
$valid_entity_type = TRUE;
if (isset($data['entity_type'])) {
$entity_type = $data['entity_type'];
}
if (isset($data['bundle'])) {
$entity_bundle = $data['bundle'];
}
if (empty($entity_type) || empty($entity_bundle)) {
$context['results']['errors'][] = t('Entity Type and Bundle are required.') . $file;
$context['sandbox']['progress']++;
$valid_entity_type = FALSE;
}
elseif (!empty($entity_type) && !empty($entity_bundle)) {
$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 {
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 {
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;
}
}
}
}
if ($valid_entity_type) {
$entity_elements = [];
$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();
}
$properties = $entityTypeManager
->getDefinitions()[$entity_type]
->getKeys();
unset($entity_elements[$properties['id']]);
$entity_elements = array_filter($entity_elements);
$data_value = $data['values'][0];
unset($data_value['vid']);
$record = [];
$data_value[$properties['bundle']] = $entity_bundle;
foreach ($entity_elements as $elementID => $element) {
if (isset($data_value[$element])) {
$record['values'][$element] = $data_value[$element];
$element_type = $fields[$element]
->getType();
if ($element_type == "entity_reference" || $element_type == "image" || $element_type == "file") {
$reference_type = $fields[$element]
->getSettings()['target_type'];
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();
}
}
}
}
}
}
if (isset($data_value['translations']) && is_array($data_value['translations'])) {
foreach ($data_value['translations'] as $translations) {
$langcode = $translations['langcode'][0]['value'];
$translations[$properties['bundle']] = $entity_bundle;
foreach ($entity_elements as $elementID => $element) {
if (isset($translations[$element])) {
if ($fields[$elementID]
->isTranslatable() == TRUE) {
$record['translations'][$langcode][$element] = $translations[$element];
$element_type = $fields[$element]
->getType();
if ($element_type == "entity_reference" || $element_type == "image" || $element_type == "file") {
$reference_type = $fields[$element]
->getSettings()['target_type'];
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();
}
}
}
}
}
}
}
}
}
$new_entity = TRUE;
if (isset($record['values']['parent'])) {
$parent_uuid = $record['values']['parent'];
$entity = $entityRepository
->loadEntityByUuid($entity_type, $parent_uuid);
unset($record['values']['parent']);
if (!empty($entity)) {
$record['values']['parent'] = $entity
->id();
}
}
if ($entity_type == 'user') {
if (isset($record['values']['pass'][0]['value'])) {
$user_password = $record['values']['pass'][0]['value'];
}
unset($record['values']['pass']);
}
if (isset($record['values']['uuid'][0]['value'])) {
$uuid = $record['values']['uuid'][0]['value'];
$entity = $entityRepository
->loadEntityByUuid($entity_type, $uuid);
if (!empty($entity)) {
$new_entity = FALSE;
foreach ($entity_elements as $elementID => $element) {
if (isset($record['values'][$elementID])) {
$entity
->set($elementID, $record['values'][$elementID]);
}
else {
$default_value = $fields[$elementID]
->getDefaultValue($entity);
$entity
->set($elementID, $default_value);
}
}
$entity
->Save();
}
}
if ($new_entity) {
$entity = $entityTypeManager
->getStorage($entity_type)
->create($record['values']);
$entity
->Save();
}
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();
$new_entity = _content_sync_db_to_entity($entity_type, $entity_bundle, $entity
->id());
$name = $entity_type . "." . $entity_bundle . "." . $entity
->uuid();
$new_entity['values'][0]['pass'][0]['value'] = $user_password;
$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();
}
$lang_default = $entity->langcode->value;
foreach ($entity
->getTranslationLanguages() as $langcode => $language) {
if ($langcode != $lang_default) {
$entity
->removeTranslation($langcode);
}
}
if (isset($record['translations']) && is_array($record['translations'])) {
foreach ($record['translations'] as $langcode => $translation) {
if ($langcode != $lang_default) {
$term_translation = $entity
->addTranslation($langcode);
foreach ($translation as $itemID => $item) {
$term_translation->{$itemID}
->setValue($item);
}
$term_translation
->save();
}
}
}
$context['results'][] = $entity
->uuid();
$context['message'] = 'UUID - ' . $entity
->uuid();
$context['sandbox']['progress']++;
}
}
function finishContentBatch($success, $results, $operations) {
if ($success) {
if (isset($results['errors'])) {
$errors = $results['errors'];
unset($results['errors']);
}
foreach ($results as $key => $result) {
if ($key != 'errors') {
\Drupal::logger('content_sync')
->notice('Processed UUID @title.', [
'@title' => $result,
'link' => 'Import',
]);
}
}
if (!empty($errors)) {
$errors = array_unique($errors);
foreach ($errors as $error) {
\Drupal::logger('content_sync')
->error($error, [
'link' => 'Import',
]);
}
drupal_set_message(\Drupal::translation()
->translate('The content was imported with errors. <a href=":content-overview">Logs</a>', [
':content-overview' => \Drupal::url('content.overview'),
]), 'warning');
\Drupal::logger('content_sync')
->warning('The content was imported with errors.', [
'link' => 'Import',
]);
}
else {
drupal_set_message(\Drupal::translation()
->translate('The content was imported successfully. <a href=":content-overview">Logs</a>', [
':content-overview' => \Drupal::url('content.overview'),
]));
\Drupal::logger('content_sync')
->notice('The content was imported successfully.', [
'link' => 'Import',
]);
}
}
else {
$message = t('Finished with an error. <a href=":content-overview">Logs</a>', [
':content-overview' => \Drupal::url('content.overview'),
]);
drupal_set_message($message);
\Drupal::logger('content_sync')
->error('Finished with an error.', [
'link' => 'Import',
]);
}
drupal_flush_all_caches();
}
function processContentExportFiles($files, &$context) {
$archiver = new ArchiveTar(file_directory_temp() . '/content.tar.gz', 'gz');
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_number'] = 0;
$context['sandbox']['max'] = count($files);
}
$entity_type = $files[$context['sandbox']['progress']]['entity_type'];
$entity_bundle = $files[$context['sandbox']['progress']]['entity_bundle'];
$entity_id = $files[$context['sandbox']['progress']]['entity_id'];
$entityTypeManager = \Drupal::entityTypeManager();
$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.') . $entity_type;
}
else {
$entity = _content_sync_db_to_entity($entity_type, $entity_bundle, $entity_id);
$name = $entity_type . "." . $entity_bundle . "." . $entity['values'][0]['uuid'][0]['value'];
$archiver
->addString("{$name}.yml", Yaml::encode($entity));
$context['message'] = $name;
$context['results'][] = $name;
}
$context['sandbox']['progress']++;
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function processContentSyncSnapshot($files, &$context) {
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_number'] = 0;
$context['sandbox']['max'] = count($files);
}
$entity_type = $files[$context['sandbox']['progress']]['entity_type'];
$entity_bundle = $files[$context['sandbox']['progress']]['entity_bundle'];
$entity_id = $files[$context['sandbox']['progress']]['entity_id'];
$entityTypeManager = \Drupal::entityTypeManager();
$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.') . $entity_type;
}
else {
$entity = _content_sync_db_to_entity($entity_type, $entity_bundle, $entity_id);
$name = $entity_type . "." . $entity_bundle . "." . $entity['values'][0]['uuid'][0]['value'];
$activeStorage = new Drupal\Core\Config\DatabaseStorage(\Drupal::database(), 'cs_db_snapshot');
$activeStorage
->write($name, $entity);
$context['message'] = $name;
$context['results'][] = $name;
}
$context['sandbox']['progress']++;
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function finishContentExportBatch($success, $results, $operations) {
if ($success) {
$errors = $results['errors'];
unset($results['errors']);
$results = array_unique($results);
foreach ($results as $key => $result) {
if ($key != 'errors') {
\Drupal::logger('content_sync')
->info('Processed UUID @title.', [
'@title' => $result,
'link' => 'Export',
]);
}
}
if (!empty($errors)) {
$errors = array_unique($errors);
foreach ($errors as $error) {
\Drupal::logger('content_sync')
->error($error);
}
drupal_set_message(\Drupal::translation()
->translate('The content was exported with errors. <a href=":content-overview">Logs</a>', [
':content-overview' => \Drupal::url('content.overview'),
]), 'warning');
\Drupal::logger('content_sync')
->warning('The content was exported with errors.', [
'link' => 'Export',
]);
}
else {
drupal_set_message(\Drupal::translation()
->translate('The content was exported successfully. <a href=":export-download">Download tar file</a>', [
':export-download' => \Drupal::url('content.export_download'),
]));
\Drupal::logger('content_sync')
->info('The content was exported successfully. <a href=":export-download">Download tar file</a>', [
':export-download' => \Drupal::url('content.export_download'),
'link' => 'Export',
]);
}
}
else {
$message = t('Finished with an error.<a href=":content-overview">Logs</a>', [
':content-overview' => \Drupal::url('content.overview'),
]);
drupal_set_message($message);
\Drupal::logger('content_sync')
->error('Finished with an error.', [
'link' => 'Export',
]);
}
}
function _content_sync_db_to_entity($entity_type, $entity_bundle, $entity_id) {
$entityTypeManager = \Drupal::entityTypeManager();
$entityFieldManager = \Drupal::service('entity_field.manager');
$fields = array_filter($entityFieldManager
->getFieldDefinitions($entity_type, $entity_bundle), function ($field_definition) {
return $field_definition;
});
$entity_elements = [];
foreach ($fields as $fieldID => $field) {
$entity_elements[$field
->getName()] = $field
->getName();
}
$properties = $entityTypeManager
->getDefinitions()[$entity_type]
->getKeys();
$entity_data = $entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$entity = [];
$entity['entity_type'] = $entity_type;
$entity['bundle'] = $entity_bundle;
unset($entity_elements[$properties['id']]);
unset($entity_elements[$properties['bundle']]);
unset($entity_elements['vid']);
$entity_elements = array_filter($entity_elements);
foreach ($entity_elements as $elementID => $element) {
if ($element == 'parent') {
$parent = $entityTypeManager
->getStorage($entity_type)
->loadParents($entity_id);
$parent = reset($parent);
if (!empty($parent)) {
$entity['values'][0][$element] = $parent
->uuid();
}
}
else {
$entity['values'][0][$element] = $entity_data
->get($element)
->getValue();
}
$element_type = $entity_data
->get($element)
->getFieldDefinition()
->getType();
if ($element_type == "entity_reference" || $element_type == "image" || $element_type == "file") {
if ($entity_data
->get($element)->entity) {
$reference_type = $entity_data
->get($element)->entity
->getEntityType()
->id();
foreach ($entity_data
->get($element)
->getValue() as $er_key => $er_val) {
$entity['values'][0][$element][$er_key]['target_id'] = $entityTypeManager
->getStorage($reference_type)
->load($er_val['target_id'])
->uuid();
}
}
}
}
if ($entity_type != "file") {
$internal_path = "/" . $entity_data
->toUrl()
->getInternalPath();
$alias = \Drupal::service('path.alias_manager')
->getAliasByPath($internal_path);
if ($internal_path != $alias) {
$entity['values'][0]['path'] = $alias;
}
}
$lang_default = $entity['values'][0]['langcode'][0]['value'];
foreach ($entity_data
->getTranslationLanguages() as $langcode => $language) {
$c = 0;
if ($entity_data
->hasTranslation($langcode)) {
$entity_data_translation = $entity_data
->getTranslation($langcode);
if ($langcode != $lang_default) {
foreach ($entity_elements as $elementID => $element) {
if ($fields[$elementID]
->isTranslatable() == TRUE) {
$entity['values'][0]['translations'][$c][$element] = $entity_data_translation
->get($element)
->getValue();
$element_type = $entity_data_translation
->get($element)
->getFieldDefinition()
->getType();
if ($element_type == "entity_reference" || $element_type == "image" || $element_type == "file") {
if ($entity_data_translation
->get($element)->entity) {
$reference_type = $entity_data_translation
->get($element)->entity
->getEntityType()
->id();
foreach ($entity_data_translation
->get($element)
->getValue() as $er_key => $er_val) {
$entity['values'][0]['translations'][$c][$element][$er_key]['target_id'] = $entityTypeManager
->getStorage($reference_type)
->load($er_val['target_id'])
->uuid();
}
}
}
}
}
}
}
}
return $entity;
}
function generateSiteUUIDFile($data, &$context) {
$archiver = new ArchiveTar(file_directory_temp() . '/content.tar.gz', 'gz');
$site_config = \Drupal::config('system.site');
$site_uuid_source = $site_config
->get('uuid');
$entity['site_uuid'] = $site_uuid_source;
$name = "site.uuid";
$archiver
->addString("{$name}.yml", Yaml::encode($entity));
if ($data == 'snapshot') {
$activeStorage = new Drupal\Core\Config\DatabaseStorage(\Drupal::database(), 'cs_db_snapshot');
$activeStorage
->write($name, $entity);
}
$context['message'] = $name;
$context['results'][] = $name;
$context['finished'] = 1;
}