Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

BCIR-247 : islandora_entity_status - Moderation Integration #9

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

Cascades entity status to all referenced entities in an Islandora repository item

## Usage
When and What operation we are performing.
- Node Update
- On status change update all media and assign same status.
- If node is collection
- Show confirmation popup before save.
- on status change or workflow status change
- update status of all attached nodes and respective attached media.
- Media presave
- Assign the status of the Media Of node.

## Requirements

This module requires the following modules/libraries:
Expand Down
1 change: 1 addition & 0 deletions islandora_entity_status.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ dependencies:
- drupal:node
- drupal:file
- islandora:islandora
- islandora_events:islandora_events
162 changes: 16 additions & 146 deletions islandora_entity_status.module
Original file line number Diff line number Diff line change
Expand Up @@ -5,160 +5,30 @@
* Hook implementations.
*/

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\islandora\IslandoraUtils;
use Drupal\media\Entity\Media;
use Drupal\media\MediaInterface;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Twig\Markup;

/**
* Implements hook_ENTITY_TYPE_presave().
*/
function islandora_entity_status_media_presave(MediaInterface $media) {
if ($media->hasField(IslandoraUtils::MEDIA_OF_FIELD)) {
$media_of = $media->get(IslandoraUtils::MEDIA_OF_FIELD);
if (!$media_of->isEmpty()) {
$node = $media_of->referencedEntities()[0];
if ($node instanceof NodeInterface) {
$node_status = intval($node->status->value);
$media->set('status', $node_status);
}
}
}
}

/**
* Implements hook_ENTITY_TYPE_update().
*/
function islandora_entity_status_node_update(EntityInterface $entity) {
// Check if the entity is a node with the bundle "islandora_object".
if ($entity->hasField(IslandoraUtils::MEMBER_OF_FIELD)) {
// Get the current node ID.
$nid = $entity->id();

// Query for media items that are associated with the current node.
$query = \Drupal::entityQuery('media')
->accessCheck(FALSE)
->condition(IslandoraUtils::MEDIA_OF_FIELD, $nid);
$media_ids = $query->execute();

// Load the media items and set their status to the same status as the node.
$media_items = Media::loadMultiple($media_ids);
foreach ($media_items as $media_item) {
$media_item->set('status', $entity->get('status')->value);
$media_item->save();
}

// Trigger the batch process for collection node.
$node_ids_to_update = find_collection_nodes($nid);
$latestStatus = $entity->get('status')->value;

islandora_entity_status_trigger_batch_process($node_ids_to_update, $latestStatus);
}
}
use Drupal\taxonomy\Entity\Term;

/**
* Implements hook_form_FORM_ID_alter().
*/
function islandora_entity_status_form_node_islandora_object_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Get the current node object.
$node = $form_state->getFormObject()->getEntity();

// Get the field_model value.
$field_value = $node->get('field_model')->getValue();
$term = Term::load($field_value[0]['target_id']);

// On `Repository Item` we need to show confirmation popup to editor.
// We tried with redirecting to a confirmation page, but it involves too
// much data handling.
$message = "<p>Status updates to this node will also apply to its child nodes, if any are present.</p>";

// Attach the custom library.
$form['#attached']['library'][] = 'islandora_entity_status/confirm-popup';
// Pass the confirmation message to JavaScript.
$form['#attached']['drupalSettings']['custom_confirm_popup']['message'] = $message;
}

/**
* Find related nodes.
*/
function find_collection_nodes($currentNodeId) {
$relatedNodeIds = [];

// Initial query to find nodes where the field_member_of contains
// the current node ID.
$query = \Drupal::entityQuery('node')
->condition('type', 'islandora_object')
->condition('field_member_of', $currentNodeId, '=')
->accessCheck(FALSE);

$result = $query->execute();

$relatedNodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($result);

if (!empty($relatedNodes)) {
foreach ($relatedNodes as $relatedNode) {
$relatedNodeIds[] = $relatedNode->id();
}
}

return $relatedNodeIds;
}

/**
* Helper function to trigger the batch process.
*/
function islandora_entity_status_trigger_batch_process($node_ids, $node_status) {
// Create a batch operation.
$operations = [
['islandora_entity_status_batch_operation', [$node_ids, $node_status]],
];

// Create a batch.
$batch = [
'title' => t('Processing nodes'),
'operations' => $operations,
'finished' => 'islandora_entity_status_batch_finished',
];

// Add the batch to the queue.
batch_set($batch);
}

/**
* Batch operation callback.
*/
function islandora_entity_status_batch_operation($node_ids, $node_status, &$context) {
// Perform your batch processing here.
// Update the status for each related node.
foreach ($node_ids as $relatedNodeId) {
$relatedNode = Node::load($relatedNodeId);
$relatedNode->set('status', $node_status);
$relatedNode->save();

// Update the progress.
$context['results'][] = t('Node %node processed and status set to %status.',
['%node' => $relatedNodeId, '%status' => $node_status]);
}
}

/**
* Batch finished callback.
*/
function islandora_entity_status_batch_finished($success, $results, $operations) {
$messenger = \Drupal::messenger();
$message = '';

if ($success) {
if (!empty($results)) {
// Batch processing completed successfully.
// Display a message indicating success.
$messenger->addMessage(t('Batch processing completed successfully.'));

foreach ($results as $result) {
$message .= '<br>' . $result;
}
$messenger->addMessage(new Markup($message, 'html'));
}
}
else {
// Batch processing failed.
$messenger->addError(t('Batch processing failed.'));
// Show popup only on collection node.
if ($term && $term->getName() == 'Collection') {
$message = "<p>Status updates to this node will also apply to its child nodes, if any are present.</p>";

// Attach the custom library.
$form['#attached']['library'][] = 'islandora_entity_status/confirm-popup';
// Pass the confirmation message to JavaScript.
$form['#attached']['drupalSettings']['custom_confirm_popup']['message'] = $message;
}
}
11 changes: 11 additions & 0 deletions islandora_entity_status.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@ services:
- '@entity_type.manager'
tags:
- { name: drush.command }

islandora_entity_status.islandora_node_event_subscriber:
class: Drupal\islandora_entity_status\EventSubscriber\IslandoraNodeEventSubscriber
arguments: ['@entity_type.manager', '@messenger']
tags:
- { name: event_subscriber }

islandora_entity_status.islandora_media_event_subscriber:
class: Drupal\islandora_entity_status\EventSubscriber\IslandoraMediaEventSubscriber
tags:
- { name: event_subscriber }
13 changes: 8 additions & 5 deletions js/confirm-popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
// Flag to prevent recursion.
var isClosingDialog = false;

// Variable to store the submit button selector.
var submitButton = $('.form-submit[value="Save"]');

// Create a dialog box.
var confirmDialog = $('<div></div>')
.html(confirmationMessage)
Expand All @@ -22,7 +25,7 @@
modal: true,
buttons: {
Cancel: function () {
$('#edit-submit--2--gin-edit-form').removeClass('submit-allowed');
submitButton.removeClass('submit-allowed');
$(this).dialog('close');
},
Save: function () {
Expand All @@ -32,9 +35,9 @@
$(this).dialog('close');
setTimeout(function () {
// Check if the submit button has a specific class.
if ($('#edit-submit--2--gin-edit-form').hasClass('submit-allowed')) {
if (submitButton.hasClass('submit-allowed')) {
// Trigger the form submission directly.
$('#edit-submit--2--gin-edit-form').click();
submitButton.click();
}
isClosingDialog = false;
}, 30);
Expand All @@ -44,12 +47,12 @@
});

// Attach the confirmation dialog to the node edit form submit button
const elements = once('confirmPopup', '#node-islandora-object-edit-form [type=submit]', context);
const elements = once('confirmPopup', '#node-islandora-object-edit-form [value=Save]', context);
elements.forEach(function (element) {
// Check if the form should be submitted.
element.addEventListener('click', function(e) {
if (element.classList.contains('submit-allowed')) {
$('#edit-submit--2--gin-edit-form').click();
submitButton.click();
} else {
// Prevent the default form submission.
e.preventDefault();
Expand Down
37 changes: 37 additions & 0 deletions src/EventSubscriber/IslandoraMediaEventSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Drupal\islandora_entity_status\EventSubscriber;

use Drupal\islandora_events\Event\IslandoraMediaEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Defines an event subscriber for Islandora Media.
*/
class IslandoraMediaEventSubscriber implements EventSubscriberInterface {

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
IslandoraMediaEvent::PRE_SAVE => 'onIslandoraMediaPresave',
];
}

/**
* Reacts to the Islandora Media presave event.
*
* @param \Drupal\islandora_events\Event\IslandoraMediaEvent $event
* The Islandora Media event.
*/
public function onIslandoraMediaPresave(IslandoraMediaEvent $event) {
$media = $event->getMedia();
$media_of_node = $event->getReferencedNode();

// Set media status same as media_of node status.
$media_of_node_status = intval($media_of_node->status->value);
$media->set('status', $media_of_node_status);
}

}
Loading
Loading