Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deletion abstraction #1017

Merged
merged 13 commits into from
May 30, 2024
130 changes: 11 additions & 119 deletions islandora.module
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,18 @@

use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\file\FileInterface;
use Drupal\islandora\Form\IslandoraSettingsForm;
use Drupal\node\NodeInterface;
use Drupal\media\MediaInterface;
use Drupal\file\FileInterface;
use Drupal\taxonomy\TermInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\NodeInterface;
use Drupal\serialization\Normalizer\CacheableNormalizerInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\file\Entity\File;
use Drupal\taxonomy\TermInterface;

/**
* Implements hook_help().
Expand Down Expand Up @@ -408,132 +407,25 @@ function islandora_media_custom_form_submit(&$form, FormStateInterface $form_sta
* Implements a submit handler for the delete form.
*/
function islandora_object_delete_form_submit($form, FormStateInterface $form_state) {

$result = $form_state->getValues('delete_associated_content');
$utils = \Drupal::service('islandora.utils');

if ($result['delete_associated_content'] == 1) {

$utils = \Drupal::service('islandora.utils');
$node = $form_state->getFormObject()->getEntity();
$medias = $utils->getMedia($node);
$media_list = [];

$entity_field_manager = \Drupal::service('entity_field.manager');
$current_user = \Drupal::currentUser();
$results = $utils->deleteMediaAndFiles($medias);
$logger = \Drupal::logger('logger.channel.islandora');
$messenger = \Drupal::messenger();

$delete_media = [];
$media_translations = [];
$media_files = [];
$entity_protected_medias = [];
$inaccessible_entities = [];

foreach ($medias as $id => $media) {
$lang = $media->language()->getId();
$selected_langcodes[$lang] = $lang;

if (!$media->access('delete', $current_user)) {
$inaccessible_entities[] = $media;
continue;
}
// Check for files.
$fields = $entity_field_manager->getFieldDefinitions('media', $media->bundle());
foreach ($fields as $field) {
$type = $field->getType();
if ($type == 'file' || $type == 'image') {
$target_id = $media->get($field->getName())->target_id;
$file = File::load($target_id);
if ($file) {
if (!$file->access('delete', $current_user)) {
$inaccessible_entities[] = $file;
continue;
}
$media_files[$id][$file->id()] = $file;
}
}
}

foreach ($selected_langcodes as $langcode) {
// We're only working with media, which are translatable.
$entity = $media->getTranslation($langcode);
if ($entity->isDefaultTranslation()) {
$delete_media[$id] = $entity;
unset($media_translations[$id]);
}
elseif (!isset($delete_media[$id])) {
$media_translations[$id][] = $entity;
}
}
if (isset($results['inaccessible'])) {
$messenger->addWarning($results['inaccessible']);
}

if ($delete_media) {
foreach ($delete_media as $id => $media) {
try {
$media->delete();
$media_list[] = $id;
$logger->notice('The media %label has been deleted.', [
'%label' => $media->label(),
]);
}
catch (Exception $e) {
$entity_protected_medias[] = $id;
}
}
}

$delete_files = array_filter($media_files, function ($media) use ($entity_protected_medias) {
return !in_array($media, $entity_protected_medias);
}, ARRAY_FILTER_USE_KEY);

if ($delete_files) {
foreach ($delete_files as $files_array) {
foreach ($files_array as $file) {
$file->delete();
$logger->notice('The file %label has been deleted.', [
'%label' => $file->label(),
]);
}
}
}

$delete_media_translations = array_filter($media_translations, function ($media) use ($entity_protected_medias) {
return !in_array($media, $entity_protected_medias);
}, ARRAY_FILTER_USE_KEY);

if ($delete_media_translations) {
foreach ($delete_media_translations as $id => $translations) {
$media = $medias[$id];
foreach ($translations as $translation) {
$media->removeTranslation($translation->language()->getId());
}
$media->save();
foreach ($translations as $translation) {
$logger->notice('The media %label @language translation has been deleted', [
'%label' => $media->label(),
'@language' => $translation->language()->getName(),
]);
}
}
}

if ($inaccessible_entities) {
$messenger->addWarning("@count items have not been deleted because you do not have the necessary permissions.", [
'@count' => count($inaccessible_entities),
]);
}

$logger->notice($results['deleted']);
$build = [
'heading' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => t("The repository item @node and @media", [
'@node' => $node->getTitle(),
'@media' => \Drupal::translation()->formatPlural(
count($media_list), 'the media with the id @media has been deleted.',
'the medias with the ids @media have been deleted.',
['@media' => implode(", ", $media_list)],
),
'@media' => $results['deleted'],
]),
],
];
Expand Down
2 changes: 1 addition & 1 deletion islandora.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ services:
arguments: ['@entity_type.manager', '@current_user', '@language_manager', '@file_system', '@islandora.utils']
islandora.utils:
class: Drupal\islandora\IslandoraUtils
arguments: ['@entity_type.manager', '@entity_field.manager', '@context.manager', '@flysystem_factory', '@language_manager']
arguments: ['@entity_type.manager', '@entity_field.manager', '@context.manager', '@flysystem_factory', '@language_manager', '@current_user']
islandora.entity_mapper:
class: Islandora\EntityMapper\EntityMapper
islandora.stomp.auth_header_listener:
Expand Down
118 changes: 17 additions & 101 deletions src/Form/ConfirmDeleteMediaAndFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@

namespace Drupal\islandora\Form;

use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Form\DeleteMultipleForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\islandora\MediaSource\MediaSourceService;
use Drupal\islandora\IslandoraUtils;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

Expand All @@ -21,11 +19,11 @@
class ConfirmDeleteMediaAndFile extends DeleteMultipleForm {

/**
* Media source service.
* The current user.
*
* @var \Drupal\islandora\MediaSource\MediaSourceService
* @var \Drupal\Core\Session\AccountInterface
*/
protected $mediaSourceService;
protected $currentUser;

/**
* Logger.
Expand All @@ -42,23 +40,22 @@ class ConfirmDeleteMediaAndFile extends DeleteMultipleForm {
protected $selection = [];

/**
* Entity field manager.
* The Islandora Utils service.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
* @var \Drupal\islandora\IslandoraUtils
*/
protected $entityFieldManager;
protected IslandoraUtils $utils;

/**
* {@inheritdoc}
*/
public function __construct(AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, PrivateTempStoreFactory $temp_store_factory, MessengerInterface $messenger, MediaSourceService $media_source_service, LoggerInterface $logger) {
public function __construct(AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, MessengerInterface $messenger, LoggerInterface $logger, IslandoraUtils $utils) {
$this->currentUser = $current_user;
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->tempStore = $temp_store_factory->get('media_and_file_delete_confirm');
$this->messenger = $messenger;
$this->mediaSourceService = $media_source_service;
$this->logger = $logger;
$this->utils = $utils;
}

/**
Expand All @@ -68,11 +65,11 @@ 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.media_source_service'),
$container->get('logger.channel.islandora'));
$container->get('logger.channel.islandora'),
$container->get('islandora.utils')
);
}

/**
Expand Down Expand Up @@ -111,94 +108,13 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
public function submitForm(array &$form, FormStateInterface $form_state) {
// Similar to parent::submitForm(), but let's blend in the related files and
// optimize based on the fact that we know we're working with media.
$total_count = 0;
$delete_media = [];
$delete_media_translations = [];
$delete_files = [];
$inaccessible_entities = [];
$media_storage = $this->entityTypeManager->getStorage('media');
$file_storage = $this->entityTypeManager->getStorage('file');
$media = $media_storage->loadMultiple(array_keys($this->selection));
foreach ($this->selection as $id => $selected_langcodes) {
$entity = $media[$id];
if (!$entity->access('delete', $this->currentUser)) {
$inaccessible_entities[] = $entity;
continue;
}
// Check for files.
$fields = $this->entityFieldManager->getFieldDefinitions('media', $entity->bundle());
foreach ($fields as $field) {
if ($field->getName() == 'thumbnail') {
continue;
}
$type = $field->getType();
if ($type == 'file' || $type == 'image') {
$target_id = $entity->get($field->getName())->target_id;
$file = File::load($target_id);
if ($file) {
if (!$file->access('delete', $this->currentUser)) {
$inaccessible_entities[] = $file;
continue;
}
if (!array_key_exists($file->id(), $delete_files)) {
$delete_files[$file->id()] = $file;
$total_count++;
}

}
}
}

foreach ($selected_langcodes as $langcode) {
// We're only working with media, which are translatable.
$entity = $entity->getTranslation($langcode);
if ($entity->isDefaultTranslation()) {
$delete_media[$id] = $entity;
unset($delete_media_translations[$id]);
$total_count += count($entity->getTranslationLanguages());
}
elseif (!isset($delete_media[$id])) {
$delete_media_translations[$id][] = $entity;
}
}
}
if ($delete_media) {
$media_storage->delete($delete_media);
foreach ($delete_media as $entity) {
$this->logger->notice('The media %label has been deleted.', [
'%label' => $entity->label(),
]);
}
}
if ($delete_files) {
$file_storage->delete($delete_files);
foreach ($delete_files as $entity) {
$this->logger->notice('The file %label has been deleted.', [
'%label' => $entity->label(),
]);
}
}
if ($delete_media_translations) {
foreach ($delete_media_translations as $id => $translations) {
$entity = $media[$id];
foreach ($translations as $translation) {
$entity->removeTranslation($translation->language()->getId());
}
$entity->save();
foreach ($translations as $translation) {
$this->logger->notice('The media %label @language translation has been deleted', [
'%label' => $entity->label(),
'@language' => $translation->language()->getName(),
]);
}
$total_count += count($translations);
}
}
if ($total_count) {
$this->messenger->addStatus($this->getDeletedMessage($total_count));
}
if ($inaccessible_entities) {
$this->messenger->addWarning($this->getInaccessibleMessage(count($inaccessible_entities)));
$results = $this->utils->deleteMediaAndFiles($media);
$this->logger->notice($results['deleted']);
$this->messenger->addStatus($results['deleted']);
if (isset($results['inaccessible'])) {
$this->messenger->addWarning($results['inaccessible']);
}
$this->tempStore->delete($this->currentUser->id());
$form_state->setRedirectUrl($this->getCancelUrl());
Expand Down
Loading
Loading