Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions config/vufind/Folio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@ available[] = "Open - Awaiting pickup"
in_transit[] = "Open - In transit"
in_transit[] = "Open - Awaiting delivery"

; POST to this webhook address (with no body) after a successful hold is placed.
; A web service hosted there may be used for follow-up actions.
; Example: generating an email to circulation staff
; (https://github.com/lehigh-university-libraries/folio-email-new-requests)
;webhook = https://some.url/some-webhook-path

[Holdings]
; This setting controls the sort order used when retrieving items from FOLIO for the
; holdings display; it should be a space-separated prioritized list of item record
Expand Down
1 change: 1 addition & 0 deletions module/VuFind/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@
'VuFind\Connection\ExternalVuFind' => 'VuFind\Connection\ExternalVuFindFactory',
'VuFind\Connection\LibGuides' => 'VuFind\Connection\LibGuidesFactory',
'VuFind\Connection\Relais' => 'VuFind\Connection\RelaisFactory',
'VuFind\Connection\Webhook' => 'Laminas\ServiceManager\Factory\InvokableFactory',
'VuFind\Content\PageLocator' => 'VuFind\Content\PageLocatorFactory',
'VuFind\Content\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
'VuFind\Content\AuthorNotes\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
Expand Down
75 changes: 75 additions & 0 deletions module/VuFind/src/VuFind/Connection/Webhook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/**
* Webhook connection class.
*
* PHP version 8
*
* Copyright (C) Villanova University 2023.
Comment thread
maccabeelevine marked this conversation as resolved.
Outdated
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see
* <https://www.gnu.org/licenses/>.
*
* @category VuFind
* @package Connection
* @author Maccabee Levine <msl321@lehigh.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org
*/

namespace VuFind\Connection;

use Psr\Log\LoggerAwareInterface;

/**
* Webhook connection class.
*
* @category VuFind
* @package Connection
* @author Maccabee Levine <msl321@lehigh.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org
*/
class Webhook implements
\VuFindHttp\HttpServiceAwareInterface,
LoggerAwareInterface
{
use \VuFindHttp\HttpServiceAwareTrait;
use \VuFind\Log\LoggerAwareTrait {
logError as error;
}

/**
* Send a webhook post to the given URL. Log but do not throw any errors.
*
* @param string $url Target URL (required for proper proxy setup for non-local addresses)
* @param ?float $timeout Request timeout in seconds (overrides configuration)
*
* @return void
*/
public function post(string $url, ?float $timeout = null): void
{
$client = $this->httpService->createClient($url, 'POST', $timeout);

try {
$response = $client->send();
if (!$response->isSuccess()) {
$this->logError(
"Failed to post to webhook. Code: {$response->getStatusCode()}, body: {$response->getBody()}"
);
}
} catch (\Exception $e) {
$this->logError('Failed to post webhook. Unexpected ' . $e::class . ': ' . (string)$e);
}
}
}
27 changes: 23 additions & 4 deletions module/VuFind/src/VuFind/ILS/Driver/Folio.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use Exception;
use Laminas\Http\Response;
use VuFind\Config\Feature\SecretTrait;
use VuFind\Connection\Webhook;
use VuFind\Exception\ILS as ILSException;
use VuFind\I18n\Translator\TranslatorAwareInterface;
use VuFind\ILS\Logic\AvailabilityStatus;
Expand Down Expand Up @@ -147,13 +148,15 @@ class Folio extends AbstractAPI implements
/**
* Constructor.
*
* @param \VuFind\Date\Converter $dateConverter Date converter object
* @param callable $sessionFactory Factory function returning
* SessionContainer object
* @param \VuFind\Date\Converter $dateConverter Date converter object
* @param callable $sessionFactory Factory function returning
* SessionContainer object
* @param Webhook $webhookConnection Connection for webhooks
*/
public function __construct(
\VuFind\Date\Converter $dateConverter,
$sessionFactory
$sessionFactory,
protected Webhook $webhookConnection
Comment thread
demiankatz marked this conversation as resolved.
Outdated
) {
$this->dateConverter = $dateConverter;
$this->sessionFactory = $sessionFactory;
Expand Down Expand Up @@ -2365,6 +2368,21 @@ protected function performHoldRequest(array $requestBody): array
];
}

/**
* Support method for placeHold(): Notify an external process
* that a request was successfully submitted.
*
* @return void
*/
protected function sendWebhookAfterHoldRequest()
{
$url = $this->config['Holds']['webhook'] ?? null;
if ($url && $this->webhookConnection) {
Comment thread
demiankatz marked this conversation as resolved.
Outdated
// Short timeout -- don't impact user.
$this->webhookConnection->post($url, 5);
}
}

/**
* Get allowed service points for a request. Returns null if data cannot be obtained.
*
Expand Down Expand Up @@ -2499,6 +2517,7 @@ public function placeHold($holdDetails)
$requestBody['requestType'] = $requestType;
$result = $this->performHoldRequest($requestBody);
if ($result['success']) {
$this->sendWebhookAfterHoldRequest();
break;
}
}
Expand Down
3 changes: 2 additions & 1 deletion module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public function __invoke(
$manager = $container->get(\Laminas\Session\SessionManager::class);
return new \Laminas\Session\Container("Folio_$namespace", $manager);
};
return parent::__invoke($container, $requestedName, [$sessionFactory]);
$webhookConnection = $container->get(\VuFind\Connection\Webhook::class);
return parent::__invoke($container, $requestedName, [$sessionFactory, $webhookConnection]);
}
}
Loading