From d1f2dba95bca565a8dc3def6bbf9e16517709d0f Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Tue, 3 Jul 2012 11:04:36 -0400
Subject: [PATCH] Began wiring up abstract search controller.

---
 .../src/VuFind/Controller/AbstractBase.php    | 120 ++++++++
 .../src/VuFind/Controller/AbstractSearch.php  | 285 ++++++++++++++++++
 .../VuFind/Controller/SearchController.php    |   4 +-
 3 files changed, 407 insertions(+), 2 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/Controller/AbstractBase.php
 create mode 100644 module/VuFind/src/VuFind/Controller/AbstractSearch.php

diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php
new file mode 100644
index 00000000000..fafcad2641c
--- /dev/null
+++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php
@@ -0,0 +1,120 @@
+<?php
+/**
+ * VuFind controller base class (defines some methods that can be shared by other
+ * controllers).
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
+ */
+namespace VuFind\Controller;
+use Zend\Mvc\Controller\ActionController;
+
+/**
+ * VuFind controller base class (defines some methods that can be shared by other
+ * controllers).
+ *
+ * @category VuFind2
+ * @package  Controller
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
+ */
+class AbstractBase extends ActionController
+{
+    /**
+     * Redirect the user to the login screen.
+     *
+     * @param string $msg    Flash message to display on login screen
+     * @param array  $extras Associative array of extra fields to store
+     *
+     * @return void
+     */
+    protected function forceLogin($msg = null, $extras = array())
+    {
+        /* TODO:
+        // Set default message if necessary.
+        if (is_null($msg)) {
+            $msg = 'You must be logged in first';
+        }
+
+        // Store the current URL as a login followup action unless we are in a
+        // lightbox (since lightboxes use a different followup mechanism).
+        if ($this->_helper->layout->getLayout() != 'lightbox') {
+            $this->_helper->followup->store($extras);
+        }
+        if (!empty($msg)) {
+            $this->_helper->flashMessenger->setNamespace('error')
+                ->addMessage($msg);
+        }
+
+        // Set a flag indicating that we are forcing login:
+        $this->_request->setParam('forcingLogin', true);
+
+        $this->_forward('Login', 'MyResearch');
+         */
+    }
+
+    /**
+     * Does the user have catalog credentials available?  Returns associative array
+     * of patron data if so, otherwise forwards to appropriate login prompt and
+     * returns false.
+     *
+     * @return array|bool
+     */
+    protected function catalogLogin()
+    {
+        /* TODO:
+        // First make sure user is logged in to VuFind:
+        $account = VF_Account_Manager::getInstance();
+        $user = $account->isLoggedIn();
+        if ($user == false) {
+            $this->forceLogin();
+            return false;
+        }
+
+        // Now check if the user has provided credentials with which to log in:
+        if (($username = $this->getRequest()->post()->get('cat_username', false))
+            && ($password = $this->getRequest()->post()->get('cat_password', false))
+        ) {
+            $patron = $account->newCatalogLogin($username, $password);
+
+            // If login failed, store a warning message:
+            if (!$patron) {
+                $this->_helper->flashMessenger->setNamespace('error')
+                    ->addMessage('Invalid Patron Login');
+            }
+        } else {
+            // If no credentials were provided, try the stored values:
+            $patron = $account->storedCatalogLogin();
+        }
+
+        // If catalog login failed, send the user to the right page:
+        if (!$patron) {
+            $this->_forward('CatalogLogin', 'MyResearch');
+        }
+
+        // Send value (either false or patron array) back to caller:
+        return $patron;
+         */
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Controller/AbstractSearch.php b/module/VuFind/src/VuFind/Controller/AbstractSearch.php
new file mode 100644
index 00000000000..cfc19210b8c
--- /dev/null
+++ b/module/VuFind/src/VuFind/Controller/AbstractSearch.php
@@ -0,0 +1,285 @@
+<?php
+/**
+ * VuFind Search Controller
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Controller;
+use VuFind\Account\Manager as AccountManager, VuFind\Search\Memory,
+    VuFind\Search\Options as SearchOptions, VuFind\Search\ResultScroller,
+    Zend\View\Model\ViewModel;
+/**
+ * VuFind Search Controller
+ *
+ * @category VuFind2
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class AbstractSearch extends AbstractBase
+{
+    protected $searchClassId = 'Solr';
+    protected $saveToHistory = true;
+    protected $logStatistics = true;
+    protected $rememberSearch = true;
+    protected $useResultScroller = true;
+    protected $user;
+
+    /**
+     * init
+     *
+     * @return void
+     */
+    public function init()
+    {
+        $this->user = AccountManager::getInstance()->isLoggedIn();
+        /* TODO
+        $this->view->searchClassId = $this->searchClassId;
+        $this->view->flashMessenger = $this->_helper->flashMessenger;
+         */
+    }
+
+    /**
+     * Handle an advanced search
+     *
+     * @return ViewModel
+     */
+    public function advancedAction()
+    {
+        $view = new ViewModel();
+        $view->options = SearchOptions::getInstance($this->searchClassId);
+        if ($view->options->getAdvancedSearchAction() === false) {
+            throw new \Exception('Advanced search not supported.');
+        }
+
+        // Handle request to edit existing saved search:
+        $view->saved = false;
+        $searchId = $this->getRequest()->query()->get('edit', false);
+        if ($searchId !== false) {
+            $view->saved = $this->restoreAdvancedSearch($searchId);
+        }
+
+        return $view;
+    }
+
+    /**
+     * Send search results to results view
+     *
+     * @return ViewModel
+     */
+    public function resultsAction()
+    {
+        $view = new ViewModel();
+
+        // Handle saved search requests:
+        $savedId = $this->getRequest()->query()->get('saved', false);
+        if ($savedId !== false) {
+            return $this->redirectToSavedSearch($savedId);
+        }
+
+        $paramsClass = $this->getParamsClass();
+        $params = new $paramsClass();
+        $params->recommendationsEnabled(true);
+        $params->initFromRequest($this->getRequest());
+        // Attempt to perform the search; if there is a problem, inspect any Solr
+        // exceptions to see if we should communicate to the user about them.
+        try {
+            $resultsClass = $this->getResultsClass();
+            $results = new $resultsClass($params);
+
+            // Explicitly execute search within controller -- this allows us to
+            // catch exceptions more reliably:
+            $results->performAndProcessSearch();
+
+            // If a "jumpto" parameter is set, deal with that now:
+            if ($jump = $this->processJumpTo($results)) {
+                return $jump;
+            }
+
+            // Send results to the view and remember the current URL as the last
+            // search.
+            $view->results = $results;
+            /* TODO
+            if ($this->rememberSearch) {
+                Memory::rememberSearch(
+                    $this->view->url() . $results->getUrl()->getParams(false)
+                );
+            }
+             */
+
+            /* TODO
+            // Add to search history:
+            if ($this->saveToHistory) {
+                $history = new VuFind_Model_Db_Search();
+                $history->saveSearch(
+                    $results,
+                    $history->getSearches(
+                        Zend_Session::getId(),
+                        isset($this->user->id) ? $this->user->id : null
+                    )
+                );
+            }
+             */
+
+            // Set up results scroller:
+            if ($this->useResultScroller) {
+                $scroller = new ResultScroller();
+                $scroller->init($results);
+            }
+        } catch (\Exception $e) {
+            // If it's a parse error or the user specified an invalid field, we
+            // should display an appropriate message:
+            if (method_exists($e, 'isParseError') && $e->isParseError()) {
+                $view->parseError = true;
+
+                // We need to create and process an "empty results" object to
+                // ensure that recommendation modules and templates behave
+                // properly when displaying the error message.
+                $view->results = new VF_Search_Empty_Results($params);
+                $view->results->performAndProcessSearch();
+            } else {
+                // Unexpected error -- let's throw this up to the next level.
+                throw $e;
+            }
+        }
+        /* TODO
+        // Save statistics:
+        if ($this->logStatistics) {
+            $statController = new VF_Statistics_Search();
+            $statController->log($results, $this->getRequest());
+        }
+         */
+
+        /* TODO
+        // Special case: If we're in RSS view, we need to render differently:
+        if ($this->view->results->getView() == 'rss') {
+            $this->_helper->viewRenderer->setNoRender();
+            $this->_helper->layout->disableLayout();
+            header('Content-type: text/xml', true);
+            echo $this->view->ResultFeed($this->view->results)->export('rss');
+        }
+         */
+        return $view;
+    }
+
+    /**
+     * Process the jumpto parameter -- either redirect to a specific record and
+     * return view model, or ignore the parameter and return false.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object.
+     *
+     * @return bool|ViewModel
+     */
+    protected function processJumpTo($results)
+    {
+        // Missing/invalid parameter?  Ignore it:
+        $jumpto = $this->getRequest()->query()->get('jumpto');
+        if (empty($jumpto) || !is_numeric($jumpto)) {
+            return false;
+        }
+
+        // Parameter out of range?  Ignore it:
+        $recordList = $results->getResults();
+        if (!isset($recordList[$jumpto - 1])) {
+            return false;
+        }
+
+        // If we got this far, we have a valid parameter so we should redirect
+        // and report success:
+        return $this->redirect()->toRoute(
+            $recordList[$jumpto - 1]->getRecordRoute(),
+            array('id' => $recordList[$jumpto - 1]->getUniqueId())
+        );
+    }
+
+    /**
+     * Get the name of the class used for setting search parameters.
+     *
+     * @return string
+     */
+    protected function getParamsClass()
+    {
+        return 'VuFind\\Search\\' . $this->searchClassId . '\\Params';
+    }
+
+    /**
+     * Get the name of the class used for retrieving search results.
+     *
+     * @return string
+     */
+    protected function getResultsClass()
+    {
+        return 'VuFind\\Search\\' . $this->searchClassId . '\\Results';
+    }
+
+    /**
+     * Either assign the requested search object to the view or display a flash
+     * message indicating why the operation failed.
+     *
+     * @param string $searchId ID value of a saved advanced search.
+     *
+     * @return bool|object     Restored search object if found, false otherwise.
+     */
+    protected function restoreAdvancedSearch($searchId)
+    {
+        /* TODO
+        // Look up search in database and fail if it is not found:
+        $searchTable = new VuFind_Model_Db_Search();
+        $rows = $searchTable->find($searchId);
+        if (count($rows) < 1) {
+            $this->_helper->flashMessenger->setNamespace('error')
+                ->addMessage('advSearchError_notFound');
+            return false;
+        }
+        $search = $rows->getRow(0);
+
+        // Fail if user has no permission to view this search:
+        if ($search->session_id != Zend_Session::getId()
+            && $search->user_id != $this->user->id
+        ) {
+            $this->_helper->flashMessenger->setNamespace('error')
+                ->addMessage('advSearchError_noRights');
+            return false;
+        }
+
+        // Restore the full search object:
+        $minSO = unserialize($search->search_object);
+        $savedSearch = $minSO->deminify();
+
+        // Fail if this is not the right type of search:
+        if ($savedSearch->getSearchType() != 'advanced') {
+            $this->_helper->flashMessenger->setNamespace('error')
+                ->addMessage('advSearchError_notAdvanced');
+            return false;
+        }
+
+        // Activate facets so we get appropriate descriptions in the filter list:
+        $savedSearch->activateAllFacets('Advanced');
+
+        // Make the object available to the view:
+        return $savedSearch;
+         */
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Controller/SearchController.php b/module/VuFind/src/VuFind/Controller/SearchController.php
index b10f0460dda..90ea464118a 100644
--- a/module/VuFind/src/VuFind/Controller/SearchController.php
+++ b/module/VuFind/src/VuFind/Controller/SearchController.php
@@ -28,7 +28,7 @@
 namespace VuFind\Controller;
 
 use VuFind\Cache\Manager as CacheManager, VuFind\Search\Solr\Params,
-    VuFind\Search\Solr\Results, Zend\Mvc\Controller\ActionController;
+    VuFind\Search\Solr\Results;
 
 /**
  * Redirects the user to the appropriate default VuFind action.
@@ -39,7 +39,7 @@ use VuFind\Cache\Manager as CacheManager, VuFind\Search\Solr\Params,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org   Main Site
  */
-class SearchController extends ActionController
+class SearchController extends AbstractSearch
 {
     /**
      * Home action
-- 
GitLab