Skip to content
Snippets Groups Projects
Commit a32f4167 authored by Robert Lange's avatar Robert Lange Committed by Dorian Merz
Browse files

refs #15273 [master-v5]

*concatenate base url and param list correctly for finc Link Resolver
** add ResolverTrait to override method getResolverUrl, improve handling of question marks / anpersand
** use getResolverUrl in finc Ezb
** add finc Redi class and use getResolverUrl of finc trait
** add tests for Ezb and Redi
* improve handling and validation of openUrl parameters
** read static openUrl parameters from Resolver.ini in method addCustomParams
** validate necessary function return values for Ezb and Redi to prevent empty links and calls to resolver service
** add OpenUrlTest for both methods
parent 0ee83b03
No related merge requests found
......@@ -54,6 +54,7 @@ use \VuFind\Resolver\Driver\AbstractBase;
class Ezb extends AbstractBase implements TranslatorAwareInterface
{
use \VuFind\I18n\Translator\TranslatorAwareTrait;
use ResolverTrait;
/**
* Base URL for link resolver
......@@ -130,9 +131,9 @@ class Ezb extends AbstractBase implements TranslatorAwareInterface
$openURL .= isset($parsed['zdbid']) ?
'%26zdbid%3D' . $parsed['zdbid'] : '';
// Make the call to the EZB and load results
$url = $this->baseUrl . '?' . $openURL;
$url = $this->getResolverUrl($openURL);
// Make the call to the EZB and load results
$feed = $this->httpClient->setUri($url)->send()->getBody();
return $feed;
}
......
......@@ -64,12 +64,11 @@ class Factory
* @param ServiceManager $sm Service manager.
*
* @return finc\Resolver\Driver\Redi
* @todo Not implemented in finc module yet?
*/
public static function getRedi(ServiceManager $sm)
{
$config = $sm->getServiceLocator()->get('VuFind\Config')->get('Resolver');
return new \VuFind\Resolver\Driver\Redi(
return new Redi(
$config->Redi->url,
$sm->getServiceLocator()->get('VuFind\Http')->createClient()
);
......
<?php
/**
* ReDi Link Resolver Driver
*
* PHP version 5
*
* Copyright (C) Leipzig University Library 2015
*
* @category VuFind
* @package Resolver_Drivers
* @author Robert Lange <lange@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 \VuFind\Resolver\Driver\Redi as RediBase;
/**
* Redi Link Resolver Driver
*
* @category VuFind
* @package Resolver_Drivers
* @author Robert Lange <lange@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
*/
class Redi extends RediBase
{
use ResolverTrait;
/**
* Fetch Links
*
* Fetches a set of links corresponding to an OpenURL
*
* @param string $openURL openURL (url-encoded)
*
* @return string raw XML returned by resolver
*/
public function fetchLinks($openURL)
{
$url = $this->getResolverUrl($openURL);
$feed = $this->httpClient->setUri($url)->send()->getBody();
return $feed;
}
}
<?php
/**
* Finc Resolver Trait
*
* PHP version 5
*
* Copyright (C) Leipzig University Library 2015
*
* 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.
*
* @category VuFind
* @package Resolver_Drivers
* @author Robert Lange <lange@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 \Zend\Config\Exception\InvalidArgumentException;
/**
* Finc Link Resolver Driver
*
* @category VuFind
* @package Resolver_Drivers
* @author Robert Lange <lange@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 ResolverTrait
{
/**
* Get Resolver Url
*
* Transform the OpenURL as needed to get a working link to the resolver.
*
* @param string $openURL openURL (url-encoded)
*
* @return string Returns resolver specific url
*/
public function getResolverUrl($openURL)
{
if (empty($this->baseUrl)) {
throw new InvalidArgumentException(
'Base url for link resolver is not correctly configured.'
);
}
if (empty($openURL)) {
return $this->baseUrl;
}
if ($openURL[0] === '?' || $openURL[0] === '&') {
$openURL = substr($openURL, 1, strlen($openURL)-1);
}
if (strpos($this->baseUrl, '?') === false) {
return $this->baseUrl . '?' . $openURL;
} else {
return $this->baseUrl . '&' . $openURL;
}
}
}
......@@ -27,6 +27,9 @@
*/
namespace finc\View\Helper\Root;
use finc\Resolver\Driver\Ezb;
use finc\Resolver\Driver\Redi;
/**
* OpenUrl view helper
*
......@@ -87,6 +90,21 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
*/
protected $recordResolvers = false;
/**
* Sufficient Resolvers attributes - at least one per resolver
*
* @var array
*/
protected $sufficientResolverParams = [
Redi::class => [
'getAIRecord'
],
Ezb::class => [
'getCleanISSN',
'getZdbId'
]
];
/**
* Constructor
*
......@@ -206,16 +224,7 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
}
$openurl = $this->recordDriver->getOpenURL();
if (isset($this->config->$resolver->custom_params)) {
foreach ($this->config->$resolver->custom_params as $customParam) {
list($key, $value) = explode(':', $customParam);
$customValue = $this->recordDriver->tryMethod($value);
if ($customValue) {
$openurl .= "&" . $key . "=" . $customValue;
}
}
}
$openurl = $this->addCustomParams($resolver, $openurl);
$embedAutoLoad = (isset($this->config->General->embed_auto_load)
? $this->config->General->embed_auto_load : false);
......@@ -307,6 +316,7 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
if (!$this->recordDriver->getOpenUrl()
|| !$this->checkContext()
|| !$this->checkIfRulesApply()
|| !$this->checkValidParams()
) {
return false;
}
......@@ -491,4 +501,68 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
// no rule matched
return false;
}
/**
* @param string $resolverName
* @param string $url
* @return string $url
*/
public function addCustomParams($resolverName, $url)
{
if (isset($this->config->$resolverName->custom_params)) {
foreach ($this->config->$resolverName->custom_params as $customParam) {
list($key, $value) = explode(':', $customParam);
if (strpos($url, $key) !== false) {
// don't override existing key
continue;
}
if (method_exists($this->recordDriver, $value)) {
$customValue = $this->recordDriver->tryMethod($value);
if ($customValue) {
// assume dynamic value
$url .= "&" . $key . "=" . $customValue;
}
} else {
// assume static value
$url .= "&" . $key . "=" . $value;
}
}
}
return $url;
}
/**
* Checks openUrlResolver for sufficient params
*
* @return bool
*/
public function checkValidParams()
{
foreach ($this->recordResolvers as $resolver) {
foreach ($this->sufficientResolverParams as $resolverClazz => $paramMethods) {
try {
if ($resolver === (new \ReflectionClass($resolverClazz))->getShortName()) {
if (count($paramMethods) == 0) {
// no param required
return true;
}
foreach ($paramMethods as $paramMethod) {
if ($paramMethod && method_exists($this->recordDriver, $paramMethod)
&& is_callable(array($this->recordDriver, $paramMethod))
&& call_user_func(array($this->recordDriver, $paramMethod))
) {
return true;
}
}
}
} catch (\ReflectionException $exception) {
// allow unexpected resolver
return true;
}
}
}
// no sufficient param found
return false;
}
}
<?php
/**
* Finc Resolver Ezb Test Class
*
* PHP version 5
*
* Copyright (C) Leipzig University Library 2017.
*
* 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.
*
* @category Finc
* @package Tests
* @author Robert Lange <lange@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
namespace FincTest\Resolver\Driver\Root;
use Zend\Http\Client\Adapter\Test as TestAdapter;
use finc\Resolver\Driver\Ezb;
/**
* Finc Resolver Redi Test Class
*
* @category Finc
* @package Tests
* @author Robert Lange <lange@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
class EzbTest extends \VuFindTest\Resolver\Driver\EzbTest
{
protected $adapter;
protected $client;
protected function initEmpty()
{
$this->adapter = new TestAdapter();
$this->client = new \Zend\Http\Client();
$this->client->setAdapter($this->adapter);
}
protected function getInstance($baseUrl = false)
{
$this->initEmpty();
return $ezb = new Ezb(
$baseUrl !== false ? (object) ['url' => $baseUrl] : (object) $this->openUrlConfig['OpenURL'],
$this->client
);
}
public function testGetResolverUrl()
{
$openUrl = "x=1&y=2";
$this->assertEquals(
"{$this->openUrlConfig['OpenURL']['url']}?$openUrl",
$this->getInstance()->getResolverUrl($openUrl)
);
}
public function testGetResolverUrlWithQuestionMarkInBaseUrl()
{
$baseUrl = "{$this->openUrlConfig['OpenURL']['url']}?site=xyz";
$openUrl = "x=1&y=2";
$this->assertEquals("$baseUrl&$openUrl", $this->getInstance($baseUrl)->getResolverUrl($openUrl));
}
public function testGetResolverUrlNoParams()
{
$this->assertEquals($this->openUrlConfig['OpenURL']['url'], $this->getInstance()->getResolverUrl(""));
}
public function testEmptyBaseUrlException()
{
$this->expectException(\Zend\Config\Exception\InvalidArgumentException::class);
$this->getInstance("")->getResolverUrl("xyz");
}
public function testRemoveLeadingConnectorFromOpenUrl()
{
$baseUrl = "http://services.dnb.de/fize-service/gvr/full.xml";
$openUrl = "&x=1&y=2";
$this->assertEquals(
"http://services.dnb.de/fize-service/gvr/full.xml?x=1&y=2",
$this->getInstance($baseUrl)->getResolverUrl($openUrl)
);
$openUrl = "?x=1&y=2";
$this->assertEquals(
"http://services.dnb.de/fize-service/gvr/full.xml?x=1&y=2",
$this->getInstance($baseUrl)->getResolverUrl($openUrl)
);
}
}
<?php
/**
* Finc Resolver Redi Test Class
*
* PHP version 5
*
* Copyright (C) Leipzig University Library 2017.
*
* 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.
*
* @category Finc
* @package Tests
* @author Robert Lange <lange@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
namespace FincTest\Resolver\Driver\Root;
use Zend\Http\Client\Adapter\Test as TestAdapter;
use finc\Resolver\Driver\Redi;
/**
* Finc Resolver Redi Test Class
*
* @category Finc
* @package Tests
* @author Robert Lange <lange@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
class RediTest extends \VuFindTest\Resolver\Driver\RediTest
{
protected $adapter;
protected $client;
protected function initEmpty()
{
$this->adapter = new TestAdapter();
$this->client = new \Zend\Http\Client();
$this->client->setAdapter($this->adapter);
}
protected function getInstance($baseUrl = false)
{
$this->initEmpty();
return $redi = new Redi(
$baseUrl !== false ? $baseUrl : $this->openUrlConfig['OpenURL']['url'],
$this->client
);
}
public function testGetResolverUrl()
{
$openUrl = "x=1&y=2";
$this->assertEquals(
"{$this->openUrlConfig['OpenURL']['url']}?$openUrl",
$this->getInstance()->getResolverUrl($openUrl)
);
}
public function testGetResolverUrlWithQuestionMarkInBaseUrl()
{
$baseUrl = "{$this->openUrlConfig['OpenURL']['url']}?site=xyz";
$openUrl = "x=1&y=2";
$this->assertEquals("$baseUrl&$openUrl", $this->getInstance($baseUrl)->getResolverUrl($openUrl));
}
public function testGetResolverUrlNoParams()
{
$this->assertEquals($this->openUrlConfig['OpenURL']['url'], $this->getInstance()->getResolverUrl(""));
}
public function testGetResolverUrlWHZ()
{
$openUrl = "rl_site=whz&issn=1941-9511";
$this->assertEquals(
"http://www.redi-bw.de/links/whz?rl_site=whz&rl_site=whz&issn=1941-9511",
$this->getInstance("http://www.redi-bw.de/links/whz?rl_site=whz")->getResolverUrl($openUrl)
);
}
public function testEmptyBaseUrlException()
{
$this->expectException(\Zend\Config\Exception\InvalidArgumentException::class);
$this->getInstance("")->getResolverUrl("");
}
}
<?php
/**
* Open Url Test Class
*
* PHP version 5
*
* Copyright (C) Leipzig University Library 2017.
*
* 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 Finc
* @package Tests
* @author Robert Lange <lange@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
namespace FincTest\View\Helper\Root;
use finc\View\Helper\Root\OpenUrl;
/**
* Open Url Test Class
*
* @category Finc
* @package Tests
* @author Robert Lange <lange@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
class OpenUrlTest extends \VuFindTest\View\Helper\Root\OpenUrlTest
{
const ISSN = 456;
const OPEN_URL = "open=url";
const ZDB_ID = 123;
public function testAddCustomParamsNoParams()
{
$instance = $this->getInstance();
$nonConfigParams = "key1=value1&foo=bar&key2=value2";
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Ezb', $nonConfigParams));
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Redi', $nonConfigParams));
}
public function testAddCustomStaticParamsForEzb()
{
$config = $this->getBaseConfigObject();
$config->General->active_resolvers = 'Ezb, Redi';
$config->Ezb->custom_params = ['foo:bar'];
$instance = $this->getInstance($config);
$nonConfigParams = "key1=value1&key2=value2";
$this->assertEquals("{$nonConfigParams}&foo=bar", $instance->addCustomParams('Ezb', $nonConfigParams));
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Redi', $nonConfigParams));
}
public function testDONTOverrideExistingParamsForEzb()
{
$config = $this->getBaseConfigObject();
$config->General->active_resolvers = 'Ezb, Redi';
$config->Ezb->custom_params = ['foo:bar'];
$instance = $this->getInstance($config);
$nonConfigParams = "key1=value1&foo=bar&key2=value2";
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Ezb', $nonConfigParams));
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Redi', $nonConfigParams));
}
public function testAddCustomStaticParamsForRedi()
{
$config = $this->getBaseConfigObject();
$config->General->active_resolvers = 'Ezb, Redi';
$config->Redi->custom_params = ['foo:bar'];
$instance = $this->getInstance($config);
$nonConfigParams = "key1=value1&key2=value2";
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Ezb', $nonConfigParams));
$this->assertEquals("{$nonConfigParams}&foo=bar", $instance->addCustomParams('Redi', $nonConfigParams));
}
public function testDONTOverrideExistingParamsForRedi()
{
$config = $this->getBaseConfigObject();
$config->General->active_resolvers = 'Ezb, Redi';
$config->Redi->custom_params = ['foo:bar'];
$instance = $this->getInstance($config);
$nonConfigParams = "key1=value1&foo=bar&key2=value2";
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Ezb', $nonConfigParams));
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Redi', $nonConfigParams));
}
public function testAddCustomDynamicParamsForEzb()
{
$config = $this->getBaseConfigObject();
$config->General->active_resolvers = 'Ezb, Redi';
$config->Ezb->custom_params = ['zdbid:getZdbId'];
$instance = $this->getInstance($config);
$nonConfigParams = "key1=value1&foo=bar&key2=value2";
$this->assertEquals(
"{$nonConfigParams}&zdbid=" . self::ZDB_ID,
$instance->addCustomParams('Ezb', $nonConfigParams)
);
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Redi', $nonConfigParams));
}
public function testAddCustomDynamicParamsForRedi()
{
$config = $this->getBaseConfigObject();
$config->General->active_resolvers = 'Ezb, Redi';
$config->Redi->custom_params = ['issn:getCleanISSN'];
$instance = $this->getInstance($config);
$nonConfigParams = "key1=value1&foo=bar&key2=value2";
$this->assertEquals(
"{$nonConfigParams}&issn=" . self::ISSN,
$instance->addCustomParams('Redi', $nonConfigParams)
);
$this->assertEquals("{$nonConfigParams}", $instance->addCustomParams('Ezb', $nonConfigParams));
}
public function testValidateParamsEzbFalse()
{
$this->rulesConfig['Ezb'] = [0 => ['include' => ["methods" => "getSourceID"]]];
$instance = $this->getInstance();
$this->assertFalse($instance->isActive());
}
public function testValidateParamsEzbTrue()
{
$this->rulesConfig['Ezb'] = [0 => ['include' => ["methods" => "getSourceID"]]];
$instanceWithIssn = $this->getInstance(false, true, false);
$this->assertTrue($instanceWithIssn->isActive());
$instanceWithZdbId = $this->getInstance(false, false, true);
$this->assertTrue($instanceWithZdbId->isActive());
$instanceWithIssnAndZdbId = $this->getInstance(false, true, true);
$this->assertTrue($instanceWithIssnAndZdbId->isActive());
}
/*
Helper Functions
*/
/**
* @param bool $config
* @param bool $recordHasIssn
* @param bool $recordHasZdbId
* @return \finc\View\Helper\Root\OpenUrl
*/
protected function getInstance($config = false, $recordHasIssn = false, $recordHasZdbId = false)
{
if (empty($config)) {
$config = $this->getBaseConfigObject();
}
$driver = $this->getBasicFincMockDriver('finc\RecordDriver\SolrDefault', $recordHasIssn, $recordHasZdbId);
$context = new \VuFind\View\Helper\Root\Context();
$openUrlClazz = new OpenUrl($context, $this->rulesConfig, $config);
$openUrlClazz->__invoke($driver, "results");
return $openUrlClazz;
}
/**
* Get mock driver that returns an openURL.
*
* @param string $class Class to mock
*
* @param bool $hasIssn
* @param bool $hasZdbId
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getBasicFincMockDriver(
$class = 'finc\RecordDriver\SolrDefault',
$hasIssn = false,
$hasZdbId = false
) {
$driver = $this->getMockBuilder($class)
->disableOriginalConstructor()->getMock();
$driver->method('tryMethod')
->will($this->returnCallback(array($this, 'getCallback')));
$driver->method('getOpenUrl')
->willReturn(self::OPEN_URL);
if ($hasIssn) {
$driver->method('getCleanISSN')
->willReturn(self::ISSN);
}
if ($hasZdbId) {
$driver->method('getZdbId')
->willReturn(self::ZDB_ID);
}
return $driver;
}
public function getCallback($foo)
{
if ($foo == "getZdbId") {
return self::ZDB_ID;
}
if ($foo == "getCleanISSN") {
return self::ISSN;
}
return null;
}
protected function getBaseConfigObject()
{
$openUrlConfig = [
'OpenURL' => [
'url' => "http://services.d-nb.de/fize-service/gvr/full.xml",
'rfr_id' => "www.ub.uni-leipzig.de",
'resolver' => "ezb",
'window_settings' => "toolbar=no",
'show_in_results' => false,
'show_in_record' => false,
'show_in_holdings' => true,
'embed' => true,
'replace_other_urls' => true
],
];
$config = [
'General' => [
'active_resolvers' => 'Ezb, Redi'
],
'Redi' => [
'url' => 'http://www.redi-bw.de/links/whz',
'resolver' => 'redi',
],
'Ezb' => [
'url' => 'http://services.dnb.de/fize-service/gvr/full.xml',
'resolver' => 'ezb',
],
'openUrlConfig' => $openUrlConfig
];
return $this->arrayToObject($config);
}
public function arrayToObject($array)
{
$obj = new \stdClass();
foreach ($array as $k => $v) {
if (strlen($k)) {
if (is_array($v)) {
$obj->{$k} = $this->arrayToObject($v); //RECURSION
} else {
$obj->{$k} = $v;
}
}
}
return $obj;
}
}
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