View source
<?php
namespace Drupal\default_content;
use Drupal\Component\Graph\Graph;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Session\AccountSwitcherInterface;
use Drupal\default_content\Event\DefaultContentEvents;
use Drupal\default_content\Event\ImportEvent;
use Drupal\default_content\Normalizer\ContentEntityNormalizerInterface;
use Drupal\file\FileInterface;
use Drupal\hal\LinkManager\LinkManagerInterface;
use Drupal\user\EntityOwnerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Serializer\Serializer;
class Importer implements ImporterInterface {
protected $linkDomain;
protected $serializer;
protected $entityTypeManager;
protected $vertexes = [];
protected $graph = [];
protected $linkManager;
protected $eventDispatcher;
protected $contentFileStorage;
protected $accountSwitcher;
protected $contentEntityNormalizer;
public function __construct(Serializer $serializer, EntityTypeManagerInterface $entity_type_manager, LinkManagerInterface $link_manager, EventDispatcherInterface $event_dispatcher, ContentFileStorageInterface $content_file_storage, $link_domain, AccountSwitcherInterface $account_switcher, ContentEntityNormalizerInterface $content_entity_normaler) {
$this->serializer = $serializer;
$this->entityTypeManager = $entity_type_manager;
$this->linkManager = $link_manager;
$this->eventDispatcher = $event_dispatcher;
$this->contentFileStorage = $content_file_storage;
$this->linkDomain = $link_domain;
$this->accountSwitcher = $account_switcher;
$this->contentEntityNormalizer = $content_entity_normaler;
}
public function importContent($module) {
$created = [];
$folder = drupal_get_path('module', $module) . "/content";
if (file_exists($folder)) {
$root_user = $this->entityTypeManager
->getStorage('user')
->load(1);
$this->accountSwitcher
->switchTo($root_user);
$file_map = [];
foreach ($this->entityTypeManager
->getDefinitions() as $entity_type_id => $entity_type) {
$reflection = new \ReflectionClass($entity_type
->getClass());
if ($reflection
->implementsInterface(ConfigEntityInterface::class)) {
continue;
}
if (!file_exists($folder . '/' . $entity_type_id)) {
continue;
}
$files = $this->contentFileStorage
->scan($folder . '/' . $entity_type_id);
$this->linkManager
->setLinkDomain($this->linkDomain);
foreach ($files as $file) {
$contents = $this
->parseFile($file);
$extension = pathinfo($file->uri, PATHINFO_EXTENSION);
if ($extension == 'json') {
$decoded = $this->serializer
->decode($contents, 'hal_json');
$item_uuid = $decoded['uuid'][0]['value'];
}
else {
$decoded = Yaml::decode($contents);
$item_uuid = $decoded['_meta']['uuid'];
}
if (isset($file_map[$item_uuid])) {
$this->linkManager
->setLinkDomain(FALSE);
throw new \Exception(sprintf('Default content with uuid "%s" exists twice: "%s" "%s"', $item_uuid, $file_map[$item_uuid]->uri, $file->uri));
}
$file->entity_type_id = $entity_type_id;
$file_map[$item_uuid] = $file;
$vertex = $this
->getVertex($item_uuid);
$this->graph[$vertex->id]['edges'] = [];
if ($extension == 'json') {
if (empty($decoded['_embedded'])) {
continue;
}
foreach ($decoded['_embedded'] as $embedded) {
foreach ($embedded as $item) {
$uuid = $item['uuid'][0]['value'];
$edge = $this
->getVertex($uuid);
$this->graph[$vertex->id]['edges'][$edge->id] = TRUE;
}
}
}
else {
if (empty($decoded['_meta']['depends'])) {
continue;
}
foreach (array_keys($decoded['_meta']['depends']) as $uuid) {
$edge = $this
->getVertex($uuid);
$this->graph[$vertex->id]['edges'][$edge->id] = TRUE;
}
}
}
}
$sorted = $this
->sortTree($this->graph);
foreach ($sorted as $link => $details) {
if (!empty($file_map[$link])) {
$file = $file_map[$link];
$entity_type_id = $file->entity_type_id;
$class = $this->entityTypeManager
->getDefinition($entity_type_id)
->getClass();
$contents = $this
->parseFile($file);
$extension = pathinfo($file->uri, PATHINFO_EXTENSION);
if ($extension == 'json') {
$entity = $this->serializer
->deserialize($contents, $class, 'hal_json', [
'request_method' => 'POST',
]);
}
else {
$entity = $this->contentEntityNormalizer
->denormalize(Yaml::decode($contents));
}
$entity
->enforceIsNew(TRUE);
if ($entity instanceof EntityOwnerInterface && empty($entity
->getOwnerId())) {
$entity
->setOwner($root_user);
}
if ($entity instanceof FileInterface) {
$file_source = \dirname($file->uri) . '/' . $entity
->getFilename();
if (\file_exists($file_source)) {
$target_directory = dirname($entity
->getFileUri());
\Drupal::service('file_system')
->prepareDirectory($target_directory, FileSystemInterface::CREATE_DIRECTORY);
$new_uri = \Drupal::service('file_system')
->copy($file_source, $entity
->getFileUri());
$entity
->setFileUri($new_uri);
}
}
$entity
->save();
$created[$entity
->uuid()] = $entity;
}
}
$this->eventDispatcher
->dispatch(DefaultContentEvents::IMPORT, new ImportEvent($created, $module));
$this->accountSwitcher
->switchBack();
}
$this
->resetTree();
$this->linkManager
->setLinkDomain(FALSE);
return $created;
}
protected function parseFile($file) {
return file_get_contents($file->uri);
}
protected function resetTree() {
$this->graph = [];
$this->vertexes = [];
}
protected function sortTree(array $graph) {
$graph_object = new Graph($graph);
$sorted = $graph_object
->searchAndSort();
uasort($sorted, 'Drupal\\Component\\Utility\\SortArray::sortByWeightElement');
return array_reverse($sorted);
}
protected function getVertex($item_link) {
if (!isset($this->vertexes[$item_link])) {
$this->vertexes[$item_link] = (object) [
'id' => $item_link,
];
}
return $this->vertexes[$item_link];
}
}