-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generalize DOI linker system to support other identifier types (#3918)
- Loading branch information
1 parent
5465f4b
commit 46a14f3
Showing
49 changed files
with
1,130 additions
and
878 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1425,10 +1425,10 @@ url = "https://api.booksite.com" | |
;[DPLA] | ||
;apiKey = http://dp.la/info/developers/codex/policies/#get-a-key | ||
|
||
; These settings affect dynamic DOI-based link inclusion; this can provide links | ||
; to full text or contextual information. | ||
[DOI] | ||
; This setting controls whether or not DOI-based links are enabled, and which | ||
; These settings affect dynamic identifier-based link inclusion; this can provide links | ||
; to full text or contextual information based on identifiers like DOI, ISBN or ISSN. | ||
[IdentifierLinks] | ||
; This setting controls whether or not ID-based links are enabled, and which | ||
; API is used to fetch the data. Currently supported options: BrowZine (requires | ||
; credentials to be configured in BrowZine.ini), Demo (which generates fake data | ||
; to simulate use of a real service, for testing), Unpaywall or false (to disable). | ||
|
@@ -1437,7 +1437,7 @@ url = "https://api.booksite.com" | |
;resolver = BrowZine | ||
|
||
; If you use multiple values in the resolver setting above, you can determine how the | ||
; software should behave when multiple resolvers return results for the same DOI. | ||
; software should behave when multiple resolvers return results for the same ID. | ||
; You can choose "first" (only return results from the first matching resolver -- | ||
; the default behavior) or "merge" (merge together all results and show them all). | ||
;multi_resolver_mode = first | ||
|
@@ -1446,12 +1446,18 @@ url = "https://api.booksite.com" | |
; Unpaywall needs an email adress, see https://unpaywall.org/products/api | ||
;unpaywall_email = "[email protected]" | ||
|
||
; The following settings control where DOI-based links are displayed: | ||
; The following settings control where ID-based links are displayed: | ||
show_in_results = true ; include in search results | ||
show_in_record = false ; include in core record metadata | ||
show_in_holdings = false ; include in holdings tab of record view | ||
|
||
; Whether to load any third-party icons for the DOI services via VuFind's cover | ||
; This setting controls which types of identifiers are used to generate links; if | ||
; the setting is omitted, all supported types (DOI, ISBN and ISSN) will be used: | ||
supportedIdentifiers[] = doi | ||
supportedIdentifiers[] = isbn | ||
supportedIdentifiers[] = issn | ||
|
||
; Whether to load any third-party icons for the ID services via VuFind's cover | ||
; loader proxy to avoid any privacy implications. Ensure that the necessary domains | ||
; are allowed in Content/coverproxyCache[] setting. Default is false. | ||
proxy_icons = true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
<?php | ||
|
||
/** | ||
* AJAX handler to look up DOI data. | ||
* AJAX handler to look up identifier-based link data. | ||
* | ||
* PHP version 8 | ||
* | ||
|
@@ -31,37 +31,30 @@ | |
|
||
use Laminas\Mvc\Controller\Plugin\Params; | ||
use Laminas\View\Renderer\RendererInterface; | ||
use VuFind\DoiLinker\PluginManager; | ||
use VuFind\IdentifierLinker\PluginManager; | ||
|
||
use function count; | ||
|
||
/** | ||
* AJAX handler to look up DOI data. | ||
* AJAX handler to look up identifier-based link data. | ||
* | ||
* @category VuFind | ||
* @package AJAX | ||
* @author Demian Katz <[email protected]> | ||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
* @link https://vufind.org/wiki/development Wiki | ||
*/ | ||
class DoiLookup extends AbstractBase | ||
class IdentifierLinksLookup extends AbstractBase | ||
{ | ||
/** | ||
* DOI Linker Plugin Manager | ||
* | ||
* @var PluginManager | ||
*/ | ||
protected $pluginManager; | ||
|
||
/** | ||
* DOI resolver configuration value, exploded into an array of options | ||
* Identifier link resolver configuration value, exploded into an array of options | ||
* | ||
* @var string[] | ||
*/ | ||
protected $resolvers; | ||
|
||
/** | ||
* Behavior to use when multiple resolvers find results for the same DOI (may | ||
* Behavior to use when multiple resolvers find results for the same identifier set (may | ||
* be 'first' -- use first match, or 'merge' -- use all results) | ||
* | ||
* @var string | ||
|
@@ -82,36 +75,29 @@ class DoiLookup extends AbstractBase | |
*/ | ||
protected $openInNewWindow = false; | ||
|
||
/** | ||
* View renderer | ||
* | ||
* @var RendererInterface | ||
*/ | ||
protected $viewRenderer = null; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param PluginManager $pluginManager DOI Linker Plugin Manager | ||
* @param PluginManager $pluginManager Identifier Linker Plugin Manager | ||
* @param RendererInterface $viewRenderer View renderer | ||
* @param array $config Main configuration | ||
*/ | ||
public function __construct( | ||
PluginManager $pluginManager, | ||
RendererInterface $viewRenderer, | ||
protected PluginManager $pluginManager, | ||
protected RendererInterface $viewRenderer, | ||
array $config | ||
) { | ||
$this->pluginManager = $pluginManager; | ||
// DOI config section is supported as a fallback for back-compatibility: | ||
$idConfig = $config['IdentifierLinks'] ?? $config['DOI'] ?? []; | ||
$this->resolvers | ||
= array_map('trim', explode(',', $config['DOI']['resolver'] ?? '')); | ||
= array_map('trim', explode(',', $idConfig['resolver'] ?? '')); | ||
// Behavior to use when multiple resolvers to find results for the same | ||
// DOI (may be 'first' -- use first match, or 'merge' -- use all | ||
// identifier set (may be 'first' -- use first match, or 'merge' -- use all | ||
// results): | ||
$this->multiMode | ||
= trim(strtolower($config['DOI']['multi_resolver_mode'] ?? 'first')); | ||
$this->proxyIcons = !empty($config['DOI']['proxy_icons']); | ||
$this->openInNewWindow = !empty($config['DOI']['new_window']); | ||
$this->viewRenderer = $viewRenderer; | ||
= trim(strtolower($idConfig['multi_resolver_mode'] ?? 'first')); | ||
$this->proxyIcons = !empty($idConfig['proxy_icons']); | ||
$this->openInNewWindow = !empty($idConfig['new_window']); | ||
} | ||
|
||
/** | ||
|
@@ -123,67 +109,77 @@ public function __construct( | |
*/ | ||
public function handleRequest(Params $params) | ||
{ | ||
$response = []; | ||
$dois = (array)$params->fromQuery('doi', []); | ||
$gatheredData = []; | ||
$ids = json_decode($params->getController()->getRequest()->getContent(), true); | ||
foreach ($this->resolvers as $resolver) { | ||
if ($this->pluginManager->has($resolver)) { | ||
$next = $this->pluginManager->get($resolver)->getLinks($dois); | ||
$next = $this->pluginManager->get($resolver)->getLinks($ids); | ||
$next = $this->processIconLinks($next); | ||
foreach ($next as $doi => $data) { | ||
foreach ($data as &$current) { | ||
$current['newWindow'] = $this->openInNewWindow; | ||
} | ||
unset($current); | ||
if (!isset($response[$doi])) { | ||
$response[$doi] = $data; | ||
foreach ($next as $key => $data) { | ||
if (!isset($gatheredData[$key])) { | ||
$gatheredData[$key] = $data; | ||
} elseif ($this->multiMode == 'merge') { | ||
$response[$doi] = array_merge($response[$doi], $data); | ||
$gatheredData[$key] = array_merge($gatheredData[$key], $data); | ||
} | ||
} | ||
// If all DOIs have been found and we're not in merge mode, we | ||
// If all keys have been found and we're not in merge mode, we | ||
// can short circuit out of here. | ||
if ( | ||
$this->multiMode !== 'merge' | ||
&& count(array_diff($dois, array_keys($response))) == 0 | ||
&& count(array_diff(array_keys($ids), array_keys($gatheredData))) == 0 | ||
) { | ||
break; | ||
} | ||
} | ||
} | ||
$response = array_map([$this, 'renderResponseChunk'], $gatheredData); | ||
return $this->formatResponse($response); | ||
} | ||
|
||
/** | ||
* Proxify external DOI icon links and render local icons | ||
* Render the links for a single record. | ||
* | ||
* @param array $data Data to render | ||
* | ||
* @return string | ||
*/ | ||
protected function renderResponseChunk(array $data): string | ||
{ | ||
$newWindow = $this->openInNewWindow; | ||
return $this->viewRenderer->render('ajax/identifierLinks.phtml', compact('data', 'newWindow')); | ||
} | ||
|
||
/** | ||
* Proxify external icon links and render local icons | ||
* | ||
* @param array $dois DOIs | ||
* @param array $data Identifier plugin data | ||
* | ||
* @return array | ||
*/ | ||
protected function processIconLinks(array $dois): array | ||
protected function processIconLinks(array $data): array | ||
{ | ||
$serverHelper = $this->viewRenderer->plugin('serverurl'); | ||
$urlHelper = $this->viewRenderer->plugin('url'); | ||
$iconHelper = $this->viewRenderer->plugin('icon'); | ||
|
||
foreach ($dois as &$doiLinks) { | ||
foreach ($doiLinks as &$doi) { | ||
if ($this->proxyIcons && !empty($doi['icon'])) { | ||
$doi['icon'] = $serverHelper( | ||
foreach ($data as &$links) { | ||
foreach ($links as &$link) { | ||
if ($this->proxyIcons && !empty($link['icon'])) { | ||
$link['icon'] = $serverHelper( | ||
$urlHelper( | ||
'cover-show', | ||
[], | ||
['query' => ['proxy' => $doi['icon']]] | ||
['query' => ['proxy' => $link['icon']]] | ||
) | ||
); | ||
} | ||
if (!empty($doi['localIcon'])) { | ||
$doi['localIcon'] = $iconHelper($doi['localIcon']); | ||
if (!empty($link['localIcon'])) { | ||
$link['localIcon'] = $iconHelper($link['localIcon'], 'icon-link__icon'); | ||
} | ||
} | ||
unset($doi); | ||
unset($link); | ||
} | ||
unset($doiLinks); | ||
return $dois; | ||
unset($links); | ||
return $data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
<?php | ||
|
||
/** | ||
* Factory for DoiLookup AJAX handler. | ||
* Factory for IdentifierLinksLookup AJAX handler. | ||
* | ||
* PHP version 8 | ||
* | ||
|
@@ -35,15 +35,15 @@ | |
use Psr\Container\ContainerInterface; | ||
|
||
/** | ||
* Factory for DoiLookup AJAX handler. | ||
* Factory for IdentifierLinksLookup AJAX handler. | ||
* | ||
* @category VuFind | ||
* @package AJAX | ||
* @author Demian Katz <[email protected]> | ||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
* @link https://vufind.org/wiki/development Wiki | ||
*/ | ||
class DoiLookupFactory implements \Laminas\ServiceManager\Factory\FactoryInterface | ||
class IdentifierLinksLookupFactory implements \Laminas\ServiceManager\Factory\FactoryInterface | ||
{ | ||
/** | ||
* Create an object | ||
|
@@ -72,7 +72,7 @@ public function __invoke( | |
$config = $container->get(\VuFind\Config\PluginManager::class) | ||
->get('config')->toArray(); | ||
return new $requestedName( | ||
$container->get(\VuFind\DoiLinker\PluginManager::class), | ||
$container->get(\VuFind\IdentifierLinker\PluginManager::class), | ||
$container->get('ViewRenderer'), | ||
$config | ||
); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.