View source
<?php
namespace Drupal\tome_sync;
use Drupal\Component\Graph\Graph;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Session\AccountSwitcherInterface;
use Drupal\tome_sync\Event\ContentCrudEvent;
use Drupal\tome_sync\Event\TomeSyncEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Serializer\Serializer;
use Drupal\Core\File\FileSystemInterface;
class Importer implements ImporterInterface {
use ContentIndexerTrait;
use AccountSwitcherTrait;
protected $contentStorage;
protected $serializer;
protected $entityTypeManager;
protected $isImporting;
protected $eventDispatcher;
protected $fileSystem;
protected $fileSync;
public function __construct(StorageInterface $content_storage, Serializer $serializer, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, AccountSwitcherInterface $account_switcher, FileSyncInterface $file_sync, FileSystemInterface $file_system) {
$this->contentStorage = $content_storage;
$this->serializer = $serializer;
$this->entityTypeManager = $entity_type_manager;
$this->isImporting = FALSE;
$this->eventDispatcher = $event_dispatcher;
$this->accountSwitcher = $account_switcher;
$this->fileSync = $file_sync;
$this->fileSystem = $file_system;
}
public function getChunkedNames() {
$graph = [];
$index = $this
->getContentIndex();
if (!$index) {
throw new \Exception('No index file was found. Check that the content export directory is writable and that content JSON is in the directory.');
}
$names = $this->contentStorage
->listAll();
foreach ($index as $name => $edges) {
if (!in_array($name, $names, TRUE)) {
continue;
}
$graph[$name]['edges'] = [];
foreach ($edges as $edge) {
if (in_array($edge, $names, TRUE)) {
$graph[$name]['edges'][$edge] = TRUE;
}
}
}
$graph_object = new Graph($graph);
$graph = $graph_object
->searchAndSort();
uasort($graph, 'Drupal\\Component\\Utility\\SortArray::sortByWeightElement');
$graph = array_reverse($graph);
$all_imported = [];
$chunked_graph = [];
while ($graph) {
$chunk = [];
foreach ($graph as $i => $node) {
$edges = array_keys($node['edges']);
if (count(array_intersect($edges, $all_imported)) === count($edges)) {
$chunk[] = $i;
unset($graph[$i]);
}
}
$all_imported = array_merge($all_imported, $chunk);
if (empty($chunk)) {
throw new \Exception('Unable to build the content graph, probably due to circular dependencies. Here is the list of entities to review: ' . implode(', ', array_keys($graph)));
}
$chunked_graph[] = $chunk;
}
return $chunked_graph;
}
public function importFiles() {
$this->fileSync
->importFiles();
}
public function importContent($entity_type_id, $uuid, $langcode = NULL) {
$this
->switchToAdmin();
$entity_type = $this->entityTypeManager
->getDefinition($entity_type_id);
$results = $this->entityTypeManager
->getStorage($entity_type_id)
->loadByProperties([
$entity_type
->getKey('uuid') => $uuid,
]);
$this
->isImporting(TRUE);
$imported_entity = NULL;
if ($langcode && $results) {
$original_entity = reset($results);
if ($original_entity instanceof ContentEntityInterface) {
$translation = $this
->loadEntityFromStorage($entity_type, $uuid, $langcode);
if ($original_entity
->hasTranslation($langcode)) {
$original_translation = $original_entity
->getTranslation($langcode);
$this
->copyFieldValues($translation, $original_translation);
$original_translation
->save();
}
else {
$original_entity
->addTranslation($langcode, $translation
->toArray());
$original_entity
->save();
}
$imported_entity = $original_entity
->getTranslation($langcode);
}
}
else {
$entity = $this
->loadEntityFromStorage($entity_type, $uuid);
if (!empty($results)) {
$original_entity = reset($results);
$this
->copyFieldValues($entity, $original_entity);
$original_entity
->save();
$imported_entity = $original_entity;
}
else {
$entity
->enforceIsNew();
$entity
->save();
$imported_entity = $entity;
}
}
$this
->isImporting(FALSE);
if (isset($imported_entity)) {
$event = new ContentCrudEvent($imported_entity);
$this->eventDispatcher
->dispatch(TomeSyncEvents::IMPORT_CONTENT, $event);
}
$this
->switchBack();
}
protected function copyFieldValues(FieldableEntityInterface $entity, FieldableEntityInterface $original_entity) {
foreach ($entity->_tomeFields as $field_name) {
$field = $entity
->get($field_name);
if ($entity
->getEntityType()
->hasKey('langcode') && $field_name === $entity
->getEntityType()
->getKey('langcode') && $field
->isEmpty()) {
continue;
}
$original_entity
->set($field_name, $field
->getValue());
}
}
protected function loadEntityFromStorage(EntityTypeInterface $entity_type, $uuid, $langcode = NULL) {
$contents = $this->contentStorage
->read(TomeSyncHelper::getContentNameFromParts($entity_type
->id(), $uuid, $langcode));
$entity = $this->serializer
->denormalize($contents, $entity_type
->getClass(), 'json');
$entity->_tomeFields = array_keys($contents);
return $entity;
}
public function isImporting($importing = NULL) {
if (is_bool($importing)) {
$this->isImporting = $importing;
}
return $this->isImporting;
}
}