diff --git a/embargo.install b/embargo.install new file mode 100644 index 0000000..bb5dda8 --- /dev/null +++ b/embargo.install @@ -0,0 +1,39 @@ +setLabel(t('Embargoed File')) + ->setDescription(t('New field for attaching media to the Embargo node.')) + ->setSetting('target_type', 'media') + ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED); + + // Install the new definition. + $definition_manager->installFieldStorageDefinition('embargoed_file', $entity_type_id, $bundle, $new_field); + } + catch (UpdateException $e) { + // Handle exception if needed. + \Drupal::logger('embargo')->error('Error adding field: @error', ['@error' => $e->getMessage()]); + return t('Update failed: @error', ['@error' => $e->getMessage()]); + } + + // Provide a message indicating the update has been applied. + return t('Added embargoed_file to the Embargo entity.'); +} diff --git a/embargo.libraries.yml b/embargo.libraries.yml new file mode 100644 index 0000000..3aff315 --- /dev/null +++ b/embargo.libraries.yml @@ -0,0 +1,7 @@ +custom_select_all_library: + version: 1.x + js: + js/custom_select_all.js: {} + dependencies: + - core/jquery + - core/once diff --git a/embargo.module b/embargo.module index c5b35dc..881f49a 100644 --- a/embargo.module +++ b/embargo.module @@ -9,6 +9,8 @@ use Drupal\Core\Database\Query\AlterableInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; use Drupal\embargo\EmbargoStorage; +use Drupal\Core\Form\FormStateInterface; +use Drupal\node\NodeInterface; /** * Implements hook_entity_type_alter(). @@ -97,3 +99,69 @@ function embargo_theme($existing, $type, $theme, $path) { ], ]; } + +/** + * Implements hook_form_FORM_ID_alter(). + */ +function embargo_form_alter(&$form, FormStateInterface $form_state, $form_id) { + if ($form_id == 'embargo_add_form' || $form_id == 'embargo_edit_form') { + // Set up visibility conditions for the embargoed_file field. + $form['embargoed_file']['#states'] = [ + 'visible' => [ + ':input[name="embargo_type"]' => ['value' => 0], + ], + ]; + + // Check if the URL contains a node ID. + $node_id = \Drupal::routeMatch()->getParameter('node'); + + if ($node_id instanceof NodeInterface) { + $node_id = $node_id->id(); + } + + // If its edit form, need to select node id differently. + if ($form_id == 'embargo_edit_form') { + $entity = $form_state->getFormObject()->getEntity(); + $field_value = $entity->embargoed_node->getValue(); + $node_id = $field_value[0]['target_id']; + } + + // If a node ID is present, filter the options of embargoed_file. + if (!empty($node_id)) { + $options = embargo_get_filtered_file_options($node_id); + $form['embargoed_file']['widget']['#options'] = $options; + } + else { + // @todo Need to update file list via ajax when Embargoed Node available. + unset($form['embargoed_file']); + } + + // JS to add Select/Unselect All link and functionality. + $form['#attached']['library'][] = 'embargo/custom_select_all_library'; + + } +} + +/** + * Helper function to get filtered options based on the node ID. + */ +function embargo_get_filtered_file_options($node_id) { + // Initialize an empty array to store matching media entities. + $matching_media = []; + + // Check if the node ID is valid. + if (!empty($node_id)) { + // Filter media entities based on the referenced node ID. + $matching_media = \Drupal::entityTypeManager() + ->getStorage('media') + ->loadByProperties(['field_media_of' => $node_id]); + } + + // Build an array of matching media labels and IDs for the checkbox options. + $options = []; + foreach ($matching_media as $media) { + $options[$media->id()] = $media->label(); + } + + return $options; +} diff --git a/js/custom_select_all.js b/js/custom_select_all.js new file mode 100644 index 0000000..3cfb4a8 --- /dev/null +++ b/js/custom_select_all.js @@ -0,0 +1,21 @@ +(function ($, Drupal, once) { + Drupal.behaviors.customSelectAll = { + attach: function (context, settings) { + // Create the link element + var selectAllLink = $('Select/Unselect All'); + + // Use `once()` to ensure the link is prepended only once + $(once('custom-select-all', '#edit-embargoed-file', context)).prepend(selectAllLink); + + // Attach the click handler directly to the link element + selectAllLink.on('click', function (event) { + event.preventDefault(); + + var checkboxes = $(':checkbox', context); // Target checkboxes within relevant context + + // Toggle checked state based on current state of the first checkbox + checkboxes.prop('checked', !checkboxes.first().prop('checked')); + }); + } + }; +})(jQuery, Drupal, once); diff --git a/src/EmbargoInterface.php b/src/EmbargoInterface.php index 62003e2..691931f 100644 --- a/src/EmbargoInterface.php +++ b/src/EmbargoInterface.php @@ -249,4 +249,22 @@ public function isUserExempt(AccountInterface $user): bool; */ public function ipIsExempt(string $ip): bool; + /** + * Gets the embargoed files. + * + * @return \Drupal\media\MediaInterface[] + * An array of media entities representing the embargoed files. + */ + public function getEmbargoedFiles(): array; + + /** + * Sets the embargoed files. + * + * @param \Drupal\media\MediaInterface[] $files + * An array of media entities representing the embargoed files. + * + * @return $this + */ + public function setEmbargoedFiles(array $files): EmbargoInterface; + } diff --git a/src/Entity/Embargo.php b/src/Entity/Embargo.php index 03f8b57..2376936 100644 --- a/src/Entity/Embargo.php +++ b/src/Entity/Embargo.php @@ -94,6 +94,27 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ]) ->setSetting('allowed_values', static::getEmbargoTypeLabels()); + $fields['embargoed_file'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(t('Embargoed Media')) + ->setDescription(t('Media attached to the Embargoed node.')) + ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) + ->setSetting('target_type', 'media') + ->setSetting('handler', 'default:media') + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'entity_reference_label', + 'weight' => 0, + ]) + ->setDisplayOptions('form', [ + 'type' => 'options_buttons', + 'weight' => 0, + 'settings' => [ + 'match_operator' => 'CONTAINS', + 'size' => '60', + 'placeholder' => '', + ], + ]); + $fields['expiration_type'] = BaseFieldDefinition::create('list_integer') ->setLabel(t('Expiration Type')) ->setDescription(t('A Indefinite embargo is never lifted.
A Scheduled embargo is lifted on the specified date.')) @@ -377,6 +398,24 @@ public function setEmbargoedNode(NodeInterface $node): EmbargoInterface { return $this; } + /** + * {@inheritdoc} + */ + public function getEmbargoedFiles(): array { + /** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field */ + $field = $this->get('embargoed_file'); + $files = $field->referencedEntities(); + return $files; + } + + /** + * {@inheritdoc} + */ + public function setEmbargoedFiles(array $files): EmbargoInterface { + $this->set('embargoed_file', $files); + return $this; + } + /** * The maximum age for which this object may be cached. *