From 8f0eef973de7dfe4a279b170681f62f9496a16b2 Mon Sep 17 00:00:00 2001 From: ajstanley Date: Mon, 10 Feb 2025 16:17:17 +0000 Subject: [PATCH] added README --- README.md | 31 +++ doi_prefill.links.menu.yml | 6 + src/Form/DOIFieldSettingsForm.php | 324 ++++++++++++++++++++++++++++++ 3 files changed, 361 insertions(+) create mode 100644 README.md create mode 100644 doi_prefill.links.menu.yml create mode 100644 src/Form/DOIFieldSettingsForm.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c5fe7e --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# DOI Prefill + +Allows users create Drupal nodes with data retrieved from Crossref. + +## Installation + +Install as +[usual](https://www.drupal.org/docs/extending-drupal/installing-modules). + +## Configuration + +The form at `admin/config/system/doi_field_setting`s allows you to map the fields returned by Crossref to fields +in your Islandora installation e.g. Crossref's `Contributors` field can be mapped to `field_contributor`, or `field_linked_agent`. + +You may optionally map the Crossref genre fields to your own taxonomy term e.g. `journal-article` to `Journal Article` + +## Usage + +After installing and enabling and configuring the module add a link to `doi-prefill/doi-prepopulate` in your [Shortcuts menu](admin/config/user-interface/shortcut/manage/default/customize) + +Navigate to the form where you can enter a DOI, a collection for your new node, and choose whether you'd like to be taken the node's edit form or be returned to the same page. + + + +## Maintainers +Current maintainers: + +* [Robertson Library](https://library.upei.ca/) + +## License +[GPLv3](http://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/doi_prefill.links.menu.yml b/doi_prefill.links.menu.yml new file mode 100644 index 0000000..4c7ba8d --- /dev/null +++ b/doi_prefill.links.menu.yml @@ -0,0 +1,6 @@ +doi_prefill.doi_settings: + title: DOI Prefill Settings + description: Configure DOI mappings + parent: system.admin_config_system + route_name: doi_prefill.doi_settings + weight: 10 diff --git a/src/Form/DOIFieldSettingsForm.php b/src/Form/DOIFieldSettingsForm.php new file mode 100644 index 0000000..f00aaf9 --- /dev/null +++ b/src/Form/DOIFieldSettingsForm.php @@ -0,0 +1,324 @@ +entityTypeManager = $entityTypeManager; + $this->entityFieldManager = $entityFieldManager; + $this->utils = $utils; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager'), + $container->get('entity_field.manager'), + $container->get('islandora.utils'), + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId(): string { + return 'doi_prefill_doi_field_settings'; + } + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames(): array { + return ['doi_prefill.settings']; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state): array { + $doi_fields = [ + 'title' => 'Title', + 'contributors' => 'Contributors', + 'publisher' => 'Publisher', + 'doi' => 'DOI', + 'genre' => 'Genre', + 'issue' => 'Issue', + 'volume' => 'Volume', + 'date_issued' => 'Date issued', + 'abstract' => 'Abstract', + 'host_title' => 'Host title', + 'date_online' => 'Date online', + 'page_range' => 'Page range', + 'series_issn' => 'Series ISSN', + ]; + + $config = $this->config('doi_prefill.settings'); + $fields = $this->entityFieldManager->getFieldDefinitions('node', 'islandora_object'); + $field_options = ['title' => 'Title']; + foreach ($fields as $field) { + if ($field instanceof FieldConfig) { + $label = (string) $field->getLabel(); + $name = $field->getName(); + $field_options[$name] = $label; + } + } + asort($field_options); + $content_types = NodeType::loadMultiple(); + $destination_content_types = []; + foreach ($content_types as $type) { + if ($this->utils->isIslandoraType('node', $type->id())) { + $destination_content_types[$type->id()] = $type->label(); + } + } + + $form['content_type'] = [ + '#type' => 'select', + '#title' => $this->t('Content Type'), + '#description' => $this->t("Choose content type for new node"), + '#options' => $destination_content_types, + '#default_value' => $config->get('content_type'), + ]; + + // Display fields in a table format. + $form['description'] = [ + '#type' => 'markup', + '#markup' => $this->t('DOI fields are returned by Crossref. Please choose field from your Islandora Installation to hold the returned value.'), + ]; + + $form['field_table'] = [ + '#type' => 'table', + '#header' => [ + $this->t('DOI Field'), + $this->t('Islandora Field'), + ], + '#prefix' => '
', + '#suffix' => '
', + ]; + foreach ($doi_fields as $machine_name => $field) { + $form['field_table'][$machine_name]['field_name'] = [ + '#plain_text' => $field, + ]; + + // Add a dropdown for each field. + $form['field_table'][$machine_name]['dropdown'] = [ + '#type' => 'select', + '#options' => $field_options, + '#default_value' => $config->get('field_settings')[$machine_name] ?? '', + ]; + } + $form['#attached']['library'][] = 'doi_prefill/doi_field_selector_styles'; + + $form['pairs_description'] = [ + '#type' => 'markup', + '#markup' => $this->t('DOI genre terms are returned by Crossref. Please choose any term you would like to replace from your own taxonomy.'), + ]; + + $doi_term_islandora_term_pairs = $form_state->get('doi_term_islandora_term_pairs'); + if (!$doi_term_islandora_term_pairs) { + $doi_term_islandora_term_pairs = $config->get('doi_term_islandora_term_pairs'); + } + if (empty($doi_term_islandora_term_pairs)) { + // Initialize as an empty array if no pairs exist. + $doi_term_islandora_term_pairs = []; + } + + // Set the form state for entry_count and doi_term_islandora_term_pairs. + $form_state->set('doi_term_islandora_term_pairs', $doi_term_islandora_term_pairs); + $entry_count = count($doi_term_islandora_term_pairs); + $form_state->set('entry_count', $entry_count); + + // Define the table structure for key-value pairs. + $form['doi_term_islandora_term_pairs'] = [ + '#type' => 'table', + '#prefix' => '
', + '#suffix' => '
', + ]; + + // Generate the table rows dynamically based on stored pairs. + foreach ($doi_term_islandora_term_pairs as $entry_id => $pair) { + $pair['entry_id'] = $entry_id; + $unique_id = $pair['entry_id'] ?? uniqid(); + $form['doi_term_islandora_term_pairs'][$unique_id]['key'] = [ + '#type' => 'textfield', + '#default_value' => $pair['key'] ?? '', + '#title' => $this->t('term from DOI'), + '#required' => TRUE, + ]; + + $form['doi_term_islandora_term_pairs'][$unique_id]['value'] = [ + '#type' => 'textfield', + '#default_value' => $pair['value'] ?? '', + '#title' => $this->t('Genre term'), + '#required' => TRUE, + ]; + + // Hidden field to store the correct entry ID. + $form['doi_term_islandora_term_pairs'][$unique_id]['entry_id'] = [ + '#type' => 'hidden', + '#value' => $entry_id, + ]; + + // Remove button for each entry. + $form['doi_term_islandora_term_pairs'][$unique_id]['remove'] = [ + '#type' => 'submit', + '#value' => $this->t('Remove'), + '#submit' => ['::removeCallback'], + '#limit_validation_errors' => [], + '#ajax' => [ + 'callback' => '::ajaxCallback', + 'wrapper' => 'key-value-pairs-wrapper', + ], + // Instead of relying on `#attributes`, set a unique `#name`! + '#name' => 'remove_' . $unique_id, + ]; + + } + + // Button to add another key-value pair. + $form['add_more'] = [ + '#type' => 'submit', + '#value' => $this->t('Add term'), + '#submit' => ['::addMoreCallback'], + '#ajax' => [ + 'callback' => '::ajaxCallback', + 'wrapper' => 'key-value-pairs-wrapper', + ], + ]; + + // Submit button for the form. + $form['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Save term mappings'), + ]; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state): void { + if (!empty($form_state->getValue('field_table'))) { + foreach ($form_state->getValue('field_table') as $doi_field => $islandora_field) { + $field_settings[$doi_field] = $islandora_field['dropdown']; + } + } + $doi_term_islandora_term_pairs = $form_state->getValue('doi_term_islandora_term_pairs'); + $content_type = $form_state->getValue('content_type'); + $this->config('doi_prefill.settings') + ->set('field_settings', $field_settings) + ->set('doi_term_islandora_term_pairs', $doi_term_islandora_term_pairs) + ->set('content_type', $content_type) + ->save(); + parent::submitForm($form, $form_state); + } + + /** + * AJAX callback to refresh the form. + */ + public function ajaxCallback(array &$form, FormStateInterface $form_state) { + return $form['doi_term_islandora_term_pairs']; + } + + /** + * Adds more key-value pair fields. + */ + public function addMoreCallback(array &$form, FormStateInterface $form_state) { + // Retrieve existing key-value pairs. + $doi_term_islandora_term_pairs = $form_state->get('doi_term_islandora_term_pairs') ?? []; + + // Get submitted values and merge with stored ones. + $user_input = $form_state->getUserInput(); + if (!empty($user_input['doi_term_islandora_term_pairs'])) { + foreach ($user_input['doi_term_islandora_term_pairs'] as $id => $values) { + if (!isset($doi_term_islandora_term_pairs[$id])) { + $doi_term_islandora_term_pairs[$id] = $values; + } + } + } + + // Add a new empty entry with a unique ID. + $unique_id = uniqid(); + $doi_term_islandora_term_pairs[$unique_id] = [ + 'key' => '', + 'value' => '', + 'unique_id' => $unique_id, + ]; + + // Store the updated values. + $form_state->set('doi_term_islandora_term_pairs', $doi_term_islandora_term_pairs); + $form_state->set('entry_count', count($doi_term_islandora_term_pairs)); + + // Rebuild the form. + $form_state->setRebuild(); + } + + /** + * Remove chosen element. + */ + public function removeCallback(array &$form, FormStateInterface $form_state) { + $triggering_element = $form_state->getTriggeringElement(); + // Using hidden field to get around Drupal's issues with ajax. + $button_name = $triggering_element['#name'] ?? ''; + + // Extract the unique ID from the button name. + if (preg_match('/remove_(.+)/', $button_name, $matches)) { + $clicked_id = $matches[1]; + } + $doi_term_islandora_term_pairs = $form_state->get('doi_term_islandora_term_pairs') ?? []; + + if (isset($doi_term_islandora_term_pairs[$clicked_id])) { + unset($doi_term_islandora_term_pairs[$clicked_id]); + } + $form_state->set('doi_term_islandora_term_pairs', $doi_term_islandora_term_pairs); + $form_state->set('entry_count', count($doi_term_islandora_term_pairs)); + $form_state->setRebuild(); + } + +}