View source
<?php
namespace Drupal\default_content_deploy;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Session\AccountSwitcherInterface;
use Drupal\hal\LinkManager\LinkManagerInterface;
use Symfony\Component\Serializer\Serializer;
class Exporter {
protected $deployManager;
protected $exporter;
protected $fileSystem;
protected $database;
protected $entityTypeManager;
protected $serializer;
protected $accountSwitcher;
private $entityTypeId;
private $bundle;
private $entityIds;
private $folder;
private $skipEntityIds;
private $exportedEntities = [];
private $mode;
private $forceUpdate;
protected $linkManager;
public function __construct(Connection $database, DeployManager $deploy_manager, EntityTypeManagerInterface $entityTypeManager, Serializer $serializer, AccountSwitcherInterface $account_switcher, FileSystemInterface $file_system, LinkManagerInterface $link_manager) {
$this->database = $database;
$this->entityTypeManager = $entityTypeManager;
$this->serializer = $serializer;
$this->accountSwitcher = $account_switcher;
$this->deployManager = $deploy_manager;
$this->fileSystem = $file_system;
$this->linkManager = $link_manager;
}
public function setEntityTypeId($entity_type) {
$content_entity_types = $this->deployManager
->getContentEntityTypes();
if (!array_key_exists($entity_type, $content_entity_types)) {
throw new \InvalidArgumentException(sprintf('Entity type "%s" does not exist', $entity_type));
}
$this->entityTypeId = (string) $entity_type;
return $this;
}
public function setEntityBundle($bundle) {
$this->bundle = $bundle;
return $this;
}
public function setEntityIds(array $entity_ids) {
$this->entityIds = $entity_ids;
return $this;
}
public function setSkipEntityIds(array $skip_entity_ids) {
$this->skipEntityIds = $skip_entity_ids;
return $this;
}
public function setMode($mode) {
$available_modes = [
'all',
'reference',
'default',
];
if (in_array($mode, $available_modes)) {
$this->mode = $mode;
}
else {
throw new \Exception('The selected mode is not available');
}
return $this;
}
public function setForceUpdate(bool $is_update) {
$this->forceUpdate = $is_update;
return $this;
}
public function setFolder(string $folder) {
$this->folder = $folder;
return $this;
}
protected function getFolder() {
$folder = $this->folder ?: $this->deployManager
->getContentFolder();
return $folder;
}
public function getResult() {
return $this->exportedEntities;
}
public function export() {
switch ($this->mode) {
case 'default':
$this
->prepareToExport();
break;
case 'reference':
$this
->prepareToExportWithReference();
break;
case 'all':
$this
->prepareToExportAllContent();
break;
}
$this
->editEntityData();
$this
->writeConfigsToFolder();
return $this;
}
private function prepareToExport() {
$entity_type = $this->entityTypeId;
$exported_entity_ids = $this
->getEntityIdsForExport();
if ($this->forceUpdate) {
$this->fileSystem
->deleteRecursive($this
->getFolder());
}
foreach ($exported_entity_ids as $entity_id) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$exported_entity = $this
->getSerializedContent($entity);
$this
->addExportedEntity($exported_entity);
}
}
private function prepareToExportWithReference() {
$entity_type = $this->entityTypeId;
$exported_entity_ids = $this
->getEntityIdsForExport();
if ($this->forceUpdate) {
$this->fileSystem
->deleteRecursive($this
->getFolder());
}
foreach ($exported_entity_ids as $entity_id) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$exported_entity = $this
->getSerializedContentWithReferences($entity);
$this
->addExportedEntity($exported_entity);
}
}
private function prepareToExportAllContent() {
$content_entity_types = $this->deployManager
->getContentEntityTypes();
if ($this->forceUpdate) {
$this->fileSystem
->deleteRecursive($this
->getFolder());
}
foreach ($content_entity_types as $entity_type => $label) {
if (!$this->skipEntityIds || !in_array($entity_type, $this->skipEntityIds)) {
$this
->setEntityTypeId($entity_type);
$query = $this->entityTypeManager
->getStorage($entity_type)
->getQuery();
$entity_ids = array_values($query
->execute());
foreach ($entity_ids as $entity_id) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$exported_entity = $this
->getSerializedContent($entity);
$this
->addExportedEntity($exported_entity);
}
}
}
}
private function getEntityIdsForExport() {
$skip_entities = $this->skipEntityIds;
$entity_ids = $this->entityIds;
$entity_type = $this->entityTypeId;
$entity_bundle = $this->bundle;
$key_bundle = $this->entityTypeManager
->getDefinition($entity_type)
->getKey('bundle');
if (empty($entity_ids)) {
$query = $this->entityTypeManager
->getStorage($entity_type)
->getQuery();
if ($entity_bundle) {
$query
->condition($key_bundle, $entity_bundle);
}
$entity_ids = $query
->execute();
}
if (!empty($skip_entities)) {
$entity_ids = array_diff($entity_ids, $skip_entities);
}
return $entity_ids;
}
private function addExportedEntity($exported_entity) {
if (is_string($exported_entity)) {
$entity = $this->serializer
->decode($exported_entity, 'hal_json');
$uuid = $entity['uuid'][0]['value'];
$entity_with_uuid[$uuid] = $exported_entity;
$exported_entity_array[$this->entityTypeId][$uuid] = $exported_entity;
}
else {
$exported_entity_array = $exported_entity;
}
$this->exportedEntities = array_replace_recursive($this->exportedEntities, $exported_entity_array);
return $this;
}
private function writeConfigsToFolder() {
foreach ($this->exportedEntities as $entity_type => $serialized_entities) {
$entity_type_folder = "{$this->getFolder()}/{$entity_type}";
$this->fileSystem
->prepareDirectory($entity_type_folder, FileSystemInterface::CREATE_DIRECTORY);
foreach ($serialized_entities as $uuid => $serialized_entity) {
file_put_contents("{$entity_type_folder}/{$uuid}.json", $serialized_entity);
}
}
return $this;
}
private function editEntityData() {
foreach ($this->exportedEntities as $entity_type => $uuids) {
foreach ($uuids as $uuid => $serialisation_entity) {
$entity_array = $this->serializer
->decode($serialisation_entity, 'hal_json');
$entity_type_object = $this->entityTypeManager
->getDefinition($entity_type);
$id_key = $entity_type_object
->getKey('id');
$entity_id = $entity_array[$id_key][0]['value'];
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
unset($entity_array[$entity_type_object
->getKey('revision')]);
if ($entity_type === 'user') {
$entity_array['pass'][0]['value'] = $entity
->getPassword();
}
$data = $this->serializer
->serialize($entity_array, 'hal_json', [
'json_encode_options' => JSON_PRETTY_PRINT,
]);
$this->exportedEntities[$entity_type][$uuid] = $data;
}
}
}
public function getSerializedContent(ContentEntityInterface $entity) {
if (PHP_SAPI === 'cli') {
$root_user = $this->entityTypeManager
->getStorage('user')
->load(1);
$this->accountSwitcher
->switchTo($root_user);
}
$host = $this->deployManager
->getCurrentHost();
$this->linkManager
->setLinkDomain($host);
$content = $this->serializer
->serialize($entity, 'hal_json', [
'json_encode_options' => JSON_PRETTY_PRINT,
]);
$this->linkManager
->setLinkDomain(FALSE);
if (PHP_SAPI === 'cli') {
$this->accountSwitcher
->switchBack();
}
return $content;
}
private function getSerializedContentWithReferences(ContentEntityInterface $entity) {
$indexed_dependencies = [
$entity
->uuid() => $entity,
];
$entities = $this
->getEntityReferencesRecursive($entity, 0, $indexed_dependencies);
$host = $this->deployManager
->getCurrentHost();
$serialized_entities = [];
$this->linkManager
->setLinkDomain($host);
if (PHP_SAPI === 'cli') {
$root_user = $this->entityTypeManager
->getStorage('user')
->load(1);
$this->accountSwitcher
->switchTo($root_user);
}
foreach ($entities as $entity) {
$serialize = $this->serializer
->serialize($entity, 'hal_json', [
'json_encode_options' => JSON_PRETTY_PRINT,
]);
$serialized_entities[$entity
->getEntityTypeId()][$entity
->uuid()] = $serialize;
}
$this->linkManager
->setLinkDomain(FALSE);
if (PHP_SAPI === 'cli') {
$this->accountSwitcher
->switchBack();
}
return $serialized_entities;
}
private function getEntityReferencesRecursive(ContentEntityInterface $entity, $depth = 0, array &$indexed_dependencies = []) {
$entity_dependencies = $entity
->referencedEntities();
foreach ($entity_dependencies as $dependent_entity) {
if (!$dependent_entity instanceof ContentEntityInterface) {
continue;
}
$key = $dependent_entity
->uuid();
if (isset($indexed_dependencies[$key])) {
continue;
}
$indexed_dependencies[$key] = $dependent_entity;
if ($depth < 6) {
$indexed_dependencies += $this
->getEntityReferencesRecursive($dependent_entity, $depth + 1, $indexed_dependencies);
}
}
return $indexed_dependencies;
}
}