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."); } } }