You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.2 KiB
197 lines
6.2 KiB
<?php |
|
|
|
/** |
|
* @file |
|
* Contains the SharePointRequestHandler class for submitting ILL requests |
|
* to a SharePoint list via a Power Automate webhook. |
|
*/ |
|
|
|
use Drupal\Core\Form\FormStateInterface; |
|
|
|
/** |
|
* Handles building and submitting ILL requests to SharePoint via Power Automate. |
|
* |
|
* Usage (from the form submit handler): |
|
* @code |
|
* \Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/sharepoint'); |
|
* $handler = new SharePointRequestHandler(); |
|
* $payload = $handler->buildPayload($form_state); |
|
* $response = $handler->submitRequest($payload); |
|
* @endcode |
|
*/ |
|
class SharePointRequestHandler |
|
{ |
|
|
|
/** |
|
* Drupal config object for upei_roblib_ill.settings. |
|
* |
|
* @var \Drupal\Core\Config\ImmutableConfig |
|
*/ |
|
protected $config; |
|
|
|
/** |
|
* Constructs a new SharePointRequestHandler. |
|
*/ |
|
public function __construct() |
|
{ |
|
$this->config = \Drupal::config('upei_roblib_ill.settings'); |
|
} |
|
|
|
/** |
|
* Builds the webhook payload 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 array |
|
* An associative array matching the Power Automate webhook payload schema. |
|
*/ |
|
public function buildPayload(FormStateInterface $form_state): array |
|
{ |
|
$storage = $form_state->getStorage(); |
|
$biblio = $storage['request'] ?? []; |
|
$patron = $form_state->getValues(); |
|
|
|
$genre = $biblio['Genre'] ?? 'article'; |
|
|
|
// Determine the author: 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']; |
|
} |
|
|
|
// Combine DOI and ISBN into a single field. |
|
$doi_isbn_parts = []; |
|
if (!empty($biblio['doi'])) { |
|
$doi_isbn_parts[] = $biblio['doi']; |
|
} |
|
if (!empty($biblio['ISBN'])) { |
|
$doi_isbn_parts[] = $biblio['ISBN']; |
|
} |
|
if (!empty($biblio['ISSN'])) { |
|
$doi_isbn_parts[] = $biblio['ISSN']; |
|
} |
|
$doi_isbn = implode('; ', $doi_isbn_parts); |
|
|
|
// Build patron full name. |
|
$first_name = $patron['FirstName'] ?? ''; |
|
$surname = $patron['Surname'] ?? ''; |
|
$patron_name = trim("$first_name $surname"); |
|
|
|
// Build notes — pack all extra info that doesn't have its own schema field. |
|
$notes_parts = []; |
|
if (!empty($biblio['ArticleTitle'])) { |
|
$notes_parts[] = 'Article/Chapter: ' . $biblio['ArticleTitle']; |
|
} |
|
if (!empty($biblio['Volume'])) { |
|
$notes_parts[] = 'Vol: ' . $biblio['Volume']; |
|
} |
|
if (!empty($biblio['Issue'])) { |
|
$notes_parts[] = 'Issue: ' . $biblio['Issue']; |
|
} |
|
if (!empty($biblio['PagesRequested'])) { |
|
$notes_parts[] = 'Pages: ' . $biblio['PagesRequested']; |
|
} |
|
if (!empty($patron['patron_type'])) { |
|
$notes_parts[] = 'Patron Type: ' . $patron['patron_type']; |
|
} |
|
if (!empty($patron['Department'])) { |
|
$notes_parts[] = 'Dept: ' . $patron['Department']; |
|
} |
|
if (!empty($patron['notes'])) { |
|
$notes_parts[] = $patron['notes']; |
|
} |
|
|
|
// All values MUST be strings — Power Automate rejects the request |
|
// if any value type does not match the trigger's JSON schema. |
|
return [ |
|
'title' => (string)($biblio['Title'] ?? ''), |
|
'author' => (string)$author, |
|
'year' => (string)($biblio['Date'] ?? ''), |
|
'doi_isbn' => (string)$doi_isbn, |
|
'format' => (string)$genre, |
|
'patronName' => (string)$patron_name, |
|
'patronEmail' => (string)($patron['DeliveryAddress'] ?? ''), |
|
'patronBarcode' => (string)($patron['campus_id'] ?? ''), |
|
'notes' => (string)implode(' | ', $notes_parts), |
|
'submittedAt' => (string)gmdate('Y-m-d\TH:i:s') . '.000Z', |
|
]; |
|
} |
|
|
|
/** |
|
* Submits the payload to the configured Power Automate webhook. |
|
* |
|
* @param array $payload |
|
* The payload array as built by buildPayload(). |
|
* |
|
* @return array |
|
* An associative array with at least a 'ConfirmMessage' key, and |
|
* optionally a 'RequestNumber' key on success. |
|
*/ |
|
public function submitRequest(array $payload): array |
|
{ |
|
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/db'); |
|
|
|
$webhook_url = $this->config->get('sharepoint_webhook_url'); |
|
if (empty($webhook_url)) { |
|
\Drupal::logger('upei_roblib_ill')->error( |
|
'SharePoint webhook URL is not configured. Please set it in the ILL settings.' |
|
); |
|
$error_response = [ |
|
'ConfirmMessage' => 'SharePoint integration is not configured. Please contact the library.', |
|
]; |
|
upei_roblib_ill_log_request($payload, $error_response); |
|
return $error_response; |
|
} |
|
|
|
// Log the outgoing payload for debugging. |
|
\Drupal::logger('upei_roblib_ill')->notice( |
|
'Submitting ILL request to SharePoint webhook. Payload: @payload', |
|
['@payload' => json_encode($payload)] |
|
); |
|
|
|
try { |
|
// Use 'json' option which handles JSON encoding and Content-Type automatically. |
|
$response = \Drupal::httpClient()->post($webhook_url, [ |
|
'json' => $payload, |
|
'timeout' => 30, |
|
]); |
|
|
|
$status_code = $response->getStatusCode(); |
|
$body = (string)$response->getBody(); |
|
$response_data = json_decode($body, TRUE) ?: []; |
|
|
|
if ($status_code >= 200 && $status_code < 300) { |
|
$result = [ |
|
'RequestNumber' => $response_data['request_number'] ?? date('YmdHis'), |
|
'ConfirmMessage' => 'Your Interlibrary Loan request has been successfully submitted.', |
|
]; |
|
} |
|
else { |
|
$message = $response_data['error'] ?? 'Unexpected response from SharePoint (HTTP ' . $status_code . ').'; |
|
$result = [ |
|
'ConfirmMessage' => 'SharePoint could not process your request: ' . $message, |
|
]; |
|
} |
|
} |
|
catch (\Exception $e) { |
|
\Drupal::logger('upei_roblib_ill')->error( |
|
'SharePoint webhook request failed: @message', |
|
['@message' => $e->getMessage()] |
|
); |
|
$result = [ |
|
'ConfirmMessage' => 'Error communicating with SharePoint: ' . $e->getMessage(), |
|
]; |
|
} |
|
|
|
upei_roblib_ill_log_request($payload, $result); |
|
return $result; |
|
} |
|
|
|
}
|
|
|