From aa3c71893e7aea98dff67e660df5f3b7832fafb0 Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 18 Oct 2022 16:10:19 -0300 Subject: [PATCH 01/32] delete media associated with an islandora object --- islandora.module | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/islandora.module b/islandora.module index 5b5446d1..708f8ec1 100644 --- a/islandora.module +++ b/islandora.module @@ -320,9 +320,10 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) 'media_extracted_text_add_form', 'media_file_add_form', 'media_image_add_form', 'media_fits_technical_metadata_add_form', 'media_video_add_form', ]; - + //kint($form); if (in_array($form['#form_id'], $media_add_forms)) { $params = \Drupal::request()->query->all(); + if (isset($params['edit'])) { $media_of_nid = $params['edit']['field_media_of']['widget'][0]['target_id']; $node = \Drupal::entityTypeManager()->getStorage('node')->load($media_of_nid); @@ -346,6 +347,7 @@ function islandora_field_widget_image_image_form_alter(&$element, $form_state, $ function islandora_add_default_image_alt_text($element, $form_state, $form) { if ($element['alt']['#access']) { $params = \Drupal::request()->query->all(); + if (isset($params['edit'])) { $media_of_nid = $params['edit']['field_media_of']['widget'][0]['target_id']; $node = \Drupal::entityTypeManager()->getStorage('node')->load($media_of_nid); @@ -423,7 +425,7 @@ function islandora_entity_extra_field_info() { if (!empty($pseudo_bundles)) { foreach ($pseudo_bundles as $key) { [$bundle, $content_entity] = explode(":", $key); - $extra_field[$content_entity][$bundle]['display'][IslandoraSettingsForm::GEMINI_PSEUDO_FIELD] = [ + $extra_field[$content_entity][$bundle]['display']['field_gemini_uri'] = [ 'label' => t('Fedora URI'), 'description' => t('The URI to the persistent'), 'weight' => 100, @@ -548,3 +550,27 @@ function islandora_preprocess_views_view_table(&$variables) { } } } + +function islandora_form_node_islandora_object_delete_form_alter(&$form, &$form_state){ + $form['delete_associated_content'] = array( + '#type' => 'checkbox', + '#title' => t('Delete all associated medias and nodes'), + ); + + $form['actions']['submit']['#submit'][] = 'islandora_form_node_islandora_object_delete_form_submit'; + return $form; +} + +function islandora_form_node_islandora_object_delete_form_submit($form, &$form_state){ + + $result = $form_state->getValues('delete_associated_content'); + + if($result['delete_associated_content'] == 1) { + $utils = \Drupal::service('islandora.utils'); + $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); + foreach ($medias as $media) { + $media->delete(); + } + } +} + From 33ce9e4e135dacc342819b0b8bea2824cd023c72 Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Thu, 27 Oct 2022 14:31:18 -0300 Subject: [PATCH 02/32] list media associated with a Islandora object --- islandora.module | 69 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/islandora.module b/islandora.module index 708f8ec1..ab9eab18 100644 --- a/islandora.module +++ b/islandora.module @@ -27,6 +27,7 @@ use Drupal\file\FileInterface; use Drupal\taxonomy\TermInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\serialization\Normalizer\CacheableNormalizerInterface; +use Drupal\Core\Entity\EntityForm; /** * Implements hook_help(). @@ -320,7 +321,7 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) 'media_extracted_text_add_form', 'media_file_add_form', 'media_image_add_form', 'media_fits_technical_metadata_add_form', 'media_video_add_form', ]; - //kint($form); + if (in_array($form['#form_id'], $media_add_forms)) { $params = \Drupal::request()->query->all(); @@ -332,6 +333,51 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) } } } + + $form_object = $form_state->getFormObject(); + + $utils = \Drupal::service('islandora.utils'); + +// kint($form,$form_state); + + if($form_object instanceof EntityForm) { + $entity = $form_object->getEntity(); + if ($utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { + $form['delete_associated_content'] = array( + '#type' => 'checkbox', + '#title' => t('Delete all associated medias and nodes'), + ); + + $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); + $media_list = ""; + + foreach($medias as $media){ + $media_list.= "<li>{$media->getName()}</li>"; + } + + $form['media_items'] = array( + '#suffix' => "<ul>{$media_list}</ul>", // Add markup after form item + ); + + $form['actions']['submit']['#submit'][] = 'islandora_object_delete_form_submit'; + return $form; + } + } + return $form; +} + +function islandora_object_delete_form_submit($form, &$form_state){ + + $result = $form_state->getValues('delete_associated_content'); + $utils = \Drupal::service('islandora.utils'); + + if($result['delete_associated_content'] == 1) { + + $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); + foreach ($medias as $media) { + $media->delete(); + } + } } /** @@ -551,26 +597,5 @@ function islandora_preprocess_views_view_table(&$variables) { } } -function islandora_form_node_islandora_object_delete_form_alter(&$form, &$form_state){ - $form['delete_associated_content'] = array( - '#type' => 'checkbox', - '#title' => t('Delete all associated medias and nodes'), - ); - - $form['actions']['submit']['#submit'][] = 'islandora_form_node_islandora_object_delete_form_submit'; - return $form; -} -function islandora_form_node_islandora_object_delete_form_submit($form, &$form_state){ - - $result = $form_state->getValues('delete_associated_content'); - - if($result['delete_associated_content'] == 1) { - $utils = \Drupal::service('islandora.utils'); - $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); - foreach ($medias as $media) { - $media->delete(); - } - } -} From 3602bb441b991dce7a08cffb98b93300b05ea907 Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 1 Nov 2022 12:16:29 -0300 Subject: [PATCH 03/32] fixed failing coding standard checks --- islandora.module | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/islandora.module b/islandora.module index ab9eab18..63018266 100644 --- a/islandora.module +++ b/islandora.module @@ -324,7 +324,6 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) if (in_array($form['#form_id'], $media_add_forms)) { $params = \Drupal::request()->query->all(); - if (isset($params['edit'])) { $media_of_nid = $params['edit']['field_media_of']['widget'][0]['target_id']; $node = \Drupal::entityTypeManager()->getStorage('node')->load($media_of_nid); @@ -333,31 +332,28 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) } } } - $form_object = $form_state->getFormObject(); $utils = \Drupal::service('islandora.utils'); -// kint($form,$form_state); - - if($form_object instanceof EntityForm) { + if ($form_object instanceof EntityForm) { $entity = $form_object->getEntity(); if ($utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { - $form['delete_associated_content'] = array( + $form['delete_associated_content'] = [ '#type' => 'checkbox', '#title' => t('Delete all associated medias and nodes'), - ); + ]; $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); $media_list = ""; - foreach($medias as $media){ - $media_list.= "<li>{$media->getName()}</li>"; + foreach ($medias as $media) { + $media_list .= "<li>{$media->getName()}</li>"; } - $form['media_items'] = array( - '#suffix' => "<ul>{$media_list}</ul>", // Add markup after form item - ); + $form['media_items'] = [ + '#suffix' => "<ul>{$media_list}</ul>", + ]; $form['actions']['submit']['#submit'][] = 'islandora_object_delete_form_submit'; return $form; @@ -366,12 +362,15 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) return $form; } -function islandora_object_delete_form_submit($form, &$form_state){ +/** + * Implements a submit handler for the delete form. + */ +function islandora_object_delete_form_submit($form, &$form_state) { $result = $form_state->getValues('delete_associated_content'); $utils = \Drupal::service('islandora.utils'); - if($result['delete_associated_content'] == 1) { + if ($result['delete_associated_content'] == 1) { $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); foreach ($medias as $media) { @@ -393,7 +392,6 @@ function islandora_field_widget_image_image_form_alter(&$element, $form_state, $ function islandora_add_default_image_alt_text($element, $form_state, $form) { if ($element['alt']['#access']) { $params = \Drupal::request()->query->all(); - if (isset($params['edit'])) { $media_of_nid = $params['edit']['field_media_of']['widget'][0]['target_id']; $node = \Drupal::entityTypeManager()->getStorage('node')->load($media_of_nid); @@ -471,7 +469,7 @@ function islandora_entity_extra_field_info() { if (!empty($pseudo_bundles)) { foreach ($pseudo_bundles as $key) { [$bundle, $content_entity] = explode(":", $key); - $extra_field[$content_entity][$bundle]['display']['field_gemini_uri'] = [ + $extra_field[$content_entity][$bundle]['display'][IslandoraSettingsForm::GEMINI_PSEUDO_FIELD] = [ 'label' => t('Fedora URI'), 'description' => t('The URI to the persistent'), 'weight' => 100, @@ -596,6 +594,3 @@ function islandora_preprocess_views_view_table(&$variables) { } } } - - - From 5bd2cdd85177397c23f4f7e3b639469597b5c9cb Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 1 Nov 2022 13:08:36 -0300 Subject: [PATCH 04/32] check if the entity is a node --- islandora.module | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/islandora.module b/islandora.module index 63018266..e8aeb232 100644 --- a/islandora.module +++ b/islandora.module @@ -333,12 +333,11 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) } } $form_object = $form_state->getFormObject(); - $utils = \Drupal::service('islandora.utils'); if ($form_object instanceof EntityForm) { $entity = $form_object->getEntity(); - if ($utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { + if ($entity->getEntityTypeId() == "node" && $utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { $form['delete_associated_content'] = [ '#type' => 'checkbox', '#title' => t('Delete all associated medias and nodes'), From fd5c38a10734efc26de0b3634c8c08a5791f8e36 Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 1 Nov 2022 16:00:22 -0300 Subject: [PATCH 05/32] added test cases for deleting node with media --- tests/src/Functional/DeleteNodeWithMedia.php | 94 ++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/src/Functional/DeleteNodeWithMedia.php diff --git a/tests/src/Functional/DeleteNodeWithMedia.php b/tests/src/Functional/DeleteNodeWithMedia.php new file mode 100644 index 00000000..b9cc8f99 --- /dev/null +++ b/tests/src/Functional/DeleteNodeWithMedia.php @@ -0,0 +1,94 @@ +<?php + +namespace Drupal\Tests\islandora\Functional; + +/** + * Tests the Delete Node with Media. + * + * @group islandora + */ +class DeleteNodeWithMedia extends IslandoraFunctionalTestBase { + + /** + * Tests delete Node and its assoicated media. + */ + public function testDeleteNodeWithMedia() { + $account = $this->drupalCreateUser([ + 'delete any media', + 'create media', + 'view media', + 'bypass node access', + ]); + $this->drupalLogin($account); + + $assert_session = $this->assertSession(); + + $testImageMediaType = $this->createMediaType('image', ['id' => 'test_image_media_type']); + $testImageMediaType->save(); + + $this->createEntityReferenceField('media', $testImageMediaType->id(), 'field_media_of', 'Media Of', 'node', 'default', [], 2); + + $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'node', + ]); + $node->save(); + + // Make an image for the Media. + $file = $this->container->get('entity_type.manager')->getStorage('file')->create([ + 'uid' => $account->id(), + 'uri' => "public://test.jpeg", + 'filename' => "test.jpeg", + 'filemime' => "image/jpeg", + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + + $this->drupalGet("node/1/delete"); + $assert_session->pageTextNotContains('Delete all associated medias and nodes'); + + // Make the media, and associate it with the image and node. + $media1 = $this->container->get('entity_type.manager')->getStorage('media')->create([ + 'bundle' => $testImageMediaType->id(), + 'name' => 'Media1', + 'field_media_image' => + [ + 'target_id' => $file->id(), + 'alt' => 'Some Alt', + 'title' => 'Some Title', + ], + 'field_media_of' => ['target_id' => $node->id()], + ]); + $media1->save(); + + $media2 = $this->container->get('entity_type.manager')->getStorage('media')->create([ + 'bundle' => $testImageMediaType->id(), + 'name' => 'Media2', + 'field_media_image' => + [ + 'target_id' => $file->id(), + 'alt' => 'Some Alt', + 'title' => 'Some Title', + ], + 'field_media_of' => ['target_id' => $node->id()], + ]); + $media2->save(); + + $delete = ['delete_associated_content' => TRUE]; + + $this->drupalGet("node/1/delete"); + $assert_session->pageTextContains('Media1'); + $assert_session->pageTextContains('Media2'); + $this->submitForm($delete, 'Delete'); + + $assert_session->pageTextContains('Media1'); + $assert_session->pageTextContains('Media2'); + + $this->drupalGet("media/1/delete"); + $assert_session->pageTextContains('Page not found'); + + $this->drupalGet("media/2/delete"); + $assert_session->pageTextContains('Page not found'); + } + +} From e3c7e6eddac3f81614f923c96463f8d24e250412 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Sat, 23 Jul 2022 14:43:48 -0300 Subject: [PATCH 06/32] Document the add members and add media pages. --- src/Controller/ManageMediaController.php | 9 ++++++++- src/Controller/ManageMembersController.php | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Controller/ManageMediaController.php b/src/Controller/ManageMediaController.php index bd670561..a58d9860 100644 --- a/src/Controller/ManageMediaController.php +++ b/src/Controller/ManageMediaController.php @@ -25,7 +25,7 @@ class ManageMediaController extends ManageMembersController { public function addToNodePage(NodeInterface $node) { $field = IslandoraUtils::MEDIA_OF_FIELD; - return $this->generateTypeList( + $add_media_list = $this->generateTypeList( 'media', 'media_type', 'entity.media.add_form', @@ -33,6 +33,13 @@ class ManageMediaController extends ManageMembersController { $field, ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] ); + + return [ + '#type' => 'markup', + '#markup' => $this->t("These available media types below have <em>@field</em> and it is configured to allow this content type.", + ['@field' => $field]), + 'add_media' => $add_media_list, + ]; } /** diff --git a/src/Controller/ManageMembersController.php b/src/Controller/ManageMembersController.php index 7f480fb3..e07ec5df 100644 --- a/src/Controller/ManageMembersController.php +++ b/src/Controller/ManageMembersController.php @@ -88,7 +88,8 @@ class ManageMembersController extends EntityController { */ public function addToNodePage(NodeInterface $node) { $field = IslandoraUtils::MEMBER_OF_FIELD; - return $this->generateTypeList( + + $add_node_list = $this->generateTypeList( 'node', 'node_type', 'node.add', @@ -96,6 +97,13 @@ class ManageMembersController extends EntityController { $field, ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] ); + + return [ + '#type' => 'markup', + '#markup' => $this->t("These available content types below have <em>@field</em> and it is configured to allow this content type.", + ['@field' => $field]), + 'add_node' => $add_node_list, + ]; } /** From 7eebb65c2b7c1f79fdfa563302836c97520176e4 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Mon, 7 Nov 2022 17:10:30 -0400 Subject: [PATCH 07/32] Clarify wording and add manage link. --- src/Controller/ManageMediaController.php | 7 +++++-- src/Controller/ManageMembersController.php | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Controller/ManageMediaController.php b/src/Controller/ManageMediaController.php index a58d9860..d15175f9 100644 --- a/src/Controller/ManageMediaController.php +++ b/src/Controller/ManageMediaController.php @@ -36,8 +36,11 @@ class ManageMediaController extends ManageMembersController { return [ '#type' => 'markup', - '#markup' => $this->t("These available media types below have <em>@field</em> and it is configured to allow this content type.", - ['@field' => $field]), + '#markup' => $this->t("The following media types can be added because they have the <code>@field</code> field. <a href=@manage_media_page>Manage media types</a>.", + [ + '@field' => $field, + '@manage_media_page' => '/admin/structure/media', + ]), 'add_media' => $add_media_list, ]; } diff --git a/src/Controller/ManageMembersController.php b/src/Controller/ManageMembersController.php index e07ec5df..bfd2cf74 100644 --- a/src/Controller/ManageMembersController.php +++ b/src/Controller/ManageMembersController.php @@ -100,8 +100,11 @@ class ManageMembersController extends EntityController { return [ '#type' => 'markup', - '#markup' => $this->t("These available content types below have <em>@field</em> and it is configured to allow this content type.", - ['@field' => $field]), + '#markup' => $this->t("The following content types can be added because they have the <code>@field</code> field. <a href=@manage_content_types>Manage content types</a>.", + [ + '@field' => $field, + '@manage_content_types' => '/admin/structure/types', + ]), 'add_node' => $add_node_list, ]; } From 386ba0ceb19e71119cb9e035381f4c93857560e1 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Mon, 7 Nov 2022 18:36:10 -0400 Subject: [PATCH 08/32] Detect access before showing manage links. --- src/Controller/ManageMediaController.php | 16 +++++++++++----- src/Controller/ManageMembersController.php | 16 +++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/Controller/ManageMediaController.php b/src/Controller/ManageMediaController.php index d15175f9..025d1d9d 100644 --- a/src/Controller/ManageMediaController.php +++ b/src/Controller/ManageMediaController.php @@ -6,6 +6,7 @@ use Drupal\islandora\IslandoraUtils; use Drupal\Core\Access\AccessResult; use Drupal\Core\Routing\RouteMatch; use Drupal\node\Entity\Node; +use Drupal\Core\Url; use Drupal\node\NodeInterface; /** @@ -34,13 +35,18 @@ class ManageMediaController extends ManageMembersController { ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] ); + $manage_link = Url::fromRoute('entity.media_type.collection')->toRenderArray(); + $manage_link['#title'] = $this->t('Manage media types'); + $manage_link['#type'] = 'link'; + $manage_link['#prefix'] = ' '; + $manage_link['#suffix'] = '.'; + return [ '#type' => 'markup', - '#markup' => $this->t("The following media types can be added because they have the <code>@field</code> field. <a href=@manage_media_page>Manage media types</a>.", - [ - '@field' => $field, - '@manage_media_page' => '/admin/structure/media', - ]), + '#markup' => $this->t("The following media types can be added because they have the <code>@field</code> field.", [ + '@field' => $field, + ]), + 'manage_link' => $manage_link, 'add_media' => $add_media_list, ]; } diff --git a/src/Controller/ManageMembersController.php b/src/Controller/ManageMembersController.php index bfd2cf74..9827ff35 100644 --- a/src/Controller/ManageMembersController.php +++ b/src/Controller/ManageMembersController.php @@ -7,6 +7,7 @@ use Drupal\Core\Render\RendererInterface; use Drupal\Core\Entity\Controller\EntityController; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Link; +use Drupal\Core\Url; use Drupal\islandora\IslandoraUtils; use Drupal\node\NodeInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -98,13 +99,18 @@ class ManageMembersController extends EntityController { ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] ); + $manage_link = Url::fromRoute('entity.node_type.collection')->toRenderArray(); + $manage_link['#title'] = $this->t('Manage content types'); + $manage_link['#type'] = 'link'; + $manage_link['#prefix'] = ' '; + $manage_link['#suffix'] = '.'; + return [ '#type' => 'markup', - '#markup' => $this->t("The following content types can be added because they have the <code>@field</code> field. <a href=@manage_content_types>Manage content types</a>.", - [ - '@field' => $field, - '@manage_content_types' => '/admin/structure/types', - ]), + '#markup' => $this->t("The following content types can be added because they have the <code>@field</code> field.", [ + '@field' => $field, + ]), + 'manage_link' => $manage_link, 'add_node' => $add_node_list, ]; } From 7ef1afffa2c814b83decb86e13677ecde764d68f Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 8 Nov 2022 13:44:38 -0400 Subject: [PATCH 09/32] delete media with files and translations --- islandora.module | 159 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 141 insertions(+), 18 deletions(-) diff --git a/islandora.module b/islandora.module index e8aeb232..9130caeb 100644 --- a/islandora.module +++ b/islandora.module @@ -28,6 +28,7 @@ use Drupal\taxonomy\TermInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\serialization\Normalizer\CacheableNormalizerInterface; use Drupal\Core\Entity\EntityForm; +use Drupal\file\Entity\File; /** * Implements hook_help(). @@ -337,25 +338,34 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) if ($form_object instanceof EntityForm) { $entity = $form_object->getEntity(); - if ($entity->getEntityTypeId() == "node" && $utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { - $form['delete_associated_content'] = [ - '#type' => 'checkbox', - '#title' => t('Delete all associated medias and nodes'), - ]; + if ($entity->getEntityTypeId() == "node" && $utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); - $media_list = ""; + if (count($medias) != 0) { + $form['delete_associated_content'] = [ + '#type' => 'checkbox', + '#title' => t('Delete all associated medias and nodes'), + ]; + + foreach ($medias as $media) { + $media_list[] = $media->getName(); + } + $form['media_items'] = [ + '#theme' => 'item_list', + '#type' => 'ul', + '#items' => $media_list, + '#attributes' => ['class' => 'mylist'], + '#wrapper_attributes' => ['class' => 'container'], + '#attached' => [ + 'library' => [ + 'islandora/drupal.islandora.theme_css', + ], + ], + ]; - foreach ($medias as $media) { - $media_list .= "<li>{$media->getName()}</li>"; + $form['actions']['submit']['#submit'][] = 'islandora_object_delete_form_submit'; + return $form; } - - $form['media_items'] = [ - '#suffix' => "<ul>{$media_list}</ul>", - ]; - - $form['actions']['submit']['#submit'][] = 'islandora_object_delete_form_submit'; - return $form; } } return $form; @@ -371,10 +381,123 @@ function islandora_object_delete_form_submit($form, &$form_state) { if ($result['delete_associated_content'] == 1) { - $medias = $utils->getMedia($form_state->getFormObject()->getEntity()); - foreach ($medias as $media) { - $media->delete(); + $node = $form_state->getFormObject()->getEntity(); + $medias = $utils->getMedia($node); + $media_list = ""; + + $entity_type_manager = \Drupal::entityTypeManager(); + $entity_field_manager = \Drupal::service('entity_field.manager'); + $current_user = \Drupal::currentUser(); + $logger = \Drupal::logger('logger.channel.islandora'); + $messenger = \Drupal::messenger(); + + $total_count = 0; + $delete_media = []; + $delete_media_translations = []; + $delete_files = []; + $inaccessible_entities = []; + $media_storage = $entity_type_manager->getStorage('media'); + $file_storage = $entity_type_manager->getStorage('file'); + + foreach ($medias as $id => $media) { + $media_list .= $id . ", "; + $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; + } + $delete_files[$file->id()] = $file; + $total_count++; + } + } + } + + 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($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 $media) { + $logger->notice('The media %label has been deleted.', [ + '%label' => $media->label(), + ]); + } + } + + if ($delete_files) { + $file_storage->delete($delete_files); + foreach ($delete_files as $media) { + $logger->notice('The file %label has been deleted.', [ + '%label' => $media->label(), + ]); + } + } + + 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(), + ]); + } + $total_count += count($translations); + } + } + + if ($inaccessible_entities) { + $messenger->addWarning("@count items has not been deleted because you do not have the necessary permissions.", [ + '@count' => count($inaccessible_entities), + ]); + } + + $build = [ + 'heading' => [ + '#type' => 'html_tag', + '#tag' => 'div', + '#value' => t("The repository item @node and @media", [ + '@node' => $node->getTitle(), + '@media' => \Drupal::translation()->formatPlural( + substr_count($media_list, ",") + 1, 'the media with the id @media has been deleted.', + 'the medias with the id @media have been deleted.', + ['@media' => mb_substr($media_list, 0, strlen($media_list) - 2)]), + ]), + ], + ]; + + $message = \Drupal::service('renderer')->renderPlain($build); + $messenger->deleteByType('status'); + $messenger->addStatus($message); } } From ef1f36f2836bcdc82a8b2ca1526924b99a54f70c Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 8 Nov 2022 16:07:27 -0400 Subject: [PATCH 10/32] Updated test cases to include file deletion --- islandora.module | 9 ++++++--- ...WithMedia.php => DeleteNodeWithMediaAndFile.php} | 13 +++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) rename tests/src/Functional/{DeleteNodeWithMedia.php => DeleteNodeWithMediaAndFile.php} (87%) diff --git a/islandora.module b/islandora.module index 9130caeb..44dc35a7 100644 --- a/islandora.module +++ b/islandora.module @@ -347,9 +347,12 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) '#title' => t('Delete all associated medias and nodes'), ]; - foreach ($medias as $media) { + $media_list = []; + + foreach ($medias as $media) { $media_list[] = $media->getName(); } + $form['media_items'] = [ '#theme' => 'item_list', '#type' => 'ul', @@ -451,9 +454,9 @@ function islandora_object_delete_form_submit($form, &$form_state) { if ($delete_files) { $file_storage->delete($delete_files); - foreach ($delete_files as $media) { + foreach ($delete_files as $file) { $logger->notice('The file %label has been deleted.', [ - '%label' => $media->label(), + '%label' => $file->label(), ]); } } diff --git a/tests/src/Functional/DeleteNodeWithMedia.php b/tests/src/Functional/DeleteNodeWithMediaAndFile.php similarity index 87% rename from tests/src/Functional/DeleteNodeWithMedia.php rename to tests/src/Functional/DeleteNodeWithMediaAndFile.php index b9cc8f99..ff793f0d 100644 --- a/tests/src/Functional/DeleteNodeWithMedia.php +++ b/tests/src/Functional/DeleteNodeWithMediaAndFile.php @@ -7,17 +7,18 @@ namespace Drupal\Tests\islandora\Functional; * * @group islandora */ -class DeleteNodeWithMedia extends IslandoraFunctionalTestBase { +class DeleteNodeWithMediaAndFile extends IslandoraFunctionalTestBase { /** * Tests delete Node and its assoicated media. */ - public function testDeleteNodeWithMedia() { + public function testDeleteNodeWithMediaAndFile() { $account = $this->drupalCreateUser([ 'delete any media', 'create media', 'view media', 'bypass node access', + 'access files overview', ]); $this->drupalLogin($account); @@ -81,14 +82,18 @@ class DeleteNodeWithMedia extends IslandoraFunctionalTestBase { $assert_session->pageTextContains('Media2'); $this->submitForm($delete, 'Delete'); - $assert_session->pageTextContains('Media1'); - $assert_session->pageTextContains('Media2'); + $assert_session->pageTextContains($media1->id()); + $assert_session->pageTextContains($media2->id()); $this->drupalGet("media/1/delete"); $assert_session->pageTextContains('Page not found'); $this->drupalGet("media/2/delete"); $assert_session->pageTextContains('Page not found'); + + $this->drupalGet("/admin/content/files"); + $assert_session->pageTextNotContains('test.jpeg'); + } } From 9b58fc9ecbd2e79cfa04be6ff12e5551931ff9bb Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Thu, 10 Nov 2022 14:56:58 -0400 Subject: [PATCH 11/32] added islandora.libraries.yml --- css/islandora.theme.css | 3 +++ islandora.libraries.yml | 5 +++++ islandora.module | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 css/islandora.theme.css create mode 100644 islandora.libraries.yml diff --git a/css/islandora.theme.css b/css/islandora.theme.css new file mode 100644 index 00000000..696587ac --- /dev/null +++ b/css/islandora.theme.css @@ -0,0 +1,3 @@ +.container .islandora-media-items { + margin: 0; +} diff --git a/islandora.libraries.yml b/islandora.libraries.yml new file mode 100644 index 00000000..047006bf --- /dev/null +++ b/islandora.libraries.yml @@ -0,0 +1,5 @@ +drupal.islandora.theme_css: + version: VERSION + css: + theme: + css/islandora.theme.css: {} diff --git a/islandora.module b/islandora.module index 44dc35a7..66c74ad5 100644 --- a/islandora.module +++ b/islandora.module @@ -357,8 +357,8 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) '#theme' => 'item_list', '#type' => 'ul', '#items' => $media_list, - '#attributes' => ['class' => 'mylist'], - '#wrapper_attributes' => ['class' => 'container'], + '#attributes' => ['class' => ['islandora-media-items']], + '#wrapper_attributes' => ['class' => ['container']], '#attached' => [ 'library' => [ 'islandora/drupal.islandora.theme_css', From 5c24c190184b680914f10bae7fbff23fa33663bb Mon Sep 17 00:00:00 2001 From: shriram <saravananshriram80@gmail.com> Date: Tue, 15 Nov 2022 14:35:01 -0400 Subject: [PATCH 12/32] added feature toggle for the behavior --- islandora.module | 4 +++- src/Form/IslandoraSettingsForm.php | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/islandora.module b/islandora.module index 66c74ad5..5cab2cce 100644 --- a/islandora.module +++ b/islandora.module @@ -333,10 +333,12 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) } } } + $form_object = $form_state->getFormObject(); $utils = \Drupal::service('islandora.utils'); + $config = \Drupal::config('islandora.settings')->get('delete_media_and_files'); - if ($form_object instanceof EntityForm) { + if ($config == 1 && $form_object instanceof EntityForm) { $entity = $form_object->getEntity(); if ($entity->getEntityTypeId() == "node" && $utils->isIslandoraType($entity->getEntityTypeId(), $entity->bundle()) && strpos($form['#form_id'], 'delete_form') !== FALSE) { diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index 5049ef16..a65ab82f 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -42,6 +42,7 @@ class IslandoraSettingsForm extends ConfigFormBase { 'year', ]; const GEMINI_PSEUDO_FIELD = 'field_gemini_uri'; + const NODE_DELETE_MEDIA_AND_FILES = 'delete_media_and_files'; /** * To list the available bundle types. @@ -201,6 +202,14 @@ class IslandoraSettingsForm extends ConfigFormBase { $fedora_url = NULL; } + $form[self::NODE_DELETE_MEDIA_AND_FILES] = [ + '#type' => 'checkbox', + '#title' => $this->t('Node Delete with Media and Files'), + '#description' => $this->t('adds a checkbox in the "Delete" tab of islandora objects to delete media and files associated with the object.' + ), + '#default_value' => (bool) $config->get(self::NODE_DELETE_MEDIA_AND_FILES), + ]; + $form[self::FEDORA_URL] = [ '#type' => 'textfield', '#title' => $this->t('Fedora URL'), @@ -351,6 +360,7 @@ class IslandoraSettingsForm extends ConfigFormBase { ->set(self::UPLOAD_FORM_LOCATION, $form_state->getValue(self::UPLOAD_FORM_LOCATION)) ->set(self::UPLOAD_FORM_ALLOWED_MIMETYPES, $form_state->getValue(self::UPLOAD_FORM_ALLOWED_MIMETYPES)) ->set(self::GEMINI_PSEUDO, $new_pseudo_types) + ->set(self::NODE_DELETE_MEDIA_AND_FILES, $form_state->getValue(self::NODE_DELETE_MEDIA_AND_FILES)) ->save(); parent::submitForm($form, $form_state); From b0c43accb83d54402cf8989232f839fb66addc0f Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Mon, 21 Nov 2022 12:20:20 -0400 Subject: [PATCH 13/32] Upgrade the EVA to 3.0. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c02d7c16..eebdd9ab 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "drupal/jwt": "^1.0.0-beta5", "drupal/filehash": "^1.1 || ^2", "drupal/prepopulate" : "^2.2", - "drupal/eva" : "^2.0", + "drupal/eva" : "^3.0", "drupal/features" : "^3.7", "drupal/migrate_plus" : "^5.1", "drupal/migrate_source_csv" : "^3.4", From 4bed36dedeac2d7c05566ef0dde1a579987addd2 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Mon, 25 Jul 2022 13:43:30 -0300 Subject: [PATCH 14/32] Revert "Allowing Image fields for multi-file media (#860)" This reverts commit a297796f47b23b9f5a778d65fe6bee110a70d6ef. --- src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php b/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php index be9eca80..54e7bde0 100644 --- a/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php +++ b/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php @@ -88,16 +88,10 @@ class AbstractGenerateDerivativeMediaFile extends AbstractGenerateDerivativeBase */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form = parent::buildConfigurationForm($form, $form_state); - $map = $this->entityFieldManager->getFieldMapByFieldType('file'); $file_fields = $map['media']; $file_options = array_combine(array_keys($file_fields), array_keys($file_fields)); - - $map = $this->entityFieldManager->getFieldMapByFieldType('image'); - $image_fields = $map['media']; - $image_options = array_combine(array_keys($image_fields), array_keys($image_fields)); - - $file_options = array_merge(['' => ''], $file_options, $image_options); + $file_options = array_merge(['' => ''], $file_options); $form['event']['#disabled'] = 'disabled'; $form['destination_field_name'] = [ From 72eaaf659adf8e0a8a27a1c18f0a6b9729db34e0 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Tue, 26 Jul 2022 13:31:22 -0300 Subject: [PATCH 15/32] Add Image fields only to Image derivative code. Co-authored-by: @ajstanley <alanjarlathstanley@gmail.com> --- .../Action/GenerateImageDerivativeFile.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php b/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php index d6f99b58..54b215f3 100644 --- a/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php +++ b/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php @@ -34,7 +34,23 @@ class GenerateImageDerivativeFile extends AbstractGenerateDerivativeMediaFile { */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form = parent::buildConfigurationForm($form, $form_state); - $form['mimetype']['#description'] = $this->t('Mimetype to convert to (e.g. application/xml, etc...)'); + $map = $this->entityFieldManager->getFieldMapByFieldType('image'); + $file_fields = $map['media']; + $file_options = array_combine(array_keys($file_fields), array_keys($file_fields)); + $file_options = array_merge(['' => ''], $file_options); + // @todo figure out how to write to thumbnail, which is not a real field. + // see https://github.com/Islandora/islandora/issues/891. + unset($file_options['thumbnail']); + + $form['destination_field_name'] = [ + '#required' => TRUE, + '#type' => 'select', + '#options' => $file_options, + '#title' => $this->t('Destination Image field Name'), + '#default_value' => $this->configuration['destination_field_name'], + '#description' => $this->t('Image field on Media to hold derivative. Cannot be the same as source'), + ]; + $form['mimetype']['#value'] = 'image/jpeg'; $form['mimetype']['#type'] = 'hidden'; return $form; From 74dcfd0fa4a321f7007f8f464c37eee4d9f5c85d Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Thu, 24 Nov 2022 19:50:10 -0400 Subject: [PATCH 16/32] Improve wording on multi-file derivative Action forms. --- .../Action/GenerateImageDerivativeFile.php | 17 +++++++++---- src/Controller/MediaSourceController.php | 3 +-- src/MediaSource/MediaSourceService.php | 4 +-- .../AbstractGenerateDerivativeMediaFile.php | 25 ++++++++++++++++--- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php b/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php index 54b215f3..e0420fe8 100644 --- a/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php +++ b/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php @@ -6,7 +6,10 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\islandora\Plugin\Action\AbstractGenerateDerivativeMediaFile; /** - * Emits a Node for generating derivatives event. + * Emits a Media for generating derivatives event. + * + * Attaches the result as a file in an image field on the emitting + * Media ("multi-file media"). * * @Action( * id = "generate_image_derivative_file", @@ -24,7 +27,6 @@ class GenerateImageDerivativeFile extends AbstractGenerateDerivativeMediaFile { $config['path'] = '[date:custom:Y]-[date:custom:m]/[media:mid]-ImageService.jpg'; $config['mimetype'] = 'application/xml'; $config['queue'] = 'islandora-connector-houdini'; - $config['destination_media_type'] = 'file'; $config['scheme'] = $this->config->get('default_scheme'); return $config; } @@ -46,13 +48,18 @@ class GenerateImageDerivativeFile extends AbstractGenerateDerivativeMediaFile { '#required' => TRUE, '#type' => 'select', '#options' => $file_options, - '#title' => $this->t('Destination Image field Name'), + '#title' => $this->t('Destination Image field'), '#default_value' => $this->configuration['destination_field_name'], - '#description' => $this->t('Image field on Media to hold derivative. Cannot be the same as source'), + '#description' => $this->t('This Action stores the derivative in an + Image field. If you need to store the result in a File field, use + "Generate a Derivative File for Media Attachment". Selected target field + must be an additional field, not the media\'s main storage field. + Selected target field must be present on the media.'), ]; $form['mimetype']['#value'] = 'image/jpeg'; - $form['mimetype']['#type'] = 'hidden'; + $form['mimetype']['#description'] = 'Mimetype to convert to. Must be + compatible with the destination image field.'; return $form; } diff --git a/src/Controller/MediaSourceController.php b/src/Controller/MediaSourceController.php index bab43fcf..3d0e7909 100644 --- a/src/Controller/MediaSourceController.php +++ b/src/Controller/MediaSourceController.php @@ -280,8 +280,7 @@ class MediaSourceController extends ControllerBase { */ public function attachToMediaAccess(AccountInterface $account, RouteMatch $route_match) { $media = $route_match->getParameter('media'); - $node = $this->utils->getParentNode($media); - return AccessResult::allowedIf($node->access('update', $account) && $account->hasPermission('create media')); + return AccessResult::allowedIf($media->access('update', $account)); } } diff --git a/src/MediaSource/MediaSourceService.php b/src/MediaSource/MediaSourceService.php index 9399e334..60e41672 100644 --- a/src/MediaSource/MediaSourceService.php +++ b/src/MediaSource/MediaSourceService.php @@ -268,8 +268,8 @@ class MediaSourceService { 'uri' => $content_location, 'filename' => $this->fileSystem->basename($content_location), 'filemime' => $mimetype, - 'status' => FILE_STATUS_PERMANENT, ]); + $file->setPermanent(); // Validate file extension. $source_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$source_field"); @@ -349,8 +349,8 @@ class MediaSourceService { 'uri' => $content_location, 'filename' => $this->fileSystem->basename($content_location), 'filemime' => $mimetype, - 'status' => FILE_STATUS_PERMANENT, ]); + $file->setPermanent(); // Validate file extension. $bundle = $media->bundle(); diff --git a/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php b/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php index 54e7bde0..f0974b0c 100644 --- a/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php +++ b/src/Plugin/Action/AbstractGenerateDerivativeMediaFile.php @@ -7,7 +7,10 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; /** - * Emits a Node for generating derivatives event. + * Emits a Media for generating derivatives event. + * + * Attaches the result as a file in a file field on the emitting + * Media ("multi-file media"). * * @Action( * id = "generate_derivative_file", @@ -88,19 +91,33 @@ class AbstractGenerateDerivativeMediaFile extends AbstractGenerateDerivativeBase */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form = parent::buildConfigurationForm($form, $form_state); + $map = $this->entityFieldManager->getFieldMapByFieldType('file'); $file_fields = $map['media']; $file_options = array_combine(array_keys($file_fields), array_keys($file_fields)); - $file_options = array_merge(['' => ''], $file_options); + + $map = $this->entityFieldManager->getFieldMapByFieldType('image'); + $image_fields = $map['media']; + $image_options = array_combine(array_keys($image_fields), array_keys($image_fields)); + + $file_options = array_merge(['' => ''], $file_options, $image_options); + + // @todo figure out how to write to thumbnail, which is not a real field. + // see https://github.com/Islandora/islandora/issues/891. + unset($file_options['thumbnail']); + $form['event']['#disabled'] = 'disabled'; $form['destination_field_name'] = [ '#required' => TRUE, '#type' => 'select', '#options' => $file_options, - '#title' => $this->t('Destination File field Name'), + '#title' => $this->t('Destination File field'), '#default_value' => $this->configuration['destination_field_name'], - '#description' => $this->t('File field on Media Type to hold derivative. Cannot be the same as source'), + '#description' => $this->t('This Action stores a derivative file + in a File or Image field on a media. The destination field + must be an additional field, not the media\'s main storage field. + Selected destination field must be present on the media.'), ]; $form['args'] = [ From 48b5333b2d8d84c5bdf3ed494aaa89085cc3c82f Mon Sep 17 00:00:00 2001 From: shriram1056 <shriram1056@outlook.com> Date: Fri, 25 Nov 2022 11:36:09 -0400 Subject: [PATCH 17/32] skip entity types protected by entity integrity reference and updated test cases for toggle feature --- config/install/islandora.settings.yml | 1 + config/schema/islandora.schema.yml | 5 +- islandora.module | 50 ++++++++++++------- .../Functional/DeleteNodeWithMediaAndFile.php | 5 ++ 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/config/install/islandora.settings.yml b/config/install/islandora.settings.yml index 8fb25fb8..179d4213 100644 --- a/config/install/islandora.settings.yml +++ b/config/install/islandora.settings.yml @@ -1,4 +1,5 @@ broker_url: 'tcp://localhost:61613' jwt_expiry: '+2 hour' gemini_url: '' +delete_media_and_files: TRUE gemini_pseudo_bundles: [] diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml index e85d5739..86b65fd0 100644 --- a/config/schema/islandora.schema.yml +++ b/config/schema/islandora.schema.yml @@ -14,6 +14,9 @@ islandora.settings: jwt_expiry: type: string label: 'How long JWTs should last before expiring.' + delete_media_and_files: + type: boolean + label: 'Node Delete with Media and Files' upload_form_location: type: string label: 'Upload Form Location' @@ -166,7 +169,7 @@ condition.plugin.node_had_namespace: pid_field: type: ignore label: 'PID field' - + field.formatter.settings.islandora_image: type: field.formatter.settings.image label: 'Islandora image field display format settings' diff --git a/islandora.module b/islandora.module index 5cab2cce..b651f291 100644 --- a/islandora.module +++ b/islandora.module @@ -373,6 +373,7 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) } } } + return $form; } @@ -390,7 +391,6 @@ function islandora_object_delete_form_submit($form, &$form_state) { $medias = $utils->getMedia($node); $media_list = ""; - $entity_type_manager = \Drupal::entityTypeManager(); $entity_field_manager = \Drupal::service('entity_field.manager'); $current_user = \Drupal::currentUser(); $logger = \Drupal::logger('logger.channel.islandora'); @@ -398,14 +398,12 @@ function islandora_object_delete_form_submit($form, &$form_state) { $total_count = 0; $delete_media = []; - $delete_media_translations = []; - $delete_files = []; + $media_translations = []; + $media_files = []; + $entity_protected_medias = []; $inaccessible_entities = []; - $media_storage = $entity_type_manager->getStorage('media'); - $file_storage = $entity_type_manager->getStorage('file'); foreach ($medias as $id => $media) { - $media_list .= $id . ", "; $lang = $media->language()->getId(); $selected_langcodes[$lang] = $lang; @@ -425,7 +423,7 @@ function islandora_object_delete_form_submit($form, &$form_state) { $inaccessible_entities[] = $file; continue; } - $delete_files[$file->id()] = $file; + $media_files[$id][$file->id()] = $file; $total_count++; } } @@ -436,33 +434,49 @@ function islandora_object_delete_form_submit($form, &$form_state) { $entity = $media->getTranslation($langcode); if ($entity->isDefaultTranslation()) { $delete_media[$id] = $entity; - unset($delete_media_translations[$id]); + unset($media_translations[$id]); $total_count += count($entity->getTranslationLanguages()); } elseif (!isset($delete_media[$id])) { - $delete_media_translations[$id][] = $entity; + $media_translations[$id][] = $entity; } } } if ($delete_media) { - $media_storage->delete($delete_media); foreach ($delete_media as $media) { - $logger->notice('The media %label has been deleted.', [ - '%label' => $media->label(), - ]); + try { + $media->delete(); + $logger->notice('The media %label has been deleted.', [ + '%label' => $media->label(), + ]); + $media_list .= $id . ", "; + } + 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) { - $file_storage->delete($delete_files); - foreach ($delete_files as $file) { - $logger->notice('The file %label has been deleted.', [ - '%label' => $file->label(), - ]); + 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]; diff --git a/tests/src/Functional/DeleteNodeWithMediaAndFile.php b/tests/src/Functional/DeleteNodeWithMediaAndFile.php index ff793f0d..40e469c5 100644 --- a/tests/src/Functional/DeleteNodeWithMediaAndFile.php +++ b/tests/src/Functional/DeleteNodeWithMediaAndFile.php @@ -19,6 +19,7 @@ class DeleteNodeWithMediaAndFile extends IslandoraFunctionalTestBase { 'view media', 'bypass node access', 'access files overview', + 'administer site configuration', ]); $this->drupalLogin($account); @@ -75,6 +76,10 @@ class DeleteNodeWithMediaAndFile extends IslandoraFunctionalTestBase { ]); $media2->save(); + $this->drupalGet("admin/config/islandora/core"); + $assert_session->pageTextContains('Node Delete with Media and Files'); + \Drupal::configFactory()->getEditable('islandora.settings')->set('delete_media_and_files', TRUE)->save(); + $delete = ['delete_associated_content' => TRUE]; $this->drupalGet("node/1/delete"); From e15b6322ff98df666a0df16200904a33cd8a2de0 Mon Sep 17 00:00:00 2001 From: shriram1056 <shriram1056@outlook.com> Date: Fri, 25 Nov 2022 13:28:24 -0400 Subject: [PATCH 18/32] fixed log message --- islandora.module | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/islandora.module b/islandora.module index b651f291..05e18c4a 100644 --- a/islandora.module +++ b/islandora.module @@ -444,13 +444,13 @@ function islandora_object_delete_form_submit($form, &$form_state) { } if ($delete_media) { - foreach ($delete_media as $media) { + foreach ($delete_media as $id => $media) { try { $media->delete(); + $media_list .= $id . ", "; $logger->notice('The media %label has been deleted.', [ '%label' => $media->label(), ]); - $media_list .= $id . ", "; } catch (Exception $e) { $entity_protected_medias[] = $id; From 541620493b197052dd42b9584eb1cb6e36b6699c Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Wed, 30 Nov 2022 10:07:19 -0400 Subject: [PATCH 19/32] Updates settings and view for filehash^2. --- composer.json | 2 +- .../config/install/filehash.settings.yml | 21 ++- .../install/views.view.file_checksum.yml | 159 ++++++++++-------- 3 files changed, 109 insertions(+), 73 deletions(-) diff --git a/composer.json b/composer.json index c02d7c16..8fe708ed 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "islandora/jsonld": "^2", "stomp-php/stomp-php": "4.* || ^5", "drupal/jwt": "^1.0.0-beta5", - "drupal/filehash": "^1.1 || ^2", + "drupal/filehash": "^2", "drupal/prepopulate" : "^2.2", "drupal/eva" : "^2.0", "drupal/features" : "^3.7", diff --git a/modules/islandora_core_feature/config/install/filehash.settings.yml b/modules/islandora_core_feature/config/install/filehash.settings.yml index 7deecc69..1ac77eec 100644 --- a/modules/islandora_core_feature/config/install/filehash.settings.yml +++ b/modules/islandora_core_feature/config/install/filehash.settings.yml @@ -1,5 +1,24 @@ algos: - sha1: sha1 + blake2b_128: '0' + blake2b_160: '0' + blake2b_224: '0' + blake2b_256: '0' + blake2b_384: '0' + blake2b_512: '0' md5: '0' + sha1: sha1 + sha224: '0' sha256: '0' + sha384: '0' + sha512_224: '0' + sha512_256: '0' + sha512: '0' + sha3_224: '0' + sha3_256: '0' + sha3_384: '0' + sha3_512: '0' dedupe: 0 +rehash: false +original: false +dedupe_original: false +mime_types: { } diff --git a/modules/islandora_core_feature/config/install/views.view.file_checksum.yml b/modules/islandora_core_feature/config/install/views.view.file_checksum.yml index b498ba66..a9fd4584 100644 --- a/modules/islandora_core_feature/config/install/views.view.file_checksum.yml +++ b/modules/islandora_core_feature/config/install/views.view.file_checksum.yml @@ -1,14 +1,14 @@ langcode: en status: true dependencies: - enforced: - module: - - islandora_core_feature module: - file - filehash - rest - serialization + enforced: + module: + - islandora_core_feature id: file_checksum label: 'File Checksum' module: views @@ -16,71 +16,24 @@ description: 'Exposes a REST endpoint for getting the checksum of a File' tag: '' base_table: file_managed base_field: fid -core: 8.x display: default: - display_plugin: default id: default display_title: Master + display_plugin: default position: 0 display_options: - access: - type: none - options: { } - cache: - type: tag - options: { } - query: - type: views_query - options: - disable_sql_rewrite: false - distinct: false - replica: false - query_comment: '' - query_tags: { } - exposed_form: - type: basic - options: - submit_button: Apply - reset_button: false - reset_button_label: Reset - exposed_sorts_label: 'Sort by' - expose_sort_order: true - sort_asc_label: Asc - sort_desc_label: Desc - pager: - type: mini - options: - items_per_page: 10 - offset: 0 - id: 0 - total_pages: null - expose: - items_per_page: false - items_per_page_label: 'Items per page' - items_per_page_options: '5, 10, 25, 50' - items_per_page_options_all: false - items_per_page_options_all_label: '- All -' - offset: false - offset_label: Offset - tags: - previous: ‹‹ - next: ›› - style: - type: serializer - row: - type: 'entity:file' - options: - relationship: none - view_mode: default fields: sha1: id: sha1 - table: filehash + table: file_managed field: sha1 relationship: none group_type: group admin_label: '' + entity_type: file + entity_field: sha1 + plugin_id: field label: '' exclude: false alter: @@ -92,7 +45,7 @@ display: external: false replace_spaces: false path_case: none - trim_whitespace: false + trim_whitespace: true alt: '' rel: '' link_class: '' @@ -106,7 +59,7 @@ display: more_link: false more_link_text: '' more_link_path: '' - strip_tags: false + strip_tags: true trim: false preserve_tags: '' html: false @@ -122,13 +75,55 @@ display: hide_empty: false empty_zero: false hide_alter_empty: true - plugin_id: standard - filters: { } - sorts: { } - header: { } - footer: { } + click_sort_column: value + type: filehash + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + pager: + type: mini + options: + offset: 0 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + access: + type: none + options: { } + cache: + type: tag + options: { } empty: { } - relationships: { } + sorts: { } arguments: fid: id: fid @@ -137,6 +132,9 @@ display: relationship: none group_type: group admin_label: '' + entity_type: file + entity_field: fid + plugin_id: file_fid default_action: 'not found' exception: value: all @@ -151,8 +149,8 @@ display: summary_options: base_path: '' count: true - items_per_page: 25 override: false + items_per_page: 25 summary: sort_order: asc number_of_records: 0 @@ -164,31 +162,46 @@ display: validate_options: { } break_phrase: false not: false - entity_type: file - entity_field: fid - plugin_id: file_fid + filters: { } + style: + type: serializer + row: + type: 'entity:file' + options: + relationship: none + view_mode: default + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + header: { } + footer: { } display_extenders: { } cache_metadata: max-age: -1 contexts: + - 'languages:language_content' - 'languages:language_interface' - request_format - url - url.query_args tags: { } rest_export_1: - display_plugin: rest_export id: rest_export_1 display_title: 'REST export' + display_plugin: rest_export position: 1 display_options: - display_extenders: { } - path: checksum/%file pager: type: some options: - items_per_page: 10 offset: 0 + items_per_page: 10 style: type: serializer options: @@ -198,6 +211,8 @@ display: type: data_field options: field_options: { } + display_extenders: { } + path: checksum/%file auth: - basic_auth - jwt_auth @@ -205,7 +220,9 @@ display: cache_metadata: max-age: -1 contexts: + - 'languages:language_content' - 'languages:language_interface' - request_format - url tags: { } + From def4fda5b6021f6d14288a6880762150648a677f Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Wed, 30 Nov 2022 10:51:05 -0400 Subject: [PATCH 20/32] Include original hash, and re-hash. --- .../config/install/filehash.settings.yml | 4 +- .../install/views.view.file_checksum.yml | 85 ++++++++++++++++++- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/modules/islandora_core_feature/config/install/filehash.settings.yml b/modules/islandora_core_feature/config/install/filehash.settings.yml index 1ac77eec..3dcae297 100644 --- a/modules/islandora_core_feature/config/install/filehash.settings.yml +++ b/modules/islandora_core_feature/config/install/filehash.settings.yml @@ -18,7 +18,7 @@ algos: sha3_384: '0' sha3_512: '0' dedupe: 0 -rehash: false -original: false +rehash: true +original: true dedupe_original: false mime_types: { } diff --git a/modules/islandora_core_feature/config/install/views.view.file_checksum.yml b/modules/islandora_core_feature/config/install/views.view.file_checksum.yml index a9fd4584..2c819101 100644 --- a/modules/islandora_core_feature/config/install/views.view.file_checksum.yml +++ b/modules/islandora_core_feature/config/install/views.view.file_checksum.yml @@ -6,6 +6,7 @@ dependencies: - filehash - rest - serialization + - user enforced: module: - islandora_core_feature @@ -88,6 +89,70 @@ display: multi_type: separator separator: ', ' field_api_classes: false + original_sha1: + id: original_sha1 + table: file_managed + field: original_sha1 + relationship: none + group_type: group + admin_label: '' + entity_type: file + entity_field: original_sha1 + plugin_id: field + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: true + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: true + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: false + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: filehash + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false pager: type: mini options: @@ -117,8 +182,9 @@ display: sort_asc_label: Asc sort_desc_label: Desc access: - type: none - options: { } + type: perm + options: + perm: 'view checksums' cache: type: tag options: { } @@ -190,6 +256,7 @@ display: - request_format - url - url.query_args + - user.permissions tags: { } rest_export_1: id: rest_export_1 @@ -211,7 +278,18 @@ display: type: data_field options: field_options: { } - display_extenders: { } + display_extenders: + matomo: + enabled: false + keyword_gets: '' + keyword_behavior: first + keyword_concat_separator: ' ' + category_behavior: none + category_gets: '' + category_concat_separator: ' ' + category_fallback: '' + category_facets: { } + category_facets_concat_separator: ', ' path: checksum/%file auth: - basic_auth @@ -224,5 +302,6 @@ display: - 'languages:language_interface' - request_format - url + - user.permissions tags: { } From 5f4a6ab3ae474f8c4e11bddb85feb36e386a2b54 Mon Sep 17 00:00:00 2001 From: Jason Hildebrand <jason@peaceworks.ca> Date: Thu, 1 Dec 2022 14:24:35 -0600 Subject: [PATCH 21/32] Eliminate warnings when using NodeHasMediaUse views filter. (#914) --- src/Plugin/views/filter/NodeHasMediaUse.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Plugin/views/filter/NodeHasMediaUse.php b/src/Plugin/views/filter/NodeHasMediaUse.php index 0209505d..3c69bddd 100644 --- a/src/Plugin/views/filter/NodeHasMediaUse.php +++ b/src/Plugin/views/filter/NodeHasMediaUse.php @@ -18,10 +18,10 @@ class NodeHasMediaUse extends FilterPluginBase { * {@inheritdoc} */ protected function defineOptions() { - return [ - 'use_uri' => ['default' => NULL], - 'negated' => ['default' => FALSE], - ]; + $options = parent::defineOptions(); + $options['use_uri'] = ['default' => NULL]; + $options['negated'] = ['default' => FALSE]; + return $options; } /** From f71f6dc2e874e85855038a107fdc163cff183038 Mon Sep 17 00:00:00 2001 From: Jason Hildebrand <jason@peaceworks.ca> Date: Thu, 1 Dec 2022 16:13:40 -0600 Subject: [PATCH 22/32] Fix warning by checking whether key is set. (#909) * Fix warning by checking whether key is set. * Adjust plugin check in integer-weight views hook. --- islandora.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/islandora.module b/islandora.module index 5b5446d1..9814820e 100644 --- a/islandora.module +++ b/islandora.module @@ -515,7 +515,7 @@ function islandora_preprocess_views_view_table(&$variables) { // Check for a weight selector field. foreach ($variables['view']->field as $field_key => $field) { - if ($field->options['plugin_id'] == 'integer_weight_selector') { + if ($field->getPluginId() == 'integer_weight_selector') { // Check if the weight selector is on the first column. $is_first_column = array_search($field_key, array_keys($variables['view']->field)) > 0 ? FALSE : TRUE; From 6c582a870227ac39022b2a20df4a554a1e2c54e3 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Thu, 1 Dec 2022 19:05:49 -0400 Subject: [PATCH 23/32] Permit newer version of migrate_plus. This version has PHP 8.1 support. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index eebdd9ab..29b40894 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "drupal/prepopulate" : "^2.2", "drupal/eva" : "^3.0", "drupal/features" : "^3.7", - "drupal/migrate_plus" : "^5.1", + "drupal/migrate_plus" : "^5.1 || ^6", "drupal/migrate_source_csv" : "^3.4", "drupal/token" : "^1.3", "drupal/flysystem" : "^2.0@alpha", From ee85472dc8b0d2e0517f7cc787da7f73271cf63b Mon Sep 17 00:00:00 2001 From: shriram1056 <saravananshriram80@gmail.com> Date: Fri, 2 Dec 2022 16:36:04 -0400 Subject: [PATCH 24/32] minor changes and post_update for delete_media_and_files --- css/{islandora.theme.css => islandora.css} | 0 islandora.libraries.yml | 4 +-- islandora.module | 32 +++++++++++++--------- islandora.post_update.php | 16 +++++++++++ src/Form/IslandoraSettingsForm.php | 2 +- 5 files changed, 38 insertions(+), 16 deletions(-) rename css/{islandora.theme.css => islandora.css} (100%) create mode 100644 islandora.post_update.php diff --git a/css/islandora.theme.css b/css/islandora.css similarity index 100% rename from css/islandora.theme.css rename to css/islandora.css diff --git a/islandora.libraries.yml b/islandora.libraries.yml index 047006bf..840dc294 100644 --- a/islandora.libraries.yml +++ b/islandora.libraries.yml @@ -1,5 +1,5 @@ -drupal.islandora.theme_css: +islandora: version: VERSION css: theme: - css/islandora.theme.css: {} + css/islandora.css: {} diff --git a/islandora.module b/islandora.module index 05e18c4a..64b65ca8 100644 --- a/islandora.module +++ b/islandora.module @@ -355,7 +355,16 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) $media_list[] = $media->getName(); } - $form['media_items'] = [ + $form['container'] = [ + '#type' => 'container', + '#states' => [ + 'visible' => [ + ':input[name="delete_associated_content"]' => ['checked' => TRUE], + ], + ], + ]; + + $form['container']['media_items'] = [ '#theme' => 'item_list', '#type' => 'ul', '#items' => $media_list, @@ -363,7 +372,7 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) '#wrapper_attributes' => ['class' => ['container']], '#attached' => [ 'library' => [ - 'islandora/drupal.islandora.theme_css', + 'islandora/islandora', ], ], ]; @@ -380,7 +389,7 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id) /** * Implements a submit handler for the delete form. */ -function islandora_object_delete_form_submit($form, &$form_state) { +function islandora_object_delete_form_submit($form, FormStateInterface $form_state) { $result = $form_state->getValues('delete_associated_content'); $utils = \Drupal::service('islandora.utils'); @@ -389,14 +398,13 @@ function islandora_object_delete_form_submit($form, &$form_state) { $node = $form_state->getFormObject()->getEntity(); $medias = $utils->getMedia($node); - $media_list = ""; + $media_list = []; $entity_field_manager = \Drupal::service('entity_field.manager'); $current_user = \Drupal::currentUser(); $logger = \Drupal::logger('logger.channel.islandora'); $messenger = \Drupal::messenger(); - $total_count = 0; $delete_media = []; $media_translations = []; $media_files = []; @@ -424,7 +432,6 @@ function islandora_object_delete_form_submit($form, &$form_state) { continue; } $media_files[$id][$file->id()] = $file; - $total_count++; } } } @@ -435,7 +442,6 @@ function islandora_object_delete_form_submit($form, &$form_state) { if ($entity->isDefaultTranslation()) { $delete_media[$id] = $entity; unset($media_translations[$id]); - $total_count += count($entity->getTranslationLanguages()); } elseif (!isset($delete_media[$id])) { $media_translations[$id][] = $entity; @@ -447,7 +453,7 @@ function islandora_object_delete_form_submit($form, &$form_state) { foreach ($delete_media as $id => $media) { try { $media->delete(); - $media_list .= $id . ", "; + $media_list[] = $id; $logger->notice('The media %label has been deleted.', [ '%label' => $media->label(), ]); @@ -490,12 +496,11 @@ function islandora_object_delete_form_submit($form, &$form_state) { '@language' => $translation->language()->getName(), ]); } - $total_count += count($translations); } } if ($inaccessible_entities) { - $messenger->addWarning("@count items has not been deleted because you do not have the necessary permissions.", [ + $messenger->addWarning("@count items have not been deleted because you do not have the necessary permissions.", [ '@count' => count($inaccessible_entities), ]); } @@ -507,9 +512,10 @@ function islandora_object_delete_form_submit($form, &$form_state) { '#value' => t("The repository item @node and @media", [ '@node' => $node->getTitle(), '@media' => \Drupal::translation()->formatPlural( - substr_count($media_list, ",") + 1, 'the media with the id @media has been deleted.', - 'the medias with the id @media have been deleted.', - ['@media' => mb_substr($media_list, 0, strlen($media_list) - 2)]), + 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)], + ), ]), ], ]; diff --git a/islandora.post_update.php b/islandora.post_update.php new file mode 100644 index 00000000..0a29e56e --- /dev/null +++ b/islandora.post_update.php @@ -0,0 +1,16 @@ +<?php + +/** + * @file + * Post updates. + */ + +/** + * Set default value for delete_media_and_files field in settings. + */ +function islandora_post_update_delete_media_and_files() { + $config_factory = \Drupal::configFactory(); + $config = $config_factory->getEditable('islandora.settings'); + $config->set('delete_media_and_files', TRUE); + $config->save(TRUE); +} diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index a65ab82f..90e0b420 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -205,7 +205,7 @@ class IslandoraSettingsForm extends ConfigFormBase { $form[self::NODE_DELETE_MEDIA_AND_FILES] = [ '#type' => 'checkbox', '#title' => $this->t('Node Delete with Media and Files'), - '#description' => $this->t('adds a checkbox in the "Delete" tab of islandora objects to delete media and files associated with the object.' + '#description' => $this->t('Adds a checkbox in the "Delete" tab of islandora objects to delete media and files associated with the object.' ), '#default_value' => (bool) $config->get(self::NODE_DELETE_MEDIA_AND_FILES), ]; From b47d37b1b69c97540a7ea7a772d7785040fbace7 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Tue, 6 Dec 2022 19:48:55 -0400 Subject: [PATCH 25/32] Fix errors when OCR field not set. --- .../islandora_iiif/src/Plugin/views/style/IIIFManifest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php b/modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php index cc4b5e94..c2a2fbc3 100644 --- a/modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php +++ b/modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php @@ -205,11 +205,13 @@ class IIIFManifest extends StylePluginBase { continue; } - $ocrs = $entity->{$ocrField->definition['field_name']}; + if (!is_null($ocrField)) { + $ocrs = $entity->{$ocrField->definition['field_name']}; + $ocr = isset($ocrs[$i]) ? $ocrs[$i] : FALSE; + } // Create the IIIF URL for this file // Visiting $iiif_url will resolve to the info.json for the image. - $ocr = isset($ocrs[$i]) ? $ocrs[$i] : FALSE; $file_url = $image->entity->createFileUrl(FALSE); $mime_type = $image->entity->getMimeType(); $iiif_url = rtrim($iiif_address, '/') . '/' . urlencode($file_url); From 0b7f12d3baeefc230fcc6f426e668a3d5ab27247 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Fri, 9 Dec 2022 11:41:36 -0400 Subject: [PATCH 26/32] No infinite derivatives. --- src/EventGenerator/EmitEvent.php | 4 ++++ src/Plugin/Action/AbstractGenerateDerivative.php | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/EventGenerator/EmitEvent.php b/src/EventGenerator/EmitEvent.php index 683f3e8b..2e0d226e 100644 --- a/src/EventGenerator/EmitEvent.php +++ b/src/EventGenerator/EmitEvent.php @@ -157,6 +157,10 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact $user = $this->entityTypeManager->getStorage('user')->load($this->account->id()); $data = $this->generateData($entity); + // If $data is the bool false, then abort. No error, but don't emit event. + if ($data === FALSE) { + return; + } $event = $this->eventDispatcher->dispatch( StompHeaderEvent::EVENT_NAME, diff --git a/src/Plugin/Action/AbstractGenerateDerivative.php b/src/Plugin/Action/AbstractGenerateDerivative.php index b22201e1..129af994 100644 --- a/src/Plugin/Action/AbstractGenerateDerivative.php +++ b/src/Plugin/Action/AbstractGenerateDerivative.php @@ -60,6 +60,13 @@ class AbstractGenerateDerivative extends AbstractGenerateDerivativeBase { throw new \RuntimeException("Could not locate taxonomy term with uri: " . $this->configuration['derivative_term_uri'], 500); } + // See if there is a destination media already set, and abort if it's the + // same as the source media. Dont cause an error, just don't continue. + $derivative_media = $this->utils->getMediaWithTerm($entity, $derivative_term); + if (!is_null($derivative_media) && $derivative_media->id() == $source_media->id()) { + return FALSE; + } + $route_params = [ 'node' => $entity->id(), 'media_type' => $this->configuration['destination_media_type'], From 41f87101226ec466ba369dcd3b98b42255dd48da Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Tue, 13 Dec 2022 16:43:06 -0400 Subject: [PATCH 27/32] Use a proper exception. --- src/EventGenerator/EmitEvent.php | 9 +++++---- src/Exception/IslandoraDerivativeException.php | 12 ++++++++++++ src/Plugin/Action/AbstractGenerateDerivative.php | 3 ++- 3 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 src/Exception/IslandoraDerivativeException.php diff --git a/src/EventGenerator/EmitEvent.php b/src/EventGenerator/EmitEvent.php index 2e0d226e..fd33fd99 100644 --- a/src/EventGenerator/EmitEvent.php +++ b/src/EventGenerator/EmitEvent.php @@ -14,6 +14,7 @@ use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\islandora\Event\StompHeaderEvent; use Drupal\islandora\Event\StompHeaderEventException; +use Drupal\islandora\Exception\IslandoraDerivativeException; use Stomp\Exception\StompException; use Stomp\StatefulStomp; use Stomp\Transport\Message; @@ -157,10 +158,6 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact $user = $this->entityTypeManager->getStorage('user')->load($this->account->id()); $data = $this->generateData($entity); - // If $data is the bool false, then abort. No error, but don't emit event. - if ($data === FALSE) { - return; - } $event = $this->eventDispatcher->dispatch( StompHeaderEvent::EVENT_NAME, @@ -172,6 +169,10 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact $event->getHeaders()->all() ); } + catch (IslandoraDerivativeException $e) { + $this->logger->info($e->getMessage()); + return; + } catch (StompHeaderEventException $e) { $this->logger->error($e->getMessage()); $this->messenger->addError($e->getMessage()); diff --git a/src/Exception/IslandoraDerivativeException.php b/src/Exception/IslandoraDerivativeException.php new file mode 100644 index 00000000..66f63606 --- /dev/null +++ b/src/Exception/IslandoraDerivativeException.php @@ -0,0 +1,12 @@ +<?php + +namespace Drupal\islandora\Exception; + +/** + * Islandora exceptions. + * + * @package islandora + */ +class IslandoraDerivativeException extends \RuntimeException +{ +} diff --git a/src/Plugin/Action/AbstractGenerateDerivative.php b/src/Plugin/Action/AbstractGenerateDerivative.php index 129af994..339d1d87 100644 --- a/src/Plugin/Action/AbstractGenerateDerivative.php +++ b/src/Plugin/Action/AbstractGenerateDerivative.php @@ -5,6 +5,7 @@ namespace Drupal\islandora\Plugin\Action; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Drupal\islandora\Exception\IslandoraDerivativeException; /** * Emits a Node event. @@ -64,7 +65,7 @@ class AbstractGenerateDerivative extends AbstractGenerateDerivativeBase { // same as the source media. Dont cause an error, just don't continue. $derivative_media = $this->utils->getMediaWithTerm($entity, $derivative_term); if (!is_null($derivative_media) && $derivative_media->id() == $source_media->id()) { - return FALSE; + throw new IslandoraDerivativeException("Halting derivative, as source and target media are the same. Derivative term: [" . $this->configuration['derivative_term_uri'] . "] Source term: [" . $this->configuration['source_term_uri'] . "] Node id: [". $entity->id() . "].", 500); } $route_params = [ From 665abfbd6c48418c30eb30a57fb394fe07a2b715 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Tue, 13 Dec 2022 17:12:44 -0400 Subject: [PATCH 28/32] phpcs. --- src/Exception/IslandoraDerivativeException.php | 3 +-- src/Plugin/Action/AbstractGenerateDerivative.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Exception/IslandoraDerivativeException.php b/src/Exception/IslandoraDerivativeException.php index 66f63606..7efe4773 100644 --- a/src/Exception/IslandoraDerivativeException.php +++ b/src/Exception/IslandoraDerivativeException.php @@ -7,6 +7,5 @@ namespace Drupal\islandora\Exception; * * @package islandora */ -class IslandoraDerivativeException extends \RuntimeException -{ +class IslandoraDerivativeException extends \RuntimeException { } diff --git a/src/Plugin/Action/AbstractGenerateDerivative.php b/src/Plugin/Action/AbstractGenerateDerivative.php index 339d1d87..b44db477 100644 --- a/src/Plugin/Action/AbstractGenerateDerivative.php +++ b/src/Plugin/Action/AbstractGenerateDerivative.php @@ -65,7 +65,7 @@ class AbstractGenerateDerivative extends AbstractGenerateDerivativeBase { // same as the source media. Dont cause an error, just don't continue. $derivative_media = $this->utils->getMediaWithTerm($entity, $derivative_term); if (!is_null($derivative_media) && $derivative_media->id() == $source_media->id()) { - throw new IslandoraDerivativeException("Halting derivative, as source and target media are the same. Derivative term: [" . $this->configuration['derivative_term_uri'] . "] Source term: [" . $this->configuration['source_term_uri'] . "] Node id: [". $entity->id() . "].", 500); + throw new IslandoraDerivativeException("Halting derivative, as source and target media are the same. Derivative term: [" . $this->configuration['derivative_term_uri'] . "] Source term: [" . $this->configuration['source_term_uri'] . "] Node id: [" . $entity->id() . "].", 500); } $route_params = [ From 7df45a083a21e33c17026ff9629d32abe5a91463 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Tue, 13 Dec 2022 19:22:12 -0400 Subject: [PATCH 29/32] Use new syntax for filehash. --- islandora.module | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/islandora.module b/islandora.module index 5b5446d1..faf24fdc 100644 --- a/islandora.module +++ b/islandora.module @@ -181,7 +181,8 @@ function islandora_file_insert(FileInterface $file) { */ function islandora_file_update(FileInterface $file) { // Exit early if unchanged. - if ($file->filehash != NULL && $file->original->filehash != NULL && $file->filehash['sha1'] == $file->original->filehash['sha1']) { + if ($file->hasField('sha1') && $file->original->hasField('sha1') + && $file->sha1->getString() == $file->original->sha1->getString()) { return; } From b326d967a692ac0051ce4fed0c3c99bb8243a964 Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Wed, 14 Dec 2022 10:39:01 -0400 Subject: [PATCH 30/32] Update dependencies. --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 43533a69..c1bfaa2d 100644 --- a/composer.json +++ b/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "drupal/context": "^4.0@beta", - "drupal/search_api": "~1.8", + "drupal/context": "^4", + "drupal/search_api": "^1.8", "islandora/jsonld": "^2", "stomp-php/stomp-php": "4.* || ^5", - "drupal/jwt": "^1.0.0-beta5", + "drupal/jwt": "^1.0", "drupal/filehash": "^2", "drupal/prepopulate" : "^2.2", "drupal/eva" : "^3.0", From 12e28f1284ef32052414a0e0a3cd74158813259e Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Wed, 14 Dec 2022 10:39:37 -0400 Subject: [PATCH 31/32] Sort dependencies. --- composer.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index c1bfaa2d..0b443c02 100644 --- a/composer.json +++ b/composer.json @@ -15,21 +15,21 @@ ], "require": { "drupal/context": "^4", - "drupal/search_api": "^1.8", - "islandora/jsonld": "^2", - "stomp-php/stomp-php": "4.* || ^5", - "drupal/jwt": "^1.0", - "drupal/filehash": "^2", - "drupal/prepopulate" : "^2.2", + "drupal/ctools": "^3.8 || ^4", "drupal/eva" : "^3.0", "drupal/features" : "^3.7", + "drupal/file_replace": "^1.1", + "drupal/filehash": "^2", + "drupal/flysystem" : "^2.0@alpha", + "drupal/jwt": "^1.0", "drupal/migrate_plus" : "^5.1 || ^6", "drupal/migrate_source_csv" : "^3.4", + "drupal/prepopulate" : "^2.2", + "drupal/search_api": "^1.8", "drupal/token" : "^1.3", - "drupal/flysystem" : "^2.0@alpha", "islandora/crayfish-commons": "^2", - "drupal/file_replace": "^1.1", - "drupal/ctools": "^3.8 || ^4" + "islandora/jsonld": "^2", + "stomp-php/stomp-php": "4.* || ^5" }, "require-dev": { "phpunit/phpunit": "^6", From cefee615c0477a1067fc703074da7aa6b24a57bd Mon Sep 17 00:00:00 2001 From: Rosie Le Faive <lefaive@gmail.com> Date: Wed, 14 Dec 2022 13:54:33 -0400 Subject: [PATCH 32/32] Warn re. tiffs and jp2s in image file derivatives. (#921) * Warn re. tiffs and jp2s in image file derivatives. * Update wording. --- .../src/Plugin/Action/GenerateImageDerivativeFile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php b/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php index e0420fe8..a6e06774 100644 --- a/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php +++ b/modules/islandora_image/src/Plugin/Action/GenerateImageDerivativeFile.php @@ -51,7 +51,7 @@ class GenerateImageDerivativeFile extends AbstractGenerateDerivativeMediaFile { '#title' => $this->t('Destination Image field'), '#default_value' => $this->configuration['destination_field_name'], '#description' => $this->t('This Action stores the derivative in an - Image field. If you need to store the result in a File field, use + Image field. If you are creating a TIFF or JP2, instead use "Generate a Derivative File for Media Attachment". Selected target field must be an additional field, not the media\'s main storage field. Selected target field must be present on the media.'),