From 4efdee17a14485b022f517b25a8b2f768c3890c2 Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Mon, 2 Jul 2012 14:32:34 -0400
Subject: [PATCH] Began porting Summon libraries (untested).

---
 .../VuFind/src/VuFind/Connection/Summon.php   | 230 ++++++++++++++++++
 .../src/VuFind/Connection/Summon/Query.php    | 123 ++++++++++
 vendor/SerialsSolutions/Summon/Zend2.php      | 124 ++++++++++
 3 files changed, 477 insertions(+)
 create mode 100644 module/VuFind/src/VuFind/Connection/Summon.php
 create mode 100644 module/VuFind/src/VuFind/Connection/Summon/Query.php
 create mode 100644 vendor/SerialsSolutions/Summon/Zend2.php

diff --git a/module/VuFind/src/VuFind/Connection/Summon.php b/module/VuFind/src/VuFind/Connection/Summon.php
new file mode 100644
index 00000000000..86e1eb514b6
--- /dev/null
+++ b/module/VuFind/src/VuFind/Connection/Summon.php
@@ -0,0 +1,230 @@
+<?php
+/**
+ * Summon Search API Interface (VuFind implementation)
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Andrew Nagy 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  Support_Classes
+ * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
+ */
+namespace VuFind\Connection;
+use SerialsSolutions\Summon\Zend2 as BaseSummon,
+    VuFind\Config\Reader as ConfigReader,
+    VuFind\Http\Client as HttpClient,
+    VuFind\Log\Logger,
+    VuFind\Solr\Utils as SolrUtils;
+
+/**
+ * Summon Search API Interface (VuFind implementation)
+ *
+ * @category VuFind2
+ * @package  Support_Classes
+ * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
+ */
+class Summon extends BaseSummon;
+{
+    /**
+     * Should boolean operators in the search string be treated as
+     * case-insensitive (false), or must they be ALL UPPERCASE (true)?
+     */
+    protected $caseSensitiveBooleans = true;
+
+    /**
+     * Will we include snippets in responses?
+     * @var bool
+     */
+    protected $snippets = false;
+
+    /**
+     * Constructor
+     *
+     * Sets up the Summon API Client
+     *
+     * @param string $apiId   Summon API ID
+     * @param string $apiKey  Summon API Key
+     * @param array  $options Associative array of additional options; legal keys:
+     *    <ul>
+     *      <li>authedUser - is the end-user authenticated?</li>
+     *      <li>debug - boolean to control debug mode</li>
+     *      <li>host - base URL of Summon API</li>
+     *      <li>sessionId - Summon session ID to apply</li>
+     *      <li>version - API version to use</li>
+     *    </ul>
+     */
+    public function __construct($apiId, $apiKey, $options = array())
+    {
+        $config = ConfigReader::getConfig('Summon');
+
+        // Store preferred boolean behavior:
+        if (!isset($options['caseSensitiveBooleans'])
+            && isset($config->General->case_sensitive_bools)
+        ) {
+            $this->caseSensitiveBooleans = $config->General->case_sensitive_bools;
+        } else {
+            $this->caseSensitiveBooleans = $options['caseSensitiveBooleans'];
+        }
+
+        // Set default snippet behavior if necessary:
+        if (isset($config->General->snippets)) {
+            $this->snippets = $config->General->snippets;
+        }
+
+        // Set default debug behavior:
+        if (!isset($options['debug'])) {
+            $options['debug'] = Logger::debugNeeded();
+        }
+
+        $timeout = isset($config->General->timeout)
+            ? $config->General->timeout : 30;
+        parent::__construct(
+            $apiId, $apiKey, $options, new HttpClient(
+                null, array('timeout' => $timeout)
+            )
+        );
+    }
+
+    /**
+     * Print a message if debug is enabled.
+     *
+     * @param string $msg Message to print
+     *
+     * @return void
+     */
+    protected function debugPrint($msg)
+    {
+        if ($this->debug) {
+            Logger::getInstance->debug("<pre>{$msg}</pre>\n");
+        }
+    }
+
+    /**
+     * Build basic Query string from search parameters (support method for
+     * buildQuery)
+     *
+     * @param array $params An array of search parameters
+     *
+     * @return string
+     */
+    protected function buildBasicQuery($params)
+    {
+        // Clean and validate input -- note that index may be in a
+        // different field depending on whether this is a basic or
+        // advanced search.
+        $lookfor = $params['lookfor'];
+        if (isset($params['field'])) {
+            $index = $params['field'];
+        } else if (isset($params['index'])) {
+            $index = $params['index'];
+        } else {
+            $index = 'AllFields';
+        }
+
+        // Force boolean operators to uppercase if we are in a
+        // case-insensitive mode:
+        if (!$this->caseSensitiveBooleans) {
+            $lookfor = SolrUtils::capitalizeBooleans($lookfor);
+        }
+
+        // Prepend the index name, unless it's the special "AllFields"
+        // index:
+        return ($index != 'AllFields') ? "{$index}:($lookfor)" : $lookfor;
+    }
+
+    /**
+     * Build Query string from search parameters
+     *
+     * @param array $search An array of search parameters
+     *
+     * @return string       The query
+     */
+    public function buildQuery($search)
+    {
+        $groups   = array();
+        $excludes = array();
+        if (is_array($search)) {
+            $query = '';
+
+            foreach ($search as $params) {
+                // Advanced Search
+                if (isset($params['group'])) {
+                    $thisGroup = array();
+                    // Process each search group
+                    foreach ($params['group'] as $group) {
+                        // Build this group individually as a basic search
+                        $thisGroup[] = $this->buildQuery(array($group));
+                    }
+                    // Is this an exclusion (NOT) group or a normal group?
+                    if ($params['group'][0]['bool'] == 'NOT') {
+                        $excludes[] = join(" OR ", $thisGroup);
+                    } else {
+                        $groups[] = join(
+                            " " . $params['group'][0]['bool'] . " ", $thisGroup
+                        );
+                    }
+                }
+
+                // Basic Search
+                if (isset($params['lookfor']) && $params['lookfor'] != '') {
+                    $query .= $this->buildBasicQuery($params);
+                }
+            }
+        }
+
+        // Put our advanced search together
+        if (count($groups) > 0) {
+            $query = "(" . join(") " . $search[0]['join'] . " (", $groups) . ")";
+        }
+        // and concatenate exclusion after that
+        if (count($excludes) > 0) {
+            $query .= " NOT ((" . join(") OR (", $excludes) . "))";
+        }
+
+        // Ensure we have a valid query to this point
+        return isset($query) ? $query : '';
+    }
+
+    /**
+     * Perform normalization and analysis of Summon return value.
+     *
+     * @param array $input The raw response from Summon
+     *
+     * @throws SerialsSolutions_Summon_Exception
+     * @return array       The processed response from Summon
+     */
+    protected function process($input)
+    {
+        $result = parent::process($input);
+
+        // Process highlighting/snippets:
+        foreach ($result['documents'] as $i => $current) {
+            // Remove snippets if not desired:
+            if (!$this->snippets) {
+                unset($result['documents'][$i]['Snippet']);
+            }
+        }
+
+        return $result;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Connection/Summon/Query.php b/module/VuFind/src/VuFind/Connection/Summon/Query.php
new file mode 100644
index 00000000000..0a5aad6ca93
--- /dev/null
+++ b/module/VuFind/src/VuFind/Connection/Summon/Query.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Summon Search API Interface (query model - VuFind implementation)
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Serials Solutions 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 SerialsSolutions
+ * @package  Summon
+ * @author   Andrew Nagy <andrew.nagy@serialssolutions.com>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
+ */
+namespace VuFind\Connection\Summon;
+
+/**
+ * Summon REST API Interface (query model - VuFind implementation)
+ *
+ * @category SerialsSolutions
+ * @package  Summon
+ * @author   Andrew Nagy <andrew.nagy@serialssolutions.com>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
+ */
+class Query extends SerialsSolutions_Summon_Query
+{
+    protected $config;
+
+    /**
+     * Constructor
+     *
+     * Sets up the Summon API Client
+     *
+     * @param string $query   Search query
+     * @param array  $options Other options to set (associative array)
+     */
+    public function __construct($query = null, $options = array())
+    {
+        parent::__construct($query, $options);
+        $this->config = VF_Config_Reader::getConfig('Summon');
+    }
+
+    /**
+     * Set up facets based on VuFind settings.
+     *
+     * @param array $facets Facet settings
+     *
+     * @return void
+     */
+    public function initFacets($facets)
+    {
+        $this->facets = array();
+        foreach ($facets as $facet) {
+            // See if parameters are included as part of the facet name;
+            // if not, override them with defaults.
+            $parts = explode(',', $facet);
+            $facetName = $parts[0];
+            $facetMode = isset($parts[1]) ? $parts[1] : 'and';
+            $facetPage = isset($parts[2]) ? $parts[2] : 1;
+            if (isset($parts[3])) {
+                $facetLimit = $parts[3];
+            } else {
+                $facetLimit = isset($this->config->Facet_Settings->facet_limit)
+                    ? $this->config->Facet_Settings->facet_limit : 30;
+            }
+            $facetParams = "{$facetMode},{$facetPage},{$facetLimit}";
+            $this->facets[] = "{$facetName},{$facetParams}";
+        }
+    }
+
+    /**
+     * Set up filters based on VuFind settings.
+     *
+     * @param array $filterList Filter settings
+     *
+     * @return void
+     */
+    public function initFilters($filterList)
+    {
+        // Which filters should be applied to our query?
+        if (!empty($filterList)) {
+            // Loop through all filters and add appropriate values to request:
+            foreach ($filterList as $filterArray) {
+                foreach ($filterArray as $filt) {
+                    $safeValue = self::escapeParam($filt['value']);
+                    // Special case -- "holdings only" is a separate parameter from
+                    // other facets.
+                    if ($filt['field'] == 'holdingsOnly') {
+                        $this->setHoldings(strtolower(trim($safeValue)) == 'true');
+                    } else if ($filt['field'] == 'excludeNewspapers') {
+                        // Special case -- support a checkbox for excluding
+                        // newspapers:
+                        $this->addFilter("ContentType,Newspaper Article,true");
+                    } else if ($range = VF_Solr_Utils::parseRange($filt['value'])) {
+                        // Special case -- range query (translate [x TO y] syntax):
+                        $from = self::escapeParam($range['from']);
+                        $to = self::escapeParam($range['to']);
+                        $this->addRangeFilter("{$filt['field']},{$from}:{$to}");
+                    } else {
+                        // Standard case:
+                        $this->addFilter("{$filt['field']},{$safeValue}");
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/vendor/SerialsSolutions/Summon/Zend2.php b/vendor/SerialsSolutions/Summon/Zend2.php
new file mode 100644
index 00000000000..c029e4d38fc
--- /dev/null
+++ b/vendor/SerialsSolutions/Summon/Zend2.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * Summon Search API Interface (Zend Framework 2 implementation)
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Serials Solutions 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 SerialsSolutions
+ * @package  Summon
+ * @author   Andrew Nagy <andrew.nagy@serialssolutions.com>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
+ */
+namespace SerialsSolutions\Summon;
+use Zend\Http\Client as HttpClient;
+
+/**
+ * Summon Search API Interface (Zend Framework 2 implementation)
+ *
+ * @category SerialsSolutions
+ * @package  Summon
+ * @author   Andrew Nagy <andrew.nagy@serialssolutions.com>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
+ */
+class Zend2 extends SerialsSolutions_Summon_Base
+{
+    /**
+     * The HTTP_Request object used for API transactions
+     * @var object HTTP_Request
+     */
+    protected $client;
+
+    /**
+     * Constructor
+     *
+     * Sets up the Summon API Client
+     *
+     * @param string           $apiId   Summon API ID
+     * @param string           $apiKey  Summon API Key
+     * @param array            $options Associative array of additional options;
+     * legal keys:
+     *    <ul>
+     *      <li>authedUser - is the end-user authenticated?</li>
+     *      <li>debug - boolean to control debug mode</li>
+     *      <li>host - base URL of Summon API</li>
+     *      <li>sessionId - Summon session ID to apply</li>
+     *      <li>version - API version to use</li>
+     *    </ul>
+     * @param Zend_Http_Client $client  HTTP client object (optional)
+     */
+    public function __construct($apiId, $apiKey, $options = array(), $client = null)
+    {
+        parent::__construct($apiId, $apiKey, $options);
+        $this->client = is_object($client) ? $client : new HttpClient();
+    }
+
+    /**
+     * Handle a fatal error.
+     *
+     * @param SerialsSolutions_Summon_Exception $e Exception to process.
+     *
+     * @return void
+     */
+    public function handleFatalError($e)
+    {
+        throw $e;
+    }
+
+    /**
+     * Perform an HTTP request.
+     *
+     * @param string $baseUrl     Base URL for request
+     * @param string $method      HTTP method for request
+     * @param string $queryString Query string to append to URL
+     * @param array  $headers     HTTP headers to send
+     *
+     * @throws SerialsSolutions_Summon_Exception
+     * @return string             HTTP response body
+     */
+    protected function httpRequest($baseUrl, $method, $queryString, $headers)
+    {
+        $this->debugPrint(
+            "{$method}: {$baseUrl}?{$queryString}"
+        );
+
+        $this->client->resetParameters();
+        if ($method == 'GET') {
+            $baseUrl .= '?' . $queryString;
+        } elseif ($method == 'POST') {
+            $this->client->setRawBody(
+                $queryString, 'application/x-www-form-urlencoded'
+            );
+        }
+
+        foreach ($headers as $key => $value) {
+            $this->client->setHeaders($key, $value);
+        }
+
+        // Send Request
+        $this->client->setUri($baseUrl);
+        $result = $this->client->setMethod($method)->send();
+        if (!$result->isSuccess()) {
+            throw new SerialsSolutions_Summon_Exception($result->getBody());
+        }
+        return $result->getBody();
+    }
+}
-- 
GitLab