rdf_sync-1.x-dev/src/Drush/Commands/RdfSyncCommands.php
src/Drush/Commands/RdfSyncCommands.php
<?php
declare(strict_types=1);
namespace Drupal\rdf_sync\Drush\Commands;
use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\rdf_sync\BatchSynchronizer;
use Drupal\rdf_sync\RdfSyncConnectionInterface;
use Drupal\rdf_sync\RdfSyncMapperInterface;
use Drupal\rdf_sync\RdfSyncSynchronizer;
use Drush\Attributes as CLI;
use Drush\Commands\DrushCommands;
use Drush\Utils\StringUtils;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Drush commands used to synchronize entities with the RDF backend.
*/
class RdfSyncCommands extends DrushCommands {
use StringTranslationTrait;
public function __construct(
protected RdfSyncSynchronizer $synchronizer,
protected EntityTypeManagerInterface $entityTypeManager,
protected EntityTypeBundleInfoInterface $entityTypeBundleInfo,
protected RdfSyncMapperInterface $mapper,
protected BatchSynchronizer $batchSynchronizer,
protected RdfSyncConnectionInterface $connection,
) {
parent::__construct();
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): self {
return new static(
$container->get('rdf_sync.synchronizer'),
$container->get('entity_type.manager'),
$container->get('entity_type.bundle.info'),
$container->get('rdf_sync.mapper'),
$container->get('rdf_sync.batch_synchronizer'),
$container->get('rdf_sync.connection'),
);
}
/**
* Enable synchronization.
*/
#[CLI\Command(name: 'rdf_sync:enable')]
public function enableSynchronization(): void {
$this->synchronizer->enableSynchronization();
$this->logger()->notice(dt('Enabled synchronization'));
}
/**
* Disable synchronization.
*/
#[CLI\Command(name: 'rdf_sync:disable')]
public function disableSynchronization(): void {
$this->synchronizer->disableSynchronization();
$this->logger()->notice(dt('Disabled synchronization'));
}
/**
* Clears the content of an entire graph.
*/
#[CLI\Command(name: 'rdf_sync:clear')]
public function clearRdfGraph(): void {
$question = $this->t('Are you sure you want to clear the content of an entire graph?');
if ($this->io()->confirm($question->render())) {
$this->connection->clearGraph();
$this->logger()->notice(dt('The RDF graphs have been cleared.'));
}
}
/**
* Synchronize the RDF backend for a given content type.
*/
#[CLI\Command(name: 'rdf_sync:synchronize')]
#[CLI\Argument(name: 'entityTypeId', description: 'The entity type (e.g., node, taxonomy_term')]
#[CLI\Option(name: 'bundle', description: 'Comma delimited list of bundles to limit on')]
public function synchronize(
string $entityTypeId,
array $options = ['bundle' => self::REQ],
): void {
$this->batchSynchronizer->initBatch($entityTypeId, $options['bundle']);
drush_backend_batch_process();
$output = $this->output();
$output->writeln($this->t('Synchronization completed.')
->render());
}
/**
* Validates the rdf_sync:synchronize command argument and options.
*/
#[CLI\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: 'rdf_sync:synchronize')]
public function validateSynchronize(CommandData $commandData): void {
$entityTypeId = $commandData->input()->getArgument('entityTypeId');
if (!$this->entityTypeManager->getDefinition($entityTypeId, FALSE)) {
throw new \InvalidArgumentException('Invalid entity type ID');
}
$passedBundles = StringUtils::csvToArray($commandData->input()->getOption('bundle'));
$availableBundles = array_keys($this->entityTypeBundleInfo->getBundleInfo($entityTypeId));
// Check for invalid passed bundles.
if ($diff = array_diff($passedBundles, $availableBundles)) {
throw new \InvalidArgumentException('Invalid bundles: ' . implode(', ', $diff));
}
// Check for unmapped passed bundles.
$unmappedBundles = array_filter($passedBundles, function (string $bundle) use ($entityTypeId): bool {
return !$this->mapper->isMappedBundle($entityTypeId, $bundle);
});
if ($unmappedBundles) {
throw new \InvalidArgumentException('Unmapped bundles: ' . implode(', ', $unmappedBundles));
}
$bundlesToProcess = $passedBundles;
if (!$bundlesToProcess) {
// If no bundles were passed, get all mapped bundles.
$bundlesToProcess = array_filter($availableBundles, function (string $bundle) use ($entityTypeId): bool {
return $this->mapper->isMappedBundle($entityTypeId, $bundle);
});
if (!$bundlesToProcess) {
throw new \InvalidArgumentException("The '$entityTypeId' entity type has no mapped bundle");
}
}
$commandData->input()->setOption('bundle', $bundlesToProcess);
}
}
