diff --git a/config/install/system.action.delete_node_and_media.yml b/config/install/system.action.delete_node_and_media.yml new file mode 100644 index 000000000..74fee13cd --- /dev/null +++ b/config/install/system.action.delete_node_and_media.yml @@ -0,0 +1,12 @@ +status: true +dependencies: + enforced: + module: + - islandora + module: + - islandora +id: delete_node_and_media +label: 'Delete node(s) and associated media' +type: node +plugin: delete_node_and_media +configuration: { } \ No newline at end of file diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml index 282f7b3c5..41b7338d1 100644 --- a/config/schema/islandora.schema.yml +++ b/config/schema/islandora.schema.yml @@ -81,6 +81,10 @@ action.configuration.delete_media_and_file: type: action_configuration_default label: 'Delete media and file' +action.configuration.delete_node_and_media: + type: action_configuration_default + label: 'Delete node and media' + condition.plugin.node_has_term: type: condition.plugin mapping: diff --git a/islandora.install b/islandora.install index 01e5a467b..fb569eb4a 100644 --- a/islandora.install +++ b/islandora.install @@ -8,6 +8,7 @@ use Drupal\Core\Extension\ExtensionNameLengthException; use Drupal\Core\Extension\MissingDependencyException; use Drupal\Core\Utility\UpdateException; +use Symfony\Component\Yaml\Yaml; /** * Adds common namespaces to jsonld.settings. @@ -221,8 +222,18 @@ function islandora_update_8008() { if ($config) { $config->set('redirect_after_media_save', FALSE); $config->save(TRUE); - return t('A new configuration option, "Redirect after media save" is now available. - It has been turned off to preserve existing behaviour. To enable this setting visit + return t('A new configuration option, "Redirect after media save" is now available. + It has been turned off to preserve existing behaviour. To enable this setting visit Configuration > Islandora > Core Settings.'); } } + +/** + * Add "Delete node and media" action. + */ +function islandora_update_9001(&$sandbox) { + $config_id = 'system.action.delete_node_and_media'; + $config_path = \Drupal::service('extension.list.module')->getPath('islandora') . '/config/install/' . $config_id . '.yml'; + $data = Yaml::parseFile($config_path); + \Drupal::configFactory()->getEditable($config_id)->setData($data)->save(TRUE); +} diff --git a/islandora.routing.yml b/islandora.routing.yml index 86d134828..f72db51c8 100644 --- a/islandora.routing.yml +++ b/islandora.routing.yml @@ -109,3 +109,10 @@ islandora.confirm_delete_media_and_file: _form: 'Drupal\islandora\Form\ConfirmDeleteMediaAndFile' requirements: _permission: 'administer media+delete any media' + +islandora.confirm_delete_node_and_media: + path: '/node/delete_with_media' + defaults: + _form: 'Drupal\islandora\Form\ConfirmDeleteNodeAndMedia' + requirements: + _permission: 'administer media+delete any media' diff --git a/src/Form/ConfirmDeleteNodeAndMedia.php b/src/Form/ConfirmDeleteNodeAndMedia.php new file mode 100755 index 000000000..d39aa702b --- /dev/null +++ b/src/Form/ConfirmDeleteNodeAndMedia.php @@ -0,0 +1,163 @@ +currentUser = $current_user; + $this->entityTypeManager = $entity_type_manager; + $this->entityFieldManager = $entity_field_manager; + $this->tempStore = $temp_store_factory->get('node_and_media_delete_confirm'); + $this->messenger = $messenger; + $this->utils = $utils; + $this->mediaSourceService = $media_source_service; + $this->logger = $logger; + $this->deletedMediaCount = 0; + $this->deletedFileCount = 0; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('current_user'), + $container->get('entity_type.manager'), + $container->get('entity_field.manager'), + $container->get('tempstore.private'), + $container->get('messenger'), + $container->get('islandora.utils'), + $container->get('islandora.media_source_service'), + $container->get('logger.channel.islandora')); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'node_and_media_delete_confirm_form'; + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return $this->formatPlural(count($this->selection), + 'Are you sure you want to delete this node and its associated media and files?', + 'Are you sure you want to delete these nodes and their associated media and files?'); + } + + /** + * {@inheritdoc} + */ + public function getCancelUrl() { + return new Url('entity.media.collection'); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) { + return parent::buildForm($form, $form_state, 'node'); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $deleted_media = 0; + $node_storage = $this->entityTypeManager->getStorage('node'); + $nodes = $node_storage->loadMultiple(array_keys($this->selection)); + $deleteable_nodes = []; + foreach ($nodes as $node) { + if ($node->access('delete', $this->currentUser)) { + $deleteable_nodes[] = $node; + } + else { + $nondeleteable_nodes = $node; + } + } + foreach ($deleteable_nodes as $candidate) { + $media = $this->utils->getMedia($candidate); + $this->utils->deleteMediaAndFiles($media); + $candidate->delete(); + } + $this->messenger->addStatus($this->getDeletedMessage(count($deleteable_nodes))); + if ($nondeleteable_nodes) { + $failures = count($nondeleteable_nodes); + $this->messenger->addStatus($this->formatPlural($failures, 'Unable to delete 1 node', 'Unable to delete @count nodes')); + } + $this->tempStore->delete($this->currentUser->id()); + $form_state->setRedirectUrl($this->getCancelUrl()); + } + +} diff --git a/src/Plugin/Action/DeleteNodeAndMedia.php b/src/Plugin/Action/DeleteNodeAndMedia.php new file mode 100755 index 000000000..2dd243872 --- /dev/null +++ b/src/Plugin/Action/DeleteNodeAndMedia.php @@ -0,0 +1,46 @@ +currentUser = $current_user; + $this->tempStore = $temp_store_factory->get('node_and_media_delete_confirm'); + $this->entityTypeManager = $entity_type_manager; + $this->configuration = $configuration; + $this->pluginId = $plugin_id; + $this->pluginDefinition = $plugin_definition; + } + + /** + * {@inheritdoc} + */ + public function executeMultiple(array $entities): void { + $selection = []; + foreach ($entities as $entity) { + $langcode = $entity->language()->getId(); + $selection[$entity->id()][$langcode] = $langcode; + } + $this->tempStore->set("{$this->currentUser->id()}:node", $selection); + } + +}