diff --git a/code/web/Drivers/LibKeyDriver.php b/code/web/Drivers/LibKeyDriver.php new file mode 100644 index 0000000000..aa70bf4279 --- /dev/null +++ b/code/web/Drivers/LibKeyDriver.php @@ -0,0 +1,24 @@ +whereAdd("id=$activeLibrary->libKeySettingId"); + if ($settings->find(true)) { + $settings->fetch(); + } + $curlWrapper = new CurlWrapper; + $response = $curlWrapper->curlGetPage("https://public-api.thirdiron.com/public/v1/libraries/" . $settings->libraryId . "/articles/doi/" . $this->extractDoi($doiUrl) . "?access_token=" . $settings->apiKey); + if (empty($response)) { + return null; + } + return json_decode($response, true)["data"]["bestIntegratorLink"]["bestLink"]; + } + public function extractDoi(string $url): string { + $doi = str_replace(["https://doi.org/", "http://"], "", $url); + return $doi; + } +} \ No newline at end of file diff --git a/code/web/RecordDrivers/MarcRecordDriver.php b/code/web/RecordDrivers/MarcRecordDriver.php index c8df3c9c9e..a76c638bba 100644 --- a/code/web/RecordDrivers/MarcRecordDriver.php +++ b/code/web/RecordDrivers/MarcRecordDriver.php @@ -1064,7 +1064,7 @@ public function getRecordActions($relatedRecord, $variationId, $isAvailable, $is } } - $this->_actions[$variationId] = array_merge($this->_actions[$variationId], $this->createActionsFromUrls($relatedUrls, null, $variationId)); + $this->_actions[$variationId] = array_merge($this->_actions[$variationId], $this->createActionsFromUrls($relatedUrls, $relatedRecord, $variationId)); if ($interface->getVariable('displayingSearchResults')) { $showHoldButton = $interface->getVariable('showHoldButtonInSearchResults'); @@ -1314,6 +1314,14 @@ function createActionsFromUrls($relatedUrls, $itemInfo = null, $variationId = 'a $i = 0; if (count($relatedUrls) > 1) { //We will show a popup to let people choose the URL they want + foreach($relatedUrls as $relatedUrl) { + $libKeyLink = $this->getLibKeyUrl($relatedUrl['url']); + if (!empty($libKeyLink)) { + $libKeyRelatedUrl = $relatedUrl; + $libKeyrelatedUrl['url'] = $libKeyLink; + $relatedUrls[] = $libKeyRelatedUrl; + } + } $title = translate([ 'text' => 'Access Online', 'isPublicFacing' => true, @@ -1328,34 +1336,52 @@ function createActionsFromUrls($relatedUrls, $itemInfo = null, $variationId = 'a 'target' => '_blank', ]; } elseif (count($relatedUrls) == 1) { - $urlInfo = reset($relatedUrls); - //Revert to access online per Karen at CCU. If people want to switch it back, we can add a per library switch - $title = translate([ - 'text' => 'Access Online', - 'isPublicFacing' => true, - ]); - $alt = 'Available online from ' . $urlInfo['source']; - $action = $configArray['Site']['url'] . '/' . $this->getModule() . '/' . $this->id . "/AccessOnline?index=$i&variationId=$variationId"; - $fileOrUrl = isset($urlInfo['url']) ? $urlInfo['url'] : $urlInfo['file']; - if (strlen($fileOrUrl) > 0) { - if (strlen($fileOrUrl) >= 3) { - $extension = strtolower(substr($fileOrUrl, strlen($fileOrUrl), 3)); - if ($extension == 'pdf') { - $title = translate([ - 'text' => 'Access PDF', - 'isPublicFacing' => true, - ]); - } - } + $libKeyLink = $this->getLibKeyUrl($relatedUrls[0]['url']); + if (!empty($libKeyLink)) { + $title = translate([ + 'text' => 'Access Online', + 'isPublicFacing' => true, + ]); $actions[] = [ - 'url' => $action, - 'redirectUrl' => $fileOrUrl, 'title' => $title, + 'url' => $libKeyLink, 'requireLogin' => false, - 'alt' => $alt, + 'type' => 'access_online', + 'id' => "accessOnline_{$this->getId()}", 'target' => '_blank', ]; + + } else { + $urlInfo = reset($relatedUrls); + + //Revert to access online per Karen at CCU. If people want to switch it back, we can add a per library switch + $title = translate([ + 'text' => 'Access Online', + 'isPublicFacing' => true, + ]); + $alt = 'Available online from ' . $urlInfo['source']; + $action = $configArray['Site']['url'] . '/' . $this->getModule() . '/' . $this->id . "/AccessOnline?index=$i&variationId=$variationId"; + $fileOrUrl = isset($urlInfo['url']) ? $urlInfo['url'] : $urlInfo['file']; + if (strlen($fileOrUrl) > 0) { + if (strlen($fileOrUrl) >= 3) { + $extension = strtolower(substr($fileOrUrl, strlen($fileOrUrl), 3)); + if ($extension == 'pdf') { + $title = translate([ + 'text' => 'Access PDF', + 'isPublicFacing' => true, + ]); + } + } + $actions[] = [ + 'url' => $action, + 'redirectUrl' => $fileOrUrl, + 'title' => $title, + 'requireLogin' => false, + 'alt' => $alt, + 'target' => '_blank', + ]; + } } } else { foreach ($relatedUrls as $urlInfo) { @@ -1391,6 +1417,11 @@ function createActionsFromUrls($relatedUrls, $itemInfo = null, $variationId = 'a return $actions; } + private function getLibKeyUrl($doiUrl) { + require_once ROOT_DIR . "/Drivers/LibKeyDriver.php"; + $libKeyDriver = new LibKeyDriver(); + return $libKeyDriver->getLibKeyLink($doiUrl); + } private $catalogDriver = null; @@ -1659,6 +1690,10 @@ public function getMoreDetailsOptions() { $interface->assign('periodicalIssues', $issues); } $links = $this->getLinks(); + $libKeyLink = $this->getLibKeyUrl($links[0]['url']); + if (!empty($libKeyLink)) { + $links[] = ['title' => $libKeyLink, 'url' => $libKeyLink]; + } $interface->assign('links', $links); $interface->assign('show856LinksAsTab', $library->getGroupedWorkDisplaySettings()->show856LinksAsTab); $interface->assign('showItemDueDates', $library->getGroupedWorkDisplaySettings()->showItemDueDates); diff --git a/code/web/release_notes/24.12.00.MD b/code/web/release_notes/24.12.00.MD index ac6bdf7c40..a3f1541e2a 100644 --- a/code/web/release_notes/24.12.00.MD +++ b/code/web/release_notes/24.12.00.MD @@ -55,6 +55,12 @@ - Remove edit button in admin view of Grapes JS Pages as breadcrumbs allow navigation back to the editor and are in keeping with the rest of Aspen. (*AB*) // Chloe - PTFSE +- LibKey (ThirdIron) integration: + - Add LibKey Settings under Third Party Enhancement (*CZ*) + - LibKey Settings can be associated with specific libraries (*CZ*) + - Add an 'Administer LibKey Settings' permission (*CZ*) + - For eContent records with DOIs, the 'Access Online' button will default to a LibKey-issued direct link to the document if the active library has a LibKey subscription and if the record is found by LibKey (*CZ*) + - LibKey links are also added under 'Links' on the detailed view for a record (*CZ*) // Pedro - PTFSE diff --git a/code/web/services/Admin/LibKeySettings.php b/code/web/services/Admin/LibKeySettings.php new file mode 100644 index 0000000000..a5a2ccaa35 --- /dev/null +++ b/code/web/services/Admin/LibKeySettings.php @@ -0,0 +1,76 @@ +limit(($page - 1) * $recordsPerPage, $recordsPerPage); + $this->applyFilters($object); + $object->orderBy($this->getSort()); + $object->find(); + $objectList = []; + while ($object->fetch()) { + $objectList[$object->id] = clone $object; + } + return $objectList; + } + + function getDefaultSort(): string { + return 'name asc'; + } + + function getObjectStructure($context = ''): array { + return LibKeySetting::getObjectStructure($context); + } + + function getPrimaryKeyColumn(): string { + return 'id'; + } + + function getIdKeyColumn(): string { + return 'id'; + } + + function getAdditionalObjectActions($existingObject): array { + return []; + } + + function getInstructions(): string { + return 'https://help.aspendiscovery.org/help/integration/enrichment'; + } + + function getBreadcrumbs(): array { + $breadcrumbs = []; + $breadcrumbs[] = new Breadcrumb('/Admin/Home', 'Administration Home'); + $breadcrumbs[] = new Breadcrumb('/Admin/Home#third_party_enrichment', 'Third Party Enrichment'); + $breadcrumbs[] = new Breadcrumb('/Admin/LibKeySettings', 'LibKey Settings'); + return $breadcrumbs; + } + + function getActiveAdminSection(): string { + return 'third_party_enrichment'; + } + + function canView(): bool { + return UserAccount::userHasPermission('Administer LibKey Settings'); + } +} \ No newline at end of file diff --git a/code/web/services/Record/AJAX.php b/code/web/services/Record/AJAX.php index 521cce66e1..9fb7f94d9e 100644 --- a/code/web/services/Record/AJAX.php +++ b/code/web/services/Record/AJAX.php @@ -1963,10 +1963,18 @@ function viewItem(): array { if ($item->itemId == $itemId) { $relatedUrls = $item->getRelatedUrls(); foreach ($relatedUrls as $relatedUrl) { - return [ - 'success' => true, - 'url' => $relatedUrl['url'] - ]; + $libKeyLink = $this->getLibKeyUrl($relatedUrl['url']); + if (!empty($libKeyLink)) { + return [ + 'success' => true, + 'url' => $libKeyLink + ]; + } else { + return [ + 'success' => true, + 'url' => $relatedUrl['url'] + ]; + } } } } @@ -1984,4 +1992,11 @@ function viewItem(): array { 'modalButtons' => "", ]; } + + private function getLibKeyUrl($doiUrl) { + require_once ROOT_DIR . "/Drivers/LibKeyDriver.php"; + $libKeyDriver = new LibKeyDriver(); + return $libKeyDriver->getLibKeyLink($doiUrl); + } } + diff --git a/code/web/sys/Account/User.php b/code/web/sys/Account/User.php index 2272c2b4b5..3d4830b8b2 100644 --- a/code/web/sys/Account/User.php +++ b/code/web/sys/Account/User.php @@ -3872,6 +3872,10 @@ public function getAdminActions() { 'Administer All System Messages', 'Administer Library System Messages', ]); + $sections['local_enrichment']->addAction(new AdminAction('System Messages', 'System Messages allow you to display messages to your patrons in specific locations.', '/Admin/SystemMessages'), [ + 'Administer All System Messages', + 'Administer Library System Messages', + ]); $sections['third_party_enrichment'] = new AdminSection('Third Party Enrichment'); $sections['third_party_enrichment']->addAction(new AdminAction('Accelerated Reader Settings', 'Define settings to load Accelerated Reader information directly from Renaissance Learning.', '/Enrichment/ARSettings'), 'Administer Third Party Enrichment API Keys'); @@ -3879,6 +3883,7 @@ public function getAdminActions() { $sections['third_party_enrichment']->addAction(new AdminAction('ContentCafe Settings', 'Define settings for ContentCafe integration.', '/Enrichment/ContentCafeSettings'), 'Administer Third Party Enrichment API Keys'); $sections['third_party_enrichment']->addAction(new AdminAction('DP.LA Settings', 'Define settings for DP.LA integration.', '/Enrichment/DPLASettings'), 'Administer Third Party Enrichment API Keys'); $sections['third_party_enrichment']->addAction(new AdminAction('Google API Settings', 'Define settings for integrating Google APIs within Aspen Discovery.', '/Enrichment/GoogleApiSettings'), 'Administer Third Party Enrichment API Keys'); + $sections['third_party_enrichment']->addAction(new AdminAction('LibKey Settings', 'Administer LibKey Settings', '/Admin/LibKeySettings'), 'Administer LibKey Settings'); $nytSettingsAction = new AdminAction('New York Times Settings', 'Define settings for integrating New York Times Content within Aspen Discovery.', '/Enrichment/NewYorkTimesSettings'); $nytListsAction = new AdminAction('New York Times Lists', 'View Lists from the New York Times and manually refresh content.', '/Enrichment/NYTLists'); if ($sections['third_party_enrichment']->addAction($nytSettingsAction, 'Administer Third Party Enrichment API Keys')) { diff --git a/code/web/sys/DBMaintenance/version_updates/24.12.00.php b/code/web/sys/DBMaintenance/version_updates/24.12.00.php index 444b6e66d6..394fc09765 100644 --- a/code/web/sys/DBMaintenance/version_updates/24.12.00.php +++ b/code/web/sys/DBMaintenance/version_updates/24.12.00.php @@ -80,6 +80,34 @@ function getUpdates24_12_00(): array { //alexander - PTFS-Europe //chloe - PTFS-Europe + 'create_libkey_module' => [ + 'title' => 'Create LibKey Module', + 'description' => 'Add LibKey to the list of modules', + 'sql' => [ + "INSERT INTO modules (name) VALUES ('LibKey')", + ], + ], // create_libkey_module + 'create_libkey_permissions' => [ + 'title' => 'Create LibKey Permissions', + 'description' => 'Add an LibKey permission section containing the Administer LibKey Settings permission', + 'sql' => [ + "INSERT INTO permissions (name, sectionName, requiredModule, weight, description) VALUES ( 'Administer LibKey Settings','LibKey','LibKey', 0, 'Allows the user to administer the integration with LibKey')", + "INSERT INTO role_permissions(roleId, permissionId) VALUES ((SELECT roleId from roles where name='opacAdmin'), (SELECT id from permissions where name='Administer LibKey Settings'))", + ], + ],// create_libkey_permissions + 'create_libkey_settings_table' => [ + 'title' => 'Create LibKey Settings Table', + 'description' => 'Add an LibKey settings table', + 'sql' => [ + "CREATE TABLE libkey_settings ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + libraryId VARCHAR(20) NOT NULL, + apiKey VARCHAR(255) NOT NULL + )", + "ALTER TABLE library ADD libKeySettingId INT NOT NULL DEFAULT -1" + ], + ],// create_libkey_permissions //James Staub - Nashville Public Library diff --git a/code/web/sys/LibKey/LibKeySetting.php b/code/web/sys/LibKey/LibKeySetting.php new file mode 100644 index 0000000000..d7e693edf8 --- /dev/null +++ b/code/web/sys/LibKey/LibKeySetting.php @@ -0,0 +1,128 @@ + [ + 'property' => 'id', + 'type' => 'label', + 'label' => 'Id', + 'description' => 'The unique id', + ], + 'name' => [ + 'property' => 'name', + 'type' => 'text', + 'label' => 'Name', + 'maxLength' => 50, + 'description' => 'A name for these settings', + 'required' => true, + ], + 'libraryId' => [ + 'property' => 'libraryId', + 'type' => 'text', + 'label' => 'Library ID', + 'maxLength' => 50, + 'description' => 'Your LibKey library Id', + 'required' => true, + ], + 'apiKey' => [ + 'property' => 'apiKey', + 'type' => 'storedPassword', + 'label' => 'Api Key', + 'description' => 'Your LibKey API Key.', + 'hideInLists' => true, + 'required' => false, + ], + 'libraries' => [ + 'property' => 'libraries', + 'type' => 'multiSelect', + 'listStyle' => 'checkboxSimple', + 'label' => 'Libraries', + 'description' => 'Define libraries that use this setting', + 'values' => $libraryList, + 'hideInLists' => true, + ], + ]; + } + + public function __get($name) { + if ($name == "libraries") { + if (!isset($this->_libraries) && $this->id) { + $this->_libraries = []; + $obj = new Library(); + $obj->libKeySettingId = $this->id; + $obj->find(); + while ($obj->fetch()) { + $this->_libraries[$obj->libraryId] = $obj->libraryId; + } + } + return $this->_libraries; + } else { + return parent::__get($name); + } + } + + public function __set($name, $value) { + if ($name == "libraries") { + $this->_libraries = $value; + } else { + parent::__set($name, $value); + } + } + + public function update($context = '') { + $ret = parent::update(); + if ($ret !== FALSE) { + $this->saveLibraries(); + } + return true; + } + + public function insert($context = '') { + $ret = parent::insert(); + if ($ret !== FALSE) { + $this->saveLibraries(); + } + return $ret; + } + + public function saveLibraries() { + if (isset ($this->_libraries) && is_array($this->_libraries)) { + $libraryList = Library::getLibraryList(!UserAccount::userHasPermission('Administer All Libraries')); + foreach ($libraryList as $libraryId => $displayName) { + $library = new Library(); + $library->libraryId = $libraryId; + $library->find(true); + if (in_array($libraryId, $this->_libraries)) { + if ($library->libKeySettingId != $this->id) { + $library->finePaymentType = 2; + $library->libKeySettingId = $this->id; + $library->update(); + } + } else { + if ($library->libKeySettingId == $this->id) { + if ($library->finePaymentType == 2) { + $library->finePaymentType = 0; + } + $library->libKeySettingId = -1; + $library->update(); + } + } + } + unset($this->_libraries); + } + } +} \ No newline at end of file diff --git a/code/web/sys/LibraryLocation/Library.php b/code/web/sys/LibraryLocation/Library.php index 260b0714a8..b2a4f2f665 100644 --- a/code/web/sys/LibraryLocation/Library.php +++ b/code/web/sys/LibraryLocation/Library.php @@ -479,6 +479,9 @@ class Library extends DataObject { public $shareItUsername; public $shareItPassword; + // LIBKEY + public $libKeySettingId; + public $allowUpdatingHolidaysFromILS; private $_cloudLibraryScope;