# Source for file Service.php

Documentation is available at Service.php

1. <?php
2. /**
3. * Copyright (c) 2007-2009, Conduit Internet Technologies, Inc.
4. * All rights reserved.
5. *
6. * Redistribution and use in source and binary forms, with or without
7. * modification, are permitted provided that the following conditions are met:
8. *
9. * - Redistributions of source code must retain the above copyright notice,
10. * this list of conditions and the following disclaimer.
11. * - Redistributions in binary form must reproduce the above copyright
12. * notice, this list of conditions and the following disclaimer in the
13. * documentation and/or other materials provided with the distribution.
14. * - Neither the name of Conduit Internet Technologies, Inc. nor the names of
15. * its contributors may be used to endorse or promote products derived from
16. * this software without specific prior written permission.
17. *
18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28. * POSSIBILITY OF SUCH DAMAGE.
29. *
30. * @copyright Copyright 2007-2009 Conduit Internet Technologies, Inc. (http://conduit-it.com)
31. * @license New BSD (http://solr-php-client.googlecode.com/svn/trunk/COPYING)
32. * @version $Id: Service.php 22 2009-11-09 22:46:54Z donovan.jimenez $
33. *
34. * @package Apache
35. * @subpackage Solr
36. * @author Donovan Jimenez <djimenez@conduit-it.com>
37. */
39. // See Issue #1 (http://code.google.com/p/solr-php-client/issues/detail?id=1)
40. // Doesn't follow typical include path conventions, but is more convenient for users
41. require_once(dirname(__FILE__) . '/Document.php');
42. require_once(dirname(__FILE__) . '/Response.php');
44. /**
45. * Starting point for the Solr API. Represents a Solr server resource and has
46. * methods for pinging, adding, deleting, committing, optimizing and searching.
47. *
48. * Example Usage:
49. * <code>
50. * ...
51. * $solr = new Apache_Solr_Service(); //or explicitly new Apache_Solr_Service('localhost', 8180, '/solr')
52. *
53. * if ($solr->ping())
54. * {
55. * $solr->deleteByQuery('*:*'); //deletes ALL documents - be careful :)
56. *
57. * $document = new Apache_Solr_Document();
58. * $document->id = uniqid(); //or something else suitably unique
59. *
60. * $document->title = 'Some Title';
61. * $document->content = 'Some content for this wonderful document. Blah blah blah.';
62. *
63. * $solr->addDocument($document); //if you're going to be adding documents in bulk using addDocuments
64. * //with an array of documents is faster
65. *
66. * $solr->commit(); //commit to see the deletes and the document
67. * $solr->optimize(); //merges multiple segments into one
68. *
69. * //and the one we all care about, search!
70. * //any other common or custom parameters to the request handler can go in the
71. * //optional 4th array argument.
72. * $solr->search('content:blah', 0, 10, array('sort' => 'timestamp desc'));
73. * }
74. * ...
75. * </code>
76. *
77. * @todo Investigate using other HTTP clients other than file_get_contents built-in handler. Could provide performance
78. * improvements when dealing with multiple requests by using HTTP's keep alive functionality
79. */
80. class Apache_Solr_Service
81. {
82. /**
83. * SVN Revision meta data for this class
84. */
85. const SVN_REVISION = '$Revision: 22 $';
87. /**
88. * SVN ID meta data for this class
89. */
90. const SVN_ID = '$Id: Service.php 22 2009-11-09 22:46:54Z donovan.jimenez $';
92. /**
93. * Response version we support
94. */
95. const SOLR_VERSION = '1.2';
97. /**
98. * Response writer we'll request - JSON. See http://code.google.com/p/solr-php-client/issues/detail?id=6#c1 for reasoning
99. */
100. const SOLR_WRITER = 'json';
102. /**
103. * NamedList Treatment constants
104. */
105. const NAMED_LIST_FLAT = 'flat';
106. const NAMED_LIST_MAP = 'map';
108. /**
109. * Search HTTP Methods
110. */
111. const METHOD_GET = 'GET';
112. const METHOD_POST = 'POST';
114. /**
115. * Servlet mappings
116. */
117. const PING_SERVLET = 'admin/ping';
118. const UPDATE_SERVLET = 'update';
119. const SEARCH_SERVLET = 'select';
120. const THREADS_SERVLET = 'admin/threads';
122. /**
123. * Server identification strings
124. *
125. * @var string
126. */
127. protected $_host, $_port, $_path;
129. /**
130. * Whether {@link Apache_Solr_Response} objects should create {@link Apache_Solr_Document}s in
131. * the returned parsed data
132. *
133. * @var boolean
134. */
135. protected $_createDocuments = true;
137. /**
138. * Whether {@link Apache_Solr_Response} objects should have multivalue fields with only a single value
139. * collapsed to appear as a single value would.
140. *
141. * @var boolean
142. */
143. protected $_collapseSingleValueArrays = true;
145. /**
146. * How NamedLists should be formatted in the output. This specifically effects facet counts. Valid values
147. * are {@link Apache_Solr_Service::NAMED_LIST_MAP} (default) or {@link Apache_Solr_Service::NAMED_LIST_FLAT}.
148. *
149. * @var string
150. */
151. protected $_namedListTreatment = self::NAMED_LIST_MAP;
153. /**
154. * Query delimiters. Someone might want to be able to change
155. * these (to use &amp; instead of & for example), so I've provided them.
156. *
157. * @var string
158. */
159. protected $_queryDelimiter = '?', $_queryStringDelimiter = '&';
161. /**
162. * Constructed servlet full path URLs
163. *
164. * @var string
165. */
166. protected $_pingUrl, $_updateUrl, $_searchUrl, $_threadsUrl;
168. /**
169. * Keep track of whether our URLs have been constructed
170. *
171. * @var boolean
172. */
173. protected $_urlsInited = false;
175. /**
176. * Reusable stream context resources for GET and POST operations
177. *
178. * @var resource
179. */
180. protected $_getContext, $_postContext;
182. /**
183. * Default HTTP timeout when one is not specified (initialized to default_socket_timeout ini setting)
184. *
185. * var float
186. */
187. protected $_defaultTimeout;
189. /**
190. * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
191. *
192. * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
193. *
194. * @param string $value
195. * @return string
196. */
197. static public function escape($value)
198. {
199. //list taken from http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
200. $pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
201. $replace = '\\\$1';
203. return preg_replace($pattern, $replace, $value);
204. }
206. /**
207. * Escape a value meant to be contained in a phrase for special query characters
208. *
209. * @param string $value
210. * @return string
211. */
212. static public function escapePhrase($value)
213. {
214. $pattern = '/("|\\\)/';
215. $replace = '\\\$1';
217. return preg_replace($pattern, $replace, $value);
218. }
220. /**
221. * Convenience function for creating phrase syntax from a value
222. *
223. * @param string $value
224. * @return string
225. */
226. static public function phrase($value)
227. {
228. return '"' . self::escapePhrase($value) . '"';
229. }
231. /**
232. * Constructor. All parameters are optional and will take on default values
233. * if not specified.
234. *
235. * @param string $host
236. * @param string $port
237. * @param string $path
238. */
239. public function __construct($host = 'localhost', $port = 8180, $path = '/solr/')
240. {
241. $this->setHost($host);
242. $this->setPort($port);
243. $this->setPath($path);
245. $this->_initUrls();
247. // create our shared get and post stream contexts
248. $this->_getContext = stream_context_create();
249. $this->_postContext = stream_context_create();
251. // determine our default http timeout from ini settings
252. $this->_defaultTimeout = (int) ini_get('default_socket_timeout');
254. // double check we didn't get 0 for a timeout
255. if ($this->_defaultTimeout <= 0)
256. {
257. $this->_defaultTimeout = 60;
258. }
259. }
261. /**
262. * Return a valid http URL given this server's host, port and path and a provided servlet name
263. *
264. * @param string $servlet
265. * @return string
266. */
267. protected function _constructUrl($servlet, $params = array())
268. {
269. if (count($params))
270. {
271. //escape all parameters appropriately for inclusion in the query string
272. $escapedParams = array();
274. foreach ($params as $key => $value)
275. {
276. $escapedParams[] = urlencode($key) . '=' . urlencode($value);
277. }
279. $queryString = $this->_queryDelimiter . implode($this->_queryStringDelimiter, $escapedParams);
280. }
281. else
282. {
283. $queryString = '';
284. }
286. return 'http://' . $this->_host . ':' . $this->_port . $this->_path . $servlet . $queryString;
287. }
289. /**
290. * Construct the Full URLs for the three servlets we reference
291. */
292. protected function _initUrls()
293. {
294. //Initialize our full servlet URLs now that we have server information
295. $this->_pingUrl = $this->_constructUrl(self::PING_SERVLET);
296. $this->_updateUrl = $this->_constructUrl(self::UPDATE_SERVLET, array('wt' => self::SOLR_WRITER ));
297. $this->_searchUrl = $this->_constructUrl(self::SEARCH_SERVLET);
298. $this->_threadsUrl = $this->_constructUrl(self::THREADS_SERVLET, array('wt' => self::SOLR_WRITER ));
300. $this->_urlsInited = true;
301. }
303. /**
304. * Central method for making a get operation against this Solr Server
305. *
306. * @param string $url
307. * @param float $timeout Read timeout in seconds
308. * @return Apache_Solr_Response
309. *
310. * @throws Exception If a non 200 response status is returned
311. */
312. protected function _sendRawGet($url, $timeout = FALSE)
313. {
314. // set the timeout if specified
315. if ($timeout !== FALSE && $timeout > 0.0)
316. {
317. // timeouts with file_get_contents seem to need
318. // to be halved to work as expected
319. $timeout = (float) $timeout / 2;
321. stream_context_set_option($this->_getContext, 'http', 'timeout', $timeout);
322. }
323. else
324. {
325. // use the default timeout pulled from default_socket_timeout otherwise
326. stream_context_set_option($this->_getContext, 'http', 'timeout', $this->_defaultTimeout);
327. }
329. //$http_response_header is set by file_get_contents
330. $response = new Apache_Solr_Response(@file_get_contents($url, false, $this->_getContext), $http_response_header, $this->_createDocuments, $this->_collapseSingleValueArrays);
332. if ($response->getHttpStatus() != 200)
333. {
334. throw new Exception('"' . $response->getHttpStatus() . '" Status: ' . $response->getHttpStatusMessage(), $response->getHttpStatus());
335. }
337. return $response;
338. }
340. /**
341. * Central method for making a post operation against this Solr Server
342. *
343. * @param string $url
344. * @param string $rawPost
345. * @param float $timeout Read timeout in seconds
346. * @param string $contentType
347. * @return Apache_Solr_Response
348. *
349. * @throws Exception If a non 200 response status is returned
350. */
351. protected function _sendRawPost($url, $rawPost, $timeout = FALSE, $contentType = 'text/xml; charset=UTF-8')
352. {
353. stream_context_set_option($this->_postContext, array(
354. 'http' => array(
355. // set HTTP method
356. 'method' => 'POST',
358. // Add our posted content type
359. 'header' => "Content-Type: $contentType",
361. // the posted content
362. 'content' => $rawPost,
364. // default timeout
365. 'timeout' => $this->_defaultTimeout
366. )
367. )
368. );
370. // set the timeout if specified
371. if ($timeout !== FALSE && $timeout > 0.0)
372. {
373. // timeouts with file_get_contents seem to need
374. // to be halved to work as expected
375. $timeout = (float) $timeout / 2;
377. stream_context_set_option($this->_postContext, 'http', 'timeout', $timeout);
378. }
380. //$http_response_header is set by file_get_contents
381. $response = new Apache_Solr_Response(@file_get_contents($url, false, $this->_postContext), $http_response_header, $this->_createDocuments, $this->_collapseSingleValueArrays);
383. if ($response->getHttpStatus() != 200)
384. {
385. throw new Exception('"' . $response->getHttpStatus() . '" Status: ' . $response->getHttpStatusMessage(), $response->getHttpStatus());
386. }
388. return $response;
389. }
391. /**
392. * Returns the set host
393. *
394. * @return string
395. */
396. public function getHost()
397. {
398. return $this->_host;
399. }
401. /**
402. * Set the host used. If empty will fallback to constants
403. *
404. * @param string $host
405. */
406. public function setHost($host)
407. {
408. //Use the provided host or use the default
409. if (empty($host))
410. {
411. throw new Exception('Host parameter is empty');
412. }
413. else
414. {
415. $this->_host = $host;
416. }
418. if ($this->_urlsInited)
419. {
420. $this->_initUrls();
421. }
422. }
424. /**
425. * Get the set port
426. *
427. * @return integer
428. */
429. public function getPort()
430. {
431. return $this->_port;
432. }
434. /**
435. * Set the port used. If empty will fallback to constants
436. *
437. * @param integer $port
438. */
439. public function setPort($port)
440. {
441. //Use the provided port or use the default
442. $port = (int) $port;
444. if ($port <= 0)
445. {
446. throw new Exception('Port is not a valid port number');
447. }
448. else
449. {
450. $this->_port = $port;
451. }
453. if ($this->_urlsInited)
454. {
455. $this->_initUrls();
456. }
457. }
459. /**
460. * Get the set path.
461. *
462. * @return string
463. */
464. public function getPath()
465. {
466. return $this->_path;
467. }
469. /**
470. * Set the path used. If empty will fallback to constants
471. *
472. * @param string $path
473. */
474. public function setPath($path)
475. {
476. $path = trim($path, '/');
478. $this->_path = '/' . $path . '/';
480. if ($this->_urlsInited)
481. {
482. $this->_initUrls();
483. }
484. }
486. /**
487. * Set the create documents flag. This determines whether {@link Apache_Solr_Response} objects will
488. * parse the response and create {@link Apache_Solr_Document} instances in place.
489. *
490. * @param unknown_type $createDocuments
491. */
492. public function setCreateDocuments($createDocuments)
493. {
494. $this->_createDocuments = (bool) $createDocuments;
495. }
497. /**
498. * Get the current state of teh create documents flag.
499. *
500. * @return boolean
501. */
502. public function getCreateDocuments()
503. {
504. return $this->_createDocuments;
505. }
507. /**
508. * Set the collapse single value arrays flag.
509. *
510. * @param boolean $collapseSingleValueArrays
511. */
512. public function setCollapseSingleValueArrays($collapseSingleValueArrays)
513. {
514. $this->_collapseSingleValueArrays = (bool) $collapseSingleValueArrays;
515. }
517. /**
518. * Get the current state of the collapse single value arrays flag.
519. *
520. * @return boolean
521. */
522. public function getCollapseSingleValueArrays()
523. {
524. return $this->_collapseSingleValueArrays;
525. }
527. /**
528. * Set how NamedLists should be formatted in the response data. This mainly effects
529. * the facet counts format.
530. *
531. * @param string $namedListTreatment
532. * @throws Exception If invalid option is set
533. */
534. public function setNamedListTreatmet($namedListTreatment)
535. {
536. switch ((string) $namedListTreatment)
537. {
538. case Apache_Solr_Service::NAMED_LIST_FLAT:
539. $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_FLAT;
540. break;
542. case Apache_Solr_Service::NAMED_LIST_MAP:
543. $this->_namedListTreatment = Apache_Solr_Service::NAMED_LIST_MAP;
544. break;
546. default:
547. throw new Exception('Not a valid named list treatement option');
548. }
549. }
551. /**
552. * Get the current setting for named list treatment.
553. *
554. * @return string
555. */
556. public function getNamedListTreatment()
557. {
558. return $this->_namedListTreatment;
559. }
562. /**
563. * Set the string used to separate the path form the query string.
564. * Defaulted to '?'
565. *
566. * @param string $queryDelimiter
567. */
568. public function setQueryDelimiter($queryDelimiter)
569. {
570. $this->_queryDelimiter = $queryDelimiter;
571. }
573. /**
574. * Set the string used to separate the parameters in thequery string
575. * Defaulted to '&'
576. *
577. * @param string $queryStringDelimiter
578. */
579. public function setQueryStringDelimiter($queryStringDelimiter)
580. {
581. $this->_queryStringDelimiter = $queryStringDelimiter;
582. }
584. /**
585. * Call the /admin/ping servlet, can be used to quickly tell if a connection to the
586. * server is able to be made.
587. *
588. * @param float $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
589. * @return float Actual time taken to ping the server, FALSE if timeout or HTTP error status occurs
590. */
591. public function ping($timeout = 2)
592. {
593. $start = microtime(true);
595. // when using timeout in context and file_get_contents
596. // it seems to take twice the timout value
597. $timeout = (float) $timeout / 2;
599. if ($timeout <= 0.0)
600. {
601. $timeout = -1;
602. }
604. $context = stream_context_create(
605. array(
606. 'http' => array(
607. 'method' => 'HEAD',
608. 'timeout' => $timeout
609. )
610. )
611. );
613. // attempt a HEAD request to the solr ping page
614. $ping = @file_get_contents($this->_pingUrl, false, $context);
616. // result is false if there was a timeout
617. // or if the HTTP status was not 200
618. if ($ping !== false)
619. {
620. return microtime(true) - $start;
621. }
622. else
623. {
624. return false;
625. }
626. }
628. /**
629. * Call the /admin/threads servlet and retrieve information about all threads in the
630. * Solr servlet's thread group. Useful for diagnostics.
631. *
632. * @return Apache_Solr_Response
633. *
634. * @throws Exception If an error occurs during the service call
635. */
636. public function threads()
637. {
638. return $this->_sendRawGet($this->_threadsUrl);
639. }
641. /**
642. * Raw Add Method. Takes a raw post body and sends it to the update service. Post body
643. * should be a complete and well formed "add" xml document.
644. *
645. * @param string $rawPost
646. * @return Apache_Solr_Response
647. *
648. * @throws Exception If an error occurs during the service call
649. */
650. public function add($rawPost)
651. {
652. return $this->_sendRawPost($this->_updateUrl, $rawPost);
653. }
655. /**
656. * Add a Solr Document to the index
657. *
658. * @param Apache_Solr_Document $document
659. * @param boolean $allowDups
660. * @param boolean $overwritePending
661. * @param boolean $overwriteCommitted
662. * @return Apache_Solr_Response
663. *
664. * @throws Exception If an error occurs during the service call
665. */
666. public function addDocument(Apache_Solr_Document $document, $allowDups = false, $overwritePending = true, $overwriteCommitted = true)
667. {
668. $dupValue = $allowDups ? 'true' : 'false';
669. $pendingValue = $overwritePending ? 'true' : 'false';
670. $committedValue = $overwriteCommitted ? 'true' : 'false';
672. $rawPost = '<add allowDups="' . $dupValue . '" overwritePending="' . $pendingValue . '" overwriteCommitted="' . $committedValue . '">';
673. $rawPost .= $this->_documentToXmlFragment($document);
674. $rawPost .= '</add>';
676. return $this->add($rawPost);
677. }
679. /**
680. * Add an array of Solr Documents to the index all at once
681. *
682. * @param array $documents Should be an array of Apache_Solr_Document instances
683. * @param boolean $allowDups
684. * @param boolean $overwritePending
685. * @param boolean $overwriteCommitted
686. * @return Apache_Solr_Response
687. *
688. * @throws Exception If an error occurs during the service call
689. */
690. public function addDocuments($documents, $allowDups = false, $overwritePending = true, $overwriteCommitted = true)
691. {
692. $dupValue = $allowDups ? 'true' : 'false';
693. $pendingValue = $overwritePending ? 'true' : 'false';
694. $committedValue = $overwriteCommitted ? 'true' : 'false';
696. $rawPost = '<add allowDups="' . $dupValue . '" overwritePending="' . $pendingValue . '" overwriteCommitted="' . $committedValue . '">';
698. foreach ($documents as $document)
699. {
700. if ($document instanceof Apache_Solr_Document)
701. {
702. $rawPost .= $this->_documentToXmlFragment($document);
703. }
704. }
706. $rawPost .= '</add>';
708. return $this->add($rawPost);
709. }
711. /**
712. * Create an XML fragment from a {@link Apache_Solr_Document} instance appropriate for use inside a Solr add call
713. *
714. * @return string
715. */
716. protected function _documentToXmlFragment(Apache_Solr_Document $document)
717. {
718. $xml = '<doc';
720. if ($document->getBoost() !== false)
721. {
722. $xml .= ' boost="' . $document->getBoost() . '"';
723. }
725. $xml .= '>';
727. foreach ($document as $key => $value)
728. {
729. $key = htmlspecialchars($key, ENT_QUOTES, 'UTF-8');
730. $fieldBoost = $document->getFieldBoost($key);
732. if (is_array($value))
733. {
734. foreach ($value as $multivalue)
735. {
736. $xml .= '<field name="' . $key . '"';
738. if ($fieldBoost !== false)
739. {
740. $xml .= ' boost="' . $fieldBoost . '"';
742. // only set the boost for the first field in the set
743. $fieldBoost = false;
744. }
746. $multivalue = htmlspecialchars($multivalue, ENT_NOQUOTES, 'UTF-8');
748. $xml .= '>' . $multivalue . '</field>';
749. }
750. }
751. else
752. {
753. $xml .= '<field name="' . $key . '"';
755. if ($fieldBoost !== false)
756. {
757. $xml .= ' boost="' . $fieldBoost . '"';
758. }
760. $value = htmlspecialchars($value, ENT_NOQUOTES, 'UTF-8');
762. $xml .= '>' . $value . '</field>';
763. }
764. }
766. $xml .= '</doc>';
768. // replace any control characters to avoid Solr XML parser exception
769. return $this->_stripCtrlChars($xml);
770. }
772. /**
773. * Replace control (non-printable) characters from string that are invalid to Solr's XML parser with a space.
774. *
775. * @param string $string
776. * @return string
777. */
778. protected function _stripCtrlChars($string)
779. {
780. // See: http://w3.org/International/questions/qa-forms-utf-8.html
781. // Printable utf-8 does not include any of these chars below x7F
782. return preg_replace('@[\x00-\x08\x0B\x0C\x0E-\x1F]@', ' ', $string);
783. }
785. /**
786. * Send a commit command. Will be synchronous unless both wait parameters are set to false.
787. *
788. * @param boolean $optimize Defaults to true
789. * @param boolean $waitFlush Defaults to true
790. * @param boolean $waitSearcher Defaults to true
791. * @param float $timeout Maximum expected duration (in seconds) of the commit operation on the server (otherwise, will throw a communication exception). Defaults to 1 hour
792. * @return Apache_Solr_Response
793. *
794. * @throws Exception If an error occurs during the service call
795. */
796. public function commit($optimize = true, $waitFlush = true, $waitSearcher = true, $timeout = 3600)
797. {
798. $optimizeValue = $optimize ? 'true' : 'false';
799. $flushValue = $waitFlush ? 'true' : 'false';
800. $searcherValue = $waitSearcher ? 'true' : 'false';
802. $rawPost = '<commit optimize="' . $optimizeValue . '" waitFlush="' . $flushValue . '" waitSearcher="' . $searcherValue . '" />';
804. return $this->_sendRawPost($this->_updateUrl, $rawPost, $timeout);
805. }
807. /**
808. * Raw Delete Method. Takes a raw post body and sends it to the update service. Body should be
809. * a complete and well formed "delete" xml document
810. *
811. * @param string $rawPost Expected to be utf-8 encoded xml document
812. * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
813. * @return Apache_Solr_Response
814. *
815. * @throws Exception If an error occurs during the service call
816. */
817. public function delete($rawPost, $timeout = 3600)
818. {
819. return $this->_sendRawPost($this->_updateUrl, $rawPost, $timeout);
820. }
822. /**
823. * Create a delete document based on document ID
824. *
825. * @param string $id Expected to be utf-8 encoded
826. * @param boolean $fromPending
827. * @param boolean $fromCommitted
828. * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
829. * @return Apache_Solr_Response
830. *
831. * @throws Exception If an error occurs during the service call
832. */
833. public function deleteById($id, $fromPending = true, $fromCommitted = true, $timeout = 3600)
834. {
835. $pendingValue = $fromPending ? 'true' : 'false';
836. $committedValue = $fromCommitted ? 'true' : 'false';
838. //escape special xml characters
839. $id = htmlspecialchars($id, ENT_NOQUOTES, 'UTF-8');
841. $rawPost = '<delete fromPending="' . $pendingValue . '" fromCommitted="' . $committedValue . '"><id>' . $id . '</id></delete>';
843. return $this->delete($rawPost, $timeout);
844. }
846. /**
847. * Create and post a delete document based on multiple document IDs.
848. *
849. * @param array $ids Expected to be utf-8 encoded strings
850. * @param boolean $fromPending
851. * @param boolean $fromCommitted
852. * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
853. * @return Apache_Solr_Response
854. *
855. * @throws Exception If an error occurs during the service call
856. */
857. public function deleteByMultipleIds($ids, $fromPending = true, $fromCommitted = true, $timeout = 3600)
858. {
859. $pendingValue = $fromPending ? 'true' : 'false';
860. $committedValue = $fromCommitted ? 'true' : 'false';
862. $rawPost = '<delete fromPending="' . $pendingValue . '" fromCommitted="' . $committedValue . '">';
864. foreach ($ids as $id)
865. {
866. //escape special xml characters
867. $id = htmlspecialchars($id, ENT_NOQUOTES, 'UTF-8');
869. $rawPost .= '<id>' . $id . '</id>';
870. }
872. $rawPost .= '</delete>';
874. return $this->delete($rawPost, $timeout);
875. }
877. /**
878. * Create a delete document based on a query and submit it
879. *
880. * @param string $rawQuery Expected to be utf-8 encoded
881. * @param boolean $fromPending
882. * @param boolean $fromCommitted
883. * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
884. * @return Apache_Solr_Response
885. *
886. * @throws Exception If an error occurs during the service call
887. */
888. public function deleteByQuery($rawQuery, $fromPending = true, $fromCommitted = true, $timeout = 3600)
889. {
890. $pendingValue = $fromPending ? 'true' : 'false';
891. $committedValue = $fromCommitted ? 'true' : 'false';
893. // escape special xml characters
894. $rawQuery = htmlspecialchars($rawQuery, ENT_NOQUOTES, 'UTF-8');
896. $rawPost = '<delete fromPending="' . $pendingValue . '" fromCommitted="' . $committedValue . '"><query>' . $rawQuery . '</query></delete>';
898. return $this->delete($rawPost, $timeout);
899. }
901. /**
902. * Send an optimize command. Will be synchronous unless both wait parameters are set
903. * to false.
904. *
905. * @param boolean $waitFlush
906. * @param boolean $waitSearcher
907. * @param float $timeout Maximum expected duration of the commit operation on the server (otherwise, will throw a communication exception)
908. * @return Apache_Solr_Response
909. *
910. * @throws Exception If an error occurs during the service call
911. */
912. public function optimize($waitFlush = true, $waitSearcher = true, $timeout = 3600)
913. {
914. $flushValue = $waitFlush ? 'true' : 'false';
915. $searcherValue = $waitSearcher ? 'true' : 'false';
917. $rawPost = '<optimize waitFlush="' . $flushValue . '" waitSearcher="' . $searcherValue . '" />';
919. return $this->_sendRawPost($this->_updateUrl, $rawPost, $timeout);
920. }
922. /**
923. * Simple Search interface
924. *
925. * @param string $query The raw query string
926. * @param int $offset The starting offset for result documents
927. * @param int $limit The maximum number of result documents to return
928. * @param array $params key / value pairs for other query parameters (see Solr documentation), use arrays for parameter keys used more than once (e.g. facet.field)
929. * @return Apache_Solr_Response
930. *
931. * @throws Exception If an error occurs during the service call
932. */
933. public function search($query, $offset = 0, $limit = 10, $params = array(), $method = self::METHOD_GET)
934. {
935. if (!is_array($params))
936. {
937. $params = array();
938. }
940. // construct our full parameters
941. // sending the version is important in case the format changes
942. $params['version'] = self::SOLR_VERSION;
944. // common parameters in this interface
945. $params['wt'] = self::SOLR_WRITER;
946. $params['json.nl'] = $this->_namedListTreatment;
948. $params['q'] = $query;
949. $params['start'] = $offset;
950. $params['rows'] = $limit;
952. // use http_build_query to encode our arguments because its faster
953. // than urlencoding all the parts ourselves in a loop
954. $queryString = http_build_query($params, null, $this->_queryStringDelimiter);
956. // because http_build_query treats arrays differently than we want to, correct the query
957. // string by changing foo[#]=bar (# being an actual number) parameter strings to just
958. // multiple foo=bar strings. This regex should always work since '=' will be urlencoded
959. // anywhere else the regex isn't expecting it
960. $queryString = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $queryString);
962. if ($method == self::METHOD_GET)
963. {
964. return $this->_sendRawGet($this->_searchUrl . $this->_queryDelimiter . $queryString);
965. }
966. else if ($method == self::METHOD_POST)
967. {
968. return $this->_sendRawPost($this->_searchUrl, $queryString, FALSE, 'application/x-www-form-urlencoded');
969. }
970. else
971. {
972. throw new Exception("Unsupported method '$method', please use the Apache_Solr_Service::METHOD_* constants");
973. }
974. }
975. }

Documentation generated on Mon, 09 Nov 2009 18:15:45 -0500 by phpDocumentor 1.4.2