From 04ee379af86a9f1b3f6df43163e2a359b3c468cc Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Wed, 5 Sep 2012 10:14:41 -0400
Subject: [PATCH] Introduced \VuFind\Search\Manager; began using it to replace
 \VuFind\Search\Options (refactoring still in progress).

---
 module/VuFind/config/module.config.php        |   7 +
 .../src/VuFind/Autocomplete/PluginManager.php |   5 +-
 module/VuFind/src/VuFind/Bootstrap.php        |   6 +
 module/VuFind/src/VuFind/Search/Manager.php   | 234 ++++++++++++++++++
 .../Theme/Root/Helper/SearchOptions.php       |   8 +-
 5 files changed, 254 insertions(+), 6 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/Search/Manager.php

diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 5455e0ddf04..ef74c507cfc 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -138,6 +138,13 @@ $config = array(
             'result-scroller' => 'VuFind\Controller\Plugin\ResultScroller',
         )
     ),
+    'search_manager' => array(
+        'default_namespace' => 'VuFind\Search',
+        'namespaces_by_id' => array(
+        ),
+        'aliases' => array(
+        ),
+    ),
     'service_manager' => array(
         'invokables' => array(
             'authmanager' => 'VuFind\Auth\Manager',
diff --git a/module/VuFind/src/VuFind/Autocomplete/PluginManager.php b/module/VuFind/src/VuFind/Autocomplete/PluginManager.php
index dff684fc82f..b8054da88f1 100644
--- a/module/VuFind/src/VuFind/Autocomplete/PluginManager.php
+++ b/module/VuFind/src/VuFind/Autocomplete/PluginManager.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/creating_a_session_handler Wiki
  */
 namespace VuFind\Autocomplete;
-use VuFind\Config\Reader as ConfigReader, VuFind\Search\Options as SearchOptions;
+use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Autocomplete handler plugin manager
@@ -73,7 +73,8 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
 
         // get Autocomplete_Type config
         $searcher = $request->get('searcher', 'Solr');
-        $options = SearchOptions::getInstance($searcher);
+        $options = $this->getServiceLocator()->get('SearchManager')
+            ->setSearchClassId($searcher)->getOptionsInstance();
         $config = ConfigReader::getConfig($options->getSearchIni());
         $types = isset($config->Autocomplete_Types) ?
             $config->Autocomplete_Types->toArray() : array();
diff --git a/module/VuFind/src/VuFind/Bootstrap.php b/module/VuFind/src/VuFind/Bootstrap.php
index 6fc202d5700..1cfaf0c9cac 100644
--- a/module/VuFind/src/VuFind/Bootstrap.php
+++ b/module/VuFind/src/VuFind/Bootstrap.php
@@ -103,6 +103,12 @@ class Bootstrap
             }
             $serviceManager->setService($serviceName, $service);
         }
+
+        // Set up search manager a little differently -- it is a more complex class
+        // that doesn't work like the other standard plugin managers.
+        $manager = new  \VuFind\Search\Manager($config['search_manager']);
+        $manager->setServiceLocator($serviceManager);
+        $serviceManager->setService('SearchManager', $manager);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Search/Manager.php b/module/VuFind/src/VuFind/Search/Manager.php
new file mode 100644
index 00000000000..9bce7153e79
--- /dev/null
+++ b/module/VuFind/src/VuFind/Search/Manager.php
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Class for managing search (options/params/results) objects.
+ *
+ * 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  Search
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org   Main Site
+ */
+namespace VuFind\Search;
+use Zend\ServiceManager\ServiceLocatorAwareInterface,
+    Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Class for managing search (options/params/results) objects.
+ *
+ * @category VuFind2
+ * @package  Search
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org   Main Site
+ */
+class Manager implements ServiceLocatorAwareInterface
+{
+    protected $config;
+    protected $classId = 'Solr';
+    protected $optionsStore = array();
+
+    /**
+     * Constructor
+     *
+     * @param array $config Configuration from VuFind module
+     */
+    public function __construct($config)
+    {
+        $this->config = $config;
+    }
+
+    /**
+     * Set the search class ID to load.  Implements a fluent interface.
+     *
+     * @param string $id Search class ID
+     *
+     * @return Manager
+     */
+    public function setSearchClassId($id)
+    {
+        $this->classId = $id;
+        return $this;
+    }
+
+    /**
+     * Get the namespace for the current search class ID.
+     *
+     * @return string
+     */
+    public function getNamespace()
+    {
+        // Process aliases first:
+        $key = isset($this->config['aliases'][$this->classId])
+            ? $this->config['aliases'][$this->classId] : $this->classId;
+
+
+        // If we have an explicit namespace configuration, use that next:
+        if (isset($this->config['namespaces_by_id'][$key])) {
+            return $this->config['namespaces_by_id'][$key];
+        }
+
+        // Use default namespace if we got this far:
+        $ns = isset($this->config['default_namespace'])
+            ? $this->config['default_namespace'] : 'VuFind\Search';
+        return $ns . '\\' . $this->classId;
+    }
+
+    /**
+     * Get the options class name for the current search class ID.
+     *
+     * @return string
+     */
+    public function getOptionsClass()
+    {
+        return $this->getNamespace() . '\Options';
+    }
+
+    /**
+     * Get the params class name for the current search class ID.
+     *
+     * @return string
+     */
+    public function getParamsClass()
+    {
+        return $this->getNamespace() . '\Params';
+    }
+
+    /**
+     * Get the results class name for the current search class ID.
+     *
+     * @return string
+     */
+    public function getResultsClass()
+    {
+        return $this->getNamespace() . '\Results';
+    }
+
+    /**
+     * Inject dependencies into an object.
+     *
+     * @param object $obj Object to inject.
+     *
+     * @return void
+     */
+    protected function injectDependencies($obj)
+    {
+        if ($obj instanceof ServiceLocatorAwareInterface) {
+            $obj->setServiceLocator($this->getServiceLocator());
+        }
+    }
+
+    /**
+     * Get an options instance for the current search class ID.
+     *
+     * @return \VuFind\Search\Base\Options
+     */
+    public function getOptionsInstance()
+    {
+        /* TODO -- uncomment this when \VuFind\Search\Options has been factored out
+        if (!isset($this->optionsStore[$this->classId])) {
+            $class = $this->getOptionsClass();
+            $this->optionsStore[$this->classId] = new $class();
+            if (!($this->optionsStore[$this->classId] instanceof Base\Options)) {
+                throw new \Exception('Invalid options object.');
+            }
+            $this->injectDependencies($this->optionsStore[$this->classId]);
+        }
+        return $this->optionsStore[$this->classId];
+         */
+        return Options::getInstance($this->classId);
+    }
+
+    /**
+     * Get a parameters object for the current search class ID.
+     *
+     * @param \VuFind\Search\Base\Options $options Search options to load (null for
+     * defaults).
+     *
+     * @return VuFind\Search\Base\Params
+     */
+    public function getParams($options = null)
+    {
+        $class = $this->getParamsClass();
+        $params = new $class($options);
+        if (!($params instanceof \VuFind\Search\Base\Params)) {
+            throw new \Exception('Invalid params object.');
+        }
+        $this->injectDependencies($params);
+        return $params;
+    }
+
+    /**
+     * Get a results object for the current search class ID.
+     *
+     * @param \VuFind\Search\Base\Params $params Search parameters to load.
+     *
+     * @return VuFind\Search\Base\Results
+     */
+    public function getResults($params = null)
+    {
+        $class = $this->getResultsClass();
+        if (null === $params) {
+            $params = $this->getParams();
+        }
+        $results = new $class($params);
+        if (!($results instanceof \VuFind\Search\Base\Results)) {
+            throw new \Exception('Invalid results object.');
+        }
+        $this->injectDependencies($results);
+        return $results;
+    }
+
+    /**
+     * Extract the name of the search class family from a class name.
+     *
+     * @param string $className Class name to examine.
+     *
+     * @return string
+     */
+    public function extractSearchClassId($className)
+    {
+        // Parse identifier out of class name of format VuFind\Search\[id]\Params:
+        $class = explode('\\', $className);
+        return $class[2];
+    }
+
+    /**
+     * Set the service locator.
+     *
+     * @param ServiceLocatorInterface $serviceLocator Locator to register
+     *
+     * @return Manager
+     */
+    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
+    {
+        $this->serviceLocator = $serviceLocator;
+        return $this;
+    }
+
+    /**
+     * Get the service locator.
+     *
+     * @return \Zend\ServiceManager\ServiceLocatorInterface
+     */
+    public function getServiceLocator()
+    {
+        return $this->serviceLocator;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Theme/Root/Helper/SearchOptions.php b/module/VuFind/src/VuFind/Theme/Root/Helper/SearchOptions.php
index 5b796e3bc47..e93c7a92d0c 100644
--- a/module/VuFind/src/VuFind/Theme/Root/Helper/SearchOptions.php
+++ b/module/VuFind/src/VuFind/Theme/Root/Helper/SearchOptions.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
  */
 namespace VuFind\Theme\Root\Helper;
-use VuFind\Search\Options, Zend\View\Helper\AbstractHelper;
 
 /**
  * "Retrieve search options" view helper
@@ -37,10 +36,10 @@ use VuFind\Search\Options, Zend\View\Helper\AbstractHelper;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
  */
-class SearchOptions extends AbstractHelper
+class SearchOptions extends AbstractServiceLocator
 {
     /**
-     * Wrapper function to the \VuFind\Search\Options getInstance function
+     * Wrapper to the search manager's getOptionsInstance method
      *
      * @param string $type The search type of the object to retrieve
      *
@@ -48,6 +47,7 @@ class SearchOptions extends AbstractHelper
      */
     public function __invoke($type = 'Solr')
     {
-        return Options::getInstance($type);
+        return $this->getServiceLocator()->get('SearchManager')
+            ->setSearchClassId($type)->getOptionsInstance();
     }
 }
\ No newline at end of file
-- 
GitLab