class ContentImporter in Content Synchronization 8.2
Same name and namespace in other branches
- 3.0.x src/Importer/ContentImporter.php \Drupal\content_sync\Importer\ContentImporter
Hierarchy
- class \Drupal\content_sync\Importer\ContentImporter implements ContentImporterInterface uses SerializedColumnNormalizerTrait
Expanded class hierarchy of ContentImporter
1 string reference to 'ContentImporter'
1 service uses ContentImporter
File
- src/
Importer/ ContentImporter.php, line 10
Namespace
Drupal\content_sync\ImporterView source
class ContentImporter implements ContentImporterInterface {
use SerializedColumnNormalizerTrait;
protected $format = 'yaml';
protected $updateEntities = TRUE;
protected $context = [];
/**
* @var \Symfony\Component\Serializer\Serializer
*/
protected $serializer;
/**
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* ContentImporter constructor.
*/
public function __construct(Serializer $serializer, EntityTypeManagerInterface $entity_type_manager) {
$this->serializer = $serializer;
$this->entityTypeManager = $entity_type_manager;
}
public function importEntity($decoded_entity, $context = []) {
$context = $this->context + $context;
if (!empty($context['entity_type'])) {
$entity_type_id = $context['entity_type'];
}
elseif (!empty($decoded_entity['_content_sync']['entity_type'])) {
$entity_type_id = $decoded_entity['_content_sync']['entity_type'];
}
else {
return NULL;
}
// Replace a menu link to a node with an actual one.
if ($entity_type_id == 'menu_link_content' && !empty($decoded_entity["_content_sync"]["menu_entity_link"])) {
$decoded_entity = $this
->alterMenuLink($decoded_entity);
}
$entity_type = $this->entityTypeManager
->getDefinition($entity_type_id);
//Exception for parent null -- allowing the term to be displayed on the taxonomy list.
if ($entity_type_id == 'taxonomy_term') {
if (empty($decoded_entity['parent'])) {
$decoded_entity['parent']['target_id'] = 0;
}
}
//Get Translations before denormalize
if (!empty($decoded_entity['_translations'])) {
$entity_translations = $decoded_entity['_translations'];
}
$entity = $this->serializer
->denormalize($decoded_entity, $entity_type
->getClass(), $this->format, $context);
if (!empty($entity)) {
// Prevent Anonymous User from being saved.
if ($entity_type_id == 'user' && !$entity
->isNew() && (int) $entity
->id() === 0) {
return $entity;
}
$entity = $this
->syncEntity($entity);
}
// Include Translations
if ($entity) {
if (isset($entity_translations) && is_array($entity_translations)) {
$this
->updateTranslation($entity, $entity_type, $entity_translations, $context);
}
}
return $entity;
}
/**
* Updates translations.
*
* @param $entity
* An entity object.
* @param \Drupal\Core\Entity\ContentEntityType $entity_type
* A ContentEntityType object.
* @param array $entity_translations
* An array of translations.
* @param $context
* The batch context.
*/
protected function updateTranslation(&$entity, $entity_type, $entity_translations, $context) {
foreach ($entity_translations as $langcode => $translation) {
// Denormalize.
$translation = $this->serializer
->denormalize($translation, $entity_type
->getClass(), $this->format, $context);
// If an entity has a translation - update one, otherwise - add a new one.
$entity_translation = $entity
->hasTranslation($langcode) ? $entity
->getTranslation($langcode) : $entity
->addTranslation($langcode);
// Get fields definitions.
$fields = $translation
->getFieldDefinitions();
foreach ($translation as $itemID => $item) {
if ($entity_translation
->hasField($itemID)) {
if ($fields[$itemID]
->isTranslatable() == TRUE) {
$entity_translation->{$itemID}
->setValue($item
->getValue());
}
}
}
// Avoid issues updating revisions.
if ($entity_translation
->getEntityType()
->hasKey('revision')) {
$entity_translation
->updateLoadedRevisionId();
$entity_translation
->setNewRevision(FALSE);
}
// Save the entity translation.
$entity_translation
->save();
}
}
/**
* Replaces a link to a node with an actual one.
*
* @param array $decoded_entity
* Array of entity values.
*
* @return array
* Array of entity values with the link values changed.
*/
protected function alterMenuLink(array $decoded_entity) {
$referenced_entity_uuid = reset($decoded_entity["_content_sync"]["menu_entity_link"]);
$referenced_entity_type = key($decoded_entity["_content_sync"]["menu_entity_link"]);
if (!preg_match('/^internal:/', $decoded_entity["link"][0]["uri"]) && ($referenced_entity = \Drupal::service('entity.repository')
->loadEntityByUuid($referenced_entity_type, $referenced_entity_uuid))) {
$url = $referenced_entity
->toUrl();
// Convert entity URIs to the entity scheme, if the path matches a route
// of the form "entity.$entity_type_id.canonical".
// @see \Drupal\Core\Url::fromEntityUri()
if ($url
->isRouted()) {
$route_name = $url
->getRouteName();
foreach (array_keys($this->entityTypeManager
->getDefinitions()) as $entity_type_id) {
if ($route_name == "entity.{$entity_type_id}.canonical" && isset($url
->getRouteParameters()[$entity_type_id])) {
$uri = "entity:{$entity_type_id}/" . $url
->getRouteParameters()[$entity_type_id];
}
}
}
else {
//$uri = $url->toUriString();
$uri = $url
->getUri();
}
$decoded_entity["link"][0]["uri"] = $uri;
}
return $decoded_entity;
}
/**
* @return string
*/
public function getFormat() {
return $this->format;
}
/**
* Synchronize a given entity.
*
* @param ContentEntityInterface $entity
* The entity to update.
*
* @return ContentEntityInterface
* The updated entity
*/
protected function syncEntity(ContentEntityInterface $entity) {
$preparedEntity = $this
->prepareEntity($entity);
if ($this
->validateEntity($preparedEntity)) {
$preparedEntity
->save();
return $preparedEntity;
}
elseif (!$preparedEntity
->isNew()) {
return $preparedEntity;
}
return NULL;
}
/**
* Serializes fields which have to be stored serialized.
*
* @param $entity
* The entity to update.
*
* @return mixed
* The entity with the fields being serialized.
*/
protected function processSerializedFields($entity) {
foreach ($entity
->getTypedData() as $name => $field_items) {
foreach ($field_items as $field_item) {
// The field to be stored in a serialized way.
if (!empty($this
->getCustomSerializedPropertyNames($field_item))) {
$unserialized_value = $field_item
->get('value')
->getValue();
$entity
->set($name, is_array($unserialized_value) ? serialize($unserialized_value) : $unserialized_value);
}
}
}
return $entity;
}
/**
* {@inheritdoc}
*/
public function prepareEntity(ContentEntityInterface $entity) {
$uuid = $entity
->uuid();
$original_entity = $this->entityTypeManager
->getStorage($entity
->getEntityTypeId())
->loadByProperties([
'uuid' => $uuid,
]);
if (!empty($original_entity)) {
$original_entity = reset($original_entity);
if (!$this->updateEntities) {
return $original_entity;
}
// Overwrite the received properties.
if (!empty($entity->_restSubmittedFields)) {
foreach ($entity->_restSubmittedFields as $field_name) {
if ($this
->isValidEntityField($original_entity, $entity, $field_name)) {
$original_entity
->set($field_name, $entity
->get($field_name)
->getValue());
}
}
}
return $this
->processSerializedFields($original_entity);
}
$duplicate = $entity
->createDuplicate();
$entity_type = $entity
->getEntityType();
$duplicate->{$entity_type
->getKey('uuid')}->value = $uuid;
return $this
->processSerializedFields($duplicate);
}
/**
* Checks if the entity field needs to be synchronized.
*
* @param ContentEntityInterface $original_entity
* The original entity.
* @param ContentEntityInterface $entity
* The entity.
* @param string $field_name
* The field name.
*
* @return bool
* True if the field needs to be synced.
*/
protected function isValidEntityField(ContentEntityInterface $original_entity, ContentEntityInterface $entity, $field_name) {
$valid = TRUE;
$entity_keys = $entity
->getEntityType()
->getKeys();
// Check if the target entity has the field.
if (!$entity
->hasField($field_name)) {
$valid = FALSE;
}
elseif (in_array($field_name, $entity_keys, TRUE)) {
// Unchanged values for entity keys don't need access checking.
if ($original_entity
->get($field_name)
->getValue() === $entity
->get($field_name)
->getValue() || isset($entity_keys['langcode']) && $field_name === $entity_keys['langcode'] && $entity
->get($field_name)
->isEmpty() || $field_name === $entity
->getEntityType()
->getKey('id') || $entity
->getEntityType()
->isRevisionable() && $field_name === $entity
->getEntityType()
->getKey('revision')) {
$valid = FALSE;
}
}
return $valid;
}
/**
* {@inheritdoc}
*/
public function validateEntity(ContentEntityInterface $entity) {
$reflection = new \ReflectionClass($entity);
$valid = TRUE;
if ($reflection
->implementsInterface('\\Drupal\\user\\UserInterface')) {
$validations = $entity
->validate();
if (count($validations)) {
/**
* @var ConstraintViolation $validation
*/
foreach ($validations as $validation) {
if (!empty($this
->getContext()['skipped_constraints']) && in_array(get_class($validation
->getConstraint()), $this
->getContext()['skipped_constraints'])) {
continue;
}
$valid = FALSE;
\Drupal::logger('content_sync')
->error($validation
->getMessage());
}
}
}
return $valid;
}
/**
* @return array
*/
public function getContext() {
return $this->context;
}
/**
* @param array $context
*/
public function setContext($context) {
$this->context = $context;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ContentImporter:: |
protected | property | ||
ContentImporter:: |
protected | property | ||
ContentImporter:: |
protected | property | ||
ContentImporter:: |
protected | property | ||
ContentImporter:: |
protected | property | ||
ContentImporter:: |
protected | function | Replaces a link to a node with an actual one. | |
ContentImporter:: |
public | function | ||
ContentImporter:: |
public | function | ||
ContentImporter:: |
public | function |
Overrides ContentImporterInterface:: |
|
ContentImporter:: |
protected | function | Checks if the entity field needs to be synchronized. | |
ContentImporter:: |
public | function | ||
ContentImporter:: |
protected | function | Serializes fields which have to be stored serialized. | |
ContentImporter:: |
public | function | ||
ContentImporter:: |
protected | function | Synchronize a given entity. | |
ContentImporter:: |
protected | function | Updates translations. | |
ContentImporter:: |
public | function | ||
ContentImporter:: |
public | function | ContentImporter constructor. | |
SerializedColumnNormalizerTrait:: |
protected | function | Checks if there is a serialized string for a column. | |
SerializedColumnNormalizerTrait:: |
protected | function | Checks if the data contains string value for serialize column. | |
SerializedColumnNormalizerTrait:: |
protected | function | Gets the names of all properties the plugin treats as serialized data. | |
SerializedColumnNormalizerTrait:: |
protected | function | Gets the names of all serialized properties. |