class Exporter in Default Content Deploy 8
A service for handling export of default content.
Hierarchy
- class \Drupal\default_content_deploy\Exporter
Expanded class hierarchy of Exporter
2 files declare their use of Exporter
- DefaultContentDeployCommands.php in src/
Commands/ DefaultContentDeployCommands.php - ExportForm.php in src/
Form/ ExportForm.php
1 string reference to 'Exporter'
1 service uses Exporter
File
- src/
Exporter.php, line 16
Namespace
Drupal\default_content_deployView source
class Exporter {
/**
* DCD Manager.
*
* @var \Drupal\default_content_deploy\DeployManager
*/
protected $deployManager;
/**
* Default content Exporter.
*
* @var \Drupal\default_content\Exporter
*/
protected $exporter;
/**
* The file system service.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* DB connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* Entity Type Manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Serializer.
*
* @var \Symfony\Component\Serializer\Serializer
*/
protected $serializer;
/**
* The account switcher service.
*
* @var \Drupal\Core\Session\AccountSwitcherInterface
*/
protected $accountSwitcher;
/**
* Entity type ID.
*
* @var string
*/
private $entityTypeId;
/**
* Type of a entity content.
*
* @var string
*/
private $bundle;
/**
* Entity IDs for export.
*
* @var array
*/
private $entityIds;
/**
* Directory to export.
*
* @var string
*/
private $folder;
/**
* Entity IDs which needs skip.
*
* @var array
*/
private $skipEntityIds;
/**
* Array of entity types and with there values for export.
*
* @var array
*/
private $exportedEntities = [];
/**
* Type of export.
*
* @var string
*/
private $mode;
/**
* Is remove old content.
*
* @var bool
*/
private $forceUpdate;
/**
* The link manager service.
*
* @var \Drupal\hal\LinkManager\LinkManagerInterface
*/
protected $linkManager;
/**
* Exporter constructor.
*
* @param \Drupal\Core\Database\Connection $database
* DB connection.
* @param \Drupal\default_content_deploy\DeployManager $deploy_manager
* DCD Manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* Entity Type Manager.
* @param \Symfony\Component\Serializer\Serializer $serializer
* Serializer.
* @param \Drupal\Core\Session\AccountSwitcherInterface $account_switcher
* The account switcher service.
* @param \Drupal\Core\File\FileSystemInterface $file_system
* The file system service.
* @param \Drupal\hal\LinkManager\LinkManagerInterface $link_manager
* The link manager service.
*/
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;
}
/**
* Set entity type ID.
*
* @param string $entity_type
* Entity Type.
*
* @return \Drupal\default_content_deploy\Exporter
*/
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;
}
/**
* Set type of a entity content.
*
* @param string $bundle
* Bundle of the entity type.
*
* @return \Drupal\default_content_deploy\Exporter
*/
public function setEntityBundle($bundle) {
$this->bundle = $bundle;
return $this;
}
/**
* Set entity IDs for export.
*
* @param array $entity_ids
* The IDs of entity.
*
* @return \Drupal\default_content_deploy\Exporter
*/
public function setEntityIds(array $entity_ids) {
$this->entityIds = $entity_ids;
return $this;
}
/**
* Set entity IDs which needs skip.
*
* @param array $skip_entity_ids
* The IDs of entity for skip.
*
* @return $this
*/
public function setSkipEntityIds(array $skip_entity_ids) {
$this->skipEntityIds = $skip_entity_ids;
return $this;
}
/**
* Set type of export.
*
* @param string $mode
* Value type of export.
*
* @return \Drupal\default_content_deploy\Exporter
*
* @throws \Exception
*/
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;
}
/**
* Is remove old content.
*
* @param bool $is_update
*
* @return \Drupal\default_content_deploy\Exporter
*/
public function setForceUpdate(bool $is_update) {
$this->forceUpdate = $is_update;
return $this;
}
/**
* Set directory to export.
*
* @param string $folder
* The content folder.
*
* @return \Drupal\default_content_deploy\Exporter
*/
public function setFolder(string $folder) {
$this->folder = $folder;
return $this;
}
/**
* Get directory to export.
*
* @return string
* The content folder.
*
* @throws \Exception
*/
protected function getFolder() {
$folder = $this->folder ?: $this->deployManager
->getContentFolder();
return $folder;
}
/**
* Array with entity types for display result.
*
* @return array
* Array with entity types.
*/
public function getResult() {
return $this->exportedEntities;
}
/**
* Export entities by entity type, id or bundle.
*
* @return \Drupal\default_content_deploy\Exporter
*
* @throws \Exception
*/
public function export() {
switch ($this->mode) {
case 'default':
$this
->prepareToExport();
break;
case 'reference':
$this
->prepareToExportWithReference();
break;
case 'all':
$this
->prepareToExportAllContent();
break;
}
// Edit and export all entities to folder.
$this
->editEntityData();
$this
->writeConfigsToFolder();
return $this;
}
/**
* Prepare content to export.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$exported_entity = $this
->getSerializedContent($entity);
$this
->addExportedEntity($exported_entity);
}
}
/**
* Prepare content with reference to export.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$exported_entity = $this
->getSerializedContentWithReferences($entity);
$this
->addExportedEntity($exported_entity);
}
}
/**
* Prepare all content on the site to export.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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) {
// Skip specified entities in --skip_entity_type option.
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) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
$exported_entity = $this
->getSerializedContent($entity);
$this
->addExportedEntity($exported_entity);
}
}
}
}
/**
* Get all entity IDs for export.
*
* @return array
* Return array of entity ids.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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 the Entity IDs option is null then load all IDs.
if (empty($entity_ids)) {
$query = $this->entityTypeManager
->getStorage($entity_type)
->getQuery();
if ($entity_bundle) {
$query
->condition($key_bundle, $entity_bundle);
}
$entity_ids = $query
->execute();
}
// Remove skipped entities from $exported_entity_ids.
if (!empty($skip_entities)) {
$entity_ids = array_diff($entity_ids, $skip_entities);
}
return $entity_ids;
}
/**
* Add array with entity info for export.
*
* @param $exported_entity
* Entity info.
*
* @return $this
*/
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;
}
/**
* Writes an array of serialized entities to a given folder.
*
* @return $this
*
* @throws \Exception
*/
private function writeConfigsToFolder() {
foreach ($this->exportedEntities as $entity_type => $serialized_entities) {
// Ensure that the folder per entity type exists.
$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;
}
/**
* Remove or add a new fields to serialize entities data.
*/
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);
// Removed data.
unset($entity_array[$entity_type_object
->getKey('revision')]);
// Add data.
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;
}
}
}
/**
* Exports a single entity as importContent expects it.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
*
* @return string
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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;
}
/**
* Exports a single entity and all its referenced entity.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
*
* @return array
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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);
}
// Serialize all entities and key them by entity TYPE and uuid.
foreach ($entities as $entity) {
$serialize = $this->serializer
->serialize($entity, 'hal_json', [
'json_encode_options' => JSON_PRETTY_PRINT,
]);
$serialized_entities[$entity
->getEntityTypeId()][$entity
->uuid()] = $serialize;
}
// Reset the link domain and the current user, if needed.
$this->linkManager
->setLinkDomain(FALSE);
if (PHP_SAPI === 'cli') {
$this->accountSwitcher
->switchBack();
}
return $serialized_entities;
}
/**
* Returns all referenced entities of an entity.
*
* This method is also recursive to support use-cases like a node -> media
* -> file.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity.
* @param int $depth
* Guard against infinite recursion.
* @param \Drupal\Core\Entity\ContentEntityInterface[] $indexed_dependencies
* Previously discovered dependencies.
*
* @return \Drupal\Core\Entity\ContentEntityInterface[]
* Keyed array of entities indexed by entity type and ID.
*/
private function getEntityReferencesRecursive(ContentEntityInterface $entity, $depth = 0, array &$indexed_dependencies = []) {
$entity_dependencies = $entity
->referencedEntities();
foreach ($entity_dependencies as $dependent_entity) {
// Config entities should not be exported but rather provided by default
// config.
if (!$dependent_entity instanceof ContentEntityInterface) {
continue;
}
// Using UUID to keep dependencies unique to prevent recursion.
$key = $dependent_entity
->uuid();
if (isset($indexed_dependencies[$key])) {
// Do not add already indexed dependencies.
continue;
}
$indexed_dependencies[$key] = $dependent_entity;
// Build in some support against infinite recursion.
if ($depth < 6) {
$indexed_dependencies += $this
->getEntityReferencesRecursive($dependent_entity, $depth + 1, $indexed_dependencies);
}
}
return $indexed_dependencies;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
Exporter:: |
protected | property | The account switcher service. | |
Exporter:: |
private | property | Type of a entity content. | |
Exporter:: |
protected | property | DB connection. | |
Exporter:: |
protected | property | DCD Manager. | |
Exporter:: |
private | property | Entity IDs for export. | |
Exporter:: |
private | property | Entity type ID. | |
Exporter:: |
protected | property | Entity Type Manager. | |
Exporter:: |
private | property | Array of entity types and with there values for export. | |
Exporter:: |
protected | property | Default content Exporter. | |
Exporter:: |
protected | property | The file system service. | |
Exporter:: |
private | property | Directory to export. | |
Exporter:: |
private | property | Is remove old content. | |
Exporter:: |
protected | property | The link manager service. | |
Exporter:: |
private | property | Type of export. | |
Exporter:: |
protected | property | Serializer. | |
Exporter:: |
private | property | Entity IDs which needs skip. | |
Exporter:: |
private | function | Add array with entity info for export. | |
Exporter:: |
private | function | Remove or add a new fields to serialize entities data. | |
Exporter:: |
public | function | Export entities by entity type, id or bundle. | |
Exporter:: |
private | function | Get all entity IDs for export. | |
Exporter:: |
private | function | Returns all referenced entities of an entity. | |
Exporter:: |
protected | function | Get directory to export. | |
Exporter:: |
public | function | Array with entity types for display result. | |
Exporter:: |
public | function | Exports a single entity as importContent expects it. | |
Exporter:: |
private | function | Exports a single entity and all its referenced entity. | |
Exporter:: |
private | function | Prepare content to export. | |
Exporter:: |
private | function | Prepare all content on the site to export. | |
Exporter:: |
private | function | Prepare content with reference to export. | |
Exporter:: |
public | function | Set type of a entity content. | |
Exporter:: |
public | function | Set entity IDs for export. | |
Exporter:: |
public | function | Set entity type ID. | |
Exporter:: |
public | function | Set directory to export. | |
Exporter:: |
public | function | Is remove old content. | |
Exporter:: |
public | function | Set type of export. | |
Exporter:: |
public | function | Set entity IDs which needs skip. | |
Exporter:: |
private | function | Writes an array of serialized entities to a given folder. | |
Exporter:: |
public | function | Exporter constructor. |