diff --git a/config/vufind/Alma.ini b/config/vufind/Alma.ini
index 8d3ec03df1356675decc47239fdd90af3e77c6a4..100c029c7c704959681ea439b584ead8ba2713de 100644
--- a/config/vufind/Alma.ini
+++ b/config/vufind/Alma.ini
@@ -28,6 +28,10 @@ extraHoldFields = comments:requiredByDate:pickUpLocation
 ; 3) a value within the Location IDs returned by getPickUpLocations()
 defaultPickUpLocation = ""
 
+; Max. no. of items displayed in the holdings tab. A paginator is used when there are
+; more holdings to display.
+itemLimit = "10"
+
 
 ; The "NewUser" section defines some default values that are used when creating an account
 ; in Alma via its API. This is only relevant if you use the authentication method "AlmaDatabase"
diff --git a/config/vufind/Demo.ini b/config/vufind/Demo.ini
index acc03bdb3b0f6dddb35ce47fca5d229f23e7555d..a435f8d21a7356b37d22ceeae5453afe8b1cc376 100644
--- a/config/vufind/Demo.ini
+++ b/config/vufind/Demo.ini
@@ -10,6 +10,12 @@ storageRetrievalRequests = true
 ; Whether to support ILL requests
 ILLRequests = true
 
+; Holds and holds-logic-related configuration options.
+[Holds]
+; Max. no. of items displayed in the holdings tab. A paginator is used when there are
+; more holdings to display. (Default = no limit)
+;itemLimit = "10"
+
 ; Configuration for retrieving sample records
 [Records]
 ; Search backend to pull records from
diff --git a/module/VuFind/src/VuFind/ILS/Connection.php b/module/VuFind/src/VuFind/ILS/Connection.php
index db0de12f09c386e9b064f174f35ecdec33071ac2..6b598e6f7437dadb48f4ff36755a9e71a3eae57a 100644
--- a/module/VuFind/src/VuFind/ILS/Connection.php
+++ b/module/VuFind/src/VuFind/ILS/Connection.php
@@ -110,6 +110,13 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     protected $failing = false;
 
+    /**
+     * Request object
+     *
+     * @var \Zend\Http\Request
+     */
+    protected $request;
+
     /**
      * Constructor
      *
@@ -117,10 +124,12 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      * representing the [Catalog] section of config.ini
      * @param \VuFind\ILS\Driver\PluginManager $driverManager Driver plugin manager
      * @param \VuFind\Config\PluginManager     $configReader  Configuration loader
+     * @param \Zend\Http\Request               $request       Request object
      */
     public function __construct(\Zend\Config\Config $config,
         \VuFind\ILS\Driver\PluginManager $driverManager,
-        \VuFind\Config\PluginManager $configReader
+        \VuFind\Config\PluginManager $configReader,
+        \Zend\Http\Request $request = null
     ) {
         if (!isset($config->driver)) {
             throw new \Exception('ILS driver setting missing.');
@@ -131,6 +140,7 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
         $this->config = $config;
         $this->configReader = $configReader;
         $this->driverManager = $driverManager;
+        $this->request = $request;
     }
 
     /**
@@ -973,6 +983,44 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
         return $result;
     }
 
+    /**
+     * Get holdings
+     *
+     * Retrieve holdings from ILS driver class and normalize result array if needed.
+     *
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Additional options
+     *
+     * @return array Array with holding data
+     */
+    public function getHolding($id, $patron = null, $options = [])
+    {
+        // Get pagination options for holdings tab
+        $holdsConfig
+            = $this->checkCapability('getConfig', ['Holds', compact('patron')])
+            ? $this->driver->getConfig('Holds') : null;
+        $itemLimit = !empty($holdsConfig['itemLimit'])
+            ? $holdsConfig['itemLimit'] : null;
+        $page = $this->request ? $this->request->getQuery('page', 1) : 1;
+        $offset = ($itemLimit && is_numeric($itemLimit))
+            ? ($page * $itemLimit) - $itemLimit
+            : null;
+        $defaultOptions = compact('page', 'itemLimit', 'offset');
+        $finalOptions = $options + $defaultOptions;
+
+        // Get the holdings from the ILS
+        $holdings = $this->__call('getHolding', [$id, $patron, $finalOptions]);
+
+        // Return all the necessary details:
+        return [
+            'total' => $holdings['total'] ?? count($holdings),
+            'holdings' => $holdings['holdings'] ?? $holdings,
+            'page' => $finalOptions['page'],
+            'itemLimit' => $finalOptions['itemLimit'],
+        ];
+    }
+
     /**
      * Default method -- pass along calls to the driver if available; return
      * false otherwise.  This allows custom functions to be implemented in
diff --git a/module/VuFind/src/VuFind/ILS/ConnectionFactory.php b/module/VuFind/src/VuFind/ILS/ConnectionFactory.php
index ad0c32df448d3de3b4eba24b55b74c0b4bc88d92..ff4992b2e66a6585dd372520a3b4336ccf0f57d4 100644
--- a/module/VuFind/src/VuFind/ILS/ConnectionFactory.php
+++ b/module/VuFind/src/VuFind/ILS/ConnectionFactory.php
@@ -62,10 +62,12 @@ class ConnectionFactory implements FactoryInterface
             throw new \Exception('Unexpected options sent to factory.');
         }
         $configManager = $container->get(\VuFind\Config\PluginManager::class);
+        $request = $container->get('Request');
         $catalog = new $requestedName(
             $configManager->get('config')->Catalog,
             $container->get(\VuFind\ILS\Driver\PluginManager::class),
-            $container->get(\VuFind\Config\PluginManager::class)
+            $container->get(\VuFind\Config\PluginManager::class),
+            $request instanceof \Zend\Http\Request ? $request : null
         );
         return $catalog->setHoldConfig(
             $container->get(\VuFind\ILS\HoldSettings::class)
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
index 1028780cc8a41ebfd20cc223afecf4634d0f9b49..bbaf2c78b0d968a138a6cec33fae4c2f6274b434 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
@@ -734,16 +734,19 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface,
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws DateException
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $holding = [];
         list($bib, $sys_no) = $this->parseId($id);
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Alma.php b/module/VuFind/src/VuFind/ILS/Driver/Alma.php
index acefab8489aea4749fba7ff3888fd6935bab0599..05b440ec65599080189e33360e5611ec8cab93e8 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Alma.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Alma.php
@@ -231,116 +231,132 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
-     *
-     * @return array         On success an associative array with the following keys:
-     *                       id, source, availability (boolean), status, location,
-     *                       reserve, callnumber, duedate, returnDate, number,
-     *                       barcode, item_notes, item_id, holding_id, addLink.
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Additional options
+     *
+     * @return array On success an array with the key "total" containing the total
+     * number of items for the given bib id, and the key "holdings" containing an
+     * array of holding information each one with these keys: id, source,
+     * availability, status, location, reserve, callnumber, duedate, returnDate,
+     * number, barcode, item_notes, item_id, holding_id, addLink, description
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, $patron = null, array $options = [])
     {
-        $results = [];
-        $copyCount = 0;
+        // Prepare result array with default values. If no API result can be received
+        // these will be returned.
+        $results['total'] = 0;
+        $results['holdings'] = [];
+
+        // Correct copy count in case of paging
+        $copyCount = $options['offset'] ?? 0;
         $username = $patron['cat_username'] ?? null;
-        $bibPath = '/bibs/' . urlencode($id) . '/holdings';
-        if ($holdings = $this->makeRequest($bibPath)) {
-            foreach ($holdings->holding as $holding) {
-                $holdingId = (string)$holding->holding_id;
-                $locationCode = (string)$holding->location;
-
-                $itemPath = $bibPath . '/' . urlencode($holdingId) . '/items';
-                if ($currentItems = $this->makeRequest($itemPath)) {
-                    foreach ($currentItems->item as $item) {
-                        $itemId = (string)$item->item_data->pid;
-                        $barcode = (string)$item->item_data->barcode;
-                        $processType = (string)$item->item_data->process_type;
-                        $itemNotes = null;
-                        if ($item->item_data->public_note != null
-                            && !empty($item->item_data->public_note)
-                        ) {
-                            $itemNotes = [(string)$item->item_data->public_note];
-                        }
-                        $requested = ((string)$item->item_data->requested == 'false')
-                            ? false
-                            : true;
-
-                        $number = ++$copyCount;
-                        $description = null;
-                        if ($item->item_data->description != null
-                            && !empty($item->item_data->description)
-                        ) {
-                            $number = (string)$item->item_data->description;
-                            $description = (string)$item->item_data->description;
-                        }
-
-                        // For some data we need to do additional API calls
-                        // due to the Alma API architecture
-                        $duedate = ($requested) ? 'requested' : null;
-                        if ($processType == 'LOAN' && !$requested) {
-                            $loanDataPath = '/bibs/' . urlencode($id) . '/holdings/'
-                                . urlencode($holdingId) . '/items/'
-                                . urlencode($itemId) . '/loans';
-                            $loanData = $this->makeRequest($loanDataPath);
-                            $loan = $loanData->item_loan;
-                            $duedate = $this->parseDate((string)$loan->due_date);
-                        }
-
-                        // Calculate request options if a user is logged-in
-                        if ($username) {
-
-                            // Call the request-options API for the logged-in user
-                            $requestOptionsPath = '/bibs/' . urlencode($id)
-                                . '/holdings/' . urlencode($holdingId) . '/items/'
-                                . urlencode($itemId) . '/request-options?user_id='
-                                . urlencode($username);
-
-                            // Make the API request
-                            $requestOptions = $this->makeRequest(
-                                $requestOptionsPath
-                            );
-
-                            // Get all possible request types from the API answer
-                            $requestTypes = $requestOptions->xpath(
-                                '/request_options/request_option//type'
-                            );
-
-                            // Add all allowed request types to an array
-                            $requestTypesArr = [];
-                            foreach ($requestTypes as $requestType) {
-                                $requestTypesArr[] = (string)$requestType;
-                            }
-
-                            // If HOLD is an allowed request type, add the link for
-                            // placing a hold
-                            $addLink = in_array('HOLD', $requestTypesArr);
-                        }
-
-                        $results[] = [
-                            'id' => $id,
-                            'source' => 'Solr',
-                            'availability' => $this->getAvailabilityFromItem($item),
-                            'status' => (string)$item
-                                ->item_data
-                                ->base_status[0]
-                                ->attributes()['desc'],
-                            'location' => $locationCode,
-                            'reserve' => 'N',   // TODO: support reserve status
-                            'callnumber' => (string)$item->holding_data->call_number,
-                            'duedate' => $duedate,
-                            'returnDate' => false, // TODO: support recent returns
-                            'number' => $number,//++$copyCount,
-                            'barcode' => empty($barcode) ? 'n/a' : $barcode,
-                            'item_notes' => $itemNotes,
-                            'item_id' => $itemId,
-                            'holding_id' => $holdingId,
-                            'addLink' => $addLink ?? false,
-                               // For Alma title-level hold requests
-                            'description' => $description
-                        ];
+
+        // Paging parameters for paginated API call. The "limit" tells the API how
+        // many items the call should return at once (e. g. 10). The "offset" defines
+        // the range (e. g. get items 30 to 40). With these parameters we are able to
+        // use a paginator for paging through many items.
+        $apiPagingParams = '';
+        if ($options['itemLimit'] ?? null) {
+            $apiPagingParams = 'limit=' . urlencode($options['itemLimit'])
+                . '&offset=' . urlencode($options['offset'] ?? 0);
+        }
+
+        // The path for the API call. We call "ALL" available items, but not at once
+        // as a pagination mechanism is used. If paging params are not set for some
+        // reason, the first 10 items are called which is the default API behaviour.
+        $itemsPath = '/bibs/' . urlencode($id) . '/holdings/ALL/items?'
+            . $apiPagingParams
+            . '&order_by=library,location,enum_a,enum_b&direction=desc';
+
+        if ($items = $this->makeRequest($itemsPath)) {
+            // Get the total number of items returned from the API call and set it to
+            // a class variable. It is then used in VuFind\RecordTab\HoldingsILS for
+            // the items paginator.
+            $results['total'] = (int)$items->attributes()->total_record_count;
+
+            foreach ($items->item as $item) {
+                $number = ++$copyCount;
+                $holdingId = (string)$item->holding_data->holding_id;
+                $itemId = (string)$item->item_data->pid;
+                $processType = (string)$item->item_data->process_type;
+                $barcode = (string)$item->item_data->barcode;
+                $requested = ((string)$item->item_data->requested == 'false')
+                             ? false
+                             : true;
+
+                // For some data we need to do additional API calls due to the Alma
+                // API architecture.
+                $duedate = ($requested) ? 'requested' : null;
+                if ($processType === 'LOAN' && !$requested) {
+                    $loanDataPath = '/bibs/' . urlencode($id) . '/holdings/'
+                        . urlencode($holdingId) . '/items/'
+                        . urlencode($itemId) . '/loans';
+                    $loanData = $this->makeRequest($loanDataPath);
+                    $loan = $loanData->item_loan;
+                    $duedate = $this->parseDate((string)$loan->due_date);
+                }
+
+                // Calculate request options if a user is logged-in
+                if ($username) {
+                    // Call the request-options API for the logged-in user
+                    $requestOptionsPath = '/bibs/' . urlencode($id)
+                       . '/holdings/' . urlencode($holdingId) . '/items/'
+                       . urlencode($itemId) . '/request-options?user_id='
+                       . urlencode($username);
+
+                    // Make the API request
+                    $requestOptions = $this->makeRequest($requestOptionsPath);
+
+                    // Get all possible request types from the API answer
+                    $requestTypes = $requestOptions->xpath(
+                        '/request_options/request_option//type'
+                    );
+
+                    // Add all allowed request types to an array
+                    $requestTypesArr = [];
+                    foreach ($requestTypes as $requestType) {
+                        $requestTypesArr[] = (string)$requestType;
                     }
+
+                    // If HOLD is an allowed request type, add the link for placing
+                    // a hold
+                    $addLink = in_array('HOLD', $requestTypesArr);
                 }
+
+                if ($item->item_data->public_note != null
+                    && !empty($item->item_data->public_note)
+                ) {
+                    $itemNotes = [(string)$item->item_data->public_note];
+                }
+
+                if ($item->item_data->description != null
+                    && !empty($item->item_data->description)
+                ) {
+                    $number = (string)$item->item_data->description;
+                    $description = (string)$item->item_data->description;
+                }
+
+                $results['holdings'][] = [
+                    'id' => $id,
+                    'source' => 'Solr',
+                    'availability' => $this->getAvailabilityFromItem($item),
+                    'status' => (string)$item->item_data->base_status[0]
+                        ->attributes()['desc'],
+                    'location' => (string)$item->item_data->location,
+                    'reserve' => 'N',   // TODO: support reserve status
+                    'callnumber' => (string)$item->holding_data->call_number,
+                    'duedate' => $duedate,
+                    'returnDate' => false, // TODO: support recent returns
+                    'number' => $number,
+                    'barcode' => empty($barcode) ? 'n/a' : $barcode,
+                    'item_notes' => $itemNotes ?? null,
+                    'item_id' => $itemId,
+                    'holding_id' => $holdingId,
+                    'addLink' => $addLink ?? false,
+                    // For Alma title-level hold requests
+                    'description' => $description ?? null
+                ];
             }
         }
 
@@ -1092,7 +1108,9 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
      */
     public function getStatus($id)
     {
-        return $this->getHolding($id);
+        $idList = [$id];
+        $status = $this->getStatuses($idList);
+        return current($status);
     }
 
     /**
@@ -1194,6 +1212,13 @@ class Alma extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterface
     {
         if (isset($this->config[$function])) {
             $functionConfig = $this->config[$function];
+
+            // Set default value for "itemLimit" in Alma driver
+            if ($function === 'Holds') {
+                $functionConfig['itemLimit'] = $functionConfig['itemLimit']
+                    ?? 10
+                    ?: 10;
+            }
         } else {
             $functionConfig = false;
         }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Amicus.php b/module/VuFind/src/VuFind/ILS/Driver/Amicus.php
index e267986e82a5c7a10e895d4eec29e4df65e5a7ec..809f0614dea5ae0c57a9e41671849931c900efdc 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Amicus.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Amicus.php
@@ -437,16 +437,19 @@ class Amicus extends AbstractBase implements TranslatorAwareInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         include_once 'File/MARC.php';
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
index 52b5d4d9ea2fea939f411139c343872ea814667c..828df269f2ed657563aa45db8987853ed52877c0 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
@@ -383,14 +383,17 @@ class DAIA extends AbstractBase implements
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getStatus($id);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Demo.php b/module/VuFind/src/VuFind/ILS/Driver/Demo.php
index b043ec2ca179fc4fc4d6afd3bb2bf8e4e897f678..0aede2d63aea41ba5ca36514e47861726e7bb660 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Demo.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Demo.php
@@ -585,7 +585,7 @@ class Demo extends AbstractBase
         $holding = [];
         $records = rand() % 15;
         for ($i = 1; $i <= $records; $i++) {
-            $holding[] = $this->getRandomHolding($id, $i, $patron);
+            $holding[] = $this->setStatus($id, [], true, $patron);
         }
         return $holding;
     }
@@ -598,16 +598,17 @@ class Demo extends AbstractBase
      *      number, barcode, availability, status, location,
      *      reserve, callnumber, duedate, is_holdable, and addLink
      * @param bool  $append  add another record or replace current record
+     * @param array $patron  Patron data
      *
      * @return array
      */
-    protected function setStatus($id, $holding = [], $append = true)
+    protected function setStatus($id, $holding = [], $append = true, $patron = null)
     {
         $id = (string)$id;
-        $session = $this->getSession();
+        $session = $this->getSession($patron['id'] ?? null);
         $i = isset($session->statuses[$id])
             ? count($session->statuses[$id]) + 1 : 1;
-        $holding = array_merge($this->getRandomHolding($id, $i), $holding);
+        $holding = array_merge($this->getRandomHolding($id, $i, $patron), $holding);
 
         // if statuses is already stored
         if ($session->statuses) {
@@ -648,14 +649,15 @@ class Demo extends AbstractBase
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options
      *
-     * @return array         On success, an associative array with the following
-     * keys: id, availability (boolean), status, location, reserve, callnumber,
+     * @return array On success, an associative array with the following keys:
+     * id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $this->checkIntermittentFailure();
 
@@ -685,8 +687,26 @@ class Demo extends AbstractBase
             $status[$i]['enumchron'] = "volume $volume, issue $seriesIssue";
         }
 
+        // Slice out a chunk if pagination is enabled.
+        $slice = null;
+        if ($options['itemLimit'] ?? null) {
+            // For sensible pagination, we need to sort by location:
+            $callback = function ($a, $b) {
+                return strcmp($a['location'], $b['location']);
+            };
+            usort($status, $callback);
+            $slice = array_slice(
+                $status,
+                $options['offset'] ?? 0,
+                $options['itemLimit']
+            );
+        }
+
         // Send back final value:
-        return $status;
+        return [
+            'total' => count($status),
+            'holdings' => $slice ?: $status,
+        ];
     }
 
     /**
@@ -2239,6 +2259,7 @@ class Demo extends AbstractBase
                 'extraHoldFields' =>
                     'comments:requestGroup:pickUpLocation:requiredByDate',
                 'defaultRequiredDate' => 'driver:0:2:0',
+                'itemLimit' => $this->config['Holds']['itemLimit'] ?? null,
             ];
         }
         if ($function == 'StorageRetrievalRequests'
diff --git a/module/VuFind/src/VuFind/ILS/Driver/DriverInterface.php b/module/VuFind/src/VuFind/ILS/Driver/DriverInterface.php
index 37cad7d7a888044d40baefc3307c34ed5087b479..22b46c392eefcf8ef240969ce59aa47323444bdd 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/DriverInterface.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/DriverInterface.php
@@ -101,15 +101,16 @@ interface DriverInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options
      *
      * @throws \VuFind\Exception\ILS
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
      */
-    public function getHolding($id, array $patron = null);
+    public function getHolding($id, array $patron = null, array $options = []);
 
     /**
      * Get Purchase History
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php b/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php
index 76d002315f0f5de2c1baa8675312c6d3c46b8953..4d0d9f2584dd8af158ae7ee47d533e59aef87d77 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php
@@ -188,16 +188,19 @@ HERE;
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $holding = [];
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Folio.php b/module/VuFind/src/VuFind/ILS/Driver/Folio.php
index 93aaffefe6d280c12d298acfa7c6e736f2675532..997211fc80d167225c76dd67433a0cb1839c6996 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Folio.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Folio.php
@@ -331,12 +331,15 @@ class Folio extends AbstractAPI implements
     /**
      * This method queries the ILS for holding information.
      *
-     * @param string $bibId  Bib-level id
-     * @param array  $patron Patron login information from $this->patronLogin
+     * @param string $bibId   Bib-level id
+     * @param array  $patron  Patron login information from $this->patronLogin
+     * @param array  $options Extra options (not currently used)
      *
      * @return array An array of associative holding arrays
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($bibId, array $patron = null)
+    public function getHolding($bibId, array $patron = null, array $options = [])
     {
         $instance = $this->getInstance($bibId);
         $query = ['query' => '(instanceId="' . $instance->id . '")'];
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Horizon.php b/module/VuFind/src/VuFind/ILS/Driver/Horizon.php
index 953767656f3202e56f4fffe9eaa3e51b852e5b8b..6ee8a0d3882ec4a8dd825efe72c9e3769420bfad 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Horizon.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Horizon.php
@@ -332,16 +332,19 @@ class Horizon extends AbstractBase implements LoggerAwareInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $sqlArray = $this->getHoldingSql($id);
         $sql = $this->buildSqlFromArray($sqlArray);
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Innovative.php b/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
index 127b000e90f85ab97ccd4fa94e6490c97db20cb1..4bf2da95e8002aff14260909825b76a430f07c92 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
@@ -267,16 +267,19 @@ class Innovative extends AbstractBase implements
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getStatus($id);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Koha.php b/module/VuFind/src/VuFind/ILS/Driver/Koha.php
index 7999f80d4119dca3b8cc907fad1e111bceb540c9..3c3d8b3398aaf603397e54b4e8378fef4b384c51 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Koha.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Koha.php
@@ -157,16 +157,19 @@ class Koha extends AbstractBase
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $holding = [];
         $available = true;
diff --git a/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php b/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php
index 022f2ed9ecc2b9289b81b1b931dfd2cb39cbf7de..4ca53c1fdc8bbc1cb6a4686b00adea490104745d 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php
@@ -770,16 +770,19 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws DateException
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $this->debug(
             "Function getHolding($id, "
diff --git a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
index db1a3ec4684bb40c3dadf2c3c26c037a8d7b1d59..0a4b657894514d58f509a4b7fbf61ec536d11699 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
@@ -245,14 +245,17 @@ class MultiBackend extends AbstractBase implements \Zend\Log\LoggerAwareInterfac
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $source = $this->getSource($id);
         $driver = $this->getDriver($source);
diff --git a/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php b/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php
index 2d0e9a6738256c0217d861769ca04f78b2cd0e46..052ed53d0330d8825a4eea19211f4f6dc3d0203c 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php
@@ -84,14 +84,17 @@ class NewGenLib extends AbstractBase
      *
      * @param string $RecordID The record id to retrieve the holdings for
      * @param array  $patron   Patron data
+     * @param array  $options  Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array           On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($RecordID, array $patron = null)
+    public function getHolding($RecordID, array $patron = null, array $options = [])
     {
         $holding = $this->getItemStatus($RecordID);
         for ($i = 0; $i < count($holding); $i++) {
diff --git a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
index 15972e22ac091dc229ac1d0567546652f9d44984..0d97256071a847cb6efd1cd81f6d7655efaa04d3 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
@@ -192,15 +192,18 @@ class NoILS extends AbstractBase implements TranslatorAwareInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $useHoldings = $this->config['settings']['useHoldings'] ?? 'none';
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Polaris.php b/module/VuFind/src/VuFind/ILS/Driver/Polaris.php
index ced82a5cba77c08f324f1384c375408f83247ae1..94f4826b36f721232ab4772fe7483920a3a91842 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Polaris.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Polaris.php
@@ -353,14 +353,17 @@ class Polaris extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterf
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @return mixed         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getStatus($id);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Sample.php b/module/VuFind/src/VuFind/ILS/Driver/Sample.php
index ce24eccb7932c6a9b82165d90dac656583d4ebde..d8a39b1e92e41c8c3f9048b1680d464a38f26c8b 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Sample.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Sample.php
@@ -107,8 +107,9 @@ class Sample extends AbstractBase
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @return mixed     On success, an associative array with the following keys:
      * id, availability (boolean), status, location, reserve, callnumber, duedate,
@@ -116,7 +117,7 @@ class Sample extends AbstractBase
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getStatus($id);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Sierra.php b/module/VuFind/src/VuFind/ILS/Driver/Sierra.php
index f42e5f3439091bdca1acba6e4d350e3e82daa900..45ffb54b1591fd242813533034c3cb406a75fe9c 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Sierra.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Sierra.php
@@ -461,16 +461,19 @@ class Sierra extends AbstractBase implements TranslatorAwareInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws DateException
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         try {
             $holdings = [];
diff --git a/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php b/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php
index 583b7fe5f5557921e2f4f0d802d03fdf10fc4405..075b903fa7676ff09fc2e4961201c945b3d0925b 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/SierraRest.php
@@ -302,8 +302,9 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface,
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @return mixed     On success, an associative array with the following keys:
      * id, availability (boolean), status, location, reserve, callnumber, duedate,
@@ -311,7 +312,7 @@ class SierraRest extends AbstractBase implements TranslatorAwareInterface,
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getItemStatusesForBib($id, true);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
index 3fb4b127f2215505960a99df0acf61d547da3706..353ded512daba667fa691655bea268d332477052 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
@@ -1020,15 +1020,18 @@ class Symphony extends AbstractBase implements LoggerAwareInterface
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getStatus($id);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php b/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php
index e5964b720e9f545689c38bc44cc1d2f43c3ee9ab..48f66f87efd8896733082374b1a390de0a631859 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php
@@ -393,16 +393,19 @@ class Unicorn extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterf
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return $this->getStatus($id);
     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Virtua.php b/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
index c71de284dc6f58f0e91e2e8bd2b7f486bb9e1a06..9a534fb5ea96bfd135564685065e27c244b84dac 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
@@ -323,16 +323,19 @@ class Virtua extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterfa
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         // Strip off the prefix from vtls exports
         $db_id = str_replace("vtls", "", $id);
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
index a29304009c0e53e30c52fff34a2a96a5c3d4336d..0aa6f718a7b6a0de0a625f07b4b8fc7ebed934be 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
@@ -1125,16 +1125,19 @@ EOT;
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws DateException
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $possibleQueries = [];
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php b/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php
index e7c7d2101f69f118cee5dbad82698e16c04ebb05..ccb27882659cc81860d8ed9d41e09a80c2a2a65f 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php
@@ -565,16 +565,19 @@ class XCNCIP2 extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterf
      * This is responsible for retrieving the holding information of a certain
      * record.
      *
-     * @param string $id     The record id to retrieve the holdings for
-     * @param array  $patron Patron data
+     * @param string $id      The record id to retrieve the holdings for
+     * @param array  $patron  Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws VuFind\Date\DateException;
      * @throws ILSException
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         $ids = null;
         if (! $this->consortium) {
diff --git a/module/VuFind/src/VuFind/ILS/Logic/Holds.php b/module/VuFind/src/VuFind/ILS/Logic/Holds.php
index 7455a0960876e9f4b41c1b621124e93484b102e6..e511ca4ea4183a8011357c5e362870b2d496f951 100644
--- a/module/VuFind/src/VuFind/ILS/Logic/Holds.php
+++ b/module/VuFind/src/VuFind/ILS/Logic/Holds.php
@@ -231,6 +231,9 @@ class Holds
         }
         return [
             'blocks' => $blocks,
+            'total' => $result['total'],
+            'page' => $result['page'],
+            'itemLimit' => $result['itemLimit'],
             'holdings' => $this->formatHoldings($holdings)
         ];
     }
@@ -245,8 +248,8 @@ class Holds
     protected function standardHoldings($result)
     {
         $holdings = [];
-        if (count($result)) {
-            foreach ($result as $copy) {
+        if ($result['total']) {
+            foreach ($result['holdings'] as $copy) {
                 $show = !in_array($copy['location'], $this->hideHoldings);
                 if ($show) {
                     $groupKey = $this->getHoldingsGroupKey($copy);
@@ -270,8 +273,8 @@ class Holds
     {
         $holdings = [];
 
-        if (count($result)) {
-            foreach ($result as $copy) {
+        if ($result['total']) {
+            foreach ($result['holdings'] as $copy) {
                 $show = !in_array($copy['location'], $this->hideHoldings);
                 if ($show) {
                     if ($holdConfig) {
@@ -315,8 +318,8 @@ class Holds
         $holds_override = isset($this->config->Catalog->allow_holds_override)
             ? $this->config->Catalog->allow_holds_override : false;
 
-        if (count($result)) {
-            foreach ($result as $copy) {
+        if ($result['total']) {
+            foreach ($result['holdings'] as $copy) {
                 $show = !in_array($copy['location'], $this->hideHoldings);
                 if ($show) {
                     $groupKey = $this->getHoldingsGroupKey($copy);
diff --git a/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php b/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
index 00f60f67224165e4afa53877fb9eabaed99cb7ca..393213a9546d791f403c4dcc50c9913f7b944f57 100644
--- a/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
+++ b/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
@@ -155,7 +155,7 @@ class TitleHolds
         static $holdings = [];
 
         if (!isset($holdings[$id])) {
-            $holdings[$id] = $this->catalog->getHolding($id);
+            $holdings[$id] = $this->catalog->getHolding($id)['holdings'];
         }
         return $holdings[$id];
     }
diff --git a/module/VuFind/src/VuFind/RecordTab/HoldingsILS.php b/module/VuFind/src/VuFind/RecordTab/HoldingsILS.php
index fd760e0aaf60b704210a7ba1fa992a02c494d352..f0c6424a8a5431ac21814cff2922ac8aa6d8e3d3 100644
--- a/module/VuFind/src/VuFind/RecordTab/HoldingsILS.php
+++ b/module/VuFind/src/VuFind/RecordTab/HoldingsILS.php
@@ -54,17 +54,29 @@ class HoldingsILS extends AbstractBase
      */
     protected $template;
 
+    /**
+     * Whether the holdings tab should be hidden when empty or not.
+     *
+     * @var bool
+     */
+    protected $hideWhenEmpty;
+
     /**
      * Constructor
      *
-     * @param \VuFind\ILS\Connection|bool $catalog  ILS connection to use to check
-     * for holdings before displaying the tab; set to null if no check is needed
-     * @param string                      $template Holdings template to use
+     * @param \VuFind\ILS\Connection|bool $catalog       ILS connection to use to
+     * check for holdings before displaying the tab; may be set to null if no check
+     * is needed.
+     * @param string                      $template      Holdings template to use
+     * @param bool                        $hideWhenEmpty Whether the
+     * holdings tab should be hidden when empty or not
      */
-    public function __construct(Connection $catalog = null, $template = null)
-    {
+    public function __construct(Connection $catalog = null, $template = null,
+        $hideWhenEmpty = false
+    ) {
         $this->catalog = $catalog;
         $this->template = $template ?? 'standard';
+        $this->hideWhenEmpty = $hideWhenEmpty;
     }
 
     /**
@@ -104,10 +116,8 @@ class HoldingsILS extends AbstractBase
      */
     public function isActive()
     {
-        if ($this->catalog) {
-            return $this->catalog->hasHoldings($this->driver->getUniqueID());
-        }
-        return true;
+        return ($this->catalog && $this->hideWhenEmpty)
+            ? $this->catalog->hasHoldings($this->driver->getUniqueID()) : true;
     }
 
     /**
@@ -119,4 +129,33 @@ class HoldingsILS extends AbstractBase
     {
         return $this->template;
     }
+
+    /**
+     * Getting a paginator for the items list.
+     *
+     * @param int $totalItemCount Total count of items for a bib record
+     * @param int $page           Currently selected page of the items paginator
+     * @param int $itemLimit      Max. no of items per page
+     *
+     * @return \Zend\Paginator\Paginator
+     */
+    public function getPaginator($totalItemCount, $page, $itemLimit)
+    {
+        // Return if a paginator is not needed or not supported ($itemLimit = null)
+        if (!$itemLimit || $totalItemCount < $itemLimit) {
+            return;
+        }
+
+        // Create the paginator
+        $nullAdapter = new \Zend\Paginator\Adapter\NullFill($totalItemCount);
+        $paginator = new \Zend\Paginator\Paginator($nullAdapter);
+
+        // Some settings for the paginator
+        $paginator
+            ->setCurrentPageNumber($page)
+            ->setItemCountPerPage($itemLimit)
+            ->setPageRange(10);
+
+        return $paginator;
+    }
 }
diff --git a/module/VuFind/src/VuFind/RecordTab/HoldingsILSFactory.php b/module/VuFind/src/VuFind/RecordTab/HoldingsILSFactory.php
index cacf087ada9db6bd7a4c01f6883bafb0ef48611e..8bee0526391cbe690eb8b65a463c6dce5dcc1451 100644
--- a/module/VuFind/src/VuFind/RecordTab/HoldingsILSFactory.php
+++ b/module/VuFind/src/VuFind/RecordTab/HoldingsILSFactory.php
@@ -67,11 +67,11 @@ class HoldingsILSFactory implements \Zend\ServiceManager\Factory\FactoryInterfac
         // object:
         $config = $container->get(\VuFind\Config\PluginManager::class)
             ->get('config');
-        $catalog = ($config->Site->hideHoldingsTabWhenEmpty ?? false)
-            ? $container->get(\VuFind\ILS\Connection::class) : null;
+        $catalog = $container->get(\VuFind\ILS\Connection::class);
         return new $requestedName(
             $catalog,
-            (string)($config->Site->holdingsTemplate ?? 'standard')
+            (string)($config->Site->holdingsTemplate ?? 'standard'),
+            (string)($config->Site->hideHoldingsTabWhenEmpty ?? false)
         );
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php
index 966ff66f38db63401534bb9e7d7a6281562e2fb0..b24510e4e5058038989c29c8daa2e695bfafbffd 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php
@@ -2458,6 +2458,8 @@ class DummyILS extends \VuFind\ILS\Driver\AbstractBase
      * @throws \VuFind\Exception\ILS
      * @return mixed     On success, an associative array with the following keys:
      * id, availability (boolean), status, location, reserve, callnumber.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getStatus($id)
     {
@@ -2474,6 +2476,8 @@ class DummyILS extends \VuFind\ILS\Driver\AbstractBase
      *
      * @throws \VuFind\Exception\ILS
      * @return array     An array of getStatus() return values on success.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getStatuses($ids)
     {
@@ -2488,13 +2492,16 @@ class DummyILS extends \VuFind\ILS\Driver\AbstractBase
      *
      * @param string $id     The record id to retrieve the holdings for
      * @param array  $patron Patron data
+     * @param array  $options Extra options (not currently used)
      *
      * @throws \VuFind\Exception\ILS
      * @return array         On success, an associative array with the following
      * keys: id, availability (boolean), status, location, reserve, callnumber,
      * duedate, number, barcode.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getHolding($id, array $patron = null)
+    public function getHolding($id, array $patron = null, array $options = [])
     {
         return [];
     }
@@ -2509,6 +2516,8 @@ class DummyILS extends \VuFind\ILS\Driver\AbstractBase
      *
      * @throws \VuFind\Exception\ILS
      * @return array     An array with the acquisitions data on success.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getPurchaseHistory($id)
     {
diff --git a/themes/bootstrap3/templates/RecordTab/holdingsils.phtml b/themes/bootstrap3/templates/RecordTab/holdingsils.phtml
index 934039e77fc6f7f30fe2eed8e1f4981161d9913d..f4ad09fb926b2f48ec8477ba7b25372d23b3549a 100644
--- a/themes/bootstrap3/templates/RecordTab/holdingsils.phtml
+++ b/themes/bootstrap3/templates/RecordTab/holdingsils.phtml
@@ -118,7 +118,9 @@
   <?php endif; ?>
 </table>
 <?php endforeach; ?>
-
+<?php if ($paginator = $this->tab->getPaginator($holdings['total'], $holdings['page'], $holdings['itemLimit'])): ?>
+  <?=$this->paginationControl($paginator, 'Sliding', 'Helpers/pagination.phtml', ['page' => $holdings['page']])?>
+<?php endif; ?>
 <?php $history = $this->driver->getRealTimeHistory(); ?>
 <?php if (is_array($history) && !empty($history)): ?>
   <h3><?=$this->transEsc("Most Recent Received Issues")?></h3>