class ContentExportCommand

Same name in this branch
  1. main core/lib/Drupal/Core/DefaultContent/ContentExportCommand.php \Drupal\Core\DefaultContent\ContentExportCommand
Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/DefaultContent/ContentExportCommand.php \Drupal\Core\DefaultContent\ContentExportCommand
  2. 11.x core/lib/Drupal/Core/DefaultContent/Command/ContentExportCommand.php \Drupal\Core\DefaultContent\Command\ContentExportCommand

Exports content entities in YAML format.

@internal This API is experimental.

Attributes

#[AsCommand(name: 'content:export', description: 'Exports content entities in YAML format.')]

Hierarchy

Expanded class hierarchy of ContentExportCommand

1 file declares its use of ContentExportCommand
ContentExportTest.php in core/tests/Drupal/FunctionalTests/DefaultContent/ContentExportTest.php

File

core/lib/Drupal/Core/DefaultContent/Command/ContentExportCommand.php, line 29

Namespace

Drupal\Core\DefaultContent\Command
View source
final class ContentExportCommand extends Command {
  use StringTranslationTrait;
  public function __construct(protected EntityTypeManagerInterface $entityTypeManager, protected EntityTypeBundleInfoInterface $entityBundleInfo, protected Exporter $exporter, protected FileSystemInterface $fileSystem) {
    parent::__construct();
  }
  
  /**
   * {@inheritdoc}
   */
  protected function configure() : void {
    $this->addArgument('entity_type_id', InputArgument::REQUIRED, 'The entity type to export (e.g., node, taxonomy_term).')
      ->addArgument('entity_id', InputArgument::OPTIONAL, 'The ID of the entity to export. Will usually be a number.')
      ->addOption('with-dependencies', 'W', InputOption::VALUE_NONE, "Recursively export all of the entities referenced by this entity into a directory structure.")
      ->addOption('bundle', 'b', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Only export entities of the specified bundle(s).')
      ->addOption('dir', 'd', InputOption::VALUE_REQUIRED, 'The path where content should be exported.')
      ->addUsage('node 42')
      ->addUsage('node 3 --with-dependencies --dir=/path/to/content')
      ->addUsage('media --bundle=image --dir=images')
      ->addUsage('taxonomy_term --bundle=tags --bundle=categories --dir=terms');
  }
  
  /**
   * {@inheritdoc}
   */
  protected function execute(InputInterface $input, OutputInterface $output) : int {
    $io = new SymfonyStyle($input, $output);
    $entity_type_id = $input->getArgument('entity_type_id');
    $entity_id = $input->getArgument('entity_id');
    $bundles = $input->getOption('bundle');
    if (!$this->entityTypeManager
      ->hasDefinition($entity_type_id)) {
      $io->error("The entity type \"{$entity_type_id}\" does not exist.");
      return Command::FAILURE;
    }
    if (!$this->entityTypeManager
      ->getDefinition($entity_type_id)
      ->entityClassImplements(ContentEntityInterface::class)) {
      $io->error("{$entity_type_id} is not a content entity type.");
      return Command::FAILURE;
    }
    // Confirm that all specified bundles exist.
    if ($bundles) {
      $unknown_bundles = array_diff($bundles, array_keys($this->entityBundleInfo
        ->getBundleInfo($entity_type_id)));
      if ($unknown_bundles) {
        $io->error("These bundles do not exist on the {$entity_type_id} entity type: " . implode(', ', $unknown_bundles));
        return Command::FAILURE;
      }
    }
    $dir = $input->getOption('dir');
    $with_dependencies = $input->getOption('with-dependencies');
    // If we're going to export multiple entities, or a single entity with its
    // dependencies, require the `--dir` option.
    if (empty($dir) && (empty($entity_id) || $with_dependencies)) {
      throw new RuntimeException('The --dir option is required to export multiple entities, or a single entity with its dependencies.');
    }
    $count = 0;
    $storage = $this->entityTypeManager
      ->getStorage($entity_type_id);
    foreach ($this->loadEntities($storage, $entity_id, $bundles) as $entity) {
      if ($with_dependencies) {
        $count += $this->exporter
          ->exportWithDependencies($entity, $dir);
      }
      elseif ($dir) {
        $this->exporter
          ->exportToFile($entity, $dir);
        $count++;
      }
      else {
        $io->write((string) $this->exporter
          ->export($entity));
        return Command::SUCCESS;
      }
    }
    // If we were trying to export a specific entity and it didn't get exported,
    // that's an error.
    if ($entity_id && $count === 0) {
      $io->error("{$entity_type_id} {$entity_id} does not exist.");
      if ($bundles) {
        $io->caution('Maybe this entity is not one of the specified bundles: ' . implode(', ', $bundles));
      }
      return Command::FAILURE;
    }
    $message = (string) $this->formatPlural($count, 'One entity was exported to @dir.', '@count entities were exported to @dir.', [
      '@dir' => $this->fileSystem
        ->realpath($dir),
    ]);
    $io->success($message);
    return Command::SUCCESS;
  }
  
  /**
   * Find entities to export and yield them one by one.
   *
   * @param \Drupal\Core\Entity\ContentEntityStorageInterface $storage
   *   The entity storage handler.
   * @param string|int|null $entity_id
   *   The ID of the specific entity to load, or NULL to load all entities
   *   (probably filtered by bundle).
   * @param string[] $bundles
   *   (optional) The bundles to filter by.
   *
   * @return iterable<\Drupal\Core\Entity\ContentEntityInterface>
   *   A generator that yields content entities.
   */
  private function loadEntities(ContentEntityStorageInterface $storage, string|int|null $entity_id, array $bundles = []) : iterable {
    $values = [];
    $entity_type = $storage->getEntityType();
    if ($bundles) {
      $values[$entity_type->getKey('bundle')] = $bundles;
    }
    if ($entity_id) {
      $values[$entity_type->getKey('id')] = $entity_id;
    }
    return $storage->loadByProperties($values);
  }

}

Members

Title Sort descending Modifiers Object type Summary Overrides
ContentExportCommand::configure protected function
ContentExportCommand::execute protected function
ContentExportCommand::loadEntities private function Find entities to export and yield them one by one.
ContentExportCommand::__construct public function
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language. 1

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.