From f752780439412e5162b9e62a0c142a2b7b6027d0 Mon Sep 17 00:00:00 2001 From: Paul Pound Date: Fri, 27 Mar 2026 09:39:52 -0300 Subject: [PATCH] updates to prepare for integration with rapidILL --- includes/rapidill.inc | 270 +++++++++++++++++++++++++++++ src/Form/RoblibIllSettingsForm.php | 45 +++++ 2 files changed, 315 insertions(+) create mode 100644 includes/rapidill.inc diff --git a/includes/rapidill.inc b/includes/rapidill.inc new file mode 100644 index 0000000..f50c5e2 --- /dev/null +++ b/includes/rapidill.inc @@ -0,0 +1,270 @@ +submitRequest($form_state); + * @endcode + */ +class RapidIllRequestHandler { + + /** + * Drupal config object for upei_roblib_ill.settings. + * + * @var \Drupal\Core\Config\ImmutableConfig + */ + protected $config; + + /** + * Constructs a new RapidIllRequestHandler. + */ + public function __construct() { + $this->config = \Drupal::config('upei_roblib_ill.settings'); + } + + /** + * Maps a form Genre value to a RapidILL RequestType enum. + * + * @param string $genre + * The genre value from the ILL form ('article', 'book', or 'chapter'). + * + * @return \RapidIll\RequestType + * The corresponding RequestType enum value. + */ + public function getRequestType(string $genre): RequestType { + return match ($genre) { + 'book' => RequestType::Book, + 'chapter' => RequestType::BookChapter, + default => RequestType::Article, + }; + } + + /** + * Builds a RapidILL InsertRequest from the Drupal form state. + * + * Reads bibliographic data from form storage (step 1) and patron data + * from the current form values (step 2). + * + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current form state containing both steps of the ILL form. + * + * @return \RapidIll\InsertRequest + * A populated InsertRequest ready to be submitted. + */ + public function buildInsertRequest(FormStateInterface $form_state): InsertRequest { + $storage = $form_state->getStorage(); + $biblio = $storage['request'] ?? []; + $patron = $form_state->getValues(); + + $genre = $biblio['Genre'] ?? 'article'; + $request = new InsertRequest(); + $request->setRequestType($this->getRequestType($genre)); + + // -- Bibliographic fields -- + if (!empty($biblio['Title'])) { + $request->setJournalTitle($biblio['Title']); + } + + if (!empty($biblio['ArticleTitle'])) { + $request->setArticleTitle($biblio['ArticleTitle']); + } + + // Use ArticleAuthor for articles/chapters, Author for books. + $author = ''; + if ($genre !== 'book' && !empty($biblio['ArticleAuthor'])) { + $author = $biblio['ArticleAuthor']; + } + elseif (!empty($biblio['Author'])) { + $author = $biblio['Author']; + } + if (!empty($author)) { + $request->setArticleAuthor($author); + } + + if (!empty($biblio['ISSN'])) { + $issn = is_array($biblio['ISSN']) ? reset($biblio['ISSN']) : $biblio['ISSN']; + if (!empty($issn)) { + $request->addIssn($issn); + } + } + + if (!empty($biblio['ISBN'])) { + $isbn = is_array($biblio['ISBN']) ? reset($biblio['ISBN']) : $biblio['ISBN']; + if (!empty($isbn)) { + $request->addIsbn($isbn); + } + } + + if (!empty($biblio['Volume'])) { + $request->setJournalVolume($biblio['Volume']); + } + + if (!empty($biblio['Issue'])) { + $request->setJournalIssue($biblio['Issue']); + } + + if (!empty($biblio['PagesRequested'])) { + $request->setArticlePages($biblio['PagesRequested']); + } + + if (!empty($biblio['Date'])) { + $request->setJournalYear($biblio['Date']); + } + + // -- Patron fields -- + if (!empty($patron['campus_id'])) { + $request->setPatronId($patron['campus_id']); + } + + $first_name = $patron['FirstName'] ?? ''; + $surname = $patron['Surname'] ?? ''; + $full_name = trim("$first_name $surname"); + if (!empty($full_name)) { + $request->setPatronName($full_name); + } + + if (!empty($patron['DeliveryAddress'])) { + $request->setPatronEmail($patron['DeliveryAddress']); + } + + if (!empty($patron['Department'])) { + $request->setPatronDepartment($patron['Department']); + } + + // Combine user notes and DOI (if present) into patron notes. + $notes_parts = []; + if (!empty($patron['notes'])) { + $notes_parts[] = $patron['notes']; + } + if (!empty($biblio['doi'])) { + $notes_parts[] = 'DOI: ' . $biblio['doi']; + } + if (!empty($notes_parts)) { + $request->setPatronNotes(implode(' | ', $notes_parts)); + } + + return $request; + } + + /** + * Creates a RapidIllClient from the module's Drupal configuration. + * + * Reads the following config keys from 'upei_roblib_ill.settings': + * - rapid_ill_username + * - rapid_ill_password + * - rapid_ill_code + * - rapid_ill_branch_name + * + * @return \RapidIll\RapidIllClient + * A configured RapidILL client. + * + * @throws \RuntimeException + * If any required configuration value is missing. + */ + protected function createClient(): RapidIllClient { + $username = $this->config->get('rapid_ill_username'); + $password = $this->config->get('rapid_ill_password'); + $rapid_code = $this->config->get('rapid_ill_code'); + $branch_name = $this->config->get('rapid_ill_branch_name'); + + if (empty($username) || empty($password) || empty($rapid_code) || empty($branch_name)) { + \Drupal::logger('upei_roblib_ill')->error( + 'RapidILL configuration is incomplete. Please set rapid_ill_username, rapid_ill_password, rapid_ill_code, and rapid_ill_branch_name in the ILL settings.' + ); + throw new \RuntimeException('RapidILL configuration is incomplete.'); + } + + return new RapidIllClient( + username: $username, + password: $password, + rapidCode: $rapid_code, + branchName: $branch_name, + ); + } + + /** + * Builds and submits a RapidILL request from the ILL loan form. + * + * This method mirrors the behaviour of upei_roblib_ill_add_request() in + * relais.inc, returning a response array with the same shape so the form's + * existing redirect logic can consume it directly. + * + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current form state. + * + * @return array + * An associative array with at least a 'ConfirmMessage' key, and + * optionally a 'RequestNumber' key on success. + */ + public function submitRequest(FormStateInterface $form_state): array { + module_load_include('inc', 'upei_roblib_ill', 'includes/db'); + module_load_include('inc', 'upei_roblib_ill', 'includes/utilities'); + + // Build the Relais-style array for logging purposes. + $relais_arr = upei_roblib_ill_build_relais_arr($form_state); + + try { + $client = $this->createClient(); + } + catch (\RuntimeException $e) { + $error_response = [ + 'ConfirmMessage' => 'RapidILL is not configured. Please contact the library.', + ]; + upei_roblib_ill_log_request($relais_arr, $error_response); + return $error_response; + } + + $insert_request = $this->buildInsertRequest($form_state); + + try { + /** @var \RapidIll\InsertResponse $response */ + $response = $client->insertRequest($insert_request); + } + catch (RapidIllException $e) { + \Drupal::logger('upei_roblib_ill')->error( + 'RapidILL request failed: @message', + ['@message' => $e->getMessage()] + ); + $error_response = [ + 'ConfirmMessage' => 'Error communicating with RapidILL: ' . $e->getMessage(), + ]; + upei_roblib_ill_log_request($relais_arr, $error_response); + return $error_response; + } + + // Build a response array compatible with the existing form redirect. + if ($response->isSuccessful) { + $result = [ + 'RequestNumber' => $response->rapidRequestId, + 'ConfirmMessage' => 'Your Interlibrary Loan request has been successfully submitted to RapidILL. Your Rapid Request ID is: ' . $response->rapidRequestId, + ]; + } + else { + $message = $response->verificationNote ?? 'Unknown error from RapidILL.'; + $result = [ + 'ConfirmMessage' => 'RapidILL could not process your request: ' . $message, + ]; + } + + upei_roblib_ill_log_request($relais_arr, $result); + return $result; + } + +} diff --git a/src/Form/RoblibIllSettingsForm.php b/src/Form/RoblibIllSettingsForm.php index 24196fd..46948b4 100644 --- a/src/Form/RoblibIllSettingsForm.php +++ b/src/Form/RoblibIllSettingsForm.php @@ -85,6 +85,41 @@ class RoblibIllSettingsForm extends FormBase { '#description' => t('The phone number we want to show to the user after a user has submitted an ILL request, Roblib uses 902-566-0445'), '#default_value' => $config->get('ill_contact_phone'), ]; + + // RapidILL settings. + $form['rapid_ill_fieldset'] = [ + '#type' => 'fieldset', + '#title' => t('RapidILL Settings'), + '#description' => t('Credentials and configuration for submitting requests via RapidILL.'), + ]; + $form['rapid_ill_fieldset']['rapid_ill_username'] = [ + '#type' => 'textfield', + '#title' => t('RapidILL Username'), + '#description' => t('Your RapidILL API username.'), + '#default_value' => $config->get('rapid_ill_username'), + '#size' => 200, + ]; + $form['rapid_ill_fieldset']['rapid_ill_password'] = [ + '#type' => 'password', + '#title' => t('RapidILL Password'), + '#description' => t('Your RapidILL API password. Leave blank to keep the existing value.'), + '#size' => 200, + ]; + $form['rapid_ill_fieldset']['rapid_ill_code'] = [ + '#type' => 'textfield', + '#title' => t('RapidILL Rapid Code'), + '#description' => t('Your library Rapid code (e.g. YOUR_RAPID_CODE).'), + '#default_value' => $config->get('rapid_ill_code'), + '#size' => 200, + ]; + $form['rapid_ill_fieldset']['rapid_ill_branch_name'] = [ + '#type' => 'textfield', + '#title' => t('RapidILL Branch Name'), + '#description' => t('Your library branch name (e.g. Main).'), + '#default_value' => $config->get('rapid_ill_branch_name'), + '#size' => 200, + ]; + $form['actions']['submit'] = [ '#type' => 'submit', '#value' => t('Save'), @@ -113,6 +148,16 @@ class RoblibIllSettingsForm extends FormBase { $config->set('ill_doi_openurl_pid', $form_state->getValue('ill_doi_openurl_pid'))->save(); $config->set('ill_contact_email', $form_state->getValue('ill_contact_email'))->save(); $config->set('ill_contact_phone', $form_state->getValue('ill_contact_phone'))->save(); + + // RapidILL settings. + $config->set('rapid_ill_username', $form_state->getValue('rapid_ill_username'))->save(); + // Only update the password if a new value was entered. + $password = $form_state->getValue('rapid_ill_password'); + if (!empty($password)) { + $config->set('rapid_ill_password', $password)->save(); + } + $config->set('rapid_ill_code', $form_state->getValue('rapid_ill_code'))->save(); + $config->set('rapid_ill_branch_name', $form_state->getValue('rapid_ill_branch_name'))->save(); } }