Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize DOI linker system to support other identifier types #3918

Open
wants to merge 52 commits into
base: dev
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
491d424
Work in progress: DOI to generic ID system.
demiankatz Sep 6, 2024
20e57fd
Merge branch 'dev' into doi-to-id-refactor
demiankatz Sep 9, 2024
a0f9e42
Progress.
demiankatz Sep 9, 2024
e988638
Style fix.
demiankatz Sep 9, 2024
23427ad
Finish proof-of-concept demo.
demiankatz Sep 9, 2024
45c885c
Improve naming.
demiankatz Sep 9, 2024
92261cb
Style fix.
demiankatz Sep 9, 2024
cef12d7
Fix end-of-file line break.
demiankatz Sep 9, 2024
b5c51c3
Merge branch 'dev' into doi-to-id-refactor
demiankatz Dec 16, 2024
032027f
Fix typo.
demiankatz Dec 16, 2024
9359623
Remove unused param.
demiankatz Dec 16, 2024
de703b0
Fix types and ID determination.
demiankatz Dec 16, 2024
7d78911
Merge branch 'dev' into doi-to-id-refactor
demiankatz Dec 16, 2024
83463bd
Switch from GET to POST.
demiankatz Dec 16, 2024
5be1f9c
Rename [DOI] config section.
demiankatz Dec 16, 2024
47d5f10
Eliminate object-based configs from view helper.
demiankatz Dec 16, 2024
644549b
Make ID types configurable.
demiankatz Dec 16, 2024
1de9bfd
Rename doi.js.
demiankatz Dec 16, 2024
07a4911
Rename module/function.
demiankatz Dec 16, 2024
94d9faf
Merge branch 'dev' into doi-to-id-refactor
demiankatz Dec 18, 2024
2b71a0a
Rename DOI-specific CSS classes; fix innerHtml logic.
demiankatz Dec 18, 2024
7293036
Rename template.
demiankatz Dec 18, 2024
9926c7d
Rename AJAX handler.
demiankatz Dec 18, 2024
c2aaf3c
Rename view helper.
demiankatz Dec 18, 2024
6ead6ba
Rename plugins.
demiankatz Dec 18, 2024
58f38a2
Remove redundant file.
demiankatz Dec 18, 2024
8299fec
Fix test.
demiankatz Dec 18, 2024
3cd191e
Make interface consistent; fix tests.
demiankatz Dec 18, 2024
3f8e4ad
Fix last test.
demiankatz Dec 18, 2024
9b4e2b9
Fix broken mink test.
demiankatz Dec 18, 2024
43d8cfd
Update DOI-related language.
demiankatz Dec 18, 2024
824035e
Merge branch 'dev' into doi-to-id-refactor
demiankatz Dec 19, 2024
e1eddb6
Add method comments.
demiankatz Dec 19, 2024
7ba08e1
JSDoc style fixes.
demiankatz Dec 19, 2024
8134253
Refactor link rendering to template.
demiankatz Dec 19, 2024
03c1054
Style: add line breaks at end of file.
demiankatz Dec 19, 2024
31c6874
Add ISSN support to BrowZine link handler.
demiankatz Dec 19, 2024
5118e63
Remove unnecessary include.
demiankatz Dec 19, 2024
576be35
Merge branch 'dev' into doi-to-id-refactor
demiankatz Dec 20, 2024
d3662ea
Fix comments; incorporate review feedback.
demiankatz Dec 20, 2024
5beb8ac
Add more types.
demiankatz Dec 20, 2024
d11f1e9
Merge branch 'dev' into doi-to-id-refactor
ThoWagen Jan 9, 2025
7886088
added test that reproduces current bug
ThoWagen Jan 9, 2025
d08e676
Merge branch 'dev' into doi-to-id-refactor
demiankatz Jan 10, 2025
1a6f319
Review feedback -- refactor defaults to factory.
demiankatz Jan 10, 2025
e95a707
Merge branch 'dev' into doi-to-id-refactor
demiankatz Jan 14, 2025
2a9862d
Add missing tag end and alt attribute.
demiankatz Jan 14, 2025
20f1239
BrowZine linker review feedback.
demiankatz Jan 14, 2025
3e567fd
Rename properties for clarity.
demiankatz Jan 14, 2025
b75e986
Refactor IdentifierLinker helper for simplicity.
demiankatz Jan 14, 2025
745a9b8
Add aria-hidden to image.
demiankatz Jan 16, 2025
9f88cba
Merge remote-tracking branch 'origin/dev' into doi-to-id-refactor
demiankatz Jan 16, 2025
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
Prev Previous commit
Next Next commit
Add ISSN support to BrowZine link handler.
demiankatz committed Dec 19, 2024

Unverified

This user has not yet uploaded their public signing key.
commit 31c68743ab61ea05c86feaeda35d0b3d544da825
18 changes: 12 additions & 6 deletions config/vufind/BrowZine.ini
Original file line number Diff line number Diff line change
@@ -30,17 +30,18 @@ load_results_with_js = true
; full Full pagination alike to the one at the bottom of results
;top_paginator = simple

; This section controls the behavior of the BrowZine DOI handler; see also
; the [DOI] section of config.ini to activate the handler.
[DOI]
; This section controls the behavior of the BrowZine identifier link handler; see also
; the [IdentifierLinks] section of config.ini to activate the handler.
[IdentifierLinks]
; Can be set to "include" to include only the options listed in the "filter"
; setting, or to "exclude" to filter out the options listed in the "filter"
; setting. The default is "none," which performs no filtering.
;filterType = exclude
; This repeatable section can be used to filter based on link type; legal
; options are the keys defined in DOIServices section.
; options are the keys defined in DOIServices and ISSNServices sections.
; Note that this setting is available for convenience and compatibility with previous
; versions. You can get the same results by changing the DOIServices section.
; versions. You can get the same results by changing the DOIServices and/or
; ISSNServices sections.
;filter[] = "browzineWebLink"
;filter[] = "fullTextFile"

@@ -49,7 +50,7 @@ load_results_with_js = true
; used. Default is false.
local_icons = false

; This section defines the services to display from BrowZine and their display order.
; This section defines the DOI services to display from BrowZine and their display order.
; Each key is a service name (see https://thirdiron.atlassian.net/wiki/x/WIDqAw for
; more information) and value contains translation key, local icon and Third Iron's
; icon asset (optional) separated by a pipe character.
@@ -58,6 +59,11 @@ browzineWebLink = "View Complete Issue|browzine-issue|https://assets.thirdiron.c
fullTextFile = "PDF Full Text|browzine-pdf|https://assets.thirdiron.com/images/integrations/browzine-pdf-download-icon.svg"
retractionNoticeUrl = "View Retraction Notice|browzine-retraction"

; This section defines the ISSN services to display from BrowZine and their display order.
; The format is the same as [DOIServices] above.
[ISSNServices]
browzineWebLink = "Browse Available Issues|browzine-issue|https://assets.thirdiron.com/images/integrations/browzine-open-book-icon.svg"

; This section defines the view options available on standard search results.
; If only one view is required, set default_view under [General] above, and
; leave this section commented out.
1 change: 1 addition & 0 deletions languages/en.ini
Original file line number Diff line number Diff line change
@@ -145,6 +145,7 @@ Breadcrumbs = "Breadcrumbs"
Brief View = "Brief View"
Browse = "Browse"
Browse Alphabetically = "Browse Alphabetically"
Browse Available Issues = "Browse Available Issues"
Browse for Authors = "Browse for Authors"
Browse Home = "Browse Home"
Browse the Catalog = "Browse the Catalog"
145 changes: 91 additions & 54 deletions module/VuFind/src/VuFind/IdentifierLinker/BrowZine.php
Original file line number Diff line number Diff line change
@@ -29,8 +29,10 @@

namespace VuFind\IdentifierLinker;

use Exception;
use VuFind\I18n\Translator\TranslatorAwareInterface;
use VuFindSearch\Backend\BrowZine\Command\LookupDoiCommand;
use VuFindSearch\Backend\BrowZine\Command\LookupIssnsCommand;
use VuFindSearch\Service;

use function in_array;
@@ -48,42 +50,20 @@ class BrowZine implements IdentifierLinkerInterface, TranslatorAwareInterface
{
use \VuFind\I18n\Translator\TranslatorAwareTrait;

/**
* Search service
*
* @var Service
*/
protected $searchService;

/**
* Configuration options
*
* @var array
*/
protected $config;

/**
* Configured DOI services
*
* @var array
*/
protected $doiServices;

/**
* Constructor
*
* @param Service $searchService Search service
* @param array $config Configuration settings
* @param array $doiServices Configured DOI services
* @param array $issnServices Configured ISSN services
*/
public function __construct(
Service $searchService,
array $config = [],
array $doiServices = []
protected Service $searchService,
protected array $config = [],
protected array $doiServices = [],
protected array $issnServices = []
) {
$this->searchService = $searchService;
$this->config = $config;
$this->doiServices = $doiServices;
}

/**
@@ -110,6 +90,32 @@ protected function arrayKeyAvailable(string $key, ?array $data): bool
return true;
}

/**
* Format a single service link.
*
* @param array $data Raw API response data
* @param string $serviceKey Key being extracted from response
* @param array $config Service-specific configuration settings
*
* @return array{link: string, label: string, data: array, localIcon: ?string, icon: ?string}
* @throws Exception
*/
protected function processServiceLink(array $data, string $serviceKey, array $config): array
{
$result = [
'link' => $data[$serviceKey],
'label' => $this->translate($config['linkText']),
'data' => $data,
];
$localIcons = !empty($this->config['local_icons']);
if (!$localIcons && !empty($config['icon'])) {
ThoWagen marked this conversation as resolved.
Show resolved Hide resolved
$result['icon'] = $config['icon'];
} else {
$result['localIcon'] = $config['localIcon'];
}
return $result;
}

/**
* Given an array of identifier arrays, perform a lookup and return an associative array
* of arrays, matching the keys of the input array. Each output array contains one or more
@@ -124,33 +130,53 @@ protected function arrayKeyAvailable(string $key, ?array $data): bool
public function getLinks(array $idArray): array
{
$response = [];
$localIcons = !empty($this->config['local_icons']);
foreach ($idArray as $idKey => $ids) {
if (!isset($ids['doi'])) {
continue;
}
$command = new LookupDoiCommand('BrowZine', $ids['doi']);
$result = $this->searchService->invoke($command)->getResult();
$data = $result['data'] ?? null;
foreach ($this->getDoiServices() as $serviceKey => $config) {
if ($this->arrayKeyAvailable($serviceKey, $data)) {
$result = [
'link' => $data[$serviceKey],
'label' => $this->translate($config['linkText']),
'data' => $data,
];
if (!$localIcons && !empty($config['icon'])) {
$result['icon'] = $config['icon'];
} else {
$result['localIcon'] = $config['localIcon'];
// If we have a DOI, that gets priority because it is more specific; otherwise we'll
// fall back and attempt the ISSN:
if (isset($ids['doi'])) {
$command = new LookupDoiCommand('BrowZine', $ids['doi']);
$result = $this->searchService->invoke($command)->getResult();
ThoWagen marked this conversation as resolved.
Show resolved Hide resolved
$data = $result['data'] ?? null;
foreach ($this->getDoiServices() as $serviceKey => $config) {
if ($this->arrayKeyAvailable($serviceKey, $data)) {
$response[$idKey][] = $this->processServiceLink($data, $serviceKey, $config);
}
}
} elseif (isset($ids['issn'])) {
$command = new LookupIssnsCommand('BrowZine', $ids['issn']);
$result = $this->searchService->invoke($command)->getResult();
ThoWagen marked this conversation as resolved.
Show resolved Hide resolved
$data = $result['data'][0] ?? null;
foreach ($this->getIssnServices() as $serviceKey => $config) {
if ($this->arrayKeyAvailable($serviceKey, $data)) {
$response[$idKey][] = $this->processServiceLink($data, $serviceKey, $config);
}
$response[$idKey][] = $result;
}
}
}
return $response;
}

/**
* Unpack service configuration into more useful array format.
*
* @param array $config Raw (pipe-delimited) configuration from BrowZine.ini
*
* @return array
*/
protected function unpackServiceConfig(array $config): array
{
$result = [];
foreach ($config as $key => $config) {
ThoWagen marked this conversation as resolved.
Show resolved Hide resolved
$parts = explode('|', $config);
$result[$key] = [
'linkText' => $parts[0],
'localIcon' => $parts[1],
'icon' => $parts[2] ?? null,
];
}
return $result;
}

/**
* Get an array of DOI services and their configuration
*
@@ -173,15 +199,26 @@ protected function getDoiServices(): array
],
];
}
$result = [];
foreach ($this->doiServices as $key => $config) {
$parts = explode('|', $config);
$result[$key] = [
'linkText' => $parts[0],
'localIcon' => $parts[1],
'icon' => $parts[2] ?? null,
return $this->unpackServiceConfig($this->doiServices);
}

/**
* Get an array of ISSN services and their configuration
*
* @return array
*/
protected function getIssnServices(): array
{
if (empty($this->issnServices)) {
$baseIconUrl = 'https://assets.thirdiron.com/images/integrations/';
ThoWagen marked this conversation as resolved.
Show resolved Hide resolved
return [
'browzineWebLink' => [
'linkText' => 'Browse Available Issues',
'localIcon' => 'browzine-issue',
'icon' => $baseIconUrl . 'browzine-open-book-icon.svg',
],
];
}
return $result;
return $this->unpackServiceConfig($this->issnServices);
}
}
16 changes: 9 additions & 7 deletions module/VuFind/src/VuFind/IdentifierLinker/BrowZineFactory.php
Original file line number Diff line number Diff line change
@@ -70,12 +70,14 @@ public function __invoke(
throw new \Exception('Unexpected options passed to factory.');
}
$search = $container->get(\VuFindSearch\Service::class);
$fullConfig = $container->get(\VuFind\Config\PluginManager::class)
->get('BrowZine');
$config = isset($fullConfig->DOI) ? $fullConfig->DOI->toArray() : [];
$doiServices = isset($fullConfig->DOIServices)
? $fullConfig->DOIServices->toArray()
: [];
return new $requestedName($search, $config, $doiServices);
$fullConfig = $container->get(\VuFind\Config\PluginManager::class)->get('BrowZine')->toArray();
// DOI config section is supported as a fallback for back-compatibility:
$config = $fullConfig['IdentifierLinks'] ?? $fullConfig['DOI'] ?? [];
return new $requestedName(
$search,
$config,
$fullConfig['DOIServices'] ?? [],
$fullConfig['ISSNServices'] ?? []
);
}
}
1 change: 1 addition & 0 deletions module/VuFind/tests/fixtures/browzine/issn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data":[{"id":5006,"type":"journals","title":"Biochemical Pharmacology","issn":"00062952","sjrValue":1.365,"coverImageUrl":"https://coverurl","browzineEnabled":true,"browzineWebLink":"https://weblink"}]}
Loading