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