From 93d7ba8ebca183704965e68393ed5c9aea62c0e0 Mon Sep 17 00:00:00 2001 From: Robert Lange <robert.lange@uni-leipzig.de> Date: Tue, 23 Jun 2020 09:37:38 +0200 Subject: [PATCH] refs #17508 [master] handle ill pickup branch * introduce PAIA options containing pickupbranch * needed to differentiate between storageId and pickuplocation of ILL items: ** read paiaConditions from FincLibero.ini ** add method 'mapOptions' to read certain or all options of PAIA conditions for details see issue/17508 --- module/finc/src/finc/ILS/Driver/PAIA.php | 74 ++ .../fincWithAnotherPickupBranchOption.json | 50 ++ .../fincWithMultiplePickupBranchOptions.json | 53 ++ .../fincWithOnePickupBranchOption.json | 66 ++ .../paia/response/fincWithUnknownOption.json | 65 ++ .../paia/response/fincWithoutOptions.json | 55 ++ .../src/fincTest/ILS/Driver/PAIATest.php | 769 ++++++++++++++++++ 7 files changed, 1132 insertions(+) create mode 100644 module/finc/tests/fixtures/paia/response/fincWithAnotherPickupBranchOption.json create mode 100644 module/finc/tests/fixtures/paia/response/fincWithMultiplePickupBranchOptions.json create mode 100644 module/finc/tests/fixtures/paia/response/fincWithOnePickupBranchOption.json create mode 100644 module/finc/tests/fixtures/paia/response/fincWithUnknownOption.json create mode 100644 module/finc/tests/fixtures/paia/response/fincWithoutOptions.json create mode 100644 module/finc/tests/unit-tests/src/fincTest/ILS/Driver/PAIATest.php diff --git a/module/finc/src/finc/ILS/Driver/PAIA.php b/module/finc/src/finc/ILS/Driver/PAIA.php index 579991694b2..6eb349d54e3 100644 --- a/module/finc/src/finc/ILS/Driver/PAIA.php +++ b/module/finc/src/finc/ILS/Driver/PAIA.php @@ -71,6 +71,11 @@ class PAIA extends \VuFind\ILS\Driver\PAIA protected $notificationsPrefix; + /** + * @var array + */ + protected $conditions; + /** * Constructor * @@ -97,6 +102,10 @@ class PAIA extends \VuFind\ILS\Driver\PAIA if (isset($this->config['PAIA']['paiaNotificationsPrefix'])) { $this->notificationsPrefix = $this->config['PAIA']['paiaNotificationsPrefix']; } + + if (isset($this->config['PAIA']['paiaConditions'])) { + $this->conditions = $this->config['PAIA']['paiaConditions']; + } } /** @@ -972,6 +981,9 @@ class PAIA extends \VuFind\ILS\Driver\PAIA $result['upc'] = null; */ + /* #17508 read optional PAIA information like pickupbranch */ + $this->mapOptions($doc, $result); + $results[] = $result; } return $results; @@ -1511,4 +1523,66 @@ class PAIA extends \VuFind\ILS\Driver\PAIA // return TRUE on success return true; } + + /*** + * finds conditions in PAIA items array and adds it as options in finc converted items array + * + * Conditions according to PAIA default are only intended for request, renew or cancel + * BUT here used for items too, therefore should be only one option per condition + * see: http://gbv.github.io/paia/paia.html#conditions-and-confirmations + * + * @param array $doc Array of PAIA input to be mapped + * @param array $result Array of PAIA output - called by reference + * @param array|null $configConditions conditions to be considered (optional, if null use config) + * + * @return bool True if any option was found, otherwise false. + */ + protected function mapOptions(array $doc, array &$result, array $configConditions = null): bool + { + $configConditions = $configConditions ?? $this->conditions ?? []; + + foreach ($configConditions as $configCondition) { + if ($optionsValues = $doc["condition"][$configCondition]["option"] ?? []) { + $found = $result["options"][$configCondition] = $optionsValues; + } + } + + return !empty($found); + } + + /** + * Get (first) option for given condition and valid options from finc converted PAIA result + * + * @param string $condition + * @param array $result + * @param boolean $onlyFirst + * @param array $validOptions + * + * @return array of option values: each either valid id or label or null if none set + */ + public function getOptions(string $condition, array $result, bool $onlyFirst, array $validOptions = null): array + { + $retval = []; + if (in_array($condition, $this->conditions)) { + $options = $result['options'][$condition] ?? []; + foreach ($options as $option) { + if (!$validOptions) { + $retval[] = $option['about'] ?? $option['id'] ?? null; + if ($onlyFirst) { + break; + } + } else { + foreach ($validOptions as $validOption) { + if (array_intersect($validOption, $option)) { + $retval[] = $option['id'] ?? $option['about'] ?? null; + if ($onlyFirst) { + break 2; + } + } + } + } + } + } + return $retval; + } } diff --git a/module/finc/tests/fixtures/paia/response/fincWithAnotherPickupBranchOption.json b/module/finc/tests/fixtures/paia/response/fincWithAnotherPickupBranchOption.json new file mode 100644 index 00000000000..75a8a368417 --- /dev/null +++ b/module/finc/tests/fixtures/paia/response/fincWithAnotherPickupBranchOption.json @@ -0,0 +1,50 @@ +HTTP/1.1 200 OK +Server: vzg-paia/2.2-RC3 (Wed Jun 01 17:38:24 CEST 2016) +Date: Mon, 20 Jun 2020 10:38:21 GMT +Cache-Control: no-cache +Access-Control-Allow-Origin: * +Access-Control-Expose-Headers: X-OAuth-Scopes, X-Accepted-OAuth-Scopes +Access-Control-Allow-Headers: Content-Type, Authorization +Pragma: no-cache +X-OAuth-Scopes: change_password read_items read_fees read_patron +X-Accepted-OAuth-Scopes: read_patron +Content-Type: application/json; charset=UTF-8 + +{ + "doc": [ + { + "status": 3, + "item": "DE-Zi4:barcode:03201978", + "about": "Urbanität als Habitus", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 4, + "item": "DE-Zi4:barcode:80086919", + "about": "Fernleihe mit Abholstation", + "condition": { + "http://purl.org/ontology/paia#PickupCondition": { + "option": [ + { + "id": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI", + "about": "Zweigbibliothek Zittau", + "amount": "2,50 EUR" + } + ] + } + }, + "storage": "Hochschulbibliothek Görlitz", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR" + }, + { + "status": 0, + "item": "ILL:13940", + "about": "Aushandlungen städtischer Größe - Eckert, Anna", + "label": "Medium im Vormerkregal", + "starttime": "2020-03-12T00:00:00+01:00" + } + ] +} diff --git a/module/finc/tests/fixtures/paia/response/fincWithMultiplePickupBranchOptions.json b/module/finc/tests/fixtures/paia/response/fincWithMultiplePickupBranchOptions.json new file mode 100644 index 00000000000..19225a142cb --- /dev/null +++ b/module/finc/tests/fixtures/paia/response/fincWithMultiplePickupBranchOptions.json @@ -0,0 +1,53 @@ +HTTP/1.1 200 OK +Server: vzg-paia/2.2-RC3 (Wed Jun 01 17:38:24 CEST 2016) +Date: Mon, 20 Jun 2020 10:38:21 GMT +Cache-Control: no-cache +Access-Control-Allow-Origin: * +Access-Control-Expose-Headers: X-OAuth-Scopes, X-Accepted-OAuth-Scopes +Access-Control-Allow-Headers: Content-Type, Authorization +Pragma: no-cache +X-OAuth-Scopes: change_password read_items read_fees read_patron +X-Accepted-OAuth-Scopes: read_patron +Content-Type: application/json; charset=UTF-8 + +{ + "doc": [ + { + "status": 3, + "item": "DE-Zi4:barcode:03201978", + "about": "Urbanität als Habitus", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 4, + "item": "DE-Zi4:barcode:80086919", + "about": "Fernleihe mit Abholstation", + "condition": { + "http://purl.org/ontology/paia#PickupCondition": { + "option": [ + { + "id": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI", + "about": "Zweigbibliothek Zittau" + }, + { + "id": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR", + "about": "Zweigbibliothek Görlitz" + } + ] + } + }, + "storage": "Hochschulbibliothek Görlitz", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR" + }, + { + "status": 0, + "item": "ILL:13940", + "about": "Aushandlungen städtischer Größe - Eckert, Anna", + "label": "Medium im Vormerkregal", + "starttime": "2020-03-12T00:00:00+01:00" + } + ] +} diff --git a/module/finc/tests/fixtures/paia/response/fincWithOnePickupBranchOption.json b/module/finc/tests/fixtures/paia/response/fincWithOnePickupBranchOption.json new file mode 100644 index 00000000000..c00ed7217e7 --- /dev/null +++ b/module/finc/tests/fixtures/paia/response/fincWithOnePickupBranchOption.json @@ -0,0 +1,66 @@ +HTTP/1.1 200 OK +Server: vzg-paia/2.2-RC3 (Wed Jun 01 17:38:24 CEST 2016) +Date: Mon, 20 Jun 2020 10:38:21 GMT +Cache-Control: no-cache +Access-Control-Allow-Origin: * +Access-Control-Expose-Headers: X-OAuth-Scopes, X-Accepted-OAuth-Scopes +Access-Control-Allow-Headers: Content-Type, Authorization +Pragma: no-cache +X-OAuth-Scopes: change_password read_items read_fees read_patron +X-Accepted-OAuth-Scopes: read_patron +Content-Type: application/json; charset=UTF-8 + +{ + "doc": [ + { + "status": 4, + "item": "DE-Zi4:barcode:80086919", + "about": "Fernleihe mit Abholstation", + "condition": { + "http://purl.org/ontology/paia#PickupCondition": { + "option": [ + { + "id": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR", + "about": "Zweigbibliothek Görlitz", + "amount": "2.50 EUR" + } + ] + } + }, + "storage": "Hochschulbibliothek Zittau", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI" + }, + { + "status": 3, + "item": "DE-Zi4:barcode:02415857", + "about": "Die Eigenlogik der Städte", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 4, + "item": "DE-Zi4:barcode:03039724", + "about": "Stadtsoziologie", + "storage": "Hochschulbibliothek Zittau", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI" + }, + { + "status": 3, + "item": "DE-Zi4:barcode:03201978", + "about": "Urbanität als Habitus", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 0, + "item": "ILL:13940", + "about": "Aushandlungen städtischer Größe - Eckert, Anna", + "label": "Medium im Vormerkregal", + "starttime": "2020-03-12T00:00:00+01:00" + } + ] +} diff --git a/module/finc/tests/fixtures/paia/response/fincWithUnknownOption.json b/module/finc/tests/fixtures/paia/response/fincWithUnknownOption.json new file mode 100644 index 00000000000..e3120951b9c --- /dev/null +++ b/module/finc/tests/fixtures/paia/response/fincWithUnknownOption.json @@ -0,0 +1,65 @@ +HTTP/1.1 200 OK +Server: vzg-paia/2.2-RC3 (Wed Jun 01 17:38:24 CEST 2016) +Date: Mon, 20 Jun 2020 10:38:21 GMT +Cache-Control: no-cache +Access-Control-Allow-Origin: * +Access-Control-Expose-Headers: X-OAuth-Scopes, X-Accepted-OAuth-Scopes +Access-Control-Allow-Headers: Content-Type, Authorization +Pragma: no-cache +X-OAuth-Scopes: change_password read_items read_fees read_patron +X-Accepted-OAuth-Scopes: read_patron +Content-Type: application/json; charset=UTF-8 + +{ + "doc": [ + { + "status": 4, + "item": "DE-Zi4:barcode:80086919", + "about": "Fernleihe mit Abholstation", + "condition": { + "http://purl.org/ontology/paia#PickupCondition": { + "option": [ + { + "id": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/unknownLocation", + "about": "Zweigbibliothek Neu aber noch nicht bekannt / konfiguriert => soll nicht angezeigt werden" + } + ] + } + }, + "storage": "Hochschulbibliothek Zittau", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI" + }, + { + "status": 3, + "item": "DE-Zi4:barcode:02415857", + "about": "Die Eigenlogik der Städte", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 4, + "item": "DE-Zi4:barcode:03039724", + "about": "Stadtsoziologie", + "storage": "Hochschulbibliothek Zittau", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI" + }, + { + "status": 3, + "item": "DE-Zi4:barcode:03201978", + "about": "Urbanität als Habitus", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 0, + "item": "ILL:13940", + "about": "Aushandlungen städtischer Größe - Eckert, Anna", + "label": "Medium im Vormerkregal", + "starttime": "2020-03-12T00:00:00+01:00" + } + ] +} diff --git a/module/finc/tests/fixtures/paia/response/fincWithoutOptions.json b/module/finc/tests/fixtures/paia/response/fincWithoutOptions.json new file mode 100644 index 00000000000..f75b1602ac8 --- /dev/null +++ b/module/finc/tests/fixtures/paia/response/fincWithoutOptions.json @@ -0,0 +1,55 @@ +HTTP/1.1 200 OK +Server: vzg-paia/2.2-RC3 (Wed Jun 01 17:38:24 CEST 2016) +Date: Mon, 20 Jun 2020 10:38:21 GMT +Cache-Control: no-cache +Access-Control-Allow-Origin: * +Access-Control-Expose-Headers: X-OAuth-Scopes, X-Accepted-OAuth-Scopes +Access-Control-Allow-Headers: Content-Type, Authorization +Pragma: no-cache +X-OAuth-Scopes: change_password read_items read_fees read_patron +X-Accepted-OAuth-Scopes: read_patron +Content-Type: application/json; charset=UTF-8 + +{ + "doc": [ + { + "status": 4, + "item": "DE-Zi4:barcode:80086919", + "about": "Fernleihe mit Abholstation", + "storage": "Hochschulbibliothek Zittau", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI" + }, + { + "status": 3, + "item": "DE-Zi4:barcode:02415857", + "about": "Die Eigenlogik der Städte", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 4, + "item": "DE-Zi4:barcode:03039724", + "about": "Stadtsoziologie", + "storage": "Hochschulbibliothek Zittau", + "storageid": "http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI" + }, + { + "status": 3, + "item": "DE-Zi4:barcode:03201978", + "about": "Urbanität als Habitus", + "renewals": 3, + "starttime": "2020-03-13T00:00:00+01:00", + "endtime": "2020-07-10T00:00:00+02:00", + "canrenew": true + }, + { + "status": 0, + "item": "ILL:13940", + "about": "Aushandlungen städtischer Größe - Eckert, Anna", + "label": "Medium im Vormerkregal", + "starttime": "2020-03-12T00:00:00+01:00" + } + ] +} diff --git a/module/finc/tests/unit-tests/src/fincTest/ILS/Driver/PAIATest.php b/module/finc/tests/unit-tests/src/fincTest/ILS/Driver/PAIATest.php new file mode 100644 index 00000000000..392a0b27049 --- /dev/null +++ b/module/finc/tests/unit-tests/src/fincTest/ILS/Driver/PAIATest.php @@ -0,0 +1,769 @@ +<?php +/** + * ILS driver test + * + * PHP version 7 + * + * Copyright (C) Leipzig University Library 2020. + * + * 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 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 Main Page + */ +namespace VuFindTest\ILS\Driver; + +use finc\ILS\Driver\PAIA as fincPAIA; +use InvalidArgumentException; +use Zend\Http\Client\Adapter\Test as TestAdapter; +use Zend\Http\Response as HttpResponse; + +/** + * ILS driver test + * + * @category VuFind + * @package FincTest + * @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 Main Page + */ +class PAIAFincTest extends \VuFindTest\ILS\Driver\PAIATest +{ + public static $pickupCondition = 'http://purl.org/ontology/paia#PickupCondition'; + + public static $validConfigWithPickUpOption = [ + 'DAIA' => + [ + 'baseUrl' => 'http://daia.gbv.de/', + ], + 'PAIA' => + [ + 'baseUrl' => 'http://paia.gbv.de/', + 'paiaConditions' => + [ + 'http://purl.org/ontology/paia#PickupCondition' + ] + ] + ]; + + public static $validConfigWithOptionForOtherInstance = [ + 'DAIA' => + [ + 'baseUrl' => 'http://daia.gbv.de/', + ], + 'PAIA' => + [ + 'baseUrl' => 'http://paia.gbv.de/', + 'paiaConditions' => + [ + 'http://purl.org/ontology/paia#PickupCondition' => 'http://data.ub.uni-leipzig.de/resource/DE-15/department/wrongPickup' + ] + ] + ]; + + + + /** + * Test + * + * @return void + */ + public function testMapOptionsPickupBranchTrue() + { + list($method, $paia) = $this->prepareByReflection(); + + $pickUpId = 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR'; + $pickUpAbout = 'Zweigbibliothek Görlitz'; + $input = [ + 'condition' => [ + self::$pickupCondition => [ + 'option' => [ + 0 => [ + 'id' => $pickUpId, + 'about' => $pickUpAbout + ] + ] + ] + ] + ]; + + + $conditions = [ + self::$pickupCondition + ]; + + $output = []; + $method->invokeArgs($paia, [$input, &$output, $conditions]); + + $this->assertEquals($pickUpId, $output['options'][self::$pickupCondition][0]['id'], + "Wrong pickup branch id!" + ); + + $this->assertEquals($pickUpAbout, $output['options'][self::$pickupCondition][0]['about'], + "Wrong pickup branch label!" + ); + } + + /** + * Test + * + * @return void + */ + public function testMapOptionsNewTrue() + { + list($method, $paia) = $this->prepareByReflection(); + + $pickUpId = 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR'; + $pickUpAbout = 'Zweigbibliothek Görlitz'; + $newOptionId = 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/newOption'; + $newOption = 'a new option within new condition'; + $input = [ + 'condition' => [ + self::$pickupCondition => [ + 'option' => [ + 0 => [ + 'id' => $pickUpId, + 'about' => $pickUpAbout + ] + ] + ], + 'http://purl.org/ontology/paia#newCondition' => [ + 'option' => [ + 0 => [ + 'id' => $newOptionId, + 'about' => $newOption + ] + ] + ] + ] + ]; + + $conditions = [ + self::$pickupCondition, + 'http://purl.org/ontology/paia#newCondition' + ]; + + $output = []; + $method->invokeArgs($paia, [$input, &$output, $conditions]); + $this->assertEquals($pickUpId, $output['options'][self::$pickupCondition][0]['id'], + "Wrong pickup branch id!" + ); + $this->assertEquals($pickUpAbout, $output['options'][self::$pickupCondition][0]['about'], + "Wrong pickup branch label!" + ); + $this->assertEquals($newOptionId, $output['options']['http://purl.org/ontology/paia#newCondition'][0]['id'], + "New option id missing!" + ); + $this->assertEquals($newOption, $output['options']['http://purl.org/ontology/paia#newCondition'][0]['about'], + "New option label missing!" + ); + } + + /** + * Test + * + * @return void + */ + public function testMapOptionsPickupBranchFalseNoConditions() + { + list($method, $paia) = $this->prepareByReflection(); + + $pickUpBranch = 'Zweigbibliothek Görlitz'; + $input = [ + 'condition' => [ + self::$pickupCondition => [ + 'option' => [ + 0 => [ + 'id' => 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR', + 'about' => $pickUpBranch + ] + ] + ] + ] + ]; + + $output = []; + $method->invokeArgs($paia, [$input, &$output, []]); + $this->assertFalse(isset($output["options"]), + "Unknown option was mapped" + ); + } + + /** + * Test + * + * @return void + */ + public function testMapOptionsPickupBranchTrueUnknownOptionId() + { + /* validate new options otherwise, e.g. by checking $presentationPickups later */ + list($method, $paia) = $this->prepareByReflection(); + + $pickUpBranch = 'Zweigbibliothek Görlitz'; + $input = [ + 'condition' => [ + self::$pickupCondition => [ + 'option' => [ + 0 => [ + 'id' => 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/fake', + 'about' => $pickUpBranch + ] + ] + ] + ] + ]; + + $conditions = [ + self::$pickupCondition + ]; + + $output = []; + $method->invokeArgs($paia, [$input, &$output, $conditions]); + $this->assertTrue(isset($output["options"]), + "Unknown option was not mapped" + ); + } + + /** + * Test + * + * @return void + */ + public function testGetMyHoldsWithoutOptionConfigurationDefined() + { + $conn = $this->createConnector('fincWithOnePickupBranchOption.json'); + /* default config */ + $conn->setConfig($this->validConfig); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* no option or pickup branch */ + $this->assertTrue(count($filtered) == 0, + "Two many items with options!" + ); + } + + /** + * Test + * + * @return void + */ + public function testGetMyHoldsWithoutPaiaResponseOptions() + { + $conn = $this->createConnector('fincWithoutOptions.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* no option nor pickup branch */ + $this->assertTrue(count($filtered) == 0, + "Two many items with options!" + ); + } + + /** + * Test + * + * @return void + */ + public function testGetMyHoldsAllowUnknownOptions() + { + $conn = $this->createConnector('fincWithUnknownOption.json'); + /* default config */ + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* no option */ + $this->assertTrue(count($filtered) > 0, + "Two many items with options!" + ); + } + + /** + * Test + * + * @return void + */ + public function testGetMyHoldsWrongInstance() + { + $conn = $this->createConnector('fincWithOnePickupBranchOption.json'); + /* default config */ + $conn->setConfig(self::$validConfigWithOptionForOtherInstance); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* no option */ + $this->assertTrue(count($filtered) == 0, + "Two many items with options!" + ); + } + + /** + * Test + * + * @return void + */ + public function testGetMyHoldsWithPickUpBranch() + { + $conn = $this->createConnector('fincWithOnePickupBranchOption.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* check pickupbranch */ + $this->assertTrue(count($filtered[0]["options"][self::$pickupCondition]) > 0, + "No pickup branch mapped!"); + + $this->assertEquals("Zweigbibliothek Görlitz", $filtered[0]["options"][self::$pickupCondition][0]["about"], + "Wrong pickup branch!" + ); + + /* but keep storage id (location) */ + $this->assertEquals("Hochschulbibliothek Zittau", $filtered[0]["location"], + "Wrong pickup branch!" + ); + } + + /** + * Test + * + * @return void + */ + public function testGetMyHoldsWithAnotherPickUpBranch() + { + $conn = $this->createConnector('fincWithAnotherPickupBranchOption.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* check pickupbranch */ + $this->assertTrue(count($filtered[0]["options"][self::$pickupCondition]) > 0, + "No pickup branch mapped!"); + + $this->assertEquals("http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI", $filtered[0]["options"][self::$pickupCondition][0]["id"], + "Wrong pickup branch id!" + ); + + $this->assertEquals("Zweigbibliothek Zittau", $filtered[0]["options"][self::$pickupCondition][0]["about"], + "Wrong pickup branch label!" + ); + + $this->assertEquals("2,50 EUR", $filtered[0]["options"][self::$pickupCondition][0]["amount"], + "Wrong pickup branch amount!" + ); + + /* but keep storage id (location) */ + $this->assertEquals("Hochschulbibliothek Görlitz", $filtered[0]["location"], + "Wrong pickup branch!" + ); + } + + /** + * Test Multiple Options => use first option when displaying items + * + * @return void + */ + public function testGetMyHoldsWithMultipleOptionsPickUpBranch() + { + $conn = $this->createConnector('fincWithMultiplePickupBranchOptions.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $result = $conn->getMyHolds($this->patron); + + $filtered = array_filter( + $result, + function ($resultItem) { + if (isset($resultItem['options'])) { + return true; + } + } + ); + + /* check pickupbranch */ + $this->assertTrue(count($filtered) == 1, + "No pickup branch mapped!"); + + $this->assertEquals("http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwZI", $filtered[0]["options"][self::$pickupCondition][0]["id"], + "Wrong pickup branch id!" + ); + + $this->assertEquals("Zweigbibliothek Zittau", $filtered[0]["options"][self::$pickupCondition][0]["about"], + "Wrong pickup branch label!" + ); + + $this->assertEquals("http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR", $filtered[0]["options"][self::$pickupCondition][1]["id"], + "Wrong pickup branch id!" + ); + + $this->assertEquals("Zweigbibliothek Görlitz", $filtered[0]["options"][self::$pickupCondition][1]["about"], + "Wrong pickup branch label!" + ); + + /* but keep storage id (location) */ + $this->assertEquals("Hochschulbibliothek Görlitz", $filtered[0]["location"], + "Wrong pickup branch!" + ); + } + + + /** + * Test + * + * @return void + */ + public function testgetOptionsReturnsIDTrue() + { + $conn = $this->createConnector('fincWithMultiplePickupBranchOptions.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $options['options'][self::$pickupCondition][0]['id'] = 'TESTID'; + + $this->assertEquals( + ['TESTID'], + $conn->getOptions(self::$pickupCondition, $options, true), + "Wrong option value" + ); + + $validOptions[0][0] = 'TESTID'; + $this->assertEquals( + ['TESTID'], + $conn->getOptions(self::$pickupCondition, $options, true, $validOptions), + "Wrong option value" + ); + } + + /** + * Test + * + * @return void + */ + public function testgetOptionsNotOnlyFirstButAll() + { + $conn = $this->createConnector('fincWithMultiplePickupBranchOptions.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $options['options'][self::$pickupCondition][0]['id'] = 'TESTID1'; + $options['options'][self::$pickupCondition][1]['id'] = 'TESTID2'; + + $this->assertEquals( + ['TESTID1', 'TESTID2'], + $conn->getOptions(self::$pickupCondition, $options, false), + "Wrong option value" + ); + + $this->assertEquals( + ['TESTID1', 'TESTID2'], + $conn->getOptions(self::$pickupCondition, $options, false, $validOptions), + "Wrong option value" + ); + + /* first option only label set */ + $options['options'][self::$pickupCondition][0]['id'] = null; + $options['options'][self::$pickupCondition][0]['about'] = 'TESTLABEL1'; + $options['options'][self::$pickupCondition][1]['id'] = 'TESTID2'; + + $this->assertEquals( + ['TESTLABEL1', 'TESTID2'], + $conn->getOptions(self::$pickupCondition, $options, false, $validOptions), + "Wrong option value" + ); + } + + /** + * Test + * + * @return void + */ + public function testgetOptionsReturnsLabelTrue() + { + $conn = $this->createConnector('fincWithMultiplePickupBranchOptions.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + $options['options'][self::$pickupCondition][0]['id'] = null; + $options['options'][self::$pickupCondition][0]['amount'] = '2,50 Euro'; + $options['options'][self::$pickupCondition][0]['about'] = 'use label when id missing'; + + $this->assertEquals( + ['use label when id missing'], + $conn->getOptions(self::$pickupCondition, $options, true), + "Wrong option value!" + ); + + /* also return label instead of id when no valid options are given */ + $options['options'][self::$pickupCondition][0]['id'] = 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR'; + $options['options'][self::$pickupCondition][0]['about'] = 'Take label, if parameter valid Options missing'; + $this->assertEquals( + ['Take label, if parameter valid Options missing'], + $conn->getOptions(self::$pickupCondition, $options, true), + "Wrong option value!" + ); + } + + /** + * Test + * + * @return void + */ + public function testgetOptionsReturnsEmptyArray() + { + $conn = $this->createConnector('fincWithMultiplePickupBranchOptions.json'); + $conn->setConfig(self::$validConfigWithPickUpOption); + $conn->init(); + + $options['options'][self::$pickupCondition][0]['id'] = 'http://data.ub.uni-leipzig.de/resource/DE-Zi4/department/zwGR'; + $options['options'][self::$pickupCondition][0]['about'] = 'Zweigbibliothek Görlitz'; + + /* invalid condition */ + $this->assertEquals( + [], + $conn->getOptions('fakeCondition', $options, true), + "Wrong option value!" + ); + + /* no options in result array */ + $this->assertEquals( + [], + $conn->getOptions('fakeCondition', [], true), + "Wrong option value!" + ); + + /* invalid option */ + $validOptions[0][0] = 'xxx'; + $this->assertEquals( + [], + $conn->getOptions(self::$pickupCondition, $options, true, $validOptions), + "Wrong option value!" + ); + + /* no option values */ + $options['options'][self::$pickupCondition][0]['id'] = null; + $options['options'][self::$pickupCondition][0]['about'] = null; + $this->assertEquals( + [""], + $conn->getOptions(self::$pickupCondition, $options, true), + "Wrong option value!" + ); + } + + /** + * Test + * + * @return void + */ + public function testCallMapOptionsTrue() : void + { + $paia = $this->getMockBuilder(PAIAMock::class) + ->enableProxyingToOriginalMethods() + ->setMethods(['mapOptions']) + ->setConstructorArgs([new \VuFind\Date\Converter(), new \Zend\Session\SessionManager()]) + ->getMock(); + + $paia->prepare("fincWithOnePickupBranchOption.json"); + + $paia->expects($this->atLeastOnce()) + ->method('mapOptions'); + + /* only used by holdings so far */ + $paia->getMyHolds($this->patron); + } + + /** + * Test + * + * @return void + */ + public function testCallMapOptionsFalse() : void + { + $paia = $this->getMockBuilder(PAIAMock::class) + ->enableProxyingToOriginalMethods() + ->setMethods(['mapOptions']) + ->setConstructorArgs([new \VuFind\Date\Converter(), new \Zend\Session\SessionManager()]) + ->getMock(); + + $paia->prepare("fincWithOnePickupBranchOption.json"); + + $paia->expects($this->never()) + ->method('mapOptions'); + + $paia->getMyILLRequests($this->patron); + $paia->getMyFines($this->patron); + $paia->getMyStorageRetrievalRequests($this->patron); + $paia->getMyTransactions($this->patron); + } + + /** + * Create connector with fixture file. + * + * @param string $fixture Fixture file + * + * @return Connector + * + * @throws InvalidArgumentException Fixture file does not exist + */ + protected function createConnector($fixture = null) + { + if (empty($fixture) || strpos($fixture, 'finc') === false) { + return parent::createConnector($fixture); + } + + $adapter = new TestAdapter(); + if ($fixture) { + $file = realpath( + __DIR__ . + '/../../../../../fixtures/paia/response/' . $fixture + ); + if (!is_string($file) || !file_exists($file) || !is_readable($file)) { + throw new InvalidArgumentException( + sprintf('Unable to load fixture file: %s ', $file) + ); + } + $response = file_get_contents($file); + $responseObj = HttpResponse::fromString($response); + $adapter->setResponse($responseObj); + } + $service = new \VuFindHttp\HttpService(); + $service->setDefaultAdapter($adapter); + $conn = new PAIAMock( + new \VuFind\Date\Converter(), + new \Zend\Session\SessionManager() + ); + $conn->setHttpService($service); + return $conn; + } + + /** + * @return array + * @throws \ReflectionException + */ + protected function prepareByReflection() + { + /* use reflection due to protected access level */ + $class = new \ReflectionClass('finc\ILS\Driver\PAIA'); + $method = $class->getMethod("mapOptions"); + $method->setAccessible(true); + + $paia = new fincPAIA( + new \VuFind\Date\Converter(), + new \Zend\Session\SessionManager() + ); + + return [$method, $paia]; + } +} + +/* helper class to make protected finc methods public and reuse Vufind mocking approach */ +class PAIAMock extends fincPAIA +{ + public function prepare($fixture) + { + $adapter = new TestAdapter(); + if ($fixture) { + $file = realpath( + __DIR__ . + '/../../../../../fixtures/paia/response/' . $fixture + ); + if (!is_string($file) || !file_exists($file) || !is_readable($file)) { + throw new InvalidArgumentException( + sprintf('Unable to load fixture file: %s ', $file) + ); + } + $response = file_get_contents($file); + $responseObj = HttpResponse::fromString($response); + $adapter->setResponse($responseObj); + } + $service = new \VuFindHttp\HttpService(); + $service->setDefaultAdapter($adapter); + $this->setHttpService($service); + $this->setConfig(PAIAFincTest::$validConfigWithPickUpOption); + parent::init(); + } + + public function parsePAIAJson($file) + { + return $this->paiaParseJsonAsArray($file); + } + + public function myHoldsMapping($items) + { + return parent::myHoldsMapping($items); + } + + public function paiaGetItems($patron, $filter = []) + { + return parent::paiaGetItems($patron, $filter); + } + + public function paiaCheckScope($scope) + { + return true; + } +} -- GitLab