From dccf71d5cc4a47bed3bb07dd80476fd90495a9b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Lahmann?= <lahmann@ub.uni-leipzig.de>
Date: Thu, 5 Feb 2015 16:54:26 +0100
Subject: [PATCH] refs #4651: * merging latest DAIA driver from vufind-org with
 JSON support into master

---
 local/config/vufind/DAIA.ini                 |  36 +-
 local/config/vufind/FincDAIA.ini             |  13 +-
 module/finc/src/finc/ILS/Driver/DAIA.php     | 512 ++++++++++++++-----
 module/finc/src/finc/ILS/Driver/FincDAIA.php | 425 ++-------------
 4 files changed, 495 insertions(+), 491 deletions(-)

diff --git a/local/config/vufind/DAIA.ini b/local/config/vufind/DAIA.ini
index 7ca1a3eedd2..aad984c296a 100644
--- a/local/config/vufind/DAIA.ini
+++ b/local/config/vufind/DAIA.ini
@@ -1,4 +1,38 @@
-[DAIA]
+; DAIA driver expects a DAIA Query API as specified in:
+; http://gbv.github.io/daiaspec/daia.html#query-api
+;
+; The settings in the [DAIA] section will be used for all DAIA requests.
+; The name of this section got refactored with VuFind 2.4, although the old
+; configuration using the [Global] section still works, it should be replaced
+; with the new [DAIA] section.
+;   Note: Settings for daiaResponseFormat and daiaIdPrefix are not supported if
+;         a pre VuFind 2.4 configuration with the [Global] section is used.
+;         i.e.:
+;              [Global]
+;              baseUrl = [your DAIA server base url]
+;              daiaIdPrefix = [this setting will have no effect]
+;              daiaResponseFormat = [this setting will have no effect]
+;
+; A default DAIA call looks like this:
+; https://daia.myuniversity.edu/?id=ppn:12345678&format=json
+;
+; This default DAIA call would be configured as:
+; [DAIA]
+; baseUrl = https://daia.myuniversity.edu
+; daiaidprefix = ppn:
+; daiaResponseFormat = json
+;
+
+; The prefix prepended to the VuFind record Id resulting in the document URI
+; used for the DAIA request (default = ppn:) (the prefix usually defines the
+; field which the DAIA server uses for the loookup - e.g. ppn: or isbn:).
+;daiaIdPrefix = "ppn:"
+
+; Set the requested DAIA response format: xml (default), json
+;daiaResponseFormat = xml
+
+[Global]
+; The base URL for the DAIA webservice.
 ; refer to http://data.ub.uni-leipzig.de/ldinfo for setting up specific DAIA-urls
 baseUrl        = http://data.ub.uni-leipzig.de/item/ISIL/identifier/
 
diff --git a/local/config/vufind/FincDAIA.ini b/local/config/vufind/FincDAIA.ini
index 2505ef8147a..3ecfc707be6 100644
--- a/local/config/vufind/FincDAIA.ini
+++ b/local/config/vufind/FincDAIA.ini
@@ -1,8 +1,8 @@
-[DAIA]
+;[DAIA]
 ; this config configures the extended DAIA-Driver FincDAIA
 ; refer to ticket #4499 for further info on configuring it
-baseUrl        = http://data.ub.uni-leipzig.de/item/ISIL/identifier/
-ilsIdentifier = "default"
+;baseUrl        = http://data.ub.uni-leipzig.de/item/ISIL/identifier/
+;ilsIdentifier = "default"
 ;ISIL = "ISIL"
 
 ; config-examples:
@@ -17,4 +17,9 @@ ilsIdentifier = "default"
 ; ilsIdentifier = "record_id"
 
 ; default
-; ilsIdentifier = "default"
\ No newline at end of file
+; ilsIdentifier = "default"
+
+[Global]
+; The base URL for the DAIA webservice.
+; refer to http://data.ub.uni-leipzig.de/ldinfo for setting up specific DAIA-urls
+baseUrl        = http://data.ub.uni-leipzig.de/item/ISIL/identifier/
diff --git a/module/finc/src/finc/ILS/Driver/DAIA.php b/module/finc/src/finc/ILS/Driver/DAIA.php
index 37b2f24d4e8..99894919879 100644
--- a/module/finc/src/finc/ILS/Driver/DAIA.php
+++ b/module/finc/src/finc/ILS/Driver/DAIA.php
@@ -3,10 +3,11 @@
  * ILS Driver for VuFind to query availability information via DAIA.
  *
  * Based on the proof-of-concept-driver by Till Kinstler, GBV.
+ * Relaunch of the daia driver developed by Oliver Goldschmidt.
  *
  * PHP version 5
  *
- * Copyright (C) Oliver Goldschmidt 2010.
+ * Copyright (C) Jochen Lienhard 2014.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -23,65 +24,72 @@
  *
  * @category VuFind2
  * @package  ILS_Drivers
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
  * @author   Oliver Goldschmidt <o.goldschmidt@tu-harburg.de>
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace finc\ILS\Driver;
-use DOMDocument, VuFind\Exception\ILS as ILSException, Zend\Log\LoggerInterface;
+use DOMDocument, VuFind\Exception\ILS as ILSException,
+    VuFindHttp\HttpServiceAwareInterface as HttpServiceAwareInterface,
+    Zend\Log\LoggerAwareInterface as LoggerAwareInterface,
+    Zend\Log\LoggerInterface as LoggerInterface;
 
 /**
  * ILS Driver for VuFind to query availability information via DAIA.
  *
- * Based on the proof-of-concept-driver by Till Kinstler, GBV.
- *
  * @category VuFind2
  * @package  ILS_Drivers
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
  * @author   Oliver Goldschmidt <o.goldschmidt@tu-harburg.de>
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
-class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAwareInterface
+class DAIA extends \VuFind\ILS\Driver\AbstractBase implements HttpServiceAwareInterface, LoggerAwareInterface
 {
     /**
-     * Base URL
+     * Base URL for DAIA Service
      *
      * @var string
      */
-    protected $baseURL;
+    protected $baseUrl;
 
     /**
-     * Logger (or false for none)
+     * DAIA query identifier prefix
      *
-     * @var LoggerInterface|bool
+     * @var string
      */
-    protected $logger = false;
+    protected $daiaIdPrefix;
 
     /**
-     * Set the logger
+     * DAIA response format
      *
-     * @param LoggerInterface $logger Logger to use.
+     * @var string
+     */
+    protected $daiaResponseFormat;
+
+	/**
+     * DAIA legacySupport flag
      *
-     * @return void
+     * @var boolean
      */
-    public function setLogger(LoggerInterface $logger)
-    {
-        $this->logger = $logger;
-    }
+    protected $legacySupport = false;
 
     /**
-     * Log a debug message.
+     * Logger (or false for none)
      *
-     * @param string $msg Message to log.
+     * @var LoggerInterface|bool
+     */
+    protected $logger = false;
+
+    /**
+     * HTTP service
      *
-     * @return void
+     * @var \VuFindHttp\HttpServiceInterface
      */
-    protected function debug($msg)
-    {
-        if ($this->logger) {
-            $this->logger->debug(get_class($this) . ": $msg");
-        }
-    }
+    protected $httpService = null;
 
     /**
      * Initialize the driver.
@@ -94,11 +102,45 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      */
     public function init()
     {
-        if (!isset($this->config['DAIA']['baseUrl'])) {
+        // DAIA.ini sections changed, therefore move old [Global] section to
+        // new [DAIA] section as fallback
+        if (isset($this->config['Global']) && !isset($this->config['DAIA'])) {
+            $this->config['DAIA'] = $this->config['Global'];
+            $this->legacySupport = true;
+        }
+
+        if (isset($this->config['DAIA']['baseUrl'])) {
+            $this->baseUrl = $this->config['DAIA']['baseUrl'];
+        } else {
             throw new ILSException('DAIA/baseUrl configuration needs to be set.');
         }
+        if (isset($this->config['DAIA']['daiaResponseFormat'])) {
+            $this->daiaResponseFormat = strtolower(
+                $this->config['DAIA']['daiaResponseFormat']
+            );
+        } else {
+            $this->debug("No daiaResponseFormat setting found, using default: xml");
+            $this->daiaResponseFormat = "xml";
+        }
+        if (isset($this->config['DAIA']['daiaIdPrefix'])) {
+            $this->daiaIdPrefix = $this->config['DAIA']['daiaIdPrefix'];
+        } else {
+            $this->debug("No daiaIdPrefix setting found, using default: ppn:");
+            $this->daiaIdPrefix = "ppn:";
+        }
+    }
 
-        $this->baseURL = $this->config['DAIA']['baseUrl'];
+    /**
+     * Public Function which retrieves renew, hold and cancel settings from the
+     * driver ini file.
+     *
+     * @param string $function The name of the feature to be checked
+     *
+     * @return array An array with key-value pairs.
+     */
+    public function getConfig($function)
+    {
+        return isset($this->config[$function]) ? $this->config[$function] : false;
     }
 
     /**
@@ -112,6 +154,7 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      * @param array  $details Item details from getHoldings return array
      *
      * @return string         URL to ILS's OPAC's place hold screen.
+     *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getHoldLink($id, $details)
@@ -133,8 +176,13 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      */
     public function getStatus($id)
     {
-        $holding = $this->daiaToHolding($id);
-        return $holding;
+        if ($this->daiaResponseFormat == 'xml') {
+            return $this->getXMLStatus($id);
+        } elseif ($this->daiaResponseFormat == 'json') {
+            return $this->getJSONStatus($id);
+        } else {
+            throw new ILSException('No matching format found for status retrieval.');
+        }
     }
 
     /**
@@ -150,24 +198,21 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      */
     public function getStatuses($ids)
     {
-        $items = array();
-        foreach ($ids as $id) {
-            $items[] = $this->getShortStatus($id);
+        $items = [];
+
+        if ($this->daiaResponseFormat == 'xml') {
+            foreach ($ids as $id) {
+                $items[] = $this->getXMLShortStatus($id);
+            }
+        } elseif ($this->daiaResponseFormat == 'json') {
+            foreach ($ids as $id) {
+                $items[] = $this->getJSONStatus($id);
+            }
+        } else {
+            throw new ILSException('No matching format found for status retrieval.');
         }
-        return $items;
-    }
 
-    /**
-     * Public Function which retrieves renew, hold and cancel settings from the
-     * driver ini file.
-     *
-     * @param string $function The name of the feature to be checked
-     *
-     * @return array An array with key-value pairs.
-     */
-    public function getConfig($function)
-    {
-        return isset($this->config[$function]) ? $this->config[$function] : false;
+        return $items;
     }
 
     /**
@@ -203,25 +248,206 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      */
     public function getPurchaseHistory($id)
     {
-        return array();
+        return [];
     }
 
     /**
-     * Query a DAIA server and return the result as DOMDocument object.
-     * The returned object is an XML document containing
-     * content as described in the DAIA format specification.
+     * Set the HTTP service to be used for HTTP requests.
      *
-     * @param string $id Document to look up.
+     * @param HttpServiceInterface $service HTTP service
      *
-     * @return DOMDocument Object representation of an XML document containing
-     * content as described in the DAIA format specification.
+     * @return void
      */
-    protected function queryDAIA($id)
+    public function setHttpService(\VuFindHttp\HttpServiceInterface $service)
     {
-        $daia = new DOMDocument();
-        $daia->load($this->baseURL . $id);
+        $this->httpService = $service;
+    }
+
+    /**
+     * Perform an HTTP request.
+     *
+     * @param string $id id for query in daia
+     *
+     * @return xml or json object
+     * @throws ILSException
+     */
+    protected function doHTTPRequest($id)
+    {
+        $contentTypes = [
+            "xml"  => "application/xml",
+            "json" => "application/json",
+        ];
+
+        $http_headers = [
+            "Content-type: " . $contentTypes[$this->daiaResponseFormat],
+            "Accept: " .  $contentTypes[$this->daiaResponseFormat]
+        ];
+
+        $params = [
+            "id" => $this->daiaIdPrefix . $id,
+            "format" => $this->daiaResponseFormat,
+        ];
+
+        try {
+            if ($this->legacySupport) {
+                // HttpRequest for DAIA legacy support as all
+                // the parameters are contained in the baseUrl
+                $result = $this->httpService->get(
+                    $this->baseUrl . $id,
+                    [], null, $http_headers
+                );
+            } else {
+                $result = $this->httpService->get(
+                    $this->baseUrl,
+                    $params, null, $http_headers
+                );
+            }
+        } catch (\Exception $e) {
+            throw new ILSException($e->getMessage());
+        }
+
+        if (!$result->isSuccess()) {
+            // throw ILSException disabled as this will be shown in VuFind-Frontend
+            //throw new ILSException('HTTP error ' . $result->getStatusCode() .
+            //                       ' retrieving status for record: ' . $id);
+            // write to Debug instead
+            $this->debug(
+                'HTTP status ' . $result->getStatusCode() .
+                ' received, retrieving availability information for record: ' . $id
+            );
+
+            // return false as DAIA request failed
+            return false;
+        }
+        return ($result->getBody());
+
+    }
+
+    /**
+     * Get Status of JSON Result
+     *
+     * This method gets a json result from the DAIA server and
+     * analyses it. Than a vufind result is build.
+     *
+     * @param string $id The id of the bib record
+     *
+     * @return array()      of items
+     */
+    protected function getJSONStatus($id)
+    {
+        // get daia json request for id and decode it
+        $daia = json_decode($this->doHTTPRequest($id), true);
+        $result = [];
+        if (array_key_exists("message", $daia)) {
+            // analyse the message for the error handling and debugging
+        }
+        if (array_key_exists("instituion", $daia)) {
+            // information about the institution that grants or
+            // knows about services and their availability
+            // this fields could be analyzed: href, content, id
+        }
+        if (array_key_exists("document", $daia)) {
+            // analyse the items
+            $dummy_item = ["id" => "0815",
+                "availability" => true,
+                "status" => "Available",
+                "location" => "physical location no HTML",
+                "reserve" => "N",
+                "callnumber" => "007",
+                "number" => "1",
+                "item_id" => "0815",
+                "barcode" => "1"];
+            // each document may contain: id, href, message, item
+            foreach ($daia["document"] as $document) {
+                $doc_id = null;
+                $doc_href = null;
+                $doc_message = null;
+                if (array_key_exists("id", $document)) {
+                    $doc_id = $document["id"];
+                }
+                if (array_key_exists("href", $document)) {
+                    // url of the document
+                    $doc_href = $document["href"];
+                }
+                if (array_key_exists("message", $document)) {
+                    // array of messages with language code and content
+                    $doc_message = $document["message"];
+                }
+                // if one or more items exist, iterate and build result-item
+                if (array_key_exists("item", $document)) {
+                    $number = 0;
+                    foreach ($document["item"] as $item) {
+                        $result_item = [];
+                        $result_item["id"] = $id;
+                        $result_item["item_id"] = $id;
+                        $number++; // count items
+                        $result_item["number"] = $number;
+                        // set default value for barcode
+                        $result_item["barcode"] = "1";
+                        // set default value for reserve
+                        $result_item["reserve"] = "N";
+                        // get callnumber
+                        if (isset($item["label"])) {
+                            $result_item["callnumber"] = $item["label"];
+                        } else {
+                            $result_item["callnumber"] = "Unknown";
+                        }
+                        // get location
+                        if (isset($item["storage"])) {
+                            $result_item["location"] = $item["storage"]["content"];
+                        } else {
+                            $result_item["location"] = "Unknown";
+                        }
+                        // status and availability will be calculated in own function
+                        $result_item = $this->calculateStatus($item)+$result_item;
+                        // add result_item to the result array
+                        $result[] = $result_item;
+                    } // end iteration on item
+                }
+            } // end iteration on document
+            // $result[]=$dummy_item;
+        }
+        return $result;
+    }
 
-        return $daia;
+    /**
+     * Calaculate Status and Availability of an item
+     *
+     * If availability is false the string of status will be shown in vufind
+     *
+     * @param string $item json DAIA item
+     *
+     * @return array("status"=>"only for VIPs" ... )
+     */
+    protected function calculateStatus($item)
+    {
+        $availability = false;
+        $status = null;
+        $duedate = null;
+        if (array_key_exists("available", $item)) {
+            // check if item is loanable or presentation
+            foreach ($item["available"] as $available) {
+                if ($available["service"] == "loan") {
+                    $availability = true;
+                }
+                if ($available["service"] == "presentation") {
+                    $availability = true;
+                }
+            }
+        }
+        if (array_key_exists("unavailable", $item)) {
+            foreach ($item["unavailable"] as $unavailable) {
+                if ($unavailable["service"] == "loan") {
+                    if (isset($unavailable["expected"])) {
+                        $duedate = $unavailable["expected"];
+                    }
+                    $status = "dummy text";
+                }
+            }
+        }
+        return (["status" => $status,
+            "availability" => $availability,
+            "duedate" => $duedate]);
     }
 
     /**
@@ -231,36 +457,48 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      *
      * @return array
      */
-    protected function daiaToHolding($id)
+    protected function getXMLStatus($id)
     {
-        $daia = $this->queryDAIA($id);
+        $daia = new DOMDocument();
+        $response = $this->doHTTPRequest($id);
+        if ($response) {
+            $daia->loadXML($response);
+        }
         // get Availability information from DAIA
         $documentlist = $daia->getElementsByTagName('document');
-        $status = array();
+
+        // handle empty DAIA response
+        if ($documentlist->length == 0
+            && $daia->getElementsByTagName("message") != null
+        ) {
+            // analyse the message for the error handling and debugging
+        }
+
+        $status = [];
         for ($b = 0; $documentlist->item($b) !== null; $b++) {
             $itemlist = $documentlist->item($b)->getElementsByTagName('item');
-            $ilslink='';
-            if ($documentlist->item($b)->attributes->getNamedItem('href')!==null) {
+            $ilslink = '';
+            if ($documentlist->item($b)->attributes->getNamedItem('href') !== null) {
                 $ilslink = $documentlist->item($b)->attributes
                     ->getNamedItem('href')->nodeValue;
             }
-            $emptyResult = array(
-                'callnumber' => '-',
-                'availability' => '0',
-                'number' => 1,
-                'reserve' => 'No',
-                'duedate' => '',
-                'queue'   => '',
-                'delay'   => '',
-                'barcode' => 'No samples',
-                'status' => '',
-                'id' => $id,
-                'location' => '',
-                'ilslink' => $ilslink,
-                'label' => 'No samples'
-            );
+            $emptyResult = [
+                    'callnumber' => '-',
+                    'availability' => '0',
+                    'number' => 1,
+                    'reserve' => 'No',
+                    'duedate' => '',
+                    'queue'   => '',
+                    'delay'   => '',
+                    'barcode' => 'No samples',
+                    'status' => '',
+                    'id' => $id,
+                    'location' => '',
+                    'ilslink' => $ilslink,
+                    'label' => 'No samples'
+            ];
             for ($c = 0; $itemlist->item($c) !== null; $c++) {
-                $result = array(
+                $result = [
                     'callnumber' => '',
                     'availability' => '0',
                     'number' => ($c+1),
@@ -277,8 +515,8 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                     'location.id' => '',
                     'location.href' => '',
                     'label' => '',
-                    'notes' => array()
-                );
+                    'notes' => [],
+                ];
                 if ($itemlist->item($c)->attributes->getNamedItem('id') !== null) {
                     $result['item_id'] = $itemlist->item($c)->attributes
                         ->getNamedItem('id')->nodeValue;
@@ -306,8 +544,13 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                         $result['location'] = $storageElements->item(0)->nodeValue;
                         //$result['location.id'] = $storageElements->item(0)
                         //  ->attributes->getNamedItem('id')->nodeValue;
-                        $result['location.href'] = $storageElements->item(0)
-                            ->attributes->getNamedItem('href')->nodeValue;
+                        $href = $storageElements->item(0)->attributes
+                            ->getNamedItem('href');
+                        if ($href !== null) {
+                            //href attribute is recommended but not mandatory
+                            $result['location.href'] = $storageElements->item(0)
+                                ->attributes->getNamedItem('href')->nodeValue;
+                        }
                         //$result['barcode'] = $result['location.id'];
                     }
                 }
@@ -377,7 +620,8 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                                 $result['loan.availability'] = '0';
                                 $result['loan_availability'] = '0';
                                 if ($expectedNode !== null) {
-                                    $result['loan.duedate'] = $expectedNode->nodeValue;
+                                    $result['loan.duedate']
+                                        = $expectedNode->nodeValue;
                                 }
                                 if ($queueNode !== null) {
                                     $result['loan.queue'] = $queueNode->nodeValue;
@@ -390,7 +634,8 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                                         = $expectedNode->nodeValue;
                                 }
                                 if ($queueNode !== null) {
-                                    $result['interloan.queue'] = $queueNode->nodeValue;
+                                    $result['interloan.queue']
+                                        = $queueNode->nodeValue;
                                 }
                                 $result['availability'] = '0';
                             } elseif ($service === 'openaccess') {
@@ -400,7 +645,8 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                                         = $expectedNode->nodeValue;
                                 }
                                 if ($queueNode !== null) {
-                                    $result['openaccess.queue'] = $queueNode->nodeValue;
+                                    $result['openaccess.queue']
+                                        = $queueNode->nodeValue;
                                 }
                                 $result['availability'] = '0';
                             }
@@ -443,13 +689,15 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                             } elseif ($service === 'interloan') {
                                 $result['interloan.availability'] = '1';
                                 if ($delayNode !== null) {
-                                    $result['interloan.delay'] = $delayNode->nodeValue;
+                                    $result['interloan.delay']
+                                        = $delayNode->nodeValue;
                                 }
                                 $result['availability'] = '1';
                             } elseif ($service === 'openaccess') {
                                 $result['openaccess.availability'] = '1';
                                 if ($delayNode !== null) {
-                                    $result['openaccess.delay'] = $delayNode->nodeValue;
+                                    $result['openaccess.delay']
+                                        = $delayNode->nodeValue;
                                 }
                                 $result['availability'] = '1';
                             }
@@ -497,23 +745,27 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
      * id, availability (boolean), status, location, reserve, callnumber, duedate,
      * number
      */
-    public function getShortStatus($id)
+    public function getXMLShortStatus($id)
     {
-        $daia = $this->queryDAIA($id);
+        $daia = new DOMDocument();
+        $response = $this->doHTTPRequest($id);
+        if ($response) {
+            $daia->loadXML($response);
+        }
         // get Availability information from DAIA
         $itemlist = $daia->getElementsByTagName('item');
         $label = "Unknown";
         $storage = "Unknown";
         $presenceOnly = '1';
-        $holding = array();
+        $holding = [];
         for ($c = 0; $itemlist->item($c) !== null; $c++) {
             $earliest_href = '';
             $storageElements = $itemlist->item($c)->getElementsByTagName('storage');
-            if ($storageElements->item(0)->nodeValue) {
+            if ($storageElements->item(0) && $storageElements->item(0)->nodeValue) {
                 if ($storageElements->item(0)->nodeValue === 'Internet') {
                     $href = $storageElements->item(0)->attributes
                         ->getNamedItem('href')->nodeValue;
-                    $storage = '<a href="'.$href.'">'.$href.'</a>';
+                    $storage = '<a href="' . $href . '">' . $href . '</a>';
                 } else {
                     $storage = $storageElements->item(0)->nodeValue;
                 }
@@ -544,14 +796,14 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                 $unavailableElements = $itemlist->item($c)
                     ->getElementsByTagName('unavailable');
                 if ($unavailableElements->item(0) !== null) {
-                    $earliest = array();
-                    $queue = array();
-                    $hrefs = array();
+                    $earliest = [];
+                    $queue = [];
+                    $hrefs = [];
                     for ($n = 0; $unavailableElements->item($n) !== null; $n++) {
                         $unavailHref = $unavailableElements->item($n)->attributes
                             ->getNamedItem('href');
                         if ($unavailHref !== null) {
-                            $hrefs['item'.$n] = $unavailHref->nodeValue;
+                            $hrefs['item' . $n] = $unavailHref->nodeValue;
                         }
                         $expectedNode = $unavailableElements->item($n)->attributes
                             ->getNamedItem('expected');
@@ -566,14 +818,14 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                             //    'expected' => $expectedNode->nodeValue,
                             //    'recall' => $unavailHref->nodeValue);
                             //array_push($earliest, $expectedNode->nodeValue);
-                            $earliest['item'.$n] = $expectedNode->nodeValue;
+                            $earliest['item' . $n] = $expectedNode->nodeValue;
                         } else {
                             array_push($earliest, "0");
                         }
                         $queueNode = $unavailableElements->item($n)->attributes
                             ->getNamedItem('queue');
                         if ($queueNode !== null) {
-                            $queue['item'.$n] = $queueNode->nodeValue;
+                            $queue['item' . $n] = $queueNode->nodeValue;
                         } else {
                             array_push($queue, "0");
                         }
@@ -585,8 +837,10 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                     foreach ($earliest as $earliest_key => $earliest_value) {
                         if ($earliest_counter === 0) {
                             $earliest_duedate = $earliest_value;
-                            $earliest_href = $hrefs[$earliest_key];
-                            $earliest_queue = $queue[$earliest_key];
+                            $earliest_href = isset($hrefs[$earliest_key])
+                                 ? $hrefs[$earliest_key] : '';
+                            $earliest_queue = isset($queue[$earliest_key])
+                                 ? $queue[$earliest_key] : '';
                         }
                         $earliest_counter = 1;
                     }
@@ -602,28 +856,56 @@ class DAIA extends \VuFind\ILS\Driver\AbstractBase implements \Zend\Log\LoggerAw
                         $status = 'missing';
                     }
                 }
-                if (!$status) {
+                if (!isset($status)) {
                     $status = 'Unavailable';
                 }
                 $availability = 0;
             }
             $reserve = 'N';
-            if ($earliest_queue > 0) {
+            if (isset($earliest_queue) && $earliest_queue > 0) {
                 $reserve = 'Y';
             }
-            $holding[] = array('availability' => $availability,
-                'id' => $id,
-                'status' => "$status",
-                'location' => "$storage",
-                'reserve' => $reserve,
-                'queue' => $earliest_queue,
-                'callnumber' => "$label",
-                'duedate' => $earliest_duedate,
-                'leanable' => $leanable,
-                'recallhref' => $earliest_href,
-                'number' => ($c+1),
-                'presenceOnly' => $presenceOnly);
+            $holding[] = [
+                'availability' => $availability,
+                'id'            => $id,
+                'status'        => isset($status) ? "$status" : '',
+                'location'      => isset($storage) ? "$storage" : '',
+                'reserve'       => isset($reserve) ? $reserve : '',
+                'queue'         => isset($earliest_queue) ? $earliest_queue : '',
+                'callnumber'    => isset($label) ? "$label" : '',
+                'duedate'       => isset($earliest_duedate) ? $earliest_duedate : '',
+                'leanable'      => isset($leanable) ? $leanable : '',
+                'recallhref'    => isset($earliest_href) ? $earliest_href : '',
+                'number'        => ($c+1),
+                'presenceOnly'  => isset($presenceOnly) ? $presenceOnly : '',
+            ];
         }
         return $holding;
     }
-}
\ No newline at end of file
+
+    /**
+     * Set the logger
+     *
+     * @param LoggerInterface $logger Logger to use.
+     *
+     * @return void
+     */
+    public function setLogger(LoggerInterface $logger)
+    {
+        $this->logger = $logger;
+    }
+
+    /**
+     * Log a debug message.
+     *
+     * @param string $msg Message to log.
+     *
+     * @return void
+     */
+    protected function debug($msg)
+    {
+        if ($this->logger) {
+            $this->logger->debug(get_class($this) . ": $msg");
+        }
+    }
+}
diff --git a/module/finc/src/finc/ILS/Driver/FincDAIA.php b/module/finc/src/finc/ILS/Driver/FincDAIA.php
index 57c71714ea7..52e32273828 100644
--- a/module/finc/src/finc/ILS/Driver/FincDAIA.php
+++ b/module/finc/src/finc/ILS/Driver/FincDAIA.php
@@ -41,7 +41,7 @@ use DOMDocument, VuFind\Exception\ILS as ILSException;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
-class FincDAIA extends DAIA implements \Zend\Log\LoggerAwareInterface
+class FincDAIA extends PAIA implements \Zend\Log\LoggerAwareInterface
 {
     /**
      * Identifier used for interaction with ILS
@@ -85,107 +85,74 @@ class FincDAIA extends DAIA implements \Zend\Log\LoggerAwareInterface
      */
     public function init()
     {
-        if (!isset($this->config['DAIA']['baseUrl'])) {
-            throw new ILSException('DAIA/baseUrl configuration needs to be set.');
-        }
-
-        $this->baseURL = $this->config['DAIA']['baseUrl'];
+        parent::init();
+
+        // due to section naming changes in DAIA.ini
+        // switch legacySupport
+        if ($this->legacySupport) {
+            // set the ILS-specific recordId for interaction with ILS
+            // get the ILS-specific identifier
+            if (!isset($this->config['Global']['ilsIdentifier'])) {
+                $this->debug("No ILS-specific identifier configured, setting ilsIdentifier=default.");
+                $this->ilsIdentifier = "default";
+            } else {
+                $this->ilsIdentifier = $this->config['Global']['ilsIdentifier'];
+            }
 
-        // set the ILS-specific recordId for interaction with ILS
-        // get the ILS-specific identifier
-        if (!isset($this->config['DAIA']['ilsIdentifier'])) {
-            $this->debug("No ILS-specific identifier configured, setting ilsIdentifier=default.");
-            $this->ilsIdentifier = "default";
+            // get ISIL from config if ILS-specific recordId is barcode for interaction with ILS
+            // get the ILS-specific identifier
+            if (!isset($this->config['Global']['ISIL'])) {
+                $this->debug("No ISIL for ILS-driver configured.");
+                $this->isil = '';
+            } else {
+                $this->isil = $this->config['Global']['ISIL'];
+            }
         } else {
-            $this->ilsIdentifier = $this->config['DAIA']['ilsIdentifier'];
-        }
+            // set the ILS-specific recordId for interaction with ILS
+            // get the ILS-specific identifier
+            if (!isset($this->config['DAIA']['ilsIdentifier'])) {
+                $this->debug("No ILS-specific identifier configured, setting ilsIdentifier=default.");
+                $this->ilsIdentifier = "default";
+            } else {
+                $this->ilsIdentifier = $this->config['DAIA']['ilsIdentifier'];
+            }
 
-        // get ISIL from config if ILS-specific recordId is barcode for interaction with ILS
-        // get the ILS-specific identifier
-        if (!isset($this->config['DAIA']['ISIL'])) {
-            $this->debug("No ISIL for ILS-driver configured.");
-            $this->isil = '';
-        } else {
-            $this->isil = $this->config['DAIA']['ISIL'];
+            // get ISIL from config if ILS-specific recordId is barcode for interaction with ILS
+            // get the ILS-specific identifier
+            if (!isset($this->config['DAIA']['ISIL'])) {
+                $this->debug("No ISIL for ILS-driver configured.");
+                $this->isil = '';
+            } else {
+                $this->isil = $this->config['DAIA']['ISIL'];
+            }
         }
 
     }
 
     /**
-     * Get the Record-Object from the RecordDriver.
-     *
-     * @param string $id ID of record to retrieve
-     *
-     * @return \VuFind\RecordDriver\AbstractBase
-     */
-    public function getRecord($id)
-    {
-        return $this->recordLoader->load($id);
-    }
-
-    /**
-     * Get Status
-     *
-     * This is responsible for retrieving the status information of a certain
-     * record.
-     *
-     * @param string $id The record id to retrieve the holdings for
-     *
-     * @throws ILSException
-     * @return mixed     On success, an associative array with the following keys:
-     * id, availability (boolean), status, location, reserve, callnumber.
-     */
-    public function getStatus($id)
-    {
-        $holding = $this->daiaToHolding($this->getILSRecordId($id));
-        return $holding;
-    }
-
-    /**
-     * Get Statuses
-     *
-     * This is responsible for retrieving the status information for a
-     * collection of records.
+     * Wrapper implementation of @queryDAIAXML($id) to perform the query
+     * with the ILS-specific identifier.
      *
-     * @param array $ids The array of record ids to retrieve the status for
+     * @param string $id Document to look up.
      *
-     * @throws ILSException
-     * @return array     An array of getStatus() return values on success.
+     * @return DOMDocument Object representation of an XML document containing
+     * content as described in the DAIA format specification.
      */
-    public function getStatuses($ids)
+    protected function doHTTPRequest($id)
     {
-        $items = array();
-        foreach ($ids as $id) {
-            $items[] = $this->getShortStatus($this->getILSRecordId($id));
-        }
-        return $items;
+        return parent::doHTTPRequest($this->getILSRecordId($id));
     }
 
     /**
-     * Query a DAIA server and return the result as DOMDocument object.
-     * The returned object is an XML document containing
-     * content as described in the DAIA format specification.
+     * Get the Record-Object from the RecordDriver.
      *
-     * @param string $id Document to look up.
+     * @param string $id ID of record to retrieve
      *
-     * @return DOMDocument Object representation of an XML document containing
-     * content as described in the DAIA format specification.
+     * @return \VuFind\RecordDriver\AbstractBase
      */
-    protected function queryDAIA($id)
+    protected function getRecord($id)
     {
-        $opts = array(
-            'http' => array(
-                'ignore_errors' => 'true',
-            )
-        );
-
-        $context = stream_context_create($opts);
-        libxml_set_streams_context($context);
-
-        $daia = new DOMDocument();
-        $daia->load($this->baseURL . $id);
-
-        return $daia;
+        return $this->recordLoader->load($id);
     }
 
     /**
@@ -198,307 +165,23 @@ class FincDAIA extends DAIA implements \Zend\Log\LoggerAwareInterface
     protected function getILSRecordId($id)
     {
         //get the ILS-specific recordId
-        if ($this->ilsIdentifier == "default") {
-            return $id;
-        } else {
+        if ($this->ilsIdentifier != "default") {
             $ilsRecordId = $this->getRecord($id)->getILSIdentifier($this->ilsIdentifier);
-            if ($ilsRecordId == '')
-            {
+            if ($ilsRecordId == '') {
                 return $id;
             } else {
                 if (is_array($ilsRecordId)) {
                     // use ISIL for identifying the correct ILS-identifier if array is returned
                     foreach ($ilsRecordId as $recordId) {
-                        if (preg_match($recordId, "/^(".$this->isil.").*$/")) {
+                        if (preg_match("/^(\(".$this->isil."\)).*$/", $recordId)) {
                             return substr($recordId, strpos($recordId, "(".$this->isil.")")+strlen("(".$this->isil.")"));
                         }
                     }
                 }
-
                 return $ilsRecordId;
             }
-
-            // DAIA Request with PPN from MarcRecord
-            //$daia = $this->queryDAIA($this->getSolrRecord($id)->getFincPPN()->getData());
-
-            // DAIA Request with PPN from Solr
-            //$daia = $this->queryDAIA($this->getSolrRecord($id)->getFincPPNSolr());
-
-            // DAIA Request with barcode
-            //$daia = $this->queryDAIA($this->getSolrRecord($id)->getFincBarcode());
-        }
-    }
-
-    /**
-     * Flatten a DAIA response to an array of holding information.
-     *
-     * @param string $id Document to look up.
-     *
-     * @return array
-     */
-    protected function daiaToHolding($id)
-    {
-        $daia = $this->queryDAIA($id);
-        // get Availability information from DAIA
-        $documentlist = $daia->getElementsByTagName('document');
-
-        // handle empty DAIA response
-        if ($documentlist->length == 0 &&
-            $daia->getElementsByTagName("message")->item(0)->attributes->getNamedItem("errno")->nodeValue == "404") {
-            $this->debug("Error: " . $daia->getElementsByTagName("message")->item(0)->attributes->getNamedItem("errno")->nodeValue
-                . " reported for DAIA request");
-        }
-
-        $status = array();
-        for ($b = 0; $documentlist->item($b) !== null; $b++) {
-            $itemlist = $documentlist->item($b)->getElementsByTagName('item');
-            $ilslink='';
-            if ($documentlist->item($b)->attributes->getNamedItem('href')!==null) {
-                $ilslink = $documentlist->item($b)->attributes
-                    ->getNamedItem('href')->nodeValue;
-            }
-            $emptyResult = array(
-                'callnumber' => '-',
-                'availability' => '0',
-                'number' => 1,
-                'reserve' => 'No',
-                'duedate' => '',
-                'queue'   => '',
-                'delay'   => '',
-                'barcode' => 'No samples',
-                'status' => '',
-                'id' => $id,
-                'location' => '',
-                'ilslink' => $ilslink,
-                'label' => 'No samples'
-            );
-            for ($c = 0; $itemlist->item($c) !== null; $c++) {
-                $result = array(
-                    'callnumber' => '',
-                    'availability' => '0',
-                    'number' => ($c+1),
-                    'reserve' => 'No',
-                    'duedate' => '',
-                    'queue'   => '',
-                    'delay'   => '',
-                    'barcode' => 1,
-                    'status' => '',
-                    'id' => $id,
-                    'item_id' => '',
-                    'recallhref' => '',
-                    'location' => '',
-                    'location.id' => '',
-                    'location.href' => '',
-                    'label' => '',
-                    'notes' => array()
-                );
-                if ($itemlist->item($c)->attributes->getNamedItem('id') !== null) {
-                    $result['item_id'] = $itemlist->item($c)->attributes
-                        ->getNamedItem('id')->nodeValue;
-                }
-                if ($itemlist->item($c)->attributes->getNamedItem('href') !== null) {
-                    $result['recallhref'] = $itemlist->item($c)->attributes
-                        ->getNamedItem('href')->nodeValue;
-                }
-                $departmentElements = $itemlist->item($c)
-                    ->getElementsByTagName('department');
-                if ($departmentElements->length > 0) {
-                    if ($departmentElements->item(0)->nodeValue) {
-                        $result['location']
-                            = $departmentElements->item(0)->nodeValue;
-                        $result['location.id'] = $departmentElements
-                            ->item(0)->attributes->getNamedItem('id')->nodeValue;
-                        $result['location.href'] = $departmentElements
-                            ->item(0)->attributes->getNamedItem('href')->nodeValue;
-                    }
-                }
-                $storageElements
-                    = $itemlist->item($c)->getElementsByTagName('storage');
-                if ($storageElements->length > 0) {
-                    if ($storageElements->item(0)->nodeValue) {
-                        $result['location'] = $storageElements->item(0)->nodeValue;
-                        //$result['location.id'] = $storageElements->item(0)
-                        //  ->attributes->getNamedItem('id')->nodeValue;
-                        $result['location.href'] = $storageElements->item(0)
-                            ->attributes->getNamedItem('href')->nodeValue;
-                        //$result['barcode'] = $result['location.id'];
-                    }
-                }
-                $barcodeElements
-                    = $itemlist->item($c)->getElementsByTagName('identifier');
-                if ($barcodeElements->length > 0) {
-                    if ($barcodeElements->item(0)->nodeValue) {
-                        $result['barcode'] = $barcodeElements->item(0)->nodeValue;
-                    }
-                }
-                $labelElements = $itemlist->item($c)->getElementsByTagName('label');
-                if ($labelElements->length > 0) {
-                    if ($labelElements->item(0)->nodeValue) {
-                        $result['label'] = $labelElements->item(0)->nodeValue;
-                        $result['callnumber']
-                            = urldecode($labelElements->item(0)->nodeValue);
-                    }
-                }
-                $messageElements
-                    = $itemlist->item($c)->getElementsByTagName('message');
-                if ($messageElements->length > 0) {
-                    for ($m = 0; $messageElements->item($m) !== null; $m++) {
-                        $errno = $messageElements->item($m)->attributes
-                            ->getNamedItem('errno')->nodeValue;
-                        if ($errno === '404') {
-                            $result['status'] = 'missing';
-                        } else if ($this->logger) {
-                            $lang = $messageElements->item($m)->attributes
-                                ->getNamedItem('lang')->nodeValue;
-                            $logString = "[DAIA] message for {$lang}: "
-                                . $messageElements->item($m)->nodeValue;
-                            $this->debug($logString);
-                        }
-                    }
-                }
-
-                //$loanAvail = 0;
-                //$loanExp = 0;
-                //$presAvail = 0;
-                //$presExp = 0;
-
-                $unavailableElements = $itemlist->item($c)
-                    ->getElementsByTagName('unavailable');
-                if ($unavailableElements->item(0) !== null) {
-                    for ($n = 0; $unavailableElements->item($n) !== null; $n++) {
-                        $service = $unavailableElements->item($n)->attributes
-                            ->getNamedItem('service');
-                        $expectedNode = $unavailableElements->item($n)->attributes
-                            ->getNamedItem('expected');
-                        $queueNode = $unavailableElements->item($n)->attributes
-                            ->getNamedItem('queue');
-                        if ($service !== null) {
-                            $service = $service->nodeValue;
-                            if ($service === 'presentation') {
-                                $result['presentation.availability'] = '0';
-                                $result['presentation_availability'] = '0';
-                                if ($expectedNode !== null) {
-                                    $result['presentation.duedate']
-                                        = $expectedNode->nodeValue;
-                                }
-                                if ($queueNode !== null) {
-                                    $result['presentation.queue']
-                                        = $queueNode->nodeValue;
-                                }
-                                $result['availability'] = '0';
-                            } elseif ($service === 'loan') {
-                                $result['loan.availability'] = '0';
-                                $result['loan_availability'] = '0';
-                                if ($expectedNode !== null) {
-                                    $result['loan.duedate'] = $expectedNode->nodeValue;
-                                }
-                                if ($queueNode !== null) {
-                                    $result['loan.queue'] = $queueNode->nodeValue;
-                                }
-                                $result['availability'] = '0';
-                            } elseif ($service === 'interloan') {
-                                $result['interloan.availability'] = '0';
-                                if ($expectedNode !== null) {
-                                    $result['interloan.duedate']
-                                        = $expectedNode->nodeValue;
-                                }
-                                if ($queueNode !== null) {
-                                    $result['interloan.queue'] = $queueNode->nodeValue;
-                                }
-                                $result['availability'] = '0';
-                            } elseif ($service === 'openaccess') {
-                                $result['openaccess.availability'] = '0';
-                                if ($expectedNode !== null) {
-                                    $result['openaccess.duedate']
-                                        = $expectedNode->nodeValue;
-                                }
-                                if ($queueNode !== null) {
-                                    $result['openaccess.queue'] = $queueNode->nodeValue;
-                                }
-                                $result['availability'] = '0';
-                            }
-                        }
-                        // TODO: message/limitation
-                        if ($expectedNode !== null) {
-                            $result['duedate'] = $expectedNode->nodeValue;
-                        }
-                        if ($queueNode !== null) {
-                            $result['queue'] = $queueNode->nodeValue;
-                        }
-                    }
-                }
-
-                $availableElements = $itemlist->item($c)
-                    ->getElementsByTagName('available');
-                if ($availableElements->item(0) !== null) {
-                    for ($n = 0; $availableElements->item($n) !== null; $n++) {
-                        $service = $availableElements->item($n)->attributes
-                            ->getNamedItem('service');
-                        $delayNode = $availableElements->item($n)->attributes
-                            ->getNamedItem('delay');
-                        if ($service !== null) {
-                            $service = $service->nodeValue;
-                            if ($service === 'presentation') {
-                                $result['presentation.availability'] = '1';
-                                $result['presentation_availability'] = '1';
-                                if ($delayNode !== null) {
-                                    $result['presentation.delay']
-                                        = $delayNode->nodeValue;
-                                }
-                                $result['availability'] = '1';
-                            } elseif ($service === 'loan') {
-                                $result['loan.availability'] = '1';
-                                $result['loan_availability'] = '1';
-                                if ($delayNode !== null) {
-                                    $result['loan.delay'] = $delayNode->nodeValue;
-                                }
-                                $result['availability'] = '1';
-                            } elseif ($service === 'interloan') {
-                                $result['interloan.availability'] = '1';
-                                if ($delayNode !== null) {
-                                    $result['interloan.delay'] = $delayNode->nodeValue;
-                                }
-                                $result['availability'] = '1';
-                            } elseif ($service === 'openaccess') {
-                                $result['openaccess.availability'] = '1';
-                                if ($delayNode !== null) {
-                                    $result['openaccess.delay'] = $delayNode->nodeValue;
-                                }
-                                $result['availability'] = '1';
-                            }
-                        }
-                        // TODO: message/limitation
-                        if ($delayNode !== null) {
-                            $result['delay'] = $delayNode->nodeValue;
-                        }
-                    }
-                }
-                // document has no availability elements, so set availability
-                // and barcode to -1
-                if ($availableElements->item(0) === null
-                    && $unavailableElements->item(0) === null
-                ) {
-                    $result['availability'] = '-1';
-                    $result['barcode'] = '-1';
-                }
-                $result['ilslink'] = $ilslink;
-                $status[] = $result;
-                /* $status = "available";
-                if (loanAvail) return 0;
-                if (presAvail) {
-                    if (loanExp) return 1;
-                    return 2;
-                }
-                if (loanExp) return 3;
-                if (presExp) return 4;
-                return 5;
-                */
-            }
-            if (count($status) === 0) {
-                $status[] = $emptyResult;
-            }
         }
-        return $status;
+        return $id;
     }
 
 }
\ No newline at end of file
-- 
GitLab