View source
<?php
namespace Drupal\content_synchronizer\Processors\Entity;
use Drupal\content_synchronizer\Events\ImportEvent;
use Drupal\content_synchronizer\Processors\ExportEntityWriter;
use Drupal\content_synchronizer\Processors\ExportProcessor;
use Drupal\content_synchronizer\Processors\ImportProcessor;
use Drupal\content_synchronizer\Service\EntityPublisher;
use Drupal\content_synchronizer\Service\GlobalReferenceManager;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Entity\Entity;
use Drupal\Core\Entity\ContentEntityType;
use Drupal\content_synchronizer\Processors\Type\TypeProcessorPluginManager;
class EntityProcessorBase extends PluginBase implements EntityProcessorInterface {
const KEY_TRANSLATIONS = 'translations';
const EXPORT_HOOK = 'content_synchronizer_export_data';
const IMPORT_HOOK = 'content_synchronizer_import_entity';
protected $propertyIdsNotToExport = [
'status',
'revision',
'revision_timestamp',
'revision_uid',
'revision_log',
'revision_translation_affected',
'created',
'id',
];
protected $globalReferenceManager;
protected $typeProcessorManager;
protected $entityProcessorManager;
protected $entityPublisher;
protected $entityType;
public final function export(Entity $entityToExport) {
if ($entityToExport
->getEntityType() instanceof ContentEntityType) {
$gid = $this
->getEntityGlobalReference($entityToExport);
if (isset($entityToExport->contentSynchronizerIsExporting)) {
return $gid;
}
else {
$dataToExport = [];
foreach ($this
->getEntityTranslations($entityToExport) as $languageId => $translation) {
$translation->contentSynchronizerIsExporting = TRUE;
$dataToExport[self::KEY_TRANSLATIONS][$languageId] = $this
->getDataToExport($translation);
if (method_exists($translation, 'getChangedTime')) {
$dataToExport[self::KEY_TRANSLATIONS][$languageId][ExportEntityWriter::FIELD_CHANGED] = $translation
->getChangedTime();
}
\Drupal::moduleHandler()
->alter(self::EXPORT_HOOK, $dataToExport[self::KEY_TRANSLATIONS][$languageId], $translation);
}
if (!empty($dataToExport)) {
$entityToExport->contentSynchronizerGid = $dataToExport[ExportEntityWriter::FIELD_GID] = $gid;
$dataToExport[ExportEntityWriter::FIELD_UUID] = $entityToExport
->uuid();
ExportProcessor::getCurrentExportProcessor()
->getWriter()
->write($entityToExport, $dataToExport);
return $gid;
}
}
}
return FALSE;
}
public function getDefaultLanguageData(array $data, $filterOnEntityDefinition = TRUE) {
if (count($data[self::KEY_TRANSLATIONS]) > 1) {
foreach ($data[self::KEY_TRANSLATIONS] as $languageId => $translationData) {
if (array_key_exists('default_langcode', $translationData) && $translationData['default_langcode'][0]['value'] == 1) {
return $translationData;
}
}
}
$defaultData = reset($data[self::KEY_TRANSLATIONS]);
if ($filterOnEntityDefinition) {
$fieldDefinitions = \Drupal::entityTypeManager()
->getStorage($this
->getGlobalReferenceManager()
->getEntityTypeFromGid($data[ExportEntityWriter::FIELD_GID]))
->getFieldStorageDefinitions();
return array_intersect_key($defaultData, $fieldDefinitions);
}
else {
return $defaultData;
}
}
protected function getEntityTranslations(Entity $entity) {
$translations = [];
foreach ($entity
->getTranslationLanguages() as $languageId => $data) {
$translations[$languageId] = \Drupal::service('entity.repository')
->getTranslationFromContext($entity, $languageId);
}
return $translations;
}
protected function createNewTranslation($languageId, Entity $existingEntity, array $dataToImport = []) {
if ($existingEntity
->isTranslatable()) {
$translation = $existingEntity
->addTranslation($languageId);
$translation->uuid = \Drupal::service('uuid')
->generate();
return $translation;
}
return NULL;
}
public final function import(array $dataToImport) {
$gid = $dataToImport[ExportEntityWriter::FIELD_GID];
$uuid = $dataToImport[ExportEntityWriter::FIELD_UUID];
$import = ImportProcessor::getCurrentImportProcessor()
->getImport();
if ($import
->gidHasAlreadyBeenImported($gid)) {
return $this
->getGlobalReferenceManager()
->getEntityByGid($gid);
}
ImportProcessor::getCurrentImportProcessor()
->getImport()
->tagHasImporting($gid);
if ($existingEntity = $this
->getGlobalReferenceManager()
->getExistingEntityByGidAndUuid($gid, $uuid)) {
if ($existingEntity) {
$backup = clone $existingEntity;
}
if ($entity = $this
->getEntityToImport($dataToImport, $existingEntity)) {
$this
->setChangedTime($entity, $dataToImport);
$this
->getEntityPublisher()
->saveEntity($entity, $gid, $backup, $dataToImport);
}
}
else {
if ($entity = $this
->getEntityToImport($dataToImport, NULL)) {
$this
->checkBundle($entity, TRUE);
$this
->setChangedTime($entity, $dataToImport);
$this
->getEntityPublisher()
->saveEntity($entity, $gid, NULL, $dataToImport);
$this
->getGlobalReferenceManager()
->createGlobalEntityByImportingEntityAndGid($entity, $gid);
}
}
if ($entity) {
ImportProcessor::getCurrentImportProcessor()
->getImport()
->tagHasImported($gid);
$this
->onEntityImported($gid, $entity);
}
return $entity;
}
private function checkBundle(\Drupal\Core\Entity\Entity $entity, $force_create = FALSE) {
$bundle_type = $entity
->getEntityType()
->getBundleEntityType();
if ($bundle_type == '') {
return;
}
$bundle_name = $entity
->bundle();
$bundle = \Drupal::entityTypeManager()
->getStorage($bundle_type)
->load($bundle_name);
if ($bundle == NULL && $force_create === TRUE) {
$this
->createBundle($bundle_type, $bundle_name);
}
}
private function createBundle($bundle_type, $bundle_name) {
$storage = \Drupal::entityTypeManager()
->getStorage($bundle_type);
$data = [];
switch ($bundle_type) {
case "taxonomy_vocabulary":
$data = [
'vid' => $bundle_name,
'name' => $bundle_name,
'weight' => 0,
];
break;
case "media_type":
$data = [
'id' => $bundle_name,
'label' => $bundle_name,
'status' => 1,
];
break;
case "paragraphs_type":
$data = [
'id' => $bundle_name,
'label' => $bundle_name,
];
break;
case "node_type":
$data = [
'type' => $bundle_name,
'name' => $bundle_name,
];
break;
}
$bundle = $storage
->create($data);
$bundle
->save();
}
protected function setChangedTime(Entity $entity, array $dataToImport) {
$dataToImport = array_key_exists('translations', $dataToImport) ? $dataToImport['translations'][$entity
->language()
->getId()] : $dataToImport;
if (array_key_exists(ExportEntityWriter::FIELD_CHANGED, $dataToImport)) {
if (method_exists($entity, 'setChangedTime')) {
$entity
->setChangedTime($dataToImport[ExportEntityWriter::FIELD_CHANGED]);
}
}
}
protected function onEntityImported($gid, Entity $entity) {
$dispatcher = \Drupal::service('event_dispatcher');
$event = new ImportEvent();
$event
->setEntity($entity);
$event
->setGid($gid);
$dispatcher
->dispatch(ImportEvent::ON_ENTITY_IMPORTER, $event);
}
public function getDataToExport(Entity $entityToExport) {
$dataToExport = [];
$contentEntityTypeKeys = $entityToExport
->getEntityType()
->getKeys();
$propertyIdsNotToExport = $this
->getPropertiesIdsNotToExportList();
$propertyIdsNotToExport += array_intersect_key($contentEntityTypeKeys, array_flip($propertyIdsNotToExport));
foreach ($contentEntityTypeKeys as $key => $name) {
if (!in_array($name, $propertyIdsNotToExport)) {
if (method_exists($entityToExport, $key)) {
$dataToExport[$name] = $entityToExport
->{$key}();
}
}
}
foreach ($entityToExport
->getTypedData()
->getProperties() as $propertyId => $propertyData) {
if (!in_array($propertyId, $propertyIdsNotToExport)) {
if ($plugin = $this
->getTypeProcessorManager()
->getInstanceByFieldType(get_class($propertyData))) {
if ($fieldDataToExport = $plugin
->getExportedData($entityToExport
->get($propertyId))) {
$dataToExport[$propertyId] = $fieldDataToExport;
}
}
}
}
return $dataToExport;
}
public function getEntityToImport(array $data, Entity $entityToImport = NULL) {
if ($entityToImport) {
$backup = clone $entityToImport;
}
if (is_null($entityToImport)) {
try {
$typeId = $this
->getGlobalReferenceManager()
->getEntityTypeFromGid($data[ExportEntityWriter::FIELD_GID]);
$defaultData = $this
->getDefaultLanguageData($data);
$typeManager = \Drupal::entityTypeManager()
->getDefinition($typeId);
$bundleKey = $typeManager
->getKey('bundle');
$entityFieldManager = \Drupal::service('entity_field.manager');
$baseDefinitions = $entityFieldManager
->getFieldDefinitions($typeId, $data[$bundleKey]);
$createData = array_intersect_key($defaultData, $baseDefinitions);
$entityToImport = \Drupal::entityTypeManager()
->getStorage($typeId)
->create($createData);
} catch (\Exception $e) {
\Drupal::messenger()
->addError('Import Process : ' . $e
->getMessage() . ' in "' . __METHOD__ . '()"');
return NULL;
}
}
$propertyIdsNotToImport = $this
->getPropertiesIdsNotToExportList();
$alreadyExistingEntityTranslations = $this
->getEntityTranslations($entityToImport);
foreach ($data[self::KEY_TRANSLATIONS] as $languageId => $translationData) {
if (!array_key_exists($languageId, $alreadyExistingEntityTranslations)) {
if ($translation = $this
->createNewTranslation($languageId, $entityToImport, $translationData)) {
$alreadyExistingEntityTranslations[$languageId] = $translation;
}
else {
continue;
}
}
$entityToUpdate = $alreadyExistingEntityTranslations[$languageId];
foreach ($entityToUpdate
->getTypedData()
->getProperties() as $propertyId => $propertyData) {
if (!in_array($propertyId, $propertyIdsNotToImport)) {
if ($plugin = $this
->getTypeProcessorManager()
->getInstanceByFieldType(get_class($propertyData))) {
$plugin
->initImportedEntity($entityToUpdate, $propertyId, $translationData);
}
}
}
if ($entityToImport
->language()
->getId() != $entityToUpdate
->language()
->getId()) {
$this
->setChangedTime($entityToImport, $translationData);
$this
->getEntityPublisher()
->saveEntity($entityToUpdate, NULL, $backup, $translationData);
}
}
return $entityToImport;
}
public function getPropertiesIdsNotToExportList() {
return $this->propertyIdsNotToExport;
}
protected function getEntityGlobalReference(Entity $entityToExport) {
$gid = $this
->getGlobalReferenceManager()
->getEntityGlobalId($entityToExport);
if (!$gid) {
$gid = $this
->getGlobalReferenceManager()
->createEntityGlobalId($entityToExport);
}
return $gid;
}
protected final function getGlobalReferenceManager() {
if (!isset($this->globalReferenceManager)) {
$this->globalReferenceManager = \Drupal::service(GlobalReferenceManager::SERVICE_NAME);
}
return $this->globalReferenceManager;
}
protected function getTypeProcessorManager() {
if (!$this->typeProcessorManager) {
$this->typeProcessorManager = \Drupal::service(TypeProcessorPluginManager::SERVICE_NAME);
}
return $this->typeProcessorManager;
}
protected function getEntityProcessorManager() {
if (!$this->entityProcessorManager) {
$this->entityProcessorManager = \Drupal::service(EntityProcessorPluginManager::SERVICE_NAME);
}
return $this->entityProcessorManager;
}
public function getEntityType() {
return $this->entityType;
}
public function setEntityType($entityType) {
$this->entityType = $entityType;
}
public function getEntityPublisher() {
if (is_null($this->entityPublisher)) {
$this->entityPublisher = \Drupal::service(EntityPublisher::SERVICE_NAME);
}
return $this->entityPublisher;
}
}