+ * ...
+ * $document->title = 'Something';
+ * echo $document->title;
+ * ...
+ *
+ *
+ * Additionally, the field values can be iterated with foreach
+ *
+ *
+ * foreach ($document as $fieldName => $fieldValue)
+ * {
+ * ...
+ * }
+ *
+ */
+class Apache_Solr_Document implements IteratorAggregate
+{
+ /**
+ * SVN Revision meta data for this class
+ */
+ const SVN_REVISION = '$Revision: 54 $';
+
+ /**
+ * SVN ID meta data for this class
+ */
+ const SVN_ID = '$Id: Document.php 54 2011-02-04 16:29:18Z donovan.jimenez $';
+
+ /**
+ * Document boost value
+ *
+ * @var float
+ */
+ protected $_documentBoost = false;
+
+ /**
+ * Document field values, indexed by name
+ *
+ * @var array
+ */
+ protected $_fields = array();
+
+ /**
+ * Document field boost values, indexed by name
+ *
+ * @var array array of floats
+ */
+ protected $_fieldBoosts = array();
+
+ /**
+ * Clear all boosts and fields from this document
+ */
+ public function clear()
+ {
+ $this->_documentBoost = false;
+
+ $this->_fields = array();
+ $this->_fieldBoosts = array();
+ }
+
+ /**
+ * Get current document boost
+ *
+ * @return mixed will be false for default, or else a float
+ */
+ public function getBoost()
+ {
+ return $this->_documentBoost;
+ }
+
+ /**
+ * Set document boost factor
+ *
+ * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+ */
+ public function setBoost($boost)
+ {
+ $boost = (float) $boost;
+
+ if ($boost > 0.0)
+ {
+ $this->_documentBoost = $boost;
+ }
+ else
+ {
+ $this->_documentBoost = false;
+ }
+ }
+
+ /**
+ * Add a value to a multi-valued field
+ *
+ * NOTE: the solr XML format allows you to specify boosts
+ * PER value even though the underlying Lucene implementation
+ * only allows a boost per field. To remedy this, the final
+ * field boost value will be the product of all specified boosts
+ * on field values - this is similar to SolrJ's functionality.
+ *
+ *
+ * $doc = new Apache_Solr_Document();
+ *
+ * $doc->addField('foo', 'bar', 2.0);
+ * $doc->addField('foo', 'baz', 3.0);
+ *
+ * // resultant field boost will be 6!
+ * echo $doc->getFieldBoost('foo');
+ *
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+ */
+ public function addField($key, $value, $boost = false)
+ {
+ if (!isset($this->_fields[$key]))
+ {
+ // create holding array if this is the first value
+ $this->_fields[$key] = array();
+ }
+ else if (!is_array($this->_fields[$key]))
+ {
+ // move existing value into array if it is not already an array
+ $this->_fields[$key] = array($this->_fields[$key]);
+ }
+
+ if ($this->getFieldBoost($key) === false)
+ {
+ // boost not already set, set it now
+ $this->setFieldBoost($key, $boost);
+ }
+ else if ((float) $boost > 0.0)
+ {
+ // multiply passed boost with current field boost - similar to SolrJ implementation
+ $this->_fieldBoosts[$key] *= (float) $boost;
+ }
+
+ // add value to array
+ $this->_fields[$key][] = $value;
+ }
+
+ /**
+ * Handle the array manipulation for a multi-valued field
+ *
+ * @param string $key
+ * @param string $value
+ * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+ *
+ * @deprecated Use addField(...) instead
+ */
+ public function setMultiValue($key, $value, $boost = false)
+ {
+ $this->addField($key, $value, $boost);
+ }
+
+ /**
+ * Get field information
+ *
+ * @param string $key
+ * @return mixed associative array of info if field exists, false otherwise
+ */
+ public function getField($key)
+ {
+ if (isset($this->_fields[$key]))
+ {
+ return array(
+ 'name' => $key,
+ 'value' => $this->_fields[$key],
+ 'boost' => $this->getFieldBoost($key)
+ );
+ }
+
+ return false;
+ }
+
+ /**
+ * Set a field value. Multi-valued fields should be set as arrays
+ * or instead use the addField(...) function which will automatically
+ * make sure the field is an array.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+ */
+ public function setField($key, $value, $boost = false)
+ {
+ $this->_fields[$key] = $value;
+ $this->setFieldBoost($key, $boost);
+ }
+
+ /**
+ * Get the currently set field boost for a document field
+ *
+ * @param string $key
+ * @return float currently set field boost, false if one is not set
+ */
+ public function getFieldBoost($key)
+ {
+ return isset($this->_fieldBoosts[$key]) ? $this->_fieldBoosts[$key] : false;
+ }
+
+ /**
+ * Set the field boost for a document field
+ *
+ * @param string $key field name for the boost
+ * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+ */
+ public function setFieldBoost($key, $boost)
+ {
+ $boost = (float) $boost;
+
+ if ($boost > 0.0)
+ {
+ $this->_fieldBoosts[$key] = $boost;
+ }
+ else
+ {
+ $this->_fieldBoosts[$key] = false;
+ }
+ }
+
+ /**
+ * Return current field boosts, indexed by field name
+ *
+ * @return array
+ */
+ public function getFieldBoosts()
+ {
+ return $this->_fieldBoosts;
+ }
+
+ /**
+ * Get the names of all fields in this document
+ *
+ * @return array
+ */
+ public function getFieldNames()
+ {
+ return array_keys($this->_fields);
+ }
+
+ /**
+ * Get the values of all fields in this document
+ *
+ * @return array
+ */
+ public function getFieldValues()
+ {
+ return array_values($this->_fields);
+ }
+
+ /**
+ * IteratorAggregate implementation function. Allows usage:
+ *
+ *
+ * foreach ($document as $key => $value)
+ * {
+ * ...
+ * }
+ *
+ */
+ public function getIterator()
+ {
+ $arrayObject = new ArrayObject($this->_fields);
+
+ return $arrayObject->getIterator();
+ }
+
+ /**
+ * Magic get for field values
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ if (isset($this->_fields[$key]))
+ {
+ return $this->_fields[$key];
+ }
+
+ return null;
+ }
+
+ /**
+ * Magic set for field values. Multi-valued fields should be set as arrays
+ * or instead use the addField(...) function which will automatically
+ * make sure the field is an array.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function __set($key, $value)
+ {
+ $this->setField($key, $value);
+ }
+
+ /**
+ * Magic isset for fields values. Do not call directly. Allows usage:
+ *
+ *
+ * isset($document->some_field);
+ *
+ *
+ * @param string $key
+ * @return boolean
+ */
+ public function __isset($key)
+ {
+ return isset($this->_fields[$key]);
+ }
+
+ /**
+ * Magic unset for field values. Do not call directly. Allows usage:
+ *
+ *
+ * unset($document->some_field);
+ *
+ *
+ * @param string $key
+ */
+ public function __unset($key)
+ {
+ unset($this->_fields[$key]);
+ unset($this->_fieldBoosts[$key]);
+ }
+}
\ No newline at end of file
diff --git a/Apache/Solr/Exception.php b/Apache/Solr/Exception.php
new file mode 100755
index 0000000..e6bc4f4
--- /dev/null
+++ b/Apache/Solr/Exception.php
@@ -0,0 +1,50 @@
+
+ */
+
+class Apache_Solr_Exception extends Exception
+{
+ /**
+ * SVN Revision meta data for this class
+ */
+ const SVN_REVISION = '$Revision: 54 $';
+
+ /**
+ * SVN ID meta data for this class
+ */
+ const SVN_ID = '$Id: Exception.php 54 2011-02-04 16:29:18Z donovan.jimenez $';
+}
\ No newline at end of file
diff --git a/Apache/Solr/HttpTransport/Abstract.php b/Apache/Solr/HttpTransport/Abstract.php
new file mode 100755
index 0000000..cf9f76d
--- /dev/null
+++ b/Apache/Solr/HttpTransport/Abstract.php
@@ -0,0 +1,89 @@
+, Donovan Jimenez
+ * ...
+ * $solr = new Apache_Solr_Service(); //or explicitly new Apache_Solr_Service('localhost', 8180, '/solr')
+ *
+ * if ($solr->ping())
+ * {
+ * $solr->deleteByQuery('*:*'); //deletes ALL documents - be careful :)
+ *
+ * $document = new Apache_Solr_Document();
+ * $document->id = uniqid(); //or something else suitably unique
+ *
+ * $document->title = 'Some Title';
+ * $document->content = 'Some content for this wonderful document. Blah blah blah.';
+ *
+ * $solr->addDocument($document); //if you're going to be adding documents in bulk using addDocuments
+ * //with an array of documents is faster
+ *
+ * $solr->commit(); //commit to see the deletes and the document
+ * $solr->optimize(); //merges multiple segments into one
+ *
+ * //and the one we all care about, search!
+ * //any other common or custom parameters to the request handler can go in the
+ * //optional 4th array argument.
+ * $solr->search('content:blah', 0, 10, array('sort' => 'timestamp desc'));
+ * }
+ * ...
+ *
+ *
+ * @todo Investigate using other HTTP clients other than file_get_contents built-in handler. Could provide performance
+ * improvements when dealing with multiple requests by using HTTP's keep alive functionality
+ */
+class Apache_Solr_Service
+{
+ /**
+ * SVN Revision meta data for this class
+ */
+ const SVN_REVISION = '$Revision: 59 $';
+
+ /**
+ * SVN ID meta data for this class
+ */
+ const SVN_ID = '$Id: Service.php 59 2011-02-08 20:38:59Z donovan.jimenez $';
+
+ /**
+ * Response writer we'll request - JSON. See http://code.google.com/p/solr-php-client/issues/detail?id=6#c1 for reasoning
+ */
+ const SOLR_WRITER = 'json';
+
+ /**
+ * NamedList Treatment constants
+ */
+ const NAMED_LIST_FLAT = 'flat';
+ const NAMED_LIST_MAP = 'map';
+
+ /**
+ * Search HTTP Methods
+ */
+ const METHOD_GET = 'GET';
+ const METHOD_POST = 'POST';
+
+ /**
+ * Servlet mappings
+ */
+ const PING_SERVLET = 'admin/ping';
+ const UPDATE_SERVLET = 'update';
+ const SEARCH_SERVLET = 'select';
+ const THREADS_SERVLET = 'admin/threads';
+ const EXTRACT_SERVLET = 'update/extract';
+
+ /**
+ * Server identification strings
+ *
+ * @var string
+ */
+ protected $_host, $_port, $_path;
+
+ /**
+ * Whether {@link Apache_Solr_Response} objects should create {@link Apache_Solr_Document}s in
+ * the returned parsed data
+ *
+ * @var boolean
+ */
+ protected $_createDocuments = true;
+
+ /**
+ * Whether {@link Apache_Solr_Response} objects should have multivalue fields with only a single value
+ * collapsed to appear as a single value would.
+ *
+ * @var boolean
+ */
+ protected $_collapseSingleValueArrays = true;
+
+ /**
+ * How NamedLists should be formatted in the output. This specifically effects facet counts. Valid values
+ * are {@link Apache_Solr_Service::NAMED_LIST_MAP} (default) or {@link Apache_Solr_Service::NAMED_LIST_FLAT}.
+ *
+ * @var string
+ */
+ protected $_namedListTreatment = self::NAMED_LIST_MAP;
+
+ /**
+ * Query delimiters. Someone might want to be able to change
+ * these (to use & instead of & for example), so I've provided them.
+ *
+ * @var string
+ */
+ protected $_queryDelimiter = '?', $_queryStringDelimiter = '&', $_queryBracketsEscaped = true;
+
+ /**
+ * Constructed servlet full path URLs
+ *
+ * @var string
+ */
+ protected $_pingUrl, $_updateUrl, $_searchUrl, $_threadsUrl;
+
+ /**
+ * Keep track of whether our URLs have been constructed
+ *
+ * @var boolean
+ */
+ protected $_urlsInited = false;
+
+ /**
+ * HTTP Transport implementation (pluggable)
+ *
+ * @var Apache_Solr_HttpTransport_Interface
+ */
+ protected $_httpTransport = false;
+
+ /**
+ * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
+ *
+ * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function escape($value)
+ {
+ //list taken from http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
+ $pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
+ $replace = '\\\$1';
+
+ return preg_replace($pattern, $replace, $value);
+ }
+
+ /**
+ * Escape a value meant to be contained in a phrase for special query characters
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function escapePhrase($value)
+ {
+ $pattern = '/("|\\\)/';
+ $replace = '\\\$1';
+
+ return preg_replace($pattern, $replace, $value);
+ }
+
+ /**
+ * Convenience function for creating phrase syntax from a value
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function phrase($value)
+ {
+ return '"' . self::escapePhrase($value) . '"';
+ }
+
+ /**
+ * Constructor. All parameters are optional and will take on default values
+ * if not specified.
+ *
+ * @param string $host
+ * @param string $port
+ * @param string $path
+ * @param Apache_Solr_HttpTransport_Interface $httpTransport
+ */
+ public function __construct($host = 'localhost', $port = 8180, $path = '/solr/', $httpTransport = false)
+ {
+ $this->setHost($host);
+ $this->setPort($port);
+ $this->setPath($path);
+
+ $this->_initUrls();
+
+ if ($httpTransport)
+ {
+ $this->setHttpTransport($httpTransport);
+ }
+
+ // check that our php version is >= 5.1.3 so we can correct for http_build_query behavior later
+ $this->_queryBracketsEscaped = version_compare(phpversion(), '5.1.3', '>=');
+ }
+
+ /**
+ * Return a valid http URL given this server's host, port and path and a provided servlet name
+ *
+ * @param string $servlet
+ * @return string
+ */
+ protected function _constructUrl($servlet, $params = array())
+ {
+ if (count($params))
+ {
+ //escape all parameters appropriately for inclusion in the query string
+ $escapedParams = array();
+
+ foreach ($params as $key => $value)
+ {
+ $escapedParams[] = urlencode($key) . '=' . urlencode($value);
+ }
+
+ $queryString = $this->_queryDelimiter . implode($this->_queryStringDelimiter, $escapedParams);
+ }
+ else
+ {
+ $queryString = '';
+ }
+
+ return 'http://' . $this->_host . ':' . $this->_port . $this->_path . $servlet . $queryString;
+ }
+
+ /**
+ * Construct the Full URLs for the three servlets we reference
+ */
+ protected function _initUrls()
+ {
+ //Initialize our full servlet URLs now that we have server information
+ $this->_extractUrl = $this->_constructUrl(self::EXTRACT_SERVLET);
+ $this->_pingUrl = $this->_constructUrl(self::PING_SERVLET);
+ $this->_searchUrl = $this->_constructUrl(self::SEARCH_SERVLET);
+ $this->_threadsUrl = $this->_constructUrl(self::THREADS_SERVLET, array('wt' => self::SOLR_WRITER ));
+ $this->_updateUrl = $this->_constructUrl(self::UPDATE_SERVLET, array('wt' => self::SOLR_WRITER ));
+
+ $this->_urlsInited = true;
+ }
+
+ protected function _generateQueryString($params)
+ {
+ // use http_build_query to encode our arguments because its faster
+ // than urlencoding all the parts ourselves in a loop
+ //
+ // because http_build_query treats arrays differently than we want to, correct the query
+ // string by changing foo[#]=bar (# being an actual number) parameter strings to just
+ // multiple foo=bar strings. This regex should always work since '=' will be urlencoded
+ // anywhere else the regex isn't expecting it
+ //
+ // NOTE: before php 5.1.3 brackets were not url encoded by http_build query - we've checked
+ // the php version in the constructor and put the results in the instance variable. Also, before
+ // 5.1.2 the arg_separator parameter was not available, so don't use it
+ if ($this->_queryBracketsEscaped)
+ {
+ $queryString = http_build_query($params, null, $this->_queryStringDelimiter);
+ return preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $queryString);
+ }
+ else
+ {
+ $queryString = http_build_query($params);
+ return preg_replace('/\\[(?:[0-9]|[1-9][0-9]+)\\]=/', '=', $queryString);
+ }
+ }
+
+ /**
+ * Central method for making a get operation against this Solr Server
+ *
+ * @param string $url
+ * @param float $timeout Read timeout in seconds
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If a non 200 response status is returned
+ */
+ protected function _sendRawGet($url, $timeout = FALSE)
+ {
+ $httpTransport = $this->getHttpTransport();
+
+ $httpResponse = $httpTransport->performGetRequest($url, $timeout);
+ $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
+
+ if ($solrResponse->getHttpStatus() != 200)
+ {
+ throw new Apache_Solr_HttpTransportException($solrResponse);
+ }
+
+ return $solrResponse;
+ }
+
+ /**
+ * Central method for making a post operation against this Solr Server
+ *
+ * @param string $url
+ * @param string $rawPost
+ * @param float $timeout Read timeout in seconds
+ * @param string $contentType
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If a non 200 response status is returned
+ */
+ protected function _sendRawPost($url, $rawPost, $timeout = FALSE, $contentType = 'text/xml; charset=UTF-8')
+ {
+ $httpTransport = $this->getHttpTransport();
+
+ $httpResponse = $httpTransport->performPostRequest($url, $rawPost, $contentType, $timeout);
+ $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
+
+ if ($solrResponse->getHttpStatus() != 200)
+ {
+ throw new Apache_Solr_HttpTransportException($solrResponse);
+ }
+
+ return $solrResponse;
+ }
+
+ /**
+ * Returns the set host
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->_host;
+ }
+
+ /**
+ * Set the host used. If empty will fallback to constants
+ *
+ * @param string $host
+ *
+ * @throws Apache_Solr_InvalidArgumentException If the host parameter is empty
+ */
+ public function setHost($host)
+ {
+ //Use the provided host or use the default
+ if (empty($host))
+ {
+ throw new Apache_Solr_InvalidArgumentException('Host parameter is empty');
+ }
+ else
+ {
+ $this->_host = $host;
+ }
+
+ if ($this->_urlsInited)
+ {
+ $this->_initUrls();
+ }
+ }
+
+ /**
+ * Get the set port
+ *
+ * @return integer
+ */
+ public function getPort()
+ {
+ return $this->_port;
+ }
+
+ /**
+ * Set the port used. If empty will fallback to constants
+ *
+ * @param integer $port
+ *
+ * @throws Apache_Solr_InvalidArgumentException If the port parameter is empty
+ */
+ public function setPort($port)
+ {
+ //Use the provided port or use the default
+ $port = (int) $port;
+
+ if ($port <= 0)
+ {
+ throw new Apache_Solr_InvalidArgumentException('Port is not a valid port number');
+ }
+ else
+ {
+ $this->_port = $port;
+ }
+
+ if ($this->_urlsInited)
+ {
+ $this->_initUrls();
+ }
+ }
+
+ /**
+ * Get the set path.
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->_path;
+ }
+
+ /**
+ * Set the path used. If empty will fallback to constants
+ *
+ * @param string $path
+ */
+ public function setPath($path)
+ {
+ $path = trim($path, '/');
+
+ $this->_path = '/' . $path . '/';
+
+ if ($this->_urlsInited)
+ {
+ $this->_initUrls();
+ }
+ }
+
+ /**
+ * Get the current configured HTTP Transport
+ *
+ * @return HttpTransportInterface
+ */
+ public function getHttpTransport()
+ {
+ // lazy load a default if one has not be set
+ if ($this->_httpTransport === false)
+ {
+ require_once(dirname(__FILE__) . '/HttpTransport/FileGetContents.php');
+
+ $this->_httpTransport = new Apache_Solr_HttpTransport_FileGetContents();
+ }
+
+ return $this->_httpTransport;
+ }
+
+ /**
+ * Set the HTTP Transport implemenation that will be used for all HTTP requests
+ *
+ * @param Apache_Solr_HttpTransport_Interface
+ */
+ public function setHttpTransport(Apache_Solr_HttpTransport_Interface $httpTransport)
+ {
+ $this->_httpTransport = $httpTransport;
+ }
+
+ /**
+ * Set the create documents flag. This determines whether {@link Apache_Solr_Response} objects will
+ * parse the response and create {@link Apache_Solr_Document} instances in place.
+ *
+ * @param boolean $createDocuments
+ */
+ public function setCreateDocuments($createDocuments)
+ {
+ $this->_createDocuments = (bool) $createDocuments;
+ }
+
+ /**
+ * Get the current state of teh create documents flag.
+ *
+ * @return boolean
+ */
+ public function getCreateDocuments()
+ {
+ return $this->_createDocuments;
+ }
+
+ /**
+ * Set the collapse single value arrays flag.
+ *
+ * @param boolean $collapseSingleValueArrays
+ */
+ public function setCollapseSingleValueArrays($collapseSingleValueArrays)
+ {
+ $this->_collapseSingleValueArrays = (bool) $collapseSingleValueArrays;
+ }
+
+ /**
+ * Get the current state of the collapse single value arrays flag.
+ *
+ * @return boolean
+ */
+ public function getCollapseSingleValueArrays()
+ {
+ return $this->_collapseSingleValueArrays;
+ }
+
+ /**
+ * Get the current default timeout setting (initially the default_socket_timeout ini setting)
+ * in seconds
+ *
+ * @return float
+ *
+ * @deprecated Use the getDefaultTimeout method on the HTTP transport implementation
+ */
+ public function getDefaultTimeout()
+ {
+ return $this->getHttpTransport()->getDefaultTimeout();
+ }
+
+ /**
+ * Set the default timeout for all calls that aren't passed a specific timeout
+ *
+ * @param float $timeout Timeout value in seconds
+ *
+ * @deprecated Use the setDefaultTimeout method on the HTTP transport implementation
+ */
+ public function setDefaultTimeout($timeout)
+ {
+ $this->getHttpTransport()->setDefaultTimeout($timeout);
+ }
+
+ /**
+ * Set how NamedLists should be formatted in the response data. This mainly effects
+ * the facet counts format.
+ *
+ * @param string $namedListTreatment
+ * @throws Apache_Solr_InvalidArgumentException If invalid option is set
+ */
+ public function setNamedListTreatment($namedListTreatment)
+ {
+ switch ((string) $namedListTreatment)
+ {
+ case Apache_Solr_Service::NAMED_LIST_FLAT:
+ $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_FLAT;
+ break;
+
+ case Apache_Solr_Service::NAMED_LIST_MAP:
+ $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_MAP;
+ break;
+
+ default:
+ throw new Apache_Solr_InvalidArgumentException('Not a valid named list treatement option');
+ }
+ }
+
+ /**
+ * Get the current setting for named list treatment.
+ *
+ * @return string
+ */
+ public function getNamedListTreatment()
+ {
+ return $this->_namedListTreatment;
+ }
+
+ /**
+ * Set the string used to separate the path form the query string.
+ * Defaulted to '?'
+ *
+ * @param string $queryDelimiter
+ */
+ public function setQueryDelimiter($queryDelimiter)
+ {
+ $this->_queryDelimiter = $queryDelimiter;
+ }
+
+ /**
+ * Set the string used to separate the parameters in thequery string
+ * Defaulted to '&'
+ *
+ * @param string $queryStringDelimiter
+ */
+ public function setQueryStringDelimiter($queryStringDelimiter)
+ {
+ $this->_queryStringDelimiter = $queryStringDelimiter;
+ }
+
+ /**
+ * Call the /admin/ping servlet, can be used to quickly tell if a connection to the
+ * server is able to be made.
+ *
+ * @param float $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
+ * @return float Actual time taken to ping the server, FALSE if timeout or HTTP error status occurs
+ */
+ public function ping($timeout = 2)
+ {
+ $start = microtime(true);
+
+ $httpTransport = $this->getHttpTransport();
+
+ $httpResponse = $httpTransport->performHeadRequest($this->_pingUrl, $timeout);
+ $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
+
+ if ($solrResponse->getHttpStatus() == 200)
+ {
+ return microtime(true) - $start;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Call the /admin/threads servlet and retrieve information about all threads in the
+ * Solr servlet's thread group. Useful for diagnostics.
+ *
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
+ */
+ public function threads()
+ {
+ return $this->_sendRawGet($this->_threadsUrl);
+ }
+
+ /**
+ * Raw Add Method. Takes a raw post body and sends it to the update service. Post body
+ * should be a complete and well formed "add" xml document.
+ *
+ * @param string $rawPost
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
+ */
+ public function add($rawPost)
+ {
+ return $this->_sendRawPost($this->_updateUrl, $rawPost);
+ }
+
+ /**
+ * Add a Solr Document to the index
+ *
+ * @param Apache_Solr_Document $document
+ * @param boolean $allowDups
+ * @param boolean $overwritePending
+ * @param boolean $overwriteCommitted
+ * @param integer $commitWithin The number of milliseconds that a document must be committed within, see @{link http://wiki.apache.org/solr/UpdateXmlMessages#The_Update_Schema} for details. If left empty this property will not be set in the request.
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
+ */
+ public function addDocument(Apache_Solr_Document $document, $allowDups = false, $overwritePending = true, $overwriteCommitted = true, $commitWithin = 0)
+ {
+ $dupValue = $allowDups ? 'true' : 'false';
+ $pendingValue = $overwritePending ? 'true' : 'false';
+ $committedValue = $overwriteCommitted ? 'true' : 'false';
+
+ $commitWithin = (int) $commitWithin;
+ $commitWithinString = $commitWithin > 0 ? " commitWithin=\"{$commitWithin}\"" : '';
+
+ $rawPost = "
+ * ...
+ * $solr = new Apache_Solr_Service(); //or explicitly new Apache_Solr_Service('localhost', 8180, '/solr')
+ *
+ * if ($solr->ping())
+ * {
+ * $solr->deleteByQuery('*:*'); //deletes ALL documents - be careful :)
+ *
+ * $document = new Apache_Solr_Document();
+ * $document->id = uniqid(); //or something else suitably unique
+ *
+ * $document->title = 'Some Title';
+ * $document->content = 'Some content for this wonderful document. Blah blah blah.';
+ *
+ * $solr->addDocument($document); //if you're going to be adding documents in bulk using addDocuments
+ * //with an array of documents is faster
+ *
+ * $solr->commit(); //commit to see the deletes and the document
+ * $solr->optimize(); //merges multiple segments into one
+ *
+ * //and the one we all care about, search!
+ * //any other common or custom parameters to the request handler can go in the
+ * //optional 4th array argument.
+ * $solr->search('content:blah', 0, 10, array('sort' => 'timestamp desc'));
+ * }
+ * ...
+ *
+ *
+ * @todo Investigate using other HTTP clients other than file_get_contents built-in handler. Could provide performance
+ * improvements when dealing with multiple requests by using HTTP's keep alive functionality
+ */
+class Apache_Solr_Service
+{
+ /**
+ * SVN Revision meta data for this class
+ */
+ const SVN_REVISION = '$Revision: 59 $';
+
+ /**
+ * SVN ID meta data for this class
+ */
+ const SVN_ID = '$Id: Service.php 59 2011-02-08 20:38:59Z donovan.jimenez $';
+
+ /**
+ * Response writer we'll request - JSON. See http://code.google.com/p/solr-php-client/issues/detail?id=6#c1 for reasoning
+ */
+ const SOLR_WRITER = 'json';
+
+ /**
+ * NamedList Treatment constants
+ */
+ const NAMED_LIST_FLAT = 'flat';
+ const NAMED_LIST_MAP = 'map';
+
+ /**
+ * Search HTTP Methods
+ */
+ const METHOD_GET = 'GET';
+ const METHOD_POST = 'POST';
+
+ /**
+ * Servlet mappings
+ */
+ const PING_SERVLET = 'admin/ping';
+ const UPDATE_SERVLET = 'update';
+ const SEARCH_SERVLET = 'select';
+ const THREADS_SERVLET = 'admin/threads';
+ const EXTRACT_SERVLET = 'update/extract';
+
+ /**
+ * Server identification strings
+ *
+ * @var string
+ */
+ protected $_host, $_port, $_path;
+
+ /**
+ * Whether {@link Apache_Solr_Response} objects should create {@link Apache_Solr_Document}s in
+ * the returned parsed data
+ *
+ * @var boolean
+ */
+ protected $_createDocuments = true;
+
+ /**
+ * Whether {@link Apache_Solr_Response} objects should have multivalue fields with only a single value
+ * collapsed to appear as a single value would.
+ *
+ * @var boolean
+ */
+ protected $_collapseSingleValueArrays = true;
+
+ /**
+ * How NamedLists should be formatted in the output. This specifically effects facet counts. Valid values
+ * are {@link Apache_Solr_Service::NAMED_LIST_MAP} (default) or {@link Apache_Solr_Service::NAMED_LIST_FLAT}.
+ *
+ * @var string
+ */
+ protected $_namedListTreatment = self::NAMED_LIST_MAP;
+
+ /**
+ * Query delimiters. Someone might want to be able to change
+ * these (to use & instead of & for example), so I've provided them.
+ *
+ * @var string
+ */
+ protected $_queryDelimiter = '?', $_queryStringDelimiter = '&', $_queryBracketsEscaped = true;
+
+ /**
+ * Constructed servlet full path URLs
+ *
+ * @var string
+ */
+ protected $_pingUrl, $_updateUrl, $_searchUrl, $_threadsUrl;
+
+ /**
+ * Keep track of whether our URLs have been constructed
+ *
+ * @var boolean
+ */
+ protected $_urlsInited = false;
+
+ /**
+ * HTTP Transport implementation (pluggable)
+ *
+ * @var Apache_Solr_HttpTransport_Interface
+ */
+ protected $_httpTransport = false;
+
+ /**
+ * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
+ *
+ * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function escape($value)
+ {
+ //list taken from http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
+ $pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
+ $replace = '\\\$1';
+
+ return preg_replace($pattern, $replace, $value);
+ }
+
+ /**
+ * Escape a value meant to be contained in a phrase for special query characters
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function escapePhrase($value)
+ {
+ $pattern = '/("|\\\)/';
+ $replace = '\\\$1';
+
+ return preg_replace($pattern, $replace, $value);
+ }
+
+ /**
+ * Convenience function for creating phrase syntax from a value
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function phrase($value)
+ {
+ return '"' . self::escapePhrase($value) . '"';
+ }
+
+ /**
+ * Constructor. All parameters are optional and will take on default values
+ * if not specified.
+ *
+ * @param string $host
+ * @param string $port
+ * @param string $path
+ * @param Apache_Solr_HttpTransport_Interface $httpTransport
+ */
+ public function __construct($host = 'localhost', $port = 8180, $path = '/solr/', $httpTransport = false)
+ {
+ $this->setHost($host);
+ $this->setPort($port);
+ $this->setPath($path);
+
+ $this->_initUrls();
+
+ if ($httpTransport)
+ {
+ $this->setHttpTransport($httpTransport);
+ }
+
+ // check that our php version is >= 5.1.3 so we can correct for http_build_query behavior later
+ $this->_queryBracketsEscaped = version_compare(phpversion(), '5.1.3', '>=');
+ }
+
+ /**
+ * Return a valid http URL given this server's host, port and path and a provided servlet name
+ *
+ * @param string $servlet
+ * @return string
+ */
+ protected function _constructUrl($servlet, $params = array())
+ {
+ if (count($params))
+ {
+ //escape all parameters appropriately for inclusion in the query string
+ $escapedParams = array();
+
+ foreach ($params as $key => $value)
+ {
+ $escapedParams[] = urlencode($key) . '=' . urlencode($value);
+ }
+
+ $queryString = $this->_queryDelimiter . implode($this->_queryStringDelimiter, $escapedParams);
+ }
+ else
+ {
+ $queryString = '';
+ }
+
+ return 'http://' . $this->_host . ':' . $this->_port . $this->_path . $servlet . $queryString;
+ }
+
+ /**
+ * Construct the Full URLs for the three servlets we reference
+ */
+ protected function _initUrls()
+ {
+ //Initialize our full servlet URLs now that we have server information
+ $this->_extractUrl = $this->_constructUrl(self::EXTRACT_SERVLET);
+ $this->_pingUrl = $this->_constructUrl(self::PING_SERVLET);
+ $this->_searchUrl = $this->_constructUrl(self::SEARCH_SERVLET);
+ $this->_threadsUrl = $this->_constructUrl(self::THREADS_SERVLET, array('wt' => self::SOLR_WRITER ));
+ $this->_updateUrl = $this->_constructUrl(self::UPDATE_SERVLET, array('wt' => self::SOLR_WRITER ));
+
+ $this->_urlsInited = true;
+ }
+
+ protected function _generateQueryString($params)
+ {
+ // use http_build_query to encode our arguments because its faster
+ // than urlencoding all the parts ourselves in a loop
+ //
+ // because http_build_query treats arrays differently than we want to, correct the query
+ // string by changing foo[#]=bar (# being an actual number) parameter strings to just
+ // multiple foo=bar strings. This regex should always work since '=' will be urlencoded
+ // anywhere else the regex isn't expecting it
+ //
+ // NOTE: before php 5.1.3 brackets were not url encoded by http_build query - we've checked
+ // the php version in the constructor and put the results in the instance variable. Also, before
+ // 5.1.2 the arg_separator parameter was not available, so don't use it
+ if ($this->_queryBracketsEscaped)
+ {
+ $queryString = http_build_query($params, null, $this->_queryStringDelimiter);
+ return preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $queryString);
+ }
+ else
+ {
+ $queryString = http_build_query($params);
+ return preg_replace('/\\[(?:[0-9]|[1-9][0-9]+)\\]=/', '=', $queryString);
+ }
+ }
+
+ /**
+ * Central method for making a get operation against this Solr Server
+ *
+ * @param string $url
+ * @param float $timeout Read timeout in seconds
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If a non 200 response status is returned
+ */
+ protected function _sendRawGet($url, $timeout = FALSE)
+ {
+ $httpTransport = $this->getHttpTransport();
+
+ $httpResponse = $httpTransport->performGetRequest($url, $timeout);
+ $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
+
+ if ($solrResponse->getHttpStatus() != 200)
+ {
+ throw new Apache_Solr_HttpTransportException($solrResponse);
+ }
+
+ return $solrResponse;
+ }
+
+ /**
+ * Central method for making a post operation against this Solr Server
+ *
+ * @param string $url
+ * @param string $rawPost
+ * @param float $timeout Read timeout in seconds
+ * @param string $contentType
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If a non 200 response status is returned
+ */
+ protected function _sendRawPost($url, $rawPost, $timeout = FALSE, $contentType = 'text/xml; charset=UTF-8')
+ {
+ $httpTransport = $this->getHttpTransport();
+
+ $httpResponse = $httpTransport->performPostRequest($url, $rawPost, $contentType, $timeout);
+ $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
+
+ if ($solrResponse->getHttpStatus() != 200)
+ {
+ throw new Apache_Solr_HttpTransportException($solrResponse);
+ }
+
+ return $solrResponse;
+ }
+
+ /**
+ * Returns the set host
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->_host;
+ }
+
+ /**
+ * Set the host used. If empty will fallback to constants
+ *
+ * @param string $host
+ *
+ * @throws Apache_Solr_InvalidArgumentException If the host parameter is empty
+ */
+ public function setHost($host)
+ {
+ //Use the provided host or use the default
+ if (empty($host))
+ {
+ throw new Apache_Solr_InvalidArgumentException('Host parameter is empty');
+ }
+ else
+ {
+ $this->_host = $host;
+ }
+
+ if ($this->_urlsInited)
+ {
+ $this->_initUrls();
+ }
+ }
+
+ /**
+ * Get the set port
+ *
+ * @return integer
+ */
+ public function getPort()
+ {
+ return $this->_port;
+ }
+
+ /**
+ * Set the port used. If empty will fallback to constants
+ *
+ * @param integer $port
+ *
+ * @throws Apache_Solr_InvalidArgumentException If the port parameter is empty
+ */
+ public function setPort($port)
+ {
+ //Use the provided port or use the default
+ $port = (int) $port;
+
+ if ($port <= 0)
+ {
+ throw new Apache_Solr_InvalidArgumentException('Port is not a valid port number');
+ }
+ else
+ {
+ $this->_port = $port;
+ }
+
+ if ($this->_urlsInited)
+ {
+ $this->_initUrls();
+ }
+ }
+
+ /**
+ * Get the set path.
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->_path;
+ }
+
+ /**
+ * Set the path used. If empty will fallback to constants
+ *
+ * @param string $path
+ */
+ public function setPath($path)
+ {
+ $path = trim($path, '/');
+
+ $this->_path = '/' . $path . '/';
+
+ if ($this->_urlsInited)
+ {
+ $this->_initUrls();
+ }
+ }
+
+ /**
+ * Get the current configured HTTP Transport
+ *
+ * @return HttpTransportInterface
+ */
+ public function getHttpTransport()
+ {
+ // lazy load a default if one has not be set
+ if ($this->_httpTransport === false)
+ {
+ require_once(dirname(__FILE__) . '/HttpTransport/FileGetContents.php');
+
+ $this->_httpTransport = new Apache_Solr_HttpTransport_FileGetContents();
+ }
+
+ return $this->_httpTransport;
+ }
+
+ /**
+ * Set the HTTP Transport implemenation that will be used for all HTTP requests
+ *
+ * @param Apache_Solr_HttpTransport_Interface
+ */
+ public function setHttpTransport(Apache_Solr_HttpTransport_Interface $httpTransport)
+ {
+ $this->_httpTransport = $httpTransport;
+ }
+
+ /**
+ * Set the create documents flag. This determines whether {@link Apache_Solr_Response} objects will
+ * parse the response and create {@link Apache_Solr_Document} instances in place.
+ *
+ * @param boolean $createDocuments
+ */
+ public function setCreateDocuments($createDocuments)
+ {
+ $this->_createDocuments = (bool) $createDocuments;
+ }
+
+ /**
+ * Get the current state of teh create documents flag.
+ *
+ * @return boolean
+ */
+ public function getCreateDocuments()
+ {
+ return $this->_createDocuments;
+ }
+
+ /**
+ * Set the collapse single value arrays flag.
+ *
+ * @param boolean $collapseSingleValueArrays
+ */
+ public function setCollapseSingleValueArrays($collapseSingleValueArrays)
+ {
+ $this->_collapseSingleValueArrays = (bool) $collapseSingleValueArrays;
+ }
+
+ /**
+ * Get the current state of the collapse single value arrays flag.
+ *
+ * @return boolean
+ */
+ public function getCollapseSingleValueArrays()
+ {
+ return $this->_collapseSingleValueArrays;
+ }
+
+ /**
+ * Get the current default timeout setting (initially the default_socket_timeout ini setting)
+ * in seconds
+ *
+ * @return float
+ *
+ * @deprecated Use the getDefaultTimeout method on the HTTP transport implementation
+ */
+ public function getDefaultTimeout()
+ {
+ return $this->getHttpTransport()->getDefaultTimeout();
+ }
+
+ /**
+ * Set the default timeout for all calls that aren't passed a specific timeout
+ *
+ * @param float $timeout Timeout value in seconds
+ *
+ * @deprecated Use the setDefaultTimeout method on the HTTP transport implementation
+ */
+ public function setDefaultTimeout($timeout)
+ {
+ $this->getHttpTransport()->setDefaultTimeout($timeout);
+ }
+
+ /**
+ * Set how NamedLists should be formatted in the response data. This mainly effects
+ * the facet counts format.
+ *
+ * @param string $namedListTreatment
+ * @throws Apache_Solr_InvalidArgumentException If invalid option is set
+ */
+ public function setNamedListTreatment($namedListTreatment)
+ {
+ switch ((string) $namedListTreatment)
+ {
+ case Apache_Solr_Service::NAMED_LIST_FLAT:
+ $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_FLAT;
+ break;
+
+ case Apache_Solr_Service::NAMED_LIST_MAP:
+ $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_MAP;
+ break;
+
+ default:
+ throw new Apache_Solr_InvalidArgumentException('Not a valid named list treatement option');
+ }
+ }
+
+ /**
+ * Get the current setting for named list treatment.
+ *
+ * @return string
+ */
+ public function getNamedListTreatment()
+ {
+ return $this->_namedListTreatment;
+ }
+
+ /**
+ * Set the string used to separate the path form the query string.
+ * Defaulted to '?'
+ *
+ * @param string $queryDelimiter
+ */
+ public function setQueryDelimiter($queryDelimiter)
+ {
+ $this->_queryDelimiter = $queryDelimiter;
+ }
+
+ /**
+ * Set the string used to separate the parameters in thequery string
+ * Defaulted to '&'
+ *
+ * @param string $queryStringDelimiter
+ */
+ public function setQueryStringDelimiter($queryStringDelimiter)
+ {
+ $this->_queryStringDelimiter = $queryStringDelimiter;
+ }
+
+ /**
+ * Call the /admin/ping servlet, can be used to quickly tell if a connection to the
+ * server is able to be made.
+ *
+ * @param float $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
+ * @return float Actual time taken to ping the server, FALSE if timeout or HTTP error status occurs
+ */
+ public function ping($timeout = 2)
+ {
+ $start = microtime(true);
+
+ $httpTransport = $this->getHttpTransport();
+
+ $httpResponse = $httpTransport->performHeadRequest($this->_pingUrl, $timeout);
+ $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
+
+ if ($solrResponse->getHttpStatus() == 200)
+ {
+ return microtime(true) - $start;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Call the /admin/threads servlet and retrieve information about all threads in the
+ * Solr servlet's thread group. Useful for diagnostics.
+ *
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
+ */
+ public function threads()
+ {
+ return $this->_sendRawGet($this->_threadsUrl);
+ }
+
+ /**
+ * Raw Add Method. Takes a raw post body and sends it to the update service. Post body
+ * should be a complete and well formed "add" xml document.
+ *
+ * @param string $rawPost
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
+ */
+ public function add($rawPost)
+ {
+ return $this->_sendRawPost($this->_updateUrl, $rawPost);
+ }
+
+ /**
+ * Add a Solr Document to the index
+ *
+ * @param Apache_Solr_Document $document
+ * @param boolean $allowDups
+ * @param boolean $overwritePending
+ * @param boolean $overwriteCommitted
+ * @param integer $commitWithin The number of milliseconds that a document must be committed within, see @{link http://wiki.apache.org/solr/UpdateXmlMessages#The_Update_Schema} for details. If left empty this property will not be set in the request.
+ * @return Apache_Solr_Response
+ *
+ * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
+ */
+ public function addDocument(Apache_Solr_Document $document, $allowDups = false, $overwritePending = true, $overwriteCommitted = true, $commitWithin = 0)
+ {
+ $dupValue = $allowDups ? 'true' : 'false';
+ $pendingValue = $overwritePending ? 'true' : 'false';
+ $committedValue = $overwriteCommitted ? 'true' : 'false';
+
+ $commitWithin = (int) $commitWithin;
+ $commitWithinString = $commitWithin > 0 ? " commitWithin=\"{$commitWithin}\"" : '';
+
+ $rawPost = "' . $response['response']->numFound . ' result(s) found
'; + if ($response['response']->numFound > 0) { + $output .= 'Book: ' . $doc->title . ' (' . $doc->author . ')
'; + $output .= 'Chapter: ' . $doc->chapter . '
'; + $output .= 'Example: ' . $doc->example . '
'; + $output .= ''; + $output .= '0 result(s) found
'; + } + } + + $commands[] = ajax_command_html("#ajax-search-result-replace", $output); + + return array('#type' => 'ajax', '#commands' => $commands); + +} -- cgit From c5681faf884fd51bc3fc842944fc39c985dc58fc Mon Sep 17 00:00:00 2001 From: prashantsinalkar Date: Wed, 23 Oct 2019 20:14:05 +0530 Subject: updated the gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 072b683..22d9c86 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,10 @@ xmlrpc.php /profiles /scripts /themes + +# Ignore vim temp. files +*.swo +*.swp +*~ +*.*.bkp +*.*~ -- cgit From f8f20597cbfe50d1a8dc3288cf0a8ac9bf6c8ffa Mon Sep 17 00:00:00 2001 From: prashantsinalkar Date: Fri, 25 Oct 2019 15:47:43 +0530 Subject: fixed responce issue --- Apache/Solr/Service.php~ | 1197 ---------------------------------------------- solr_search.module | 6 +- 2 files changed, 3 insertions(+), 1200 deletions(-) delete mode 100755 Apache/Solr/Service.php~ diff --git a/Apache/Solr/Service.php~ b/Apache/Solr/Service.php~ deleted file mode 100755 index 8352dd8..0000000 --- a/Apache/Solr/Service.php~ +++ /dev/null @@ -1,1197 +0,0 @@ - - */ - -// See Issue #1 (http://code.google.com/p/solr-php-client/issues/detail?id=1) -// Doesn't follow typical include path conventions, but is more convenient for users -require_once(dirname(__FILE__) . '/Exception.php'); -require_once(dirname(__FILE__) . '/HttpTransportException.php'); -require_once(dirname(__FILE__) . '/InvalidArgumentException.php'); - -require_once(dirname(__FILE__) . '/Document.php'); -require_once(dirname(__FILE__) . '/Response.php'); - -require_once(dirname(__FILE__) . '/HttpTransport/Interface.php'); - -/** - * Starting point for the Solr API. Represents a Solr server resource and has - * methods for pinging, adding, deleting, committing, optimizing and searching. - * - * Example Usage: - *
- * ...
- * $solr = new Apache_Solr_Service(); //or explicitly new Apache_Solr_Service('localhost', 8180, '/solr')
- *
- * if ($solr->ping())
- * {
- * $solr->deleteByQuery('*:*'); //deletes ALL documents - be careful :)
- *
- * $document = new Apache_Solr_Document();
- * $document->id = uniqid(); //or something else suitably unique
- *
- * $document->title = 'Some Title';
- * $document->content = 'Some content for this wonderful document. Blah blah blah.';
- *
- * $solr->addDocument($document); //if you're going to be adding documents in bulk using addDocuments
- * //with an array of documents is faster
- *
- * $solr->commit(); //commit to see the deletes and the document
- * $solr->optimize(); //merges multiple segments into one
- *
- * //and the one we all care about, search!
- * //any other common or custom parameters to the request handler can go in the
- * //optional 4th array argument.
- * $solr->search('content:blah', 0, 10, array('sort' => 'timestamp desc'));
- * }
- * ...
- *
- *
- * @todo Investigate using other HTTP clients other than file_get_contents built-in handler. Could provide performance
- * improvements when dealing with multiple requests by using HTTP's keep alive functionality
- */
-class Apache_Solr_Service
-{
- /**
- * SVN Revision meta data for this class
- */
- const SVN_REVISION = '$Revision: 59 $';
-
- /**
- * SVN ID meta data for this class
- */
- const SVN_ID = '$Id: Service.php 59 2011-02-08 20:38:59Z donovan.jimenez $';
-
- /**
- * Response writer we'll request - JSON. See http://code.google.com/p/solr-php-client/issues/detail?id=6#c1 for reasoning
- */
- const SOLR_WRITER = 'json';
-
- /**
- * NamedList Treatment constants
- */
- const NAMED_LIST_FLAT = 'flat';
- const NAMED_LIST_MAP = 'map';
-
- /**
- * Search HTTP Methods
- */
- const METHOD_GET = 'GET';
- const METHOD_POST = 'POST';
-
- /**
- * Servlet mappings
- */
- const PING_SERVLET = 'admin/ping';
- const UPDATE_SERVLET = 'update';
- const SEARCH_SERVLET = 'select';
- const THREADS_SERVLET = 'admin/threads';
- const EXTRACT_SERVLET = 'update/extract';
-
- /**
- * Server identification strings
- *
- * @var string
- */
- protected $_host, $_port, $_path;
-
- /**
- * Whether {@link Apache_Solr_Response} objects should create {@link Apache_Solr_Document}s in
- * the returned parsed data
- *
- * @var boolean
- */
- protected $_createDocuments = true;
-
- /**
- * Whether {@link Apache_Solr_Response} objects should have multivalue fields with only a single value
- * collapsed to appear as a single value would.
- *
- * @var boolean
- */
- protected $_collapseSingleValueArrays = true;
-
- /**
- * How NamedLists should be formatted in the output. This specifically effects facet counts. Valid values
- * are {@link Apache_Solr_Service::NAMED_LIST_MAP} (default) or {@link Apache_Solr_Service::NAMED_LIST_FLAT}.
- *
- * @var string
- */
- protected $_namedListTreatment = self::NAMED_LIST_MAP;
-
- /**
- * Query delimiters. Someone might want to be able to change
- * these (to use & instead of & for example), so I've provided them.
- *
- * @var string
- */
- protected $_queryDelimiter = '?', $_queryStringDelimiter = '&', $_queryBracketsEscaped = true;
-
- /**
- * Constructed servlet full path URLs
- *
- * @var string
- */
- protected $_pingUrl, $_updateUrl, $_searchUrl, $_threadsUrl;
-
- /**
- * Keep track of whether our URLs have been constructed
- *
- * @var boolean
- */
- protected $_urlsInited = false;
-
- /**
- * HTTP Transport implementation (pluggable)
- *
- * @var Apache_Solr_HttpTransport_Interface
- */
- protected $_httpTransport = false;
-
- /**
- * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
- *
- * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
- *
- * @param string $value
- * @return string
- */
- static public function escape($value)
- {
- //list taken from http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
- $pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
- $replace = '\\\$1';
-
- return preg_replace($pattern, $replace, $value);
- }
-
- /**
- * Escape a value meant to be contained in a phrase for special query characters
- *
- * @param string $value
- * @return string
- */
- static public function escapePhrase($value)
- {
- $pattern = '/("|\\\)/';
- $replace = '\\\$1';
-
- return preg_replace($pattern, $replace, $value);
- }
-
- /**
- * Convenience function for creating phrase syntax from a value
- *
- * @param string $value
- * @return string
- */
- static public function phrase($value)
- {
- return '"' . self::escapePhrase($value) . '"';
- }
-
- /**
- * Constructor. All parameters are optional and will take on default values
- * if not specified.
- *
- * @param string $host
- * @param string $port
- * @param string $path
- * @param Apache_Solr_HttpTransport_Interface $httpTransport
- */
- public function __construct($host = 'localhost', $port = 8180, $path = '/solr/', $httpTransport = false)
- {
- $this->setHost($host);
- $this->setPort($port);
- $this->setPath($path);
-
- $this->_initUrls();
-
- if ($httpTransport)
- {
- $this->setHttpTransport($httpTransport);
- }
-
- // check that our php version is >= 5.1.3 so we can correct for http_build_query behavior later
- $this->_queryBracketsEscaped = version_compare(phpversion(), '5.1.3', '>=');
- }
-
- /**
- * Return a valid http URL given this server's host, port and path and a provided servlet name
- *
- * @param string $servlet
- * @return string
- */
- protected function _constructUrl($servlet, $params = array())
- {
- if (count($params))
- {
- //escape all parameters appropriately for inclusion in the query string
- $escapedParams = array();
-
- foreach ($params as $key => $value)
- {
- $escapedParams[] = urlencode($key) . '=' . urlencode($value);
- }
-
- $queryString = $this->_queryDelimiter . implode($this->_queryStringDelimiter, $escapedParams);
- }
- else
- {
- $queryString = '';
- }
-
- return 'http://' . $this->_host . ':' . $this->_port . $this->_path . $servlet . $queryString;
- }
-
- /**
- * Construct the Full URLs for the three servlets we reference
- */
- protected function _initUrls()
- {
- //Initialize our full servlet URLs now that we have server information
- $this->_extractUrl = $this->_constructUrl(self::EXTRACT_SERVLET);
- $this->_pingUrl = $this->_constructUrl(self::PING_SERVLET);
- $this->_searchUrl = $this->_constructUrl(self::SEARCH_SERVLET);
- $this->_threadsUrl = $this->_constructUrl(self::THREADS_SERVLET, array('wt' => self::SOLR_WRITER ));
- $this->_updateUrl = $this->_constructUrl(self::UPDATE_SERVLET, array('wt' => self::SOLR_WRITER ));
-
- $this->_urlsInited = true;
- }
-
- protected function _generateQueryString($params)
- {
- // use http_build_query to encode our arguments because its faster
- // than urlencoding all the parts ourselves in a loop
- //
- // because http_build_query treats arrays differently than we want to, correct the query
- // string by changing foo[#]=bar (# being an actual number) parameter strings to just
- // multiple foo=bar strings. This regex should always work since '=' will be urlencoded
- // anywhere else the regex isn't expecting it
- //
- // NOTE: before php 5.1.3 brackets were not url encoded by http_build query - we've checked
- // the php version in the constructor and put the results in the instance variable. Also, before
- // 5.1.2 the arg_separator parameter was not available, so don't use it
- if ($this->_queryBracketsEscaped)
- {
- $queryString = http_build_query($params, null, $this->_queryStringDelimiter);
- return preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $queryString);
- }
- else
- {
- $queryString = http_build_query($params);
- return preg_replace('/\\[(?:[0-9]|[1-9][0-9]+)\\]=/', '=', $queryString);
- }
- }
-
- /**
- * Central method for making a get operation against this Solr Server
- *
- * @param string $url
- * @param float $timeout Read timeout in seconds
- * @return Apache_Solr_Response
- *
- * @throws Apache_Solr_HttpTransportException If a non 200 response status is returned
- */
- protected function _sendRawGet($url, $timeout = FALSE)
- {
- $httpTransport = $this->getHttpTransport();
-
- $httpResponse = $httpTransport->performGetRequest($url, $timeout);
- $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
-
- if ($solrResponse->getHttpStatus() != 200)
- {
- throw new Apache_Solr_HttpTransportException($solrResponse);
- }
-
- return $solrResponse;
- }
-
- /**
- * Central method for making a post operation against this Solr Server
- *
- * @param string $url
- * @param string $rawPost
- * @param float $timeout Read timeout in seconds
- * @param string $contentType
- * @return Apache_Solr_Response
- *
- * @throws Apache_Solr_HttpTransportException If a non 200 response status is returned
- */
- protected function _sendRawPost($url, $rawPost, $timeout = FALSE, $contentType = 'text/xml; charset=UTF-8')
- {
- $httpTransport = $this->getHttpTransport();
-
- $httpResponse = $httpTransport->performPostRequest($url, $rawPost, $contentType, $timeout);
- $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
-
- if ($solrResponse->getHttpStatus() != 200)
- {
- throw new Apache_Solr_HttpTransportException($solrResponse);
- }
-
- return $solrResponse;
- }
-
- /**
- * Returns the set host
- *
- * @return string
- */
- public function getHost()
- {
- return $this->_host;
- }
-
- /**
- * Set the host used. If empty will fallback to constants
- *
- * @param string $host
- *
- * @throws Apache_Solr_InvalidArgumentException If the host parameter is empty
- */
- public function setHost($host)
- {
- //Use the provided host or use the default
- if (empty($host))
- {
- throw new Apache_Solr_InvalidArgumentException('Host parameter is empty');
- }
- else
- {
- $this->_host = $host;
- }
-
- if ($this->_urlsInited)
- {
- $this->_initUrls();
- }
- }
-
- /**
- * Get the set port
- *
- * @return integer
- */
- public function getPort()
- {
- return $this->_port;
- }
-
- /**
- * Set the port used. If empty will fallback to constants
- *
- * @param integer $port
- *
- * @throws Apache_Solr_InvalidArgumentException If the port parameter is empty
- */
- public function setPort($port)
- {
- //Use the provided port or use the default
- $port = (int) $port;
-
- if ($port <= 0)
- {
- throw new Apache_Solr_InvalidArgumentException('Port is not a valid port number');
- }
- else
- {
- $this->_port = $port;
- }
-
- if ($this->_urlsInited)
- {
- $this->_initUrls();
- }
- }
-
- /**
- * Get the set path.
- *
- * @return string
- */
- public function getPath()
- {
- return $this->_path;
- }
-
- /**
- * Set the path used. If empty will fallback to constants
- *
- * @param string $path
- */
- public function setPath($path)
- {
- $path = trim($path, '/');
-
- $this->_path = '/' . $path . '/';
-
- if ($this->_urlsInited)
- {
- $this->_initUrls();
- }
- }
-
- /**
- * Get the current configured HTTP Transport
- *
- * @return HttpTransportInterface
- */
- public function getHttpTransport()
- {
- // lazy load a default if one has not be set
- if ($this->_httpTransport === false)
- {
- require_once(dirname(__FILE__) . '/HttpTransport/FileGetContents.php');
-
- $this->_httpTransport = new Apache_Solr_HttpTransport_FileGetContents();
- }
-
- return $this->_httpTransport;
- }
-
- /**
- * Set the HTTP Transport implemenation that will be used for all HTTP requests
- *
- * @param Apache_Solr_HttpTransport_Interface
- */
- public function setHttpTransport(Apache_Solr_HttpTransport_Interface $httpTransport)
- {
- $this->_httpTransport = $httpTransport;
- }
-
- /**
- * Set the create documents flag. This determines whether {@link Apache_Solr_Response} objects will
- * parse the response and create {@link Apache_Solr_Document} instances in place.
- *
- * @param boolean $createDocuments
- */
- public function setCreateDocuments($createDocuments)
- {
- $this->_createDocuments = (bool) $createDocuments;
- }
-
- /**
- * Get the current state of teh create documents flag.
- *
- * @return boolean
- */
- public function getCreateDocuments()
- {
- return $this->_createDocuments;
- }
-
- /**
- * Set the collapse single value arrays flag.
- *
- * @param boolean $collapseSingleValueArrays
- */
- public function setCollapseSingleValueArrays($collapseSingleValueArrays)
- {
- $this->_collapseSingleValueArrays = (bool) $collapseSingleValueArrays;
- }
-
- /**
- * Get the current state of the collapse single value arrays flag.
- *
- * @return boolean
- */
- public function getCollapseSingleValueArrays()
- {
- return $this->_collapseSingleValueArrays;
- }
-
- /**
- * Get the current default timeout setting (initially the default_socket_timeout ini setting)
- * in seconds
- *
- * @return float
- *
- * @deprecated Use the getDefaultTimeout method on the HTTP transport implementation
- */
- public function getDefaultTimeout()
- {
- return $this->getHttpTransport()->getDefaultTimeout();
- }
-
- /**
- * Set the default timeout for all calls that aren't passed a specific timeout
- *
- * @param float $timeout Timeout value in seconds
- *
- * @deprecated Use the setDefaultTimeout method on the HTTP transport implementation
- */
- public function setDefaultTimeout($timeout)
- {
- $this->getHttpTransport()->setDefaultTimeout($timeout);
- }
-
- /**
- * Set how NamedLists should be formatted in the response data. This mainly effects
- * the facet counts format.
- *
- * @param string $namedListTreatment
- * @throws Apache_Solr_InvalidArgumentException If invalid option is set
- */
- public function setNamedListTreatment($namedListTreatment)
- {
- switch ((string) $namedListTreatment)
- {
- case Apache_Solr_Service::NAMED_LIST_FLAT:
- $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_FLAT;
- break;
-
- case Apache_Solr_Service::NAMED_LIST_MAP:
- $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_MAP;
- break;
-
- default:
- throw new Apache_Solr_InvalidArgumentException('Not a valid named list treatement option');
- }
- }
-
- /**
- * Get the current setting for named list treatment.
- *
- * @return string
- */
- public function getNamedListTreatment()
- {
- return $this->_namedListTreatment;
- }
-
- /**
- * Set the string used to separate the path form the query string.
- * Defaulted to '?'
- *
- * @param string $queryDelimiter
- */
- public function setQueryDelimiter($queryDelimiter)
- {
- $this->_queryDelimiter = $queryDelimiter;
- }
-
- /**
- * Set the string used to separate the parameters in thequery string
- * Defaulted to '&'
- *
- * @param string $queryStringDelimiter
- */
- public function setQueryStringDelimiter($queryStringDelimiter)
- {
- $this->_queryStringDelimiter = $queryStringDelimiter;
- }
-
- /**
- * Call the /admin/ping servlet, can be used to quickly tell if a connection to the
- * server is able to be made.
- *
- * @param float $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
- * @return float Actual time taken to ping the server, FALSE if timeout or HTTP error status occurs
- */
- public function ping($timeout = 2)
- {
- $start = microtime(true);
-
- $httpTransport = $this->getHttpTransport();
-
- $httpResponse = $httpTransport->performHeadRequest($this->_pingUrl, $timeout);
- $solrResponse = new Apache_Solr_Response($httpResponse, $this->_createDocuments, $this->_collapseSingleValueArrays);
-
- if ($solrResponse->getHttpStatus() == 200)
- {
- return microtime(true) - $start;
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Call the /admin/threads servlet and retrieve information about all threads in the
- * Solr servlet's thread group. Useful for diagnostics.
- *
- * @return Apache_Solr_Response
- *
- * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
- */
- public function threads()
- {
- return $this->_sendRawGet($this->_threadsUrl);
- }
-
- /**
- * Raw Add Method. Takes a raw post body and sends it to the update service. Post body
- * should be a complete and well formed "add" xml document.
- *
- * @param string $rawPost
- * @return Apache_Solr_Response
- *
- * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
- */
- public function add($rawPost)
- {
- return $this->_sendRawPost($this->_updateUrl, $rawPost);
- }
-
- /**
- * Add a Solr Document to the index
- *
- * @param Apache_Solr_Document $document
- * @param boolean $allowDups
- * @param boolean $overwritePending
- * @param boolean $overwriteCommitted
- * @param integer $commitWithin The number of milliseconds that a document must be committed within, see @{link http://wiki.apache.org/solr/UpdateXmlMessages#The_Update_Schema} for details. If left empty this property will not be set in the request.
- * @return Apache_Solr_Response
- *
- * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
- */
- public function addDocument(Apache_Solr_Document $document, $allowDups = false, $overwritePending = true, $overwriteCommitted = true, $commitWithin = 0)
- {
- $dupValue = $allowDups ? 'true' : 'false';
- $pendingValue = $overwritePending ? 'true' : 'false';
- $committedValue = $overwriteCommitted ? 'true' : 'false';
-
- $commitWithin = (int) $commitWithin;
- $commitWithinString = $commitWithin > 0 ? " commitWithin=\"{$commitWithin}\"" : '';
-
- $rawPost = "Book: ' . $doc->title . ' (' . $doc->author . ')
'; - $output .= 'Chapter: ' . $doc->chapter . '
'; - $output .= 'Example: ' . $doc->example . '
'; - $output .= 'Links: ⤵ Download entire book » View this example
'; + $output .= 'Chapter: ' . $doc->chapter[0] . '
'; + $output .= 'Example: ' . $doc->example[0] . '
'; + $output .= ''; $output .= '