From 0ad732f46d91d6b73b28b3ba5009165293ff738c Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Mon, 17 Dec 2018 15:25:32 -0500
Subject: [PATCH] Refactored historicloansAction pagination logic to helper
 class. - Inspired by Ere Maijala's work on #1268.

---
 .../Controller/MyResearchController.php       | 107 +++++-------
 .../src/VuFind/ILS/PaginationHelper.php       | 153 ++++++++++++++++++
 2 files changed, 191 insertions(+), 69 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/ILS/PaginationHelper.php

diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php
index 244b17acbc6..8adfeee7a11 100644
--- a/module/VuFind/src/VuFind/Controller/MyResearchController.php
+++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php
@@ -32,6 +32,7 @@ use VuFind\Exception\Forbidden as ForbiddenException;
 use VuFind\Exception\ILS as ILSException;
 use VuFind\Exception\ListPermission as ListPermissionException;
 use VuFind\Exception\Mail as MailException;
+use VuFind\ILS\PaginationHelper;
 use VuFind\Search\RecommendListener;
 use Zend\Stdlib\Parameters;
 use Zend\View\Model\ViewModel;
@@ -47,6 +48,13 @@ use Zend\View\Model\ViewModel;
  */
 class MyResearchController extends AbstractBase
 {
+    /**
+     * ILS Pagination Helper
+     *
+     * @var PaginationHelper
+     */
+    protected $paginationHelper = null;
+
     /**
      * Are we currently in a lightbox context?
      *
@@ -1273,73 +1281,31 @@ class MyResearchController extends AbstractBase
             return $this->createViewModel();
         }
 
-        // Get page and page size:
-        $page = (int)$this->params()->fromQuery('page', 1);
+        // Get paging setup:
         $config = $this->getConfig();
-        $limit = isset($config->Catalog->historic_loan_page_size)
-            ? $config->Catalog->historic_loan_page_size : 50;
-        $ilsPaging = true;
-        if (isset($functionConfig['max_results'])) {
-            $limit = min([$functionConfig['max_results'], $limit]);
-        } elseif (isset($functionConfig['page_size'])) {
-            if (!in_array($limit, $functionConfig['page_size'])) {
-                $limit = $functionConfig['default_page_size']
-                    ?? $functionConfig['page_size'][0];
-            }
-        } else {
-            $ilsPaging = false;
-        }
-
-        // Get sort settings
-        $sort = false;
-        if (!empty($functionConfig['sort'])) {
-            $sort = $this->params()->fromQuery('sort');
-            if (!isset($functionConfig['sort'][$sort])) {
-                if (isset($functionConfig['default_sort'])) {
-                    $sort = $functionConfig['default_sort'];
-                } else {
-                    reset($functionConfig['sort']);
-                    $sort = key($functionConfig['sort']);
-                }
-            }
-        }
-
-        // Configure call params
-        $params = [
-            'sort' => $sort
-        ];
-        if ($ilsPaging) {
-            $params['page'] = $page;
-            $params['limit'] = $limit;
-        }
+        $pageOptions = $this->getPaginationHelper()->getOptions(
+            (int)$this->params()->fromQuery('page', 1),
+            $this->params()->fromQuery('sort'),
+            $config->Catalog->historic_loan_page_size ?? 50,
+            $functionConfig
+        );
 
         // Get checked out item details:
-        $result = $catalog->getMyTransactionHistory($patron, $params);
+        $result
+            = $catalog->getMyTransactionHistory($patron, $pageOptions['ilsParams']);
 
         if (isset($result['success']) && !$result['success']) {
             $this->flashMessenger()->addErrorMessage($result['status']);
             return $this->createViewModel();
         }
 
-        // Build paginator if needed:
-        if ($ilsPaging && $limit < $result['count']) {
-            $adapter = new \Zend\Paginator\Adapter\NullFill($result['count']);
-            $paginator = new \Zend\Paginator\Paginator($adapter);
-            $paginator->setItemCountPerPage($limit);
-            $paginator->setCurrentPageNumber($page);
-            $pageStart = $paginator->getAbsoluteItemNumber(1) - 1;
-            $pageEnd = $paginator->getAbsoluteItemNumber($limit) - 1;
-        } elseif ($limit > 0 && $limit < $result['count']) {
-            $adapter = new \Zend\Paginator\Adapter\ArrayAdapter(
-                $result['transactions']
-            );
-            $paginator = new \Zend\Paginator\Paginator($adapter);
-            $paginator->setItemCountPerPage($limit);
-            $paginator->setCurrentPageNumber($page);
+        $paginator = $this->getPaginationHelper()->getPaginator(
+            $pageOptions, $result['count'], $result['transactions']
+        );
+        if ($paginator) {
             $pageStart = $paginator->getAbsoluteItemNumber(1) - 1;
-            $pageEnd = $paginator->getAbsoluteItemNumber($limit) - 1;
+            $pageEnd = $paginator->getAbsoluteItemNumber($pageOptions['limit']) - 1;
         } else {
-            $paginator = false;
             $pageStart = 0;
             $pageEnd = $result['count'];
         }
@@ -1347,25 +1313,15 @@ class MyResearchController extends AbstractBase
         $transactions = $hiddenTransactions = [];
         foreach ($result['transactions'] as $i => $current) {
             // Build record driver (only for the current visible page):
-            if ($ilsPaging || ($i >= $pageStart && $i <= $pageEnd)) {
+            if ($pageOptions['ilsPaging'] || ($i >= $pageStart && $i <= $pageEnd)) {
                 $transactions[] = $this->getDriverForILSRecord($current);
             } else {
                 $hiddenTransactions[] = $current;
             }
         }
 
-        // Handle view params for sorting
-        $sortList = [];
-        if (!empty($functionConfig['sort'])) {
-            foreach ($functionConfig['sort'] as $key => $value) {
-                $sortList[$key] = [
-                    'desc' => $value,
-                    'url' => '?sort=' . urlencode($key),
-                    'selected' => $sort == $key
-                ];
-            }
-        }
-
+        $sortList = $pageOptions['sortList'];
+        $params = $pageOptions['ilsParams'];
         return $this->createViewModel(
             compact(
                 'transactions', 'paginator', 'params',
@@ -1757,4 +1713,17 @@ class MyResearchController extends AbstractBase
         }
         return $view;
     }
+
+    /**
+     * Get the ILS pagination helper
+     *
+     * @return PaginationHelper
+     */
+    protected function getPaginationHelper()
+    {
+        if (null === $this->paginationHelper) {
+            $this->paginationHelper = new PaginationHelper();
+        }
+        return $this->paginationHelper;
+    }
 }
diff --git a/module/VuFind/src/VuFind/ILS/PaginationHelper.php b/module/VuFind/src/VuFind/ILS/PaginationHelper.php
new file mode 100644
index 00000000000..30db96d6e36
--- /dev/null
+++ b/module/VuFind/src/VuFind/ILS/PaginationHelper.php
@@ -0,0 +1,153 @@
+<?php
+/**
+ * ILS Pagination Helper
+ *
+ * This class helps build paginators for ILS-provided data.
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2018.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
+ */
+namespace VuFind\ILS;
+
+/**
+ * ILS Pagination Helper
+ *
+ * This class helps build paginators for ILS-provided data.
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
+ */
+class PaginationHelper
+{
+    /**
+     * Support method for getPagingSetup() -- validate the active sort option.
+     *
+     * @param array $functionConfig Function config returned from the ILS
+     */
+    protected function validateSort($functionConfig, $sort)
+    {
+        // If sort is disabled, all settings are invalid...
+        if (empty($functionConfig['sort'])) {
+            return false;
+        }
+        // If provided setting is valid, use it...
+        if (isset($functionConfig['sort'][$sort])) {
+            return $sort;
+        }
+        // At this point, we need to find a reasonable value, either the configured
+        // default or the first valid sort value...
+        if (isset($functionConfig['default_sort'])) {
+            return $functionConfig['default_sort'];
+        }
+        reset($functionConfig['sort']);
+        return key($functionConfig['sort']);
+    }
+
+    /**
+     * Support method for getPagingSetup() -- determine the list of sort options.
+     *
+     * @param array  $functionConfig Function config returned from the ILS
+     * @param string $sort           Currently active sort option
+     */
+    protected function getSortList($functionConfig, $sort)
+    {
+        $sortList = [];
+        if (!empty($functionConfig['sort'])) {
+            foreach ($functionConfig['sort'] as $key => $value) {
+                $sortList[$key] = [
+                    'desc' => $value,
+                    'url' => '?sort=' . urlencode($key),
+                    'selected' => $sort == $key
+                ];
+            }
+        }
+        return $sortList;
+    }
+
+    /**
+     * Get paging settings and request data for paged ILS requests.
+     *
+     * @param int    $page            Current page (1-based)
+     * @param string $sort            Current sort setting (null for none)
+     * @param int    $defaultPageSize Default page size
+     * @param array  $functionConfig  Function config returned from the ILS
+     *
+     * @return array
+     */
+    public function getOptions($page, $sort, $defaultPageSize,
+        $functionConfig
+    ) {
+        // Get page and page size:
+        $limit = $defaultPageSize;
+        $ilsPaging = true;
+        if (isset($functionConfig['max_results'])) {
+            $limit = min([$functionConfig['max_results'], $limit]);
+        } elseif (isset($functionConfig['page_size'])) {
+            if (!in_array($limit, $functionConfig['page_size'])) {
+                $limit = $functionConfig['default_page_size']
+                    ?? $functionConfig['page_size'][0];
+            }
+        } else {
+            $ilsPaging = false;
+        }
+        // Collect ILS call params
+        $ilsParams = ['sort' => $this->validateSort($functionConfig, $sort)];
+        if ($ilsPaging) {
+            $ilsParams['page'] = $page;
+            $ilsParams['limit'] = $limit;
+        }
+        $sortList = $this->getSortList($functionConfig, $ilsParams['sort']);
+        return compact('page', 'limit', 'ilsPaging', 'ilsParams', 'sortList');
+    }
+
+    /**
+     * Build a paginator with the paging options and ILS results if necessary
+     *
+     * @param array $pageOptions Paging options and parameters (returned by the
+     * getOptions method)
+     * @param int   $count       Result count
+     * @param array $records     Result records
+     *
+     * @return false|\Zend\Paginator\Paginator
+     */
+    public function getPaginator($pageOptions, $count, $records)
+    {
+        $limit = $pageOptions['limit'];
+        if ($pageOptions['ilsPaging'] && $limit < $count) {
+            $adapter = new \Zend\Paginator\Adapter\NullFill($count);
+        } elseif ($limit > 0 && $limit < $count) {
+            $adapter = new \Zend\Paginator\Adapter\ArrayAdapter($records);
+        } else {
+            return false;
+        }
+        $paginator = new \Zend\Paginator\Paginator($adapter);
+        $paginator->setItemCountPerPage($limit);
+        $paginator->setCurrentPageNumber($pageOptions['page']);
+        return $paginator;
+    }
+}
\ No newline at end of file
-- 
GitLab