From 837835727f21f16a4192e2418dd4c84f9807e566 Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Tue, 3 Jul 2012 11:03:39 -0400
Subject: [PATCH] Namespaced recommendation modules (not tested yet).

---
 .../src/VuFind/Recommend/AuthorFacets.php     | 149 ++++++
 .../src/VuFind/Recommend/AuthorInfo.php       | 440 ++++++++++++++++++
 .../VuFind/Recommend/AuthorityRecommend.php   | 191 ++++++++
 .../src/VuFind/Recommend/CatalogResults.php   |  53 +++
 .../src/VuFind/Recommend/EuropeanaResults.php | 196 ++++++++
 .../Recommend/EuropeanaResultsDeferred.php    | 121 +++++
 .../src/VuFind/Recommend/ExpandFacets.php     | 122 +++++
 .../src/VuFind/Recommend/FavoriteFacets.php   |  54 +++
 .../VuFind/Recommend/OpenLibrarySubjects.php  | 196 ++++++++
 .../Recommend/OpenLibrarySubjectsDeferred.php | 137 ++++++
 .../src/VuFind/Recommend/PubDateVisAjax.php   | 186 ++++++++
 .../VuFind/Recommend/RecommendInterface.php   |  87 ++++
 .../VuFind/Recommend/ResultGoogleMapAjax.php  | 118 +++++
 .../src/VuFind/Recommend/SearchObject.php     | 123 +++++
 .../src/VuFind/Recommend/SideFacets.php       | 161 +++++++
 .../src/VuFind/Recommend/SummonDatabases.php  | 116 +++++
 .../src/VuFind/Recommend/SummonResults.php    |  52 +++
 .../src/VuFind/Recommend/SwitchType.php       | 126 +++++
 .../VuFind/src/VuFind/Recommend/TopFacets.php | 135 ++++++
 .../VuFind/Recommend/WorldCatIdentities.php   | 109 +++++
 .../src/VuFind/Recommend/WorldCatTerms.php    | 123 +++++
 21 files changed, 2995 insertions(+)
 create mode 100644 module/VuFind/src/VuFind/Recommend/AuthorFacets.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/AuthorInfo.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/AuthorityRecommend.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/CatalogResults.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/EuropeanaResults.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/EuropeanaResultsDeferred.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/ExpandFacets.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/FavoriteFacets.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/OpenLibrarySubjects.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/OpenLibrarySubjectsDeferred.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/PubDateVisAjax.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/RecommendInterface.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/SearchObject.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/SideFacets.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/SummonDatabases.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/SummonResults.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/SwitchType.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/TopFacets.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/WorldCatIdentities.php
 create mode 100644 module/VuFind/src/VuFind/Recommend/WorldCatTerms.php

diff --git a/module/VuFind/src/VuFind/Recommend/AuthorFacets.php b/module/VuFind/src/VuFind/Recommend/AuthorFacets.php
new file mode 100644
index 00000000000..18fd6e97e65
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/AuthorFacets.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * AuthorFacets Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @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
+ */
+namespace VuFind\Recommend;
+use VuFind\Search\SolrAuthorFacets\Options as SolrAuthorFacetsOptions,
+    VuFind\Search\SolrAuthorFacets\Params as SolrAuthorFacetsParams,
+    VuFind\Search\SolrAuthorFacets\Results as SolrAuthorFacetsResults,
+    Zend\Http\Request, Zend\StdLib\Parameters;
+
+/**
+ * AuthorFacets Recommendations Module
+ *
+ * This class provides recommendations displaying authors on top of the page. Default
+ * on author searches.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @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 AuthorFacets implements RecommendInterface
+{
+    protected $settings;
+    protected $searchObject;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Save the basic parameters:
+        $this->settings = $settings;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // No action needed here.
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->results = $results;
+    }
+
+    /**
+     * Returns search term.
+     *
+     * @return string
+     */
+    public function getSearchTerm()
+    {
+        $search = $this->results->getSearchTerms();
+        if (isset($search[0]['lookfor'])) {
+            return $search[0]['lookfor'];
+        }
+        return '';
+    }
+
+    /**
+     * Process similar authors from an author search
+     *
+     * @return  array     Facets data arrays
+     */
+    public function getSimilarAuthors()
+    {
+        // Do not provide recommendations for blank searches:
+        $lookfor = $this->getSearchTerm();
+        if (empty($lookfor)) {
+            return array('count' => 0, 'list' => array());
+        }
+
+        // Set up a special limit for the AuthorFacets search object:
+        $options = new SolrAuthorFacetsOptions();
+        $options->setLimitOptions(array(10));
+
+        // Initialize an AuthorFacets search object using parameters from the
+        // current Solr search object.
+        $request = new Request();
+        $request->setQuery(new Parameters(array('lookfor' => $lookfor));
+        $params = new SolrAuthorFacetsParams($options);
+        $params->initFromRequest($request);
+
+        // Send back the results:
+        $results = new SolrAuthorFacetsResults($params);
+        return array(
+            // Total authors (currently there is no way to calculate this without
+            // risking out-of-memory errors or slow results, so we set this to
+            // false; if we are able to find this information out in the future,
+            // we can fill it in here and the templates will display it).
+            'count' => false,
+            'list' => $results->getResults()
+        );
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/AuthorInfo.php b/module/VuFind/src/VuFind/Recommend/AuthorInfo.php
new file mode 100644
index 00000000000..5161dfc19b8
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/AuthorInfo.php
@@ -0,0 +1,440 @@
+<?php
+/**
+ * AuthorInfo Recommendations Module
+ *
+ * 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  Recommendations
+ * @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
+ */
+namespace VuFind\Recommend;
+use VuFind\Config\Reader as ConfigReader, VuFind\Http\Client as HttpClient,
+    VuFind\Translator\Translator;
+
+/**
+ * AuthorInfo Recommendations Module
+ *
+ * This class gathers information from the Wikipedia API and publishes the results
+ * to a module at the top of an author's results page
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ * @view     AuthorInfoFacets.phtml
+ */
+class AuthorInfo implements RecommendInterface
+{
+    protected $searchObject;
+    protected $lang;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        $this->lang = Zend_Registry::getInstance()
+            ->get('Zend_Translate')
+            ->getAdapter()->getLocale();
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // No action needed here.
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->searchObject = $results;
+    }
+
+    /**
+     * Returns info from Wikipedia to the view
+     *
+     * @reference _parseWikipedia : Home.php (VuFind 1)
+     * @refauthor Rushikesh Katikar <rushikesh.katikar@gmail.com>
+     *
+     * @return array info = {
+     *              'description' : string : extracted/formatted Wikipedia text
+     *              'image'       : string : url of the Wikipedia page's image
+     *              'altimge'     : string : alt text for the image
+     *              'name'        : string : title of Wikipedia article
+     *              'wiki_lang'   : string : truncated from the lang. settings
+     *           }
+     */
+    public function getAuthorInfo()
+    {
+        // Don't load Wikipedia content if Wikipedia is disabled:
+        $config = ConfigReader::getConfig();
+        if (!isset($config->Content->authors)
+            || !stristr($config->Content->authors, 'wikipedia')
+        ) {
+            return null;
+        }
+
+        return $this->getWikipedia($this->getAuthor());
+    }
+
+    /**
+     * getWikipedia
+     *
+     * This method is responsible for connecting to Wikipedia via the REST API
+     * and pulling the content for the relevant author.
+     *
+     * @param string $author The author name to search for
+     *
+     * @return array
+     */
+    protected function getWikipedia($author)
+    {
+        // Get information from Wikipedia API
+        $uri = 'http://' . $this->lang . '.wikipedia.org/w/api.php' .
+               '?action=query&prop=revisions&rvprop=content&format=php' .
+               '&list=allpages&titles=' . urlencode($author);
+
+        $client = new HttpClient();
+        $client->setUri($uri);
+        $response = $client->setMethod('GET')->send();
+
+        if ($response->isSuccess()) {
+            return $this->parseWikipedia(unserialize($response->getBody()));
+        }
+        return null;
+    }
+
+    /**
+     * _parseWikipedia
+     *
+     * This method is responsible for parsing the output from the Wikipedia
+     * REST API.
+     *
+     * @param string $body The Wikipedia response to parse
+     *
+     * @return array
+     * @author Rushikesh Katikar <rushikesh.katikar@gmail.com>
+     */
+    protected function parseWikipedia($body)
+    {
+        // Check if data exists or not
+        if (isset($body['query']['pages']['-1'])) {
+            return null;
+        }
+
+        // Get the default page
+        $body = array_shift($body['query']['pages']);
+        $info = array('name' => $body['title'], 'wiki_lang' => $this->lang);
+
+        // Get the latest revision
+        $body = array_shift($body['revisions']);
+        // Check for redirection
+        $as_lines = explode("\n", $body['*']);
+        if (stristr($as_lines[0], '#REDIRECT')) {
+            preg_match('/\[\[(.*)\]\]/', $as_lines[0], $matches);
+            return $this->getWikipedia($matches[1]);
+        }
+
+        /* Infobox */
+
+        // We are looking for the infobox inside "{{...}}"
+        //   It may contain nested blocks too, thus the recursion
+        preg_match_all('/\{([^{}]++|(?R))*\}/s', $body['*'], $matches);
+        // print "<p>".htmlentities($body['*'])."</p>\n";
+        foreach ($matches[1] as $m) {
+            // If this is the Infobox
+            if (substr($m, 0, 8) == "{Infobox") {
+                // Keep the string for later, we need the body block that follows it
+                $infoboxStr = "{".$m."}";
+                // Get rid of the last pair of braces and split
+                $infobox = explode("\n|", substr($m, 1, -1));
+                // Look through every row of the infobox
+                foreach ($infobox as $row) {
+                    $data  = explode("=", $row);
+                    $key   = trim(array_shift($data));
+                    $value = trim(join("=", $data));
+
+                    // At the moment we only want stuff related to the image.
+                    switch (strtolower($key)) {
+                    case "img":
+                    case "image":
+                    case "image:":
+                    case "image_name":
+                        $imageName = str_replace(' ', '_', $value);
+                        break;
+                    case "caption":
+                    case "img_capt":
+                    case "image_caption":
+                        $image_caption = $value;
+                        break;
+                    default:
+                        /* Nothing else... yet */
+                        break;
+                    }
+                }
+            }
+        }
+
+        /* Image */
+
+        // If we didn't successfully extract an image from the infobox, let's see if
+        // we can find one in the body -- we'll just take the first match:
+        if (!isset($imageName)) {
+            $pattern = '/(\x5b\x5b)Image:([^\x5d]*)(\x5d\x5d)/U';
+            preg_match_all($pattern, $body['*'], $matches);
+            if (isset($matches[2][0])) {
+                $parts = explode('|', $matches[2][0]);
+                $imageName = str_replace(' ', '_', $parts[0]);
+                if (count($parts) > 1) {
+                    $image_caption = strip_tags(
+                        preg_replace('/({{).*(}})/U', '', $parts[count($parts) - 1])
+                    );
+                }
+            }
+        }
+
+        // Given an image name found above, look up the associated URL:
+        if (isset($imageName)) {
+            $imageUrl = $this->getWikipediaImageURL($imageName);
+        }
+
+        /* Body */
+
+        if (isset($infoboxStr)) {
+            // Start of the infobox
+            $start  = strpos($body['*'], $infoboxStr);
+            // + the length of the infobox
+            $offset = strlen($infoboxStr);
+            // Every after the infobox
+            $body   = substr($body['*'], $start + $offset);
+        } else {
+            // No infobox -- use whole thing:
+            $body = $body['*'];
+        }
+        // Find the first heading
+        $end    = strpos($body, "==");
+        // Now cull our content back to everything before the first heading
+        $body   = trim(substr($body, 0, $end));
+
+        // Remove unwanted image/file links
+        // Nested brackets make this annoying: We can't add 'File' or 'Image' as
+        //    mandatory because the recursion fails, or as optional because then
+        //    normal links get hit.
+        //    ... unless there's a better pattern? TODO
+        // eg. [[File:Johann Sebastian Bach.jpg|thumb|Bach in a 1748 portrait by
+        //     [[Elias Gottlob Haussmann|Haussmann]]]]
+        $open    = "\\[";
+        $close   = "\\]";
+        $content = "(?>[^\\[\\]]+)";  // Anything but [ or ]
+        // We can either find content or recursive brackets:
+        $recursive_match = "($content|(?R))*";
+        preg_match_all("/".$open.$recursive_match.$close."/Us", $body, $new_matches);
+        // Loop through every match (link) we found
+        if (is_array($new_matches)) {
+            foreach ($new_matches as $nm) {
+                // Might be an array of arrays
+                if (is_array($nm)) {
+                    foreach ($nm as $n) {
+                        // If it's a file link get rid of it
+                        if (strtolower(substr($n, 0, 7)) == "[[file:"
+                            || strtolower(substr($n, 0, 8)) == "[[image:"
+                        ) {
+                            $body = str_replace($n, "", $body);
+                        }
+                    }
+                } else {
+                    // Or just a normal array...
+                    // If it's a file link get rid of it
+                    if (strtolower(substr($n, 0, 7)) == "[[file:"
+                        || strtolower(substr($n, 0, 8)) == "[[image:"
+                    ) {
+                        $body = str_replace($nm, "", $body);
+                    }
+                }
+            }
+        }
+
+        // Initialize arrays of processing instructions
+        $pattern = array();
+        $replacement = array();
+
+        // Convert wikipedia links
+        $pattern[] = '/(\x5b\x5b)([^\x5d|]*)(\x5d\x5d)/Us';
+        $replacement[]
+            = '<a href="___baseurl___?lookfor=%22$2%22&amp;type=AllFields">$2</a>';
+        $pattern[] = '/(\x5b\x5b)([^\x5d]*)\x7c([^\x5d]*)(\x5d\x5d)/Us';
+        $replacement[]
+            = '<a href="___baseurl___?lookfor=%22$2%22&amp;type=AllFields">$3</a>';
+
+        // Fix pronunciation guides
+        $pattern[] = '/({{)pron-en\|([^}]*)(}})/Us';
+        $replacement[] = Translator::translate("pronounced") . " /$2/";
+
+        // Fix dashes
+        $pattern[] = '/{{ndash}}/';
+        $replacement[] = ' - ';
+
+        // Removes citations
+        $pattern[] = '/({{)[^}]*(}})/Us';
+        $replacement[] = "";
+        //  <ref ... > ... </ref> OR <ref> ... </ref>
+        $pattern[] = '/<ref[^\/]*>.*<\/ref>/Us';
+        $replacement[] = "";
+        //    <ref ... />
+        $pattern[] = '/<ref.*\/>/Us';
+        $replacement[] = "";
+
+        // Removes comments followed by carriage returns to avoid excess whitespace
+        $pattern[] = '/<!--.*-->\n*/Us';
+        $replacement[] = '';
+
+        // Formatting
+        $pattern[] = "/'''([^']*)'''/Us";
+        $replacement[] = '<strong>$1</strong>';
+
+        // Trim leading newlines (which can result from leftovers after stripping
+        // other items above).  We want this to be greedy.
+        $pattern[] = '/^\n*/s';
+        $replacement[] = '';
+
+        // Convert multiple newlines into two breaks
+        // We DO want this to be greedy
+        $pattern[] = "/\n{2,}/s";
+        $replacement[] = '<br/><br/>';
+
+        $body = preg_replace($pattern, $replacement, $body);
+
+        if (isset($imageUrl) && $imageUrl != false) {
+            $info['image'] = $imageUrl;
+            if (isset($image_caption)) {
+                $info['altimage'] = $image_caption;
+            }
+        }
+        $info['description'] = $body;
+
+        return $info;
+    }
+
+    /**
+     * Takes the search term and extracts a normal name from it
+     *
+     * @return string
+     */
+    protected function getAuthor()
+    {
+        $search = $this->searchObject->getSearchTerms();
+        if (isset($search[0]['lookfor'])) {
+            $author = $search[0]['lookfor'];
+            // remove quotes
+            $author = str_replace('"', '', $author);
+            // remove dates
+            $author = preg_replace('/[0-9]+-[0-9]*/', '', $author);
+            // if name is rearranged by commas
+            $author = trim($author, ', .');
+            $nameParts = explode(', ', $author);
+            $last = $nameParts[0];
+            // - move all names up an index, move last name to last
+            // - Last, First M. -> First M. Last
+            for ($i=1;$i<count($nameParts);$i++) {
+                $nameParts[$i-1] = $nameParts[$i];
+            }
+            $nameParts[count($nameParts)-1] = $last;
+            $author = implode($nameParts, ' ');
+            // remove punctuation
+            return $author;
+        }
+        return '';
+    }
+
+    /**
+     * This method is responsible for obtaining an image URL based on a name.
+     *
+     * @param string $imageName The image name to look up
+     *
+     * @return mixed            URL on success, false on failure
+     */
+    protected function getWikipediaImageURL($imageName)
+    {
+        $url = "http://{$this->lang}.wikipedia.org/w/api.php" .
+               '?prop=imageinfo&action=query&iiprop=url&iiurlwidth=150&format=php' .
+               '&titles=Image:' . urlencode($imageName);
+
+        $client = new HttpClient();
+        try {
+            $client->setUri($url);
+            $result = $client->setMethod('GET')->send();
+        } catch (\Exception $e) {
+            return false;
+        }
+        if (!$result->isSuccess()) {
+            return false;
+        }
+
+        if ($response = $result->getBody()) {
+            if ($imageinfo = unserialize($response)) {
+                if (isset($imageinfo['query']['pages']['-1']['imageinfo'][0]['url'])
+                ) {
+                    $imageUrl
+                        = $imageinfo['query']['pages']['-1']['imageinfo'][0]['url'];
+                }
+
+                // Hack for wikipedia api, just in case we couldn't find it
+                //   above look for a http url inside the response.
+                if (!isset($imageUrl)) {
+                    preg_match('/\"http:\/\/(.*)\"/', $response, $matches);
+                    if (isset($matches[1])) {
+                        $imageUrl = 'http://' .
+                            substr($matches[1], 0, strpos($matches[1], '"'));
+                    }
+                }
+            }
+        }
+
+        return isset($imageUrl) ? $imageUrl : false;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/AuthorityRecommend.php b/module/VuFind/src/VuFind/Recommend/AuthorityRecommend.php
new file mode 100644
index 00000000000..70ca9635410
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/AuthorityRecommend.php
@@ -0,0 +1,191 @@
+<?php
+/**
+ * AuthorityRecommend Recommendations Module
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2012.
+ *
+ * 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  Recommendations
+ * @author   Lutz Biedinger (National Library of Ireland)
+ * <vufind-tech@lists.sourceforge.net>
+ * @author   Ronan McHugh (National Library of Ireland)
+ * <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Recommend;
+use VuFind\Search\SolrAuth\Params as SolrAuthParams,
+    VuFind\Search\SolrAuth\Results as SolrAuthResults,
+    Zend\Http\Request, Zend\StdLib\Parameters;
+
+/**
+ * AuthorityRecommend Module
+ *
+ * This class provides recommendations based on Authority records.
+ * i.e. searches for a pseudonym will provide the user with a link
+ * to the official name (according to the Authority index)
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Lutz Biedinger (National Library of Ireland)
+ * <vufind-tech@lists.sourceforge.net>
+ * @author   Ronan McHugh (National Library of Ireland)
+ * <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class AuthorityRecommend implements RecommendInterface
+{
+    protected $searchObject;
+    protected $lookfor;
+    protected $filters = array();
+    protected $results = array();
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        $params = explode(':', $settings);
+        for ($i = 0; $i < count($params); $i += 2) {
+            if (isset($params[$i+1])) {
+                $this->filters[] = $params[$i] . ':(' . $params[$i + 1] . ')';
+            }
+        }
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Save user search query:
+        $this->lookfor = $request->query()->get('lookfor');
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        // function will return blank on Advanced Search
+        if ($results->getSearchType()== 'advanced') {
+            return;
+        }
+
+        // Build an advanced search request that prevents Solr from retrieving
+        // records that would already have been retrieved by a search of the biblio
+        // core, i.e. it only returns results where $lookfor IS found in in the
+        // "Heading" search and IS NOT found in the "MainHeading" search defined
+        // in authsearchspecs.yaml.
+        $query = new Parameters(
+            array(
+                'join' => 'AND',
+                'bool0' => array('AND'),
+                'lookfor0' => array($this->lookfor),
+                'type0' => array('Heading'),
+                'bool1' => array('NOT'),
+                'lookfor1' => array($this->lookfor),
+                'type1' => array('MainHeading')
+            )
+        );
+        $request = new Request();
+        $request->setQuery($query);
+
+        // Initialise and process search:
+        $authParams = new SolrAuthParams();
+        $authParams->initFromRequest($request);
+        foreach ($this->filters as $filter) {
+            $authParams->addHiddenFilter($filter);
+        }
+        $authResults = new SolrAuthResults($authParams);
+
+        // loop through records and assign id and headings to separate arrays defined
+        // above
+        foreach ($authResults->getResults() as $result) {
+            // Extract relevant details:
+            $recordArray = array(
+                'id' => $result->getUniqueID(),
+                'heading' => $result->getBreadcrumb()
+            );
+
+            // check for duplicates before adding record to recordSet
+            if (!$this->inArrayR($recordArray['heading'], $this->results)) {
+                array_push($this->results, $recordArray);
+            } else {
+                continue;
+            }
+        }
+    }
+
+    /**
+     * Get results (for use in the view).
+     *
+     * @return array
+     */
+    public function getResults()
+    {
+        return $this->results;
+    }
+
+    /**
+     * inArrayR
+     *
+     * Helper function to do recursive searches of multi-dimensional arrays.
+     *
+     * @param string $needle   Search term
+     * @param array  $haystack Multi-dimensional array
+     *
+     * @return bool
+     */
+    public function inArrayR($needle, $haystack)
+    {
+        foreach ($haystack as $v) {
+            if ($needle == $v) {
+                return true;
+            } elseif (is_array($v)) {
+                if ($this->inArrayR($needle, $v)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/CatalogResults.php b/module/VuFind/src/VuFind/Recommend/CatalogResults.php
new file mode 100644
index 00000000000..5c621c7058d
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/CatalogResults.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * CatalogResults Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+
+/**
+ * CatalogResults Recommendations Module
+ *
+ * This class provides recommendations by doing a search of the catalog; useful
+ * for displaying catalog recommendations in other modules (i.e. Summon, Web, etc.)
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class CatalogResults extends SearchObject
+{
+    /**
+     * Get the search class ID to use for building search objects.
+     *
+     * @return string
+     */
+    protected function getSearchClassId()
+    {
+        return 'Solr';
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php b/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php
new file mode 100644
index 00000000000..1f2064cea33
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * EuropeanaResults Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Lutz Biedinger <lutz.biedinger@gmail.com>
+ * @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\Recommend;
+use VuFind\Config\Reader as ConfigReader;
+
+/**
+ * EuropeanaResults Recommendations Module
+ *
+ * This class provides recommendations by using the WorldCat Terminologies API.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Lutz Biedinger <lutz.biedinger@gmail.com>
+ * @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
+ */
+class EuropeanaResults implements RecommendInterface
+{
+    protected $requestParam;
+    protected $limit;
+    protected $baseUrl;
+    protected $targetUrl;
+    protected $excludeProviders;
+    protected $searchSite;
+    protected $sitePath;
+    protected $key;
+    protected $lookfor;
+    protected $results;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Parse out parameters:
+        $params = explode(':', $settings);
+        $this->baseUrl = (isset($params[0]) && !empty($params[0]))
+            ? $params[0] : 'api.europeana.eu/api/opensearch.rss';
+        $this->requestParam = (isset($params[1]) && !empty($params[1]))
+            ? $params[1] : 'searchTerms';
+        $this->limit = isset($params[2]) && is_numeric($params[2])
+                        && $params[2] > 0 ? intval($params[2]) : 5;
+        $this->excludeProviders = (isset($params[3]) && !empty($params[3]))
+            ? $params[3] : array();
+        //make array
+        if (!empty($this->excludeProviders)) {
+            $this->excludeProviders = explode(',', $this->excludeProviders);
+        }
+
+        //get the key from config.ini
+        $config = ConfigReader::getConfig();
+        $this->key = $config->Content->europeanaAPI;
+        $this->searchSite = "Europeana.eu";
+    }
+
+    /**
+     * getURL
+     *
+     * This method builds the url which will be send to retrieve the RSS results
+     *
+     * @param string $targetUrl        Base URL
+     * @param string $requestParam     Parameter name to add
+     * @param array  $excludeProviders An array of providers to exclude when
+     * getting results.
+     *
+     * @return string The url to be sent
+     */
+    protected function getURL($targetUrl, $requestParam, $excludeProviders)
+    {
+        // build url
+        $url = $targetUrl . "?" . $requestParam . "=" . $this->lookfor;
+        //add providers to ignore
+        foreach ($excludeProviders as $provider) {
+            $provider = trim($provider);
+            if (!empty($provider)) {
+                $url .= urlencode(' NOT europeana_dataProvider:"' . $provider . '"');
+            }
+        }
+        $url .= '&wskey=' . urlencode($this->key);
+
+        //return complete url
+        return $url;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Collect the best possible search term(s):
+        $this->lookfor =  $request->query()->get('lookfor', '');
+        if (empty($this->lookfor) && is_object($params)) {
+            $this->lookfor = $params->extractAdvancedTerms();
+        }
+        $this->lookfor = urlencode(trim($this->lookfor));
+        $this->sitePath = 'http://www.europeana.eu/portal/search.html?query=' .
+            $this->lookfor;
+        $this->targetUrl = $this->getURL(
+            'http://' . $this->baseUrl, $this->requestParam, $this->excludeProviders
+        );
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        /* TODO
+        Zend_Feed::setHttpClient(new VF_Http_Client());
+        $parsedFeed = Zend_Feed::import($this->targetUrl);
+        $resultsProcessed = array();
+        foreach ($parsedFeed as $key => $value) {
+            $link = (string)$value->link;
+            if (!empty($link)) {
+                $resultsProcessed[] = array(
+                    'title' => (string)$value->title,
+                    'link' => substr($link, 0, strpos($link, '.srw')) . '.html',
+                    'enclosure' => (string)$value->enclosure['url']
+                );
+            }
+            if (count($resultsProcessed) == $this->limit) {
+                break;
+            }
+        }
+
+        if (!empty($resultsProcessed)) {
+            $this->results = array(
+                'worksArray' => $resultsProcessed,
+                'feedTitle' => $this->searchSite,
+                'sourceLink' => $this->sitePath
+            );
+        } else {
+            $this->results = false;
+        }
+         */
+    }
+
+    /**
+     * Get the results of the query (false if none).
+     *
+     * @return array|bool
+     */
+    public function getResults()
+    {
+        return $this->results;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/EuropeanaResultsDeferred.php b/module/VuFind/src/VuFind/Recommend/EuropeanaResultsDeferred.php
new file mode 100644
index 00000000000..8b3f1c7da9e
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/EuropeanaResultsDeferred.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * EuropeanaResultsDeferred Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Lutz Biedinger <lutz.biedinger@gmail.com>
+ * @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\Recommend;
+
+/**
+ * EuropeanaResultsDeferred Recommendations Module
+ *
+ * This class sets up an AJAX call to trigger a call to the EuropeanaResults
+ * module.  
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Lutz Biedinger <lutz.biedigner@gmail.com>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
+ */
+class EuropeanaResultsDeferred implements RecommendInterface
+{
+    protected $rawParams;
+    protected $lookfor;
+    protected $processedParams;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        $this->rawParams = $settings;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Parse out parameters:
+        $settings = explode(':', $this->rawParams);
+
+        // Make sure all elements of the params array are filled in, even if just
+        // with a blank string, so we can rebuild the parameters to pass through
+        // AJAX later on!
+        for ($i = 0; $i < 4; $i++) {
+            $settings[$i] = isset($settings[$i]) ? $settings[$i] : '';
+        }
+
+        // Collect the best possible search term(s):
+        $this->lookfor =  $request->query()->get('lookfor', '');
+        if (empty($this->lookfor) && is_object($params)) {
+            $this->lookfor = $params->extractAdvancedTerms();
+        }
+        $this->lookfor = trim($this->lookfor);
+        $this->processedParams = implode(':', $settings);
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        // No action needed
+    }
+
+    /**
+     * Get the URL parameters needed to make the AJAX recommendation request.
+     *
+     * @return string
+     */
+    public function getUrlParams()
+    {
+        return 'mod=EuropeanaResults&params=' . urlencode($this->processedParams)
+            . '&lookfor=' . urlencode($this->lookfor);
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/ExpandFacets.php b/module/VuFind/src/VuFind/Recommend/ExpandFacets.php
new file mode 100644
index 00000000000..edf4765e078
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/ExpandFacets.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * ExpandFacets Module Controller
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) Villanova University 2011.
+ *
+ * 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  Recommendations
+ * @author   Mark Triggs <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Recommend;
+use VuFind\Config\Reader as ConfigReader;
+
+/**
+ * Recommendation class to expand recommendation interfaces
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class ExpandFacets implements RecommendInterface
+{
+    protected $facets;
+    protected $settings;
+    protected $searchObject;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Save the basic parameters:
+        $this->settings = $settings;
+        
+        // Parse the additional settings:
+        $settings = explode(':', $settings);
+        $mainSection = empty($settings[0]) ? 'Results' : $settings[0];
+        $checkboxSection = isset($settings[1]) ? $settings[1] : false;
+        $iniName = isset($settings[2]) ? $settings[2] : 'facets';
+
+        // Load the desired facet information...
+        $config = ConfigReader::getConfig($iniName);
+
+        // All standard facets to display:
+        $this->facets = isset($config->$mainSection) ?
+            $config->$mainSection->toArray() : array();
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Turn on side facets in the search results:
+        foreach ($this->facets as $name => $desc) {
+            $params->addFacet($name, $desc);
+        }
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->searchObject = $results;
+    }
+
+    /**
+     * process
+     *
+     * Called after the SearchObject has performed its main search.  This may be
+     * used to extract necessary information from the SearchObject or to perform
+     * completely unrelated processing.
+     *
+     * @return void
+     */
+    public function getExpandedSet()
+    {
+        return $this->searchObject->getFacetList($this->facets);
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/FavoriteFacets.php b/module/VuFind/src/VuFind/Recommend/FavoriteFacets.php
new file mode 100644
index 00000000000..a05df435463
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/FavoriteFacets.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * FavoriteFacets Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+
+/**
+ * FavoriteFacets Recommendations Module
+ *
+ * This class provides special facets for the Favorites area (tags/lists)
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class FavoriteFacets extends SideFacets
+{
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        $this->mainFacets = array('lists' => 'Your Lists', 'tags' => 'Your Tags');
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/OpenLibrarySubjects.php b/module/VuFind/src/VuFind/Recommend/OpenLibrarySubjects.php
new file mode 100644
index 00000000000..60bfa42612a
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/OpenLibrarySubjects.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * OpenLibrarySubjects Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Eoghan Ó Carragáin <eoghan.ocarragain@gmail.com>
+ * @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\Recommend;
+use VuFind\Connection\OpenLibrary, VuFind\Solr\Utils as SolrUtils;
+
+/**
+ * OpenLibrarySubjects Recommendations Module
+ *
+ * This class provides recommendations by doing a search of the catalog; useful
+ * for displaying catalog recommendations in other modules (i.e. Summon, Web, etc.)
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Eoghan Ó Carragáin <eoghan.ocarragain@gmail.com>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
+ */
+class OpenLibrarySubjects implements RecommendInterface
+{
+    protected $requestParam;
+    protected $limit;
+    protected $pubFilter;
+    protected $publishedIn = '';
+    protected $subject;
+    protected $subjectTypes;
+    protected $result = false;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Parse out parameters:
+        $params = explode(':', $settings);
+        $this->requestParam = empty($params[0]) ? 'lookfor' : $params[0];
+        $this->limit = isset($params[1]) && is_numeric($params[1]) && $params[1] > 0
+            ? intval($params[1]) : 5;
+        $this->pubFilter = (!isset($params[2]) || empty($params[2])) ?
+            'publishDate' : $params[2];
+        if (strtolower(trim($this->pubFilter)) == 'false') {
+            $this->pubFilter = false;
+        }
+
+        if (isset($params[3])) {
+            $this->subjectTypes = explode(',', $params[3]);
+        } else {
+            $this->subjectTypes = array("topic");
+        }
+
+        // A 4th parameter is not specified in searches.ini, if it exists
+        //     it has been passed in by an AJAX call and carries the
+        //     publication date range in the form YYYY-YYYY
+        if (isset($params[4]) && strstr($params[4], '-') != false) {
+            $this->publishedIn = $params[4];
+        }
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Get and normalise $requestParam
+        $this->subject =  $request->query()->get($this->requestParam);
+
+        // Set up the published date range if it has not already been provided:
+        if (empty($this->publishedIn) && $this->pubFilter) {
+            $this->publishedIn = $this->getPublishedDates(
+                $this->pubFilter, $params, $request
+            );
+        }
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        // Only proceed if we have a request parameter value
+        if (!empty($this->subject)) {
+            $result = array();
+            $ol = new OpenLibrary();
+            $result = $ol->getSubjects(
+                $this->subject, $this->publishedIn, $this->subjectTypes, true, false,
+                $this->limit, null, true
+            );
+
+            if (!empty($result)) {
+                $this->result = array(
+                    'worksArray' => $result, 'subject' => $this->subject
+                );
+            }
+        }
+    }
+
+    /**
+     * Support function to get publication date range. Return string in the form
+     * "YYYY-YYYY"
+     *
+     * @param string                     $field   Name of filter field to check for
+     * date limits
+     * @param \VuFind\Search\Params\Base $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return string
+     * @access protected
+     */
+    protected function getPublishedDates($field, $params, $request)
+    {
+        // Try to extract range details from request parameters or SearchObject:
+        $from = $request->query()->get($field . 'from');
+        $to = $request->query()->get($field . 'to');
+        if (!is_null($from) && !is_null($to)) {
+            $range = array('from' => $from, 'to' => $to);
+        } else if (is_object($params)) {
+            $currentFilters = $params->getFilters();
+            if (isset($currentFilters[$field][0])) {
+                $range = SolrUtils::parseRange($currentFilters[$field][0]);
+            }
+        }
+
+        // Normalize range if we found one:
+        if (isset($range)) {
+            if (empty($range['from']) || $range['from'] == '*') {
+                $range['from'] = 0;
+            }
+            if (empty($range['to']) || $range['to'] == '*') {
+                $range['to'] = date('Y') + 1;
+            }
+            return $range['from'] . '-' . $range['to'];
+        }
+
+        // No range found?  Return empty string:
+        return '';
+    }
+
+    /**
+     * Get the results of the subject query -- false if none, otherwise an array
+     * with 'worksArray' and 'subject' keys.
+     *
+     * @return bool|array
+     */
+    public function getResult()
+    {
+        return $this->result;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/OpenLibrarySubjectsDeferred.php b/module/VuFind/src/VuFind/Recommend/OpenLibrarySubjectsDeferred.php
new file mode 100644
index 00000000000..31fc6157805
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/OpenLibrarySubjectsDeferred.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * OpenLibrarySubjects Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Eoghan Ó Carragáin <eoghan.ocarragain@gmail.com>
+ * @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\Recommend;
+
+/**
+ * OpenLibrarySubjects Recommendations Module
+ *
+ * This class provides recommendations by doing a search of the catalog; useful
+ * for displaying catalog recommendations in other modules (i.e. Summon, Web, etc.)
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Eoghan Ó Carragáin <eoghan.ocarragain@gmail.com>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
+ */
+class OpenLibrarySubjectsDeferred extends OpenLibrarySubjects
+{
+    protected $rawParams;
+    protected $processedParams;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        $this->rawParams = $settings;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Parse out parameters:
+        $settings = explode(':', $this->rawParams);
+        $this->requestParam = empty($settings[0]) ? 'lookfor' : $settings[0];
+        $settings[0] = $this->requestParam;
+
+        // Make sure all elements of the params array are filled in, even if just
+        // with a blank string, so we can rebuild the parameters to pass through
+        // AJAX later on!
+        $settings[1] = isset($settings[1]) ? $settings[1] : '';
+
+        // If Publication Date filter is to be applied, get the range and add it to
+        //    $settings since the $searchObject will not be available after the AJAX
+        //    call
+        if (!isset($settings[2]) || empty($settings[2])) {
+            $settings[2] = 'publishDate';
+        }
+        $pubDateRange = strtolower($settings[2]) == 'false' ?
+            array() : $this->getPublishedDates($settings[2], $params, $request);
+        if (!empty($pubDateRange)) {
+            // Check if [Subject types] parameter has been supplied in searches.ini
+            if (!isset($settings[3])) {
+                $settings[3] = '';
+            }
+            $settings[4] = $pubDateRange;
+        }
+
+        $this->processedParams = implode(':', $settings);
+
+        // Collect the best possible search term(s):
+        $this->subject =  $request->query()->get($this->requestParam);
+        if (empty($this->subject) && is_object($params)) {
+            $this->subject = $params->extractAdvancedTerms();
+        }
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        // No action needed
+    }
+
+    /**
+     * Get the URL parameters needed to make the AJAX recommendation request.
+     *
+     * @return string
+     */
+    public function getUrlParams()
+    {
+        return 'mod=OpenLibrarySubjects&params=' . urlencode($this->processedParams)
+            . '&' . urlencode($this->requestParam) . '=' . urlencode($this->subject);
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/PubDateVisAjax.php b/module/VuFind/src/VuFind/Recommend/PubDateVisAjax.php
new file mode 100644
index 00000000000..d3c757ed70a
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/PubDateVisAjax.php
@@ -0,0 +1,186 @@
+<?php
+/**
+ * publishDateVis
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Till Kinstler 2011.
+ *
+ * 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  Recommendations
+ * @author   Till Kinstler <kinstler@gbv.de>
+ * @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\Recommend;
+
+/**
+ * PubDateVisAjax Recommendations Module
+ *
+ * This class displays a visualisation of facet values in a recommendation module
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Till Kinstler <kinstler@gbv.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/building_a_recommendations_module Wiki
+ */
+class PubDateVisAjax implements RecommendInterface
+{
+    protected $settings;
+    protected $results;
+    protected $facets;
+    protected $zooming;
+    protected $dateFacets = array();
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Save the basic parameters:
+        $this->settings = $settings;
+
+        // Parse the additional settings:
+        $params = explode(':', $settings);
+        if ($params[0] == "true" || $params[0] == "false") {
+            $this->zooming = $params[0];
+            $this->dateFacets = array_slice($params, 1);
+        } else {
+            $this->zooming = "false";
+            $this->dateFacets = $params;
+        }
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // No action needed.
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->searchObject = $results;
+    }
+
+    /**
+     * getVisFacets
+     *
+     * Basic get
+     *
+     * @return array
+     */
+    public function getVisFacets()
+    {
+        return $this->processDateFacets(
+            $this->searchObject->getFilters()
+        );
+    }
+
+    /**
+     * getZooming
+     *
+     * Basic get
+     *
+     * @return array
+     */
+    public function getZooming()
+    {
+        if (isset($this->zooming)) {
+            return $this->zooming;
+        }
+        return 'false';
+    }
+
+    /**
+     * getFacetFields
+     *
+     * Basic get
+     *
+     * @return array
+     */
+    public function getFacetFields()
+    {
+        return implode(':', $this->dateFacets);
+    }
+
+    /**
+     * getSearchParams
+     *
+     * @return string of params
+     */
+    public function getSearchParams()
+    {
+        // Get search parameters and return them minus the leading ?:
+        return substr($this->searchObject->getUrl()->getParams(false), 1);
+    }
+
+    /**
+     * Support method for getVisData() -- extract details from applied filters.
+     *
+     * @param array $filters Current filter list
+     *
+     * @return array
+     */
+    protected function processDateFacets($filters)
+    {
+        $result = array();
+        foreach ($this->dateFacets as $current) {
+            $from = $to = '';
+            if (isset($filters[$current])) {
+                foreach ($filters[$current] as $filter) {
+                    if (preg_match('/\[\d+ TO \d+\]/', $filter)) {
+                        $range = explode(' TO ', trim($filter, '[]'));
+                        $from = $range[0] == '*' ? '' : $range[0];
+                        $to = $range[1] == '*' ? '' : $range[1];
+                        break;
+                    }
+                }
+            }
+            $result[$current] = array($from, $to);
+            $result[$current]['label']
+                = $this->searchObject->getFacetLabel($current);
+        }
+        return $result;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/RecommendInterface.php b/module/VuFind/src/VuFind/Recommend/RecommendInterface.php
new file mode 100644
index 00000000000..813f16cf011
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/RecommendInterface.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Search Recommendations Interface
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2009.
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+
+/**
+ * Search Recommendations Interface
+ *
+ * This interface class is the definition of the required methods for
+ * generating search recommendations.
+ *
+ * Note that every class implementing this interface needs to be accompanied by
+ * a template file in the Recommend subdirectory of every theme's template
+ * directory.  For example, VF_Recommend_SideFacets needs a corresponding
+ * Recommend/SideFacets.phtml template.  The template will be rendered as a
+ * partial with two available variables: recommend (the recommendation object)
+ * and results (the search results object).
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+interface RecommendInterface
+{
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings);
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request);
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results);
+}
diff --git a/module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php b/module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php
new file mode 100644
index 00000000000..63937e25a0e
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * AuthorInfo Recommendations Module
+ *
+ * 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  Recommendations
+ * @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
+ */
+namespace VuFind\Recommend;
+use Zend\Registry;
+
+/**
+ * AuthorInfo Recommendations Module
+ *
+ * This class gathers information from the Wikipedia API and publishes the results
+ * to a module at the top of an author's results page
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Lutz Biedinger <lutz.biedinger@gmail.com>
+ * @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
+ * @view     AuthorInfoFacets.phtml
+ */
+class ResultGoogleMapAjax implements RecommendInterface
+{
+    protected $searchObject;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // No special settings
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // No action needed here.
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->searchObject = $results;
+    }
+
+    /**
+     * getUserLang
+     *
+     * @return string of lang
+     */
+    public function userLang()
+    {
+        return Registry::getInstance()
+                    ->get('Zend_Translate')
+                    ->getAdapter()
+                    ->getLocale();
+    }
+
+    /**
+     * getSearchParams
+     *
+     * @return string of params
+     */
+    public function getSearchParams()
+    {
+        // Get search parameters and return them minus the leading ?:
+        return substr($this->searchObject->getUrl()->getParams(false), 1);
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/SearchObject.php b/module/VuFind/src/VuFind/Recommend/SearchObject.php
new file mode 100644
index 00000000000..6df63cebed3
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/SearchObject.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Abstract SearchObject Recommendations Module (needs to be extended to use
+ * a particular search object).
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+
+/**
+ * Abstract SearchObject Recommendations Module (needs to be extended to use
+ * a particular search object).
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+abstract class SearchObject implements RecommendInterface
+{
+    protected $results;
+    protected $limit;
+    protected $requestParam;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        $settings = explode(':', $settings);
+        $this->requestParam = empty($settings[0]) ? 'lookfor' : $settings[0];
+        $this->limit
+            = (isset($settings[1]) && is_numeric($settings[1]) && $settings[1] > 0)
+            ? intval($settings[1]) : 5;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Build a search parameters object:
+        $id = $this->getSearchClassId();
+        $paramsClass = 'VuFind\\Search\\' . $id . '\\Params';
+        $params = new $paramsClass();
+        $params->setLimit($this->limit);
+        $params->setBasicSearch($request->query()->get($this->requestParam));
+
+        // Perform the search:
+        $resultsClass = 'VuFind\\Search\\' . $id . '\\Results';
+        $this->results = new $resultsClass($params);
+        $this->results->performAndProcessSearch();
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        // No action needed.
+    }
+
+    /**
+     * Get search results.
+     *
+     * @return VF_Search_Base_Results
+     */
+    public function getResults()
+    {
+        return $this->results;
+    }
+
+    /**
+     * Get the search class ID to use for building search objects.
+     *
+     * @return string
+     */
+    abstract protected function getSearchClassId();
+}
diff --git a/module/VuFind/src/VuFind/Recommend/SideFacets.php b/module/VuFind/src/VuFind/Recommend/SideFacets.php
new file mode 100644
index 00000000000..9ad9b839000
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/SideFacets.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * SideFacets Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+use VuFind\Config\Reader as ConfigReader, VuFind\Solr\Utils as SolrUtils;
+
+/**
+ * SideFacets Recommendations Module
+ *
+ * This class provides recommendations displaying facets beside search results
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class SideFacets implements RecommendInterface
+{
+    protected $dateFacets = array();
+    protected $mainFacets = array();
+    protected $checkboxFacets = array();
+    protected $results;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Parse the additional settings:
+        $settings = explode(':', $settings);
+        $mainSection = empty($settings[0]) ? 'Results' : $settings[0];
+        $checkboxSection = isset($settings[1]) ? $settings[1] : false;
+        $iniName = isset($settings[2]) ? $settings[2] : 'facets';
+
+        // Load the desired facet information...
+        $config = ConfigReader::getConfig($iniName);
+
+        // All standard facets to display:
+        $this->mainFacets = isset($config->$mainSection) ?
+            $config->$mainSection->toArray() : array();
+
+        // Get a list of fields that should be displayed as date ranges rather than
+        // standard facet lists.
+        if (isset($config->SpecialFacets->dateRange)) {
+            $this->dateFacets = $config->SpecialFacets->dateRange->toArray();
+        }
+
+        // Checkbox facets:
+        $this->checkboxFacets
+            = ($checkboxSection && isset($config->$checkboxSection))
+            ? $config->$checkboxSection->toArray() : array();
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Turn on side facets in the search results:
+        foreach ($this->mainFacets as $name => $desc) {
+            $params->addFacet($name, $desc);
+        }
+        foreach ($this->checkboxFacets as $name => $desc) {
+            $params->addCheckboxFacet($name, $desc);
+        }
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->results = $results;
+    }
+
+    /**
+     * getFacetSet
+     *
+     * Get facet information from the search results.
+     *
+     * @return array
+     */
+    public function getFacetSet()
+    {
+        return $this->results->getFacetList($this->mainFacets);
+    }
+
+    /**
+     * getDateFacets
+     *
+     * Return date facet information in a format processed for use in the view.
+     *
+     * @return array Array of from/to value arrays keyed by field.
+     */
+    public function getDateFacets()
+    {
+        $filters = $this->results->getFilters();
+        $result = array();
+        foreach ($this->dateFacets as $current) {
+            $from = $to = '';
+            if (isset($filters[$current])) {
+                foreach ($filters[$current] as $filter) {
+                    if ($range = SolrUtils::parseRange($filter)) {
+                        $from = $range['from'] == '*' ? '' : $range['from'];
+                        $to = $range['to'] == '*' ? '' : $range['to'];
+                        break;
+                    }
+                }
+            }
+            $result[$current] = array($from, $to);
+        }
+        return $result;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/SummonDatabases.php b/module/VuFind/src/VuFind/Recommend/SummonDatabases.php
new file mode 100644
index 00000000000..54e8b65f537
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/SummonDatabases.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * SummonDatabases Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+use VuFind\Search\Summon\Params as SummonParams,
+    VuFind\Search\Summon\Results as SummonResults;
+
+/**
+ * SummonDatabases Recommendations Module
+ *
+ * This class provides database recommendations by doing a search of Summon.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class SummonDatabases implements RecommendInterface
+{
+    protected $databases;
+    protected $requestParam;
+    protected $lookfor;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Only one setting -- HTTP request field containing search terms (ignored
+        // if $searchObject is Summon type).
+        $this->requestParam = empty($settings) ? 'lookfor' : $settings;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Save search query in case we need it later:
+        $this->lookfor = $request->query()->get($this->requestParam);
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        // If we received a Summon search object, we'll use that.  If not, we need
+        // to create a new Summon search object using the specified request 
+        // parameter for search terms.
+        if ($results->getSearchClassId() != 'Summon') {
+            $params = new SummonParams();
+            $params->setBasicSearch($this->lookfor);
+            $results = new SummonResults($params);
+            $results->performAndProcessSearch();
+        }
+        $this->databases = $results->getDatabaseRecommendations();
+    }
+
+    /**
+     * Get database results.
+     *
+     * @return array
+     */
+    public function getResults()
+    {
+        return $this->databases;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/SummonResults.php b/module/VuFind/src/VuFind/Recommend/SummonResults.php
new file mode 100644
index 00000000000..586ffaecd5f
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/SummonResults.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * SummonResults Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+
+/**
+ * SummonResults Recommendations Module
+ *
+ * This class provides recommendations by doing a search of Summon.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class SummonResults extends SearchObject
+{
+    /**
+     * Get the search class ID to use for building search objects.
+     *
+     * @return string
+     */
+    protected function getSearchClassId()
+    {
+        return 'Summon';
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/SwitchType.php b/module/VuFind/src/VuFind/Recommend/SwitchType.php
new file mode 100644
index 00000000000..ab6759d9052
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/SwitchType.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * SwitchType Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @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
+ */
+namespace VuFind\Recommend;
+
+/**
+ * SwitchType Recommendations Module
+ *
+ * This class recommends switching to a different search type.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @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 SwitchType implements RecommendInterface
+{
+    protected $newHandler;      // search handler to try
+    protected $newHandlerName;  // on-screen description of handler
+    protected $active;          // is this module active?
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     *
+     * TopFacets:[ini section]:[ini name]
+     *      Display facets listed in the specified section of the specified ini file;
+     *      if [ini name] is left out, it defaults to "facets."
+     */
+    public function __construct($settings)
+    {
+        $params = explode(':', $settings);
+        $this->newHandler = !empty($params[0]) ? $params[0] : 'AllFields';
+        $this->newHandlerName = isset($params[1]) ? $params[1] : 'All Fields';
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $handler = $results->getSearchHandler();
+
+        // If the handler is null, we can't figure out a single handler, so this
+        // is probably an advanced search.  In that case, we shouldn't try to change
+        // anything!  We should only show recommendations if we know what handler is
+        // being used and can determine that it is not the same as the new handler
+        // that we want to recommend.
+        $this->active = (!is_null($handler) && $handler != $this->newHandler);
+    }
+
+    /**
+     * Get the new search handler, or false if it does not apply.
+     *
+     * @return string
+     */
+    public function getNewHandler()
+    {
+        return $this->active ? $this->newHandler : false;
+    }
+
+    /**
+     * Get the description of the new search handler.
+     *
+     * @return string
+     */
+    public function getNewHandlerName()
+    {
+        return $this->newHandlerName;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/TopFacets.php b/module/VuFind/src/VuFind/Recommend/TopFacets.php
new file mode 100644
index 00000000000..113fb2b07ef
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/TopFacets.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * SideFacets Recommendations Module
+ *
+ * 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  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @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
+ */
+namespace VuFind\Recommend;
+use VuFind\Config\Reader as ConfigReader;
+
+/**
+ * SideFacets Recommendations Module
+ *
+ * This class provides recommendations displaying facets beside search results
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @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 TopFacets implements RecommendInterface
+{
+    protected $facets;
+    protected $baseSettings;
+    protected $results;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     *
+     * TopFacets:[ini section]:[ini name]
+     *      Display facets listed in the specified section of the specified ini file;
+     *      if [ini name] is left out, it defaults to "facets."
+     */
+    public function __construct($settings)
+    {
+        $settings = explode(':', $settings);
+        $mainSection = empty($settings[0]) ? 'ResultsTop':$settings[0];
+        $iniName = isset($settings[1]) ? $settings[1] : 'facets';
+
+        // Load the desired facet information:
+        $config = ConfigReader::getConfig($iniName);
+        $this->facets = isset($config->$mainSection)
+            ? $config->$mainSection->toArray() : array();
+
+        // Load other relevant settings:
+        $this->baseSettings = array(
+            'rows' => $config->Results_Settings->top_rows,
+            'cols' => $config->Results_Settings->top_cols
+        );
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // Turn on top facets in the search results:
+        foreach ($this->facets as $name => $desc) {
+            $params->addFacet($name, $desc);
+        }
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->results = $results;
+    }
+
+    /**
+     * Get facet information taken from the search.
+     *
+     * @return array
+     */
+    public function getTopFacetSet()
+    {
+        return $this->results->getFacetList($this->facets);
+    }
+
+    /**
+     * Get configuration settings related to top facets.
+     *
+     * @return array
+     */
+    public function getTopFacetSettings()
+    {
+        return $this->baseSettings;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/WorldCatIdentities.php b/module/VuFind/src/VuFind/Recommend/WorldCatIdentities.php
new file mode 100644
index 00000000000..b57c125c8f8
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/WorldCatIdentities.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * WorldCatIdentities Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+use VuFind\Connection\WorldCatUtils;
+
+/**
+ * WorldCatIdentities Recommendations Module
+ *
+ * This class provides recommendations by using the WorldCat Terminologies API.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class WorldCatIdentities implements RecommendInterface
+{
+    protected $searchObject;
+    protected $settings;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Save the basic parameters:
+        $this->settings = $settings;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // No action needed.
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->searchObject = $results;
+    }
+
+    /**
+     * Get identities related to the query.
+     *
+     * @return array
+     */
+    public function getIdentities()
+    {
+        // Extract the first search term from the search object:
+        $search = $this->searchObject->getSearchTerms();
+        $lookfor = isset($search[0]['lookfor']) ? $search[0]['lookfor'] : '';
+
+        // Get terminology information:
+        $wc = new WorldCatUtils();
+        return $wc->getRelatedIdentities($lookfor);
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Recommend/WorldCatTerms.php b/module/VuFind/src/VuFind/Recommend/WorldCatTerms.php
new file mode 100644
index 00000000000..ef333d53603
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/WorldCatTerms.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * WorldCatTerms Recommendations Module
+ *
+ * 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  Recommendations
+ * @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\Recommend;
+use VuFind\Connection\WorldCatUtils;
+
+/**
+ * WorldCatTerms Recommendations Module
+ *
+ * This class provides recommendations by using the WorldCat Terminologies API.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @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
+ */
+class WorldCatTerms implements RecommendInterface
+{
+    protected $searchObject;
+    protected $vocab;
+
+    /**
+     * Constructor
+     *
+     * Establishes base settings for making recommendations.
+     *
+     * @param string $settings Settings from searches.ini.
+     */
+    public function __construct($settings)
+    {
+        // Pick a vocabulary (either user-specified, or LCSH by default):
+        $params = trim($settings);
+        $this->vocab = empty($params) ? 'lcsh' : $params;
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\Http\Request         $request Zend request object
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+        // No action needed.
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->searchObject = $results;
+    }
+
+    /**
+     * Get terms related to the query.
+     *
+     * @return array
+     */
+    public function getTerms()
+    {
+        // Extract the first search term from the search object:
+        $search = $this->searchObject->getSearchTerms();
+        $lookfor = isset($search[0]['lookfor']) ? $search[0]['lookfor'] : '';
+
+        // Get terminology information:
+        $wc = new WorldCatUtils();
+        $terms = $wc->getRelatedTerms($lookfor, $this->vocab);
+
+        // Wipe out any empty or unexpected sections of the related terms array;
+        // this will make it easier to only display content in the template if
+        // we have something worth displaying.
+        if (is_array($terms)) {
+            $desiredKeys = array('exact', 'broader', 'narrower');
+            foreach ($terms as $key => $value) {
+                if (empty($value) || !in_array($key, $desiredKeys)) {
+                    unset($terms[$key]);
+                }
+            }
+        }
+        return $terms;
+    }
+}
\ No newline at end of file
-- 
GitLab