9 changed files with 383 additions and 118 deletions
@ -0,0 +1,80 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
namespace Drupal\islandora_batch_action\Batch; |
||||||
|
|
||||||
|
use Drupal\Core\Batch\BatchBuilder; |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides a batch job to perform a Drupal Action on a list of node IDs. |
||||||
|
*/ |
||||||
|
final class ActionBatch { |
||||||
|
|
||||||
|
/** |
||||||
|
* Executes the batch job. |
||||||
|
* |
||||||
|
* @param array $entity_ids |
||||||
|
* An array of entity IDs. |
||||||
|
* @param string $action_id |
||||||
|
* The action plugin ID to perform on each node. |
||||||
|
* @param string $entity_type |
||||||
|
* Must be either node or media |
||||||
|
*/ |
||||||
|
public function run(array $entity_ids, string $action_id, string $entity_type): void { |
||||||
|
$batch_builder = new BatchBuilder(); |
||||||
|
|
||||||
|
$batch_builder->setTitle(t('Performing batch action on entities.')) |
||||||
|
->setInitMessage(t('Starting the batch action.')) |
||||||
|
->setProgressMessage(t('Processing @current out of @total.')) |
||||||
|
->setErrorMessage(t('An error occurred.')); |
||||||
|
|
||||||
|
foreach ($entity_ids as $entity_id) { |
||||||
|
$batch_builder->addOperation([__CLASS__, 'processEntity'], [ |
||||||
|
$entity_id, |
||||||
|
$action_id, |
||||||
|
$entity_type, |
||||||
|
]); |
||||||
|
} |
||||||
|
batch_set($batch_builder->toArray()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Processes an individual entity for the batch operation. |
||||||
|
* |
||||||
|
* @param int $entity_id |
||||||
|
* The entity ID to process. |
||||||
|
* @param string $action_id |
||||||
|
* The action plugin ID. |
||||||
|
* @param array $context |
||||||
|
* The batch context array. |
||||||
|
*/ |
||||||
|
public static function processEntity(int $entity_id, string $action_id, string $entity_type, array &$context): void { |
||||||
|
$entityTypeManager = \Drupal::service('entity_type.manager'); |
||||||
|
$entity = $entityTypeManager->getStorage($entity_type)->load($entity_id); |
||||||
|
if (!$entity) { |
||||||
|
$context['results']['failed'][] = $entity_id; |
||||||
|
return; |
||||||
|
} |
||||||
|
$action_storage = $entityTypeManager->getStorage('action'); |
||||||
|
$configured_action = $action_storage->load($action_id); |
||||||
|
|
||||||
|
if (!$configured_action) { |
||||||
|
$context['results']['failed'][] = $entity_id; |
||||||
|
return; |
||||||
|
} |
||||||
|
try { |
||||||
|
$configured_action->execute([$entity]); |
||||||
|
$context['results']['processed'][] = $entity_id; |
||||||
|
} |
||||||
|
catch (\Exception $e) { |
||||||
|
\Drupal::logger('islandora_batch_action') |
||||||
|
->error('Batch action failed for node @nid: @message', [ |
||||||
|
'@nid' => $entity_id, |
||||||
|
'@message' => $e->getMessage(), |
||||||
|
]); |
||||||
|
$context['results']['failed'][] = $entity_id; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,76 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
declare(strict_types=1); |
|
||||||
|
|
||||||
namespace Drupal\islandora_batch_action\Batch; |
|
||||||
|
|
||||||
use Drupal\Core\Batch\BatchBuilder; |
|
||||||
|
|
||||||
/** |
|
||||||
* Provides a batch job to perform a Drupal Action on a list of node IDs. |
|
||||||
*/ |
|
||||||
final class NodeActionBatch { |
|
||||||
|
|
||||||
/** |
|
||||||
* Executes the batch job. |
|
||||||
* |
|
||||||
* @param array $node_ids |
|
||||||
* An array of node IDs. |
|
||||||
* @param string $action_id |
|
||||||
* The action plugin ID to perform on each node. |
|
||||||
*/ |
|
||||||
public function run(array $node_ids, string $action_id): void { |
|
||||||
$batch_builder = new BatchBuilder(); |
|
||||||
|
|
||||||
$batch_builder->setTitle(t('Performing batch action on nodes.')) |
|
||||||
->setInitMessage(t('Starting the batch action.')) |
|
||||||
->setProgressMessage(t('Processing @current out of @total.')) |
|
||||||
->setErrorMessage(t('An error occurred.')); |
|
||||||
|
|
||||||
// Register the operation for each node. |
|
||||||
foreach ($node_ids as $node_id) { |
|
||||||
$batch_builder->addOperation([__CLASS__, 'processNode'], [$node_id, $action_id]); |
|
||||||
} |
|
||||||
|
|
||||||
batch_set($batch_builder->toArray()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Processes an individual node for the batch operation. |
|
||||||
* |
|
||||||
* @param int $node_id |
|
||||||
* The node ID to process. |
|
||||||
* @param string $action_id |
|
||||||
* The action plugin ID. |
|
||||||
* @param array $context |
|
||||||
* The batch context array. |
|
||||||
*/ |
|
||||||
public static function processNode(int $node_id, string $action_id, array &$context): void { |
|
||||||
$entityTypeManager = \Drupal::service('entity_type.manager'); |
|
||||||
$node = $entityTypeManager->getStorage('node')->load($node_id); |
|
||||||
if (!$node) { |
|
||||||
$context['results']['failed'][] = $node_id; |
|
||||||
return; |
|
||||||
} |
|
||||||
$action_storage = $entityTypeManager->getStorage('action'); |
|
||||||
$configured_action = $action_storage->load($action_id); |
|
||||||
|
|
||||||
if (!$configured_action) { |
|
||||||
$context['results']['failed'][] = $node_id; |
|
||||||
return; |
|
||||||
} |
|
||||||
try { |
|
||||||
$configured_action->execute([$node]); |
|
||||||
$context['results']['processed'][] = $node_id; |
|
||||||
} |
|
||||||
catch (\Exception $e) { |
|
||||||
\Drupal::logger('islandora_batch_action')->error('Batch action failed for node @nid: @message', [ |
|
||||||
'@nid' => $node_id, |
|
||||||
'@message' => $e->getMessage(), |
|
||||||
]); |
|
||||||
$context['results']['failed'][] = $node_id; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,100 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
namespace Drupal\islandora_batch_action\Form; |
||||||
|
|
||||||
|
use Drupal\Core\Form\FormBase; |
||||||
|
use Drupal\Core\Form\FormStateInterface; |
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||||
|
use Drupal\islandora_batch_action\IslandoraBatchActionUtils; |
||||||
|
use Drupal\media\Entity\MediaType; |
||||||
|
use Drupal\islandora_batch_action\Batch\ActionBatch; |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides a Islandora Batch Action form. |
||||||
|
*/ |
||||||
|
final class MediaActionsForm extends FormBase { |
||||||
|
|
||||||
|
/** |
||||||
|
* The Batch Action Utils service. |
||||||
|
* |
||||||
|
* @var \Drupal\islandora_batch_action\IslandoraBatchActionUtils |
||||||
|
*/ |
||||||
|
protected IslandoraBatchActionUtils $islandoraBatchActionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* The batch job service. |
||||||
|
* |
||||||
|
* @var \Drupal\islandora_batch_action\Batch\ActionBatch |
||||||
|
*/ |
||||||
|
protected ActionBatch $batchJob; |
||||||
|
|
||||||
|
public function __construct(IslandoraBatchActionUtils $islandoraBatchActionUtils, ActionBatch $batchJob,) { |
||||||
|
$this->islandoraBatchActionUtils = $islandoraBatchActionUtils; |
||||||
|
$this->batchJob = $batchJob; |
||||||
|
} |
||||||
|
|
||||||
|
public static function create(ContainerInterface $container) { |
||||||
|
return new static( |
||||||
|
$container->get('islandora_batch_action.utils'), |
||||||
|
$container->get('islandora_batch_action.action_batch'), |
||||||
|
); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function getFormId(): string { |
||||||
|
return 'islandora_batch_action_generate_dimensions'; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function buildForm(array $form, FormStateInterface $form_state): array { |
||||||
|
|
||||||
|
$form['media_type'] = [ |
||||||
|
'#type' => 'select', |
||||||
|
'#title' => $this->t('Media Type'), |
||||||
|
'#options' => $this->islandoraBatchActionUtils->getMediaOptions(), |
||||||
|
'#required' => TRUE, |
||||||
|
]; |
||||||
|
$form['usage'] = [ |
||||||
|
'#type' => 'select', |
||||||
|
'#title' => $this->t('Media Use'), |
||||||
|
'#options' => $this->islandoraBatchActionUtils->getVocabularyOptions('islandora_media_use'), |
||||||
|
'#required' => TRUE, |
||||||
|
]; |
||||||
|
$form['media_action'] = [ |
||||||
|
'#type' => 'select', |
||||||
|
'#title' => $this->t('Action'), |
||||||
|
'#options' => $this->islandoraBatchActionUtils->getMediaActions(), |
||||||
|
'#required' => TRUE, |
||||||
|
]; |
||||||
|
|
||||||
|
$form['actions'] = [ |
||||||
|
'#type' => 'actions', |
||||||
|
'submit' => [ |
||||||
|
'#type' => 'submit', |
||||||
|
'#value' => $this->t('Create batch'), |
||||||
|
], |
||||||
|
]; |
||||||
|
|
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function submitForm(array &$form, FormStateInterface $form_state): void { |
||||||
|
$media_type = $form_state->getValue('media_type'); |
||||||
|
$tid = $form_state->getValue('usage'); |
||||||
|
$mids = $this->islandoraBatchActionUtils->getMediaList($media_type, $tid); |
||||||
|
$action_id = $form_state->getValue('media_action'); |
||||||
|
$this->batchJob->run($mids, $action_id, 'media'); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
namespace Drupal\islandora_batch_action\Plugin\Action; |
||||||
|
|
||||||
|
use Drupal\Core\Access\AccessResultInterface; |
||||||
|
use Drupal\Core\Action\ActionBase; |
||||||
|
use Drupal\Core\Annotation\Action; |
||||||
|
use Drupal\Core\Entity\ContentEntityInterface; |
||||||
|
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||||
|
use Drupal\Core\File\FileSystemInterface; |
||||||
|
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; |
||||||
|
use Drupal\Core\Session\AccountInterface; |
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Provides a Generate Image Media Dimensions action. |
||||||
|
* |
||||||
|
* @Action( |
||||||
|
* id = "islandora_batch_action_generate_image_media_dimensions", |
||||||
|
* label = @Translation("Generate Image Media Dimensions"), |
||||||
|
* type = "media", |
||||||
|
* category = @Translation("Custom"), |
||||||
|
* ) |
||||||
|
*/ |
||||||
|
final class GenerateImageMediaDimensions extends ActionBase implements ContainerFactoryPluginInterface { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. |
||||||
|
*/ |
||||||
|
public function __construct( |
||||||
|
array $configuration, |
||||||
|
$plugin_id, |
||||||
|
$plugin_definition, |
||||||
|
private readonly EntityTypeManagerInterface $entityTypeManager, |
||||||
|
private readonly FileSystemInterface $fileSystem |
||||||
|
) { |
||||||
|
parent::__construct($configuration, $plugin_id, $plugin_definition); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Dependency injection factory. |
||||||
|
*/ |
||||||
|
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { |
||||||
|
return new self( |
||||||
|
$configuration, |
||||||
|
$plugin_id, |
||||||
|
$plugin_definition, |
||||||
|
$container->get('entity_type.manager'), |
||||||
|
$container->get('file_system') |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Access check. |
||||||
|
*/ |
||||||
|
public function access($entity, AccountInterface $account = NULL, $return_as_object = FALSE): AccessResultInterface|bool { |
||||||
|
$access = $entity->access('update', $account, TRUE) |
||||||
|
->andIf($entity->get('field_height')->access('edit', $account, TRUE)); |
||||||
|
return $return_as_object ? $access : $access->isAllowed(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Action execution. |
||||||
|
*/ |
||||||
|
public function execute(ContentEntityInterface $entity = NULL): void { |
||||||
|
$height = $entity->get('field_height')->getValue()[0]['value']; |
||||||
|
$width = $entity->get('field_width')->getValue()[0]['value']; |
||||||
|
$field = $entity->hasField('field_media_file') ? 'field_media_file' : 'field_media_image'; |
||||||
|
if (!$width || !$height) { |
||||||
|
if ($entity->hasField($field) && !$entity->get($field)->isEmpty()) { |
||||||
|
$file = $entity->get($field)->entity; |
||||||
|
$realpath = $this->fileSystem->realpath($file->getFileUri()); |
||||||
|
$dimensions = getimagesize($realpath); |
||||||
|
if ($dimensions) { |
||||||
|
$entity->set('field_height', $dimensions[1]); |
||||||
|
$entity->set('field_width', $dimensions[0]); |
||||||
|
$entity->save(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue