View source
<?php
namespace Drupal\acquia_contenthub\EventSubscriber\Cdf;
use Acquia\ContentHubClient\CDF\CDFObject;
use Drupal\acquia_contenthub\AcquiaContentHubEvents;
use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\Event\CreateCdfEntityEvent;
use Drupal\acquia_contenthub\Event\ExcludeEntityFieldEvent;
use Drupal\acquia_contenthub\Event\ParseCdfEntityEvent;
use Drupal\acquia_contenthub\Event\SerializeAdditionalMetadataEvent;
use Drupal\acquia_contenthub\Event\SerializeCdfEntityFieldEvent;
use Drupal\acquia_contenthub\Event\UnserializeAdditionalMetadataEvent;
use Drupal\acquia_contenthub\Event\UnserializeCdfEntityFieldEvent;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\depcalc\DependencyCalculator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ContentEntityHandler implements EventSubscriberInterface {
protected $calculator;
protected $configFactory;
protected $dispatcher;
protected $clientFactory;
protected $languageManager;
public function __construct(DependencyCalculator $calculator, ConfigFactoryInterface $config_factory, EventDispatcherInterface $dispatcher, ClientFactory $factory) {
$this->calculator = $calculator;
$this->configFactory = $config_factory;
$this->dispatcher = $dispatcher;
$this->clientFactory = $factory;
$this->languageManager = \Drupal::languageManager();
}
public static function getSubscribedEvents() {
$events[AcquiaContentHubEvents::CREATE_CDF_OBJECT][] = [
'onCreateCdf',
100,
];
$events[AcquiaContentHubEvents::PARSE_CDF][] = [
'onParseCdf',
100,
];
return $events;
}
public function onCreateCdf(CreateCdfEntityEvent $event) {
$entity = $event
->getEntity();
if (!$entity instanceof ContentEntityInterface) {
return;
}
$settings = $this->clientFactory
->getSettings();
$cdf = new CDFObject('drupal8_content_entity', $entity
->uuid(), date('c'), date('c'), $settings
->getUuid());
$metadata = [
'default_language' => $entity
->language()
->getId(),
];
if ($dependencies = $event
->getDependencies()) {
$metadata['dependencies'] = $dependencies;
}
$cdf
->setMetadata($metadata);
$fields = [];
foreach ($entity as $field_name => $field) {
$exclude_field_event = new ExcludeEntityFieldEvent($entity, $field_name, $field);
$this->dispatcher
->dispatch(AcquiaContentHubEvents::EXCLUDE_CONTENT_ENTITY_FIELD, $exclude_field_event);
if ($exclude_field_event
->isExcluded()) {
continue;
}
$field_event = new SerializeCdfEntityFieldEvent($entity, $field_name, $field, $cdf);
$this->dispatcher
->dispatch(AcquiaContentHubEvents::SERIALIZE_CONTENT_ENTITY_FIELD, $field_event);
$fields[$field_name] = $field_event
->getFieldData();
}
$metadata = $cdf
->getMetadata();
$metadata['data'] = base64_encode(json_encode($fields));
$cdf
->setMetadata($metadata);
$serialize_additional_metadata_event = new SerializeAdditionalMetadataEvent($entity, $cdf);
$this->dispatcher
->dispatch(AcquiaContentHubEvents::SERIALIZE_ADDITIONAL_METADATA, $serialize_additional_metadata_event);
$cdf = $serialize_additional_metadata_event
->getCdf();
$event
->addCdf($cdf);
}
public function onParseCdf(ParseCdfEntityEvent $event) {
$cdf = $event
->getCdf();
if ($cdf
->getType() !== 'drupal8_content_entity') {
return;
}
$default_language = $cdf
->getMetadata()['default_language'];
if (empty($default_language)) {
throw new \Exception(sprintf("No language available for entity with UUID %s.", $cdf
->getUuid()));
}
$langcodes = $cdf
->getMetadata()['languages'];
$entity_values = [];
$entity_type_id = $cdf
->getAttribute('entity_type')
->getValue()['und'];
$entity_type = $this
->getEntityTypeManager()
->getDefinition($entity_type_id);
$langcode_key = $entity_type
->hasKey('langcode') ? $entity_type
->getKey('langcode') : 'langcode';
$bundle_id = $cdf
->getAttribute('bundle')
->getValue()['und'];
foreach (json_decode(base64_decode($cdf
->getMetadata()['data']), TRUE) as $field_name => $field) {
if ($field_name === 'uuid' && $event
->hasEntity() && $cdf
->getUuid() !== $event
->getEntity()
->uuid()) {
continue;
}
$unserialize_event = new UnserializeCdfEntityFieldEvent($entity_type, $bundle_id, $field_name, $field, $cdf
->getMetadata()['field'][$field_name], $event
->getStack());
$this->dispatcher
->dispatch(AcquiaContentHubEvents::UNSERIALIZE_CONTENT_ENTITY_FIELD, $unserialize_event);
$value = $unserialize_event
->getValue();
$entity_values = NestedArray::mergeDeep($entity_values, $value);
}
if (!$event
->isMutable()) {
return;
}
if (!$event
->hasEntity()) {
if (!array_key_exists($langcode_key, $entity_values[$default_language])) {
$entity_values[$default_language][$langcode_key] = $default_language;
}
$formatted_default_language = $this
->removeChannelId($default_language);
if ($formatted_default_language !== $default_language) {
$entity_values[$formatted_default_language] = $entity_values[$default_language];
$entity_values[$formatted_default_language][$langcode_key] = $formatted_default_language;
unset($entity_values[$default_language]);
}
$entity = $this
->getEntityTypeManager()
->getStorage($entity_type_id)
->create($entity_values[$formatted_default_language]);
unset($entity_values[$formatted_default_language]);
}
else {
$entity = $event
->getEntity();
}
foreach ($entity_values as $langcode => $values) {
if (!in_array($langcode, $langcodes)) {
continue;
}
$langcode = $this
->removeChannelId($langcode);
$values[$langcode_key] = $langcode;
if (isset($values['content_translation_source'])) {
$values['content_translation_source'] = $this
->removeChannelId($values['content_translation_source']);
}
if (!$entity
->hasTranslation($langcode)) {
try {
$entity
->addTranslation($langcode, $values);
} catch (\InvalidArgumentException $ex) {
throw new \Exception(sprintf("Cannot add translation '%s' for Entity (%s, %s): %s.", $langcode, $entity
->getEntityTypeId(), $entity
->uuid(), $ex
->getMessage()));
}
}
else {
$entity = $entity
->getTranslation($langcode);
foreach ($entity as $field_name => $field) {
if (isset($values[$field_name])) {
$entity
->set($field_name, $values[$field_name]);
}
}
}
}
$unserialize_additional_metadata_event = new UnserializeAdditionalMetadataEvent($entity, $cdf);
$this->dispatcher
->dispatch(AcquiaContentHubEvents::UNSERIALIZE_ADDITIONAL_METADATA, $unserialize_additional_metadata_event);
$entity = $unserialize_additional_metadata_event
->getEntity();
$event
->setEntity($entity);
}
protected function getEntityTypeManager() : EntityTypeManagerInterface {
return \Drupal::entityTypeManager();
}
protected function removeChannelId(string $langcode) {
$pattern = '/(\\w+)_(\\d+)/i';
$replacement = '${1}';
return preg_replace($pattern, $replacement, $langcode);
}
}