4 changed files with 153 additions and 0 deletions
@ -0,0 +1,6 @@ |
|||||||
|
services: |
||||||
|
pdf_action.commands: |
||||||
|
class: Drupal\pdf_action\Commands\PdfDerivativeCommands |
||||||
|
arguments: ['@entity_type.manager'] |
||||||
|
tags: |
||||||
|
- { name: drush.command } |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
services: |
||||||
|
pdf_action.commands: |
||||||
|
class: Drupal\pdf_action\Commands\PdfDerivativeCommands |
||||||
|
arguments: ['@entity_type.manager'] |
||||||
|
tags: |
||||||
|
- { name: drush.command } |
||||||
@ -0,0 +1,137 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Drupal\pdf_action\Commands; |
||||||
|
|
||||||
|
use Drush\Commands\DrushCommands; |
||||||
|
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||||
|
|
||||||
|
class PdfDerivativeCommands extends DrushCommands { |
||||||
|
|
||||||
|
protected EntityTypeManagerInterface $entityTypeManager; |
||||||
|
|
||||||
|
public function __construct(EntityTypeManagerInterface $entityTypeManager) { |
||||||
|
parent::__construct(); |
||||||
|
$this->entityTypeManager = $entityTypeManager; |
||||||
|
} |
||||||
|
|
||||||
|
public static function create(ContainerInterface $container): self { |
||||||
|
return new static( |
||||||
|
$container->get('entity_type.manager') |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate PDF derivatives using flexible filters. |
||||||
|
* |
||||||
|
* @command pdf:derive |
||||||
|
* |
||||||
|
* @option model Filter by field_model taxonomy term ID(s), comma separated |
||||||
|
* @option nid-start Minimum NID |
||||||
|
* @option nid-end Maximum NID |
||||||
|
* @option nids Explicit NID list (comma separated) |
||||||
|
* @option limit Max number of nodes to process |
||||||
|
* @option chunk Chunk size for processing (default 50) |
||||||
|
* @option dry-run Show what would run without executing action |
||||||
|
*/ |
||||||
|
public function derive(array $options = [ |
||||||
|
'model' => NULL, |
||||||
|
'nid-start' => NULL, |
||||||
|
'nid-end' => NULL, |
||||||
|
'nids' => NULL, |
||||||
|
'limit' => NULL, |
||||||
|
'chunk' => 50, |
||||||
|
'dry-run' => FALSE, |
||||||
|
]) { |
||||||
|
|
||||||
|
$query = $this->entityTypeManager |
||||||
|
->getStorage('node') |
||||||
|
->getQuery() |
||||||
|
->accessCheck(FALSE); |
||||||
|
|
||||||
|
// --- Model filter --- |
||||||
|
if (!empty($options['model'])) { |
||||||
|
$models = array_map('intval', explode(',', $options['model'])); |
||||||
|
$query->condition('field_model.target_id', $models, 'IN'); |
||||||
|
$this->logger()->notice('Filtering by model: ' . implode(',', $models)); |
||||||
|
} |
||||||
|
|
||||||
|
// --- NID range --- |
||||||
|
if (!empty($options['nid-start'])) { |
||||||
|
$query->condition('nid', (int) $options['nid-start'], '>='); |
||||||
|
} |
||||||
|
|
||||||
|
if (!empty($options['nid-end'])) { |
||||||
|
$query->condition('nid', (int) $options['nid-end'], '<='); |
||||||
|
} |
||||||
|
|
||||||
|
// --- Explicit NIDs --- |
||||||
|
if (!empty($options['nids'])) { |
||||||
|
$nids = array_map('intval', explode(',', $options['nids'])); |
||||||
|
$query->condition('nid', $nids, 'IN'); |
||||||
|
} |
||||||
|
|
||||||
|
// --- Limit --- |
||||||
|
if (!empty($options['limit'])) { |
||||||
|
$query->range(0, (int) $options['limit']); |
||||||
|
} |
||||||
|
|
||||||
|
$nids = $query->execute(); |
||||||
|
|
||||||
|
if (!$nids) { |
||||||
|
$this->logger()->warning('No nodes matched.'); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
$total = count($nids); |
||||||
|
$this->logger()->notice("Matched $total nodes."); |
||||||
|
|
||||||
|
// Load action |
||||||
|
$action = $this->entityTypeManager |
||||||
|
->getStorage('action') |
||||||
|
->load('create_pdf_derivative'); |
||||||
|
|
||||||
|
if (!$action) { |
||||||
|
$this->logger()->error('Action pdf_action_create_pdf_derivative not found.'); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
$node_storage = $this->entityTypeManager->getStorage('node'); |
||||||
|
|
||||||
|
$processed = 0; |
||||||
|
$chunk_size = max(1, (int) $options['chunk']); |
||||||
|
$dry_run = !empty($options['dry-run']); |
||||||
|
|
||||||
|
foreach (array_chunk($nids, $chunk_size) as $chunk) { |
||||||
|
|
||||||
|
$nodes = $node_storage->loadMultiple($chunk); |
||||||
|
|
||||||
|
foreach ($nodes as $node) { |
||||||
|
|
||||||
|
if ($dry_run) { |
||||||
|
$this->logger()->notice("DRY RUN: Would process NID {$node->id()}"); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
$action->execute($node); |
||||||
|
$processed++; |
||||||
|
} |
||||||
|
catch (\Throwable $e) { |
||||||
|
$this->logger()->error("Failed NID {$node->id()}: {$e->getMessage()}"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!$dry_run) { |
||||||
|
$this->logger()->notice("Processed $processed / $total"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ($dry_run) { |
||||||
|
$this->logger()->success("Dry run complete. $total nodes matched."); |
||||||
|
} |
||||||
|
else { |
||||||
|
$this->logger()->success("Done. Processed $processed nodes."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue