Skip to content
Snippets Groups Projects
Commit 20ace5a8 authored by André Lahmann's avatar André Lahmann Committed by Robert Lange
Browse files

refs #20764 [finc] add EZB resolver driver trait in finc for easier mergin and...

refs #20764 [finc] add EZB resolver driver trait in finc for easier mergin and preparation of pull request

* make title selector a static variable that can be overwritten
* add electronic result type 10 for Unknown Electronic
* format rft.date and map rft properties

co-authored by: Robert Lange <robert.lange@uni-leipzig.de>
parent 6f1cc98c
No related merge requests found
<?php
/**
* EZB Link Resolver Driver Trait
*
* EZB is a free service -- the API endpoint is available at
* http://services.dnb.de/fize-service/gvr/full.xml
*
* API documentation is available at
* http://www.zeitschriftendatenbank.de/services/journals-online-print
*
* PHP version 7
*
* Copyright (C) Markus Fischer, info@flyingfischer.ch
*
* last update: 2011-04-13
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package Resolver_Drivers
* @author Markus Fischer <info@flyingfischer.ch>
* @author André Lahmann <lahmann@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
*/
namespace finc\Resolver\Driver;
use DOMDocument;
use DOMXpath;
/**
* EZB Link Resolver Driver
*
* @category VuFind
* @package Resolver_Drivers
* @author Markus Fischer <info@flyingfischer.ch>
* @author André Lahmann <lahmann@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
*/
trait EzbTrait
{
/**
* As the JOP resolver provides also generic labels 'Article', 'Journal'
* etc. in element AccessLevel this label can be used as title for
* resolver results by setting this variable to 'AccessLevel'
*
* @var string
*/
protected static $xpathTitleSelector = 'Title';
/**
* Parse Links
*
* Parses an XML file returned by a link resolver
* and converts it to a standardised format for display
*
* @param string $xmlstr Raw XML returned by resolver
*
* @return array Array of values
*/
public function parseLinks($xmlstr)
{
$records = []; // array to return
$xml = new DOMDocument();
if (!@$xml->loadXML($xmlstr)) {
return $records;
}
$xpath = new DOMXpath($xml);
// get results for online
$this->getElectronicResults('0', 'Free', $records, $xpath);
$this->getElectronicResults('1', 'Partially free', $records, $xpath);
$this->getElectronicResults('2', 'Licensed', $records, $xpath);
$this->getElectronicResults('3', 'Partially licensed', $records, $xpath);
$this->getElectronicResults('4', 'Not free', $records, $xpath);
$this->getElectronicResults('10', 'Unknown Electronic', $records, $xpath);
// get results for print, only if available
$this->getPrintResults('2', 'Print available', $records, $xpath);
$this->getPrintResults('3', 'Print partially available', $records, $xpath);
$this->getPrintResults('10', 'Unknown Print', $records, $xpath);
return $records;
}
/**
* Downgrade an OpenURL from v1.0 to v0.1 for compatibility with EZB.
*
* @param array $parsed Array of parameters parsed from the OpenURL.
*
* @return string EZB-compatible v0.1 OpenURL
*/
protected function downgradeOpenUrl($parsed)
{
$downgraded = [];
// prepare content for downgrading
// resolver only accepts date formats YYYY, YYYY-MM, and YYYY-MM-DD
// in case we have a date in another format, drop the date information
if (isset($parsed['rft.date'])
&& !preg_match('/^\d{4}(-\d\d(-\d\d)?)?$/', $parsed['rft.date'])
) {
unset($parsed['rft.date']);
}
$map = [
'rfr_id' => 'sid',
'rft.date' => 'date',
'rft.issn' => 'issn',
'rft.isbn' => 'isbn', // isbn is supported as of 12/2021
'rft.volume' => 'volume',
'rft.issue' => 'issue',
'rft.spage' => 'spage',
'rft.pages' => 'pages',
];
// ignore all other parameters
foreach ($parsed as $key => $value) {
// exclude empty parameters
if (isset($value) && $value !== '') {
if (isset($map[$key])) {
$downgraded[] = "{$map[$key]}=$value";
} elseif (in_array($key, $map)) {
$downgraded[] = "$key=$value";
}
}
}
if (!empty($downgraded)) {
// we need 'genre' but only the values
// article or journal are allowed...
return "genre=article&" . implode('&', $downgraded);
}
return implode('&', $parsed);
}
/**
* Extract electronic results from the EZB response and inject them into the
* $records array.
*
* @param string $state The state attribute value to extract
* @param string $coverage The coverage string to associate with the state
* @param array $records The array of results to update
* @param DOMXpath $xpath The XPath object containing parsed XML
*
* @return void
*/
protected function getElectronicResults($state, $coverage, &$records, $xpath)
{
$results = $xpath->query(
"/OpenURLResponseXML/Full/ElectronicData/ResultList/Result[@state=" .
$state . "]"
);
/*
* possible state values:
* -1 ISSN nicht eindeutig
* 0 Standort-unabhängig frei zugänglich
* 1 Standort-unabhängig teilweise zugänglich (Unschärfe bedingt durch
* unspezifische Anfrage oder Moving-Wall)
* 2 Lizenziert
* 3 Für gegebene Bibliothek teilweise lizenziert (Unschärfe bedingt durch
* unspezifische Anfrage oder Moving-Wall)
* 4 nicht lizenziert
* 5 Zeitschrift gefunden
* Angaben über Erscheinungsjahr, Datum ... liegen außerhalb des
* hinterlegten bibliothekarischen Zeitraums
* 10 Unbekannt (ISSN unbekannt, Bibliothek unbekannt)
*/
$state_access_mapping = [
'-1' => 'error',
'0' => 'open',
'1' => 'open',
'2' => 'limited',
'3' => 'limited',
'4' => 'denied',
'5' => 'denied',
'10' => 'unknown'
];
$i = 0;
foreach ($results as $result) {
$record = [];
// get title from XPath Element defined in $xpathTitleSelector
$titleXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
"Result[@state={$state}][" . ($i + 1) . "]/" .
static::$xpathTitleSelector;
$title = $xpath->query($titleXP, $result)->item(0);
if (isset($title)) {
$record['title'] = strip_tags($title->nodeValue);
}
// get additional coverage information
$additionalXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
"Result[@state={$state}][" . ($i + 1) . "]/Additionals/Additional";
$additionalType = ['nali', 'intervall', 'moving_wall'];
$additionals = [];
foreach ($additionalType as $type) {
$additional = $xpath
->query($additionalXP . "[@type='" . $type . "']", $result)
->item(0);
if (isset($additional->nodeValue)) {
$additionals[$type] = strip_tags($additional->nodeValue);
}
}
$record['coverage']
= !empty($additionals) ? implode("; ", $additionals) : $coverage;
$record['access'] = $state_access_mapping[$state];
// try to find direct access URL
$accessUrlXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
"Result[@state={$state}][" . ($i + 1) . "]/AccessURL";
$accessUrl = $xpath->query($accessUrlXP, $result)->item(0);
// try to find journal URL as fallback for direct access URL
$journalUrlXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
"Result[@state={$state}][" . ($i + 1) . "]/JournalURL";
$journalUrl = $xpath->query($journalUrlXP, $result)->item(0);
// return direct access URL if available otherwise journal URL fallback
if (isset($accessUrl->nodeValue)) {
$record['href'] = $accessUrl->nodeValue;
} elseif (isset($journalUrl)) {
$record['href'] = $journalUrl->nodeValue;
}
// Service type needs to be hard-coded for calling code to properly
// categorize links. The commented code below picks a more appropriate
// value but won't work for now -- retained for future reference.
//$service_typeXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/"
// . "Result[@state={$state}][".($i+1)."]/AccessLevel";
//$record['service_type']
// = $xpath->query($service_typeXP, $result)->item(0)->nodeValue;
$record['service_type'] = 'getFullTxt';
array_push($records, $record);
$i++;
}
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment