Skip to content

Commit

Permalink
Deletion abstraction (#1017)
Browse files Browse the repository at this point in the history
* Change to Boolean logic

* remove accidental newline

* abstracted media and file deletion

* abstracted media and file deletion

* codered

* fixed test

* Update IslandoraUtils.php

Fixed PHPDoc

* Update IslandoraUtils.php

Tweaked PHPDocs

* Type hint

* More complete parameter description

---------

Co-authored-by: Rosie Le Faive <[email protected]>
  • Loading branch information
ajstanley and rosiel committed May 30, 2024
1 parent b8f0b9c commit 71d131a
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 229 deletions.
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

0 comments on commit 71d131a

Please sign in to comment.