Batch Jobs for missing derivatives
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.5 KiB

<?php
namespace Drupal\islandora_batch_action\Commands;
use Drupal\node\Entity\Node;
use Drush\Commands\DrushCommands;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Database\Connection;
/**
* Provides Drush commands for batch actions on nodes.
*/
class BatchActionCommands extends DrushCommands {
protected $entityTypeManager;
protected $database;
/**
* Constructs the BatchActionCommands object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\Core\Database\Connection $database
* The database connection.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database) {
$this->entityTypeManager = $entity_type_manager;
$this->database = $database;
}
/**
* Runs a batch action on a list of nodes.
*
* @command batch:action
* @param string $action_id
* The machine name of the action to run.
*
* @usage drush batch:action my_custom_action
*/
public function runBatchAction($action_id) {
$action = $this->entityTypeManager->getStorage("action")->load($action_id);
if (!$action) {
$this->logger()->error("Action not found: $action_id");
return;
}
$node_ids = $this->generateNodeList();
if (empty($node_ids)) {
$this->logger()->notice("No nodes found to process.");
return;
}
$batch = [
'title' => t('Running action on nodes'),
'operations' => [],
'finished' => [__CLASS__, 'batchFinished'],
];
foreach ($node_ids as $nid) {
$batch['operations'][] = [
[__CLASS__, 'processNode'],
[$nid, $action_id],
];
}
batch_set($batch);
drush_backend_batch_process();
}
/**
* Generates a list of node IDs that do not have 'Intermediate File' media.
*
* @return array
* An array of node IDs.
*/
/**
* Generates a list of node IDs that do not have 'Intermediate File' media
* but have the model field set to 'Image'.
*
* @return array
* An array of node IDs.
*/
/**
* Generates a list of node IDs that do not have 'Intermediate File' media
* but have the model field set to 'Image'.
*
* @return array
* An array of node IDs.
*/
protected function generateNodeList() {
// Subquery to get the TID for the term 'Image'.
$image_tid_query = $this->database->select('taxonomy_term_field_data', 't')
->fields('t', ['tid'])
->condition('t.name', 'Image')
->condition('t.vid', 'islandora_models')
->execute()
->fetchField();
if (!$image_tid_query) {
$this->logger()->error("Taxonomy term 'Image' not found.");
return [];
}
$this->logger()->notice("Taxonomy term 'Image' is $image_tid_query.");
// Subquery to get nids with 'Intermediate File' media.
$subquery = $this->database->select('node', 'n')
->fields('n', ['nid']);
$subquery->innerJoin('media__field_media_of', 'mo', 'n.nid = mo.field_media_of_target_id');
$subquery->innerJoin('media__field_media_use', 'mu', 'mu.entity_id = mo.entity_id');
$subquery->innerJoin('taxonomy_term_field_data', 't', 'mu.field_media_use_target_id = t.tid');
$subquery->condition('t.name', 'Intermediate File');
// Main query to get all nids excluding the subquery result,
// and where field_model_target_id is equal to the TID of 'Image' using EXISTS.
$query = $this->database->select('node', 'n')
->fields('n', ['nid'])
->condition('n.nid', $subquery, 'NOT IN');
// Adding the EXISTS condition for field_model_target_id.
$query->exists(
$this->database->select('node__field_model', 'fm')
->fields('fm', ['entity_id'])
->condition('fm.entity_id', 'n.nid', '=')
->condition('fm.field_model_target_id', $image_tid_query)
);
return $query->execute()->fetchCol();
}
/**
* Processes an individual node in the batch.
*
* @param int $nid
* The node ID.
* @param string $action_id
* The action ID.
* @param array $context
* The batch context.
*/
public static function processNode($nid, $action_id, array &$context) {
$node = Node::load($nid);
$action = \Drupal::entityTypeManager()->getStorage("action")->load($action_id);
if (!$node) {
$context['results']['errors'][] = "Node not found: $nid";
return;
}
if (!$action) {
$context['results']['errors'][] = "Action not found: $action_id";
return;
}
try {
$action->execute([$node]);
$context['results']['processed'][] = "Processed action on node $nid";
}
catch (\Exception $e) {
$context['results']['errors'][] = "Error processing node $nid: " . $e->getMessage();
}
}
/**
* Callback for batch finished.
*
* @param bool $success
* Whether the batch completed successfully.
* @param array $results
* An array of results.
* @param array $operations
* The list of operations.
*/
public static function batchFinished($success, array $results, array $operations) {
if ($success) {
\Drupal::messenger()->addMessage("Batch process completed successfully.");
if (!empty($results['processed'])) {
\Drupal::messenger()->addMessage("Processed nodes: " . implode(', ', $results['processed']));
}
if (!empty($results['errors'])) {
\Drupal::messenger()->addError("Errors encountered: " . implode(', ', $results['errors']));
}
}
else {
\Drupal::messenger()->addError("Batch process encountered an error.");
}
}
}