commit b795062ca0e0dffa3f770e082a6120beb91c4b2f Author: ajstanley Date: Fri Jan 31 16:29:27 2025 +0000 initial commit diff --git a/css/doi_prefill.css b/css/doi_prefill.css new file mode 100644 index 0000000..8874d43 --- /dev/null +++ b/css/doi_prefill.css @@ -0,0 +1,13 @@ +.form-inline { + display: flex; + gap: 20px; + flex-wrap: wrap; + max-width: 100%; + justify-content: space-evenly; +} + + +.form-inline .form-item { + flex: 1; + min-width: 250px; +} diff --git a/doi_prefill.info.yml b/doi_prefill.info.yml new file mode 100644 index 0000000..fafc86a --- /dev/null +++ b/doi_prefill.info.yml @@ -0,0 +1,8 @@ +name: 'DOI Prefill' +type: module +description: 'Generates Link to Prepopulate DOI ingest form' +package: Custom +core_version_requirement: ^10 || ^11 +dependencies: + - islandora:islandora + - prepopulate:prepopulate diff --git a/doi_prefill.libraries.yml b/doi_prefill.libraries.yml new file mode 100644 index 0000000..bcd07b0 --- /dev/null +++ b/doi_prefill.libraries.yml @@ -0,0 +1,5 @@ +styles: + version: 1.x + css: + theme: + css/doi_prefill.css: {} diff --git a/doi_prefill.module b/doi_prefill.module new file mode 100644 index 0000000..519ec1d --- /dev/null +++ b/doi_prefill.module @@ -0,0 +1,6 @@ +configFactory->get('system.site')->get('mail'); + $endpoint = 'https://api.crossref.org/works'; + $encoded_doi = urlencode($identifier); + $url = "{$endpoint}/{$encoded_doi}"; + + try { + $response = $this->httpClient->get($url, [ + 'headers' => [ + 'accept' => 'application/json', + 'User-Agent' => 'YourProjectName/1.0 (mailto:your-email@example.com)', + 'User-Agent' => "IslandScholar/ (mailto:{$site_email})", + ], + ]); + $data = $response->getBody()->getContents(); + $values = json_decode($data, TRUE); + + return $values['message']; + } + catch (\Exception $e) { + $this->loggerChannelIslandora->error('Failed to fetch citation from CrossRef: ' . $e->getMessage()); + return NULL; + } + } + +} diff --git a/src/Form/DoiPrepopulateForm.php b/src/Form/DoiPrepopulateForm.php new file mode 100644 index 0000000..6e160e8 --- /dev/null +++ b/src/Form/DoiPrepopulateForm.php @@ -0,0 +1,227 @@ +doiApi = $doiApi; + $this->entityTypeManager = $entityTypeManager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + // Instantiates this form class. + return new static( + // Load the service required to construct this class. + $container->get('doi_prefill.crossref_api_reader'), + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId(): string { + return 'doi_prefill_doi_prepopulate'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state): array { + $terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadByProperties([ + 'name' => 'Collection', + 'vid' => 'islandora_models', + ]); + $term = reset($terms); + $collection_ids = \Drupal::entityQuery('node') + ->accessCheck(FALSE) + ->condition('field_model', $term->id()) + ->execute(); + $collections = $this->entityTypeManager->getStorage('node')->loadMultiple($collection_ids); + $options = []; + foreach ($collections as $id => $collection) { + $options[$id] = $collection->label(); + } + + $form['container'] = [ + '#type' => 'container', + '#attributes' => ['class' => ['form-inline']], + ]; + $form['container']['doi'] = [ + '#type' => 'textfield', + '#title' => $this->t('Enter DOI'), + '#required' => TRUE, + ]; + $form['container']['collection'] = [ + '#title' => $this->t('Collection'), + '#type' => 'select', + '#options' => $options, + '#required' => TRUE, + + ]; + $form['container']['redirect'] = [ + '#type' => 'select', + '#title' => $this->t("After submission?"), + '#options' => [ + 'edit' => $this->t('Edit after submission'), + 'resume' => $this->t('Return to this form'), + ], + '#default_value' => 'edit', + ]; + $form['#attached']['library'][] = 'doi_prefill/styles'; + + $form['actions'] = [ + '#type' => 'actions', + 'submit' => [ + '#type' => 'submit', + '#value' => $this->t('Send'), + ], + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state): void { + $doi = trim($form_state->getValue('doi')); + $collection = $form_state->getValue('collection'); + $contents = $this->doiApi->getWork($doi); + + // Build typed relations. + $typed_relations = []; + $vid = 'person'; + foreach ($contents['author'] as $author) { + $author_term = "{$author['family']}"; + if (isset($author['given'])) { + $author_term = "{$author_term}, {$author['given']}"; + } + $term = $this->getOrCreateTerm($author_term, $vid); + $typed_relations[] = [ + 'target_id' => $term->id(), + 'rel_type' => 'relators:aut', + ]; + } + $genre = $this->getOrCreateTerm($contents['type'], 'genre'); + + // Build new node. + $new_node = Node::create([ + 'title' => $contents['title'][0], + 'field_member_of' => $collection, + 'type' => 'islandora_object', + 'field_linked_agent' => $typed_relations, + 'field_publisher' => $contents['publisher'], + 'field_doi' => $doi, + 'field_genre' => $genre->id(), + 'field_issue' => $contents['issue'], + 'field_volume' => $contents['volume'], + ]); + + // Optional fields. + if (isset($contents['abstract'])) { + $new_node->set('field_abstract', [ + 'value' => $contents['abstract'], + 'format' => 'basic_html', + ]); + } + if (isset($contents['published-online'])) { + $field_date_online = []; + foreach ($contents['published-online']['date-parts'] as $date_parts) { + $field_date_online[] = ['value' => implode('-', $date_parts)]; + } + $new_node->set('field_date_online', $field_date_online); + } + + // Multivalued fields. + $field_edtf_date_issued = []; + foreach ($contents['created']['date-parts'] as $date_parts) { + $field_edtf_date_issued[] = ['value' => implode('-', $date_parts)]; + } + $new_node->set('field_edtf_date_issued', $field_edtf_date_issued); + + $field_issn = []; + foreach ($contents['ISSN'] as $issn) { + $field_issn[] = ['value' => $issn]; + } + $new_node->set('field_issn', $field_issn); + $new_node->save(); + if ($form_state->getValue('redirect') == 'edit') { + + $destination = "/node/{$new_node->id()}/edit"; + $response = new RedirectResponse($destination); + $response->send(); + } + + } + + /** + * Check if a term exists in a vocabulary. If not, create it. + * + * @param string $term_name + * The name of the term. + * @param string $vocabulary + * The machine name of the vocabulary. + * + * @return \Drupal\taxonomy\Entity\Term|null + * The term entity if found or created, or NULL on failure. + */ + public function getOrCreateTerm($term_name, $vocabulary) { + $terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadByProperties([ + 'name' => $term_name, + 'vid' => $vocabulary, + ]); + + if ($terms) { + // Return the first found term. + return reset($terms); + } + + // If the term does not exist, create it. + $term = Term::create([ + 'name' => $term_name, + 'vid' => $vocabulary, + ]); + $term->save(); + return $term; + + } + +}