type Status report
message unknown handler: standad
description The request sent by the client was syntactically incorrect (unknown handler: standad).
type Status report
message /solr/doesnotexist/select
description The requested resource (/solr/doesnotexist/select) is not available.
43 | * ...
44 | * $document->title = 'Something';
45 | * echo $document->title;
46 | * ...
47 | *
48 | *
49 | * Additionally, the field values can be iterated with foreach
50 | *
51 | *
52 | * foreach ($document as $fieldName => $fieldValue)
53 | * {
54 | * ...
55 | * }
56 | *
57 | */
58 | class Apache_Solr_Document implements IteratorAggregate
59 | {
60 | /**
61 | * SVN Revision meta data for this class
62 | */
63 | const SVN_REVISION = '$Revision$';
64 |
65 | /**
66 | * SVN ID meta data for this class
67 | */
68 | const SVN_ID = '$Id$';
69 |
70 | /**
71 | * Document boost value
72 | *
73 | * @var float
74 | */
75 | protected $_documentBoost = false;
76 |
77 | /**
78 | * Document field values, indexed by name
79 | *
80 | * @var array
81 | */
82 | protected $_fields = array();
83 |
84 | /**
85 | * Document field boost values, indexed by name
86 | *
87 | * @var array array of floats
88 | */
89 | protected $_fieldBoosts = array();
90 |
91 | /**
92 | * Clear all boosts and fields from this document
93 | */
94 | public function clear()
95 | {
96 | $this->_documentBoost = false;
97 |
98 | $this->_fields = array();
99 | $this->_fieldBoosts = array();
100 | }
101 |
102 | /**
103 | * Get current document boost
104 | *
105 | * @return mixed will be false for default, or else a float
106 | */
107 | public function getBoost()
108 | {
109 | return $this->_documentBoost;
110 | }
111 |
112 | /**
113 | * Set document boost factor
114 | *
115 | * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
116 | */
117 | public function setBoost($boost)
118 | {
119 | $boost = (float) $boost;
120 |
121 | if ($boost > 0.0)
122 | {
123 | $this->_documentBoost = $boost;
124 | }
125 | else
126 | {
127 | $this->_documentBoost = false;
128 | }
129 | }
130 |
131 | /**
132 | * Add a value to a multi-valued field
133 | *
134 | * NOTE: the solr XML format allows you to specify boosts
135 | * PER value even though the underlying Lucene implementation
136 | * only allows a boost per field. To remedy this, the final
137 | * field boost value will be the product of all specified boosts
138 | * on field values - this is similar to SolrJ's functionality.
139 | *
140 | *
141 | * $doc = new Apache_Solr_Document();
142 | *
143 | * $doc->addField('foo', 'bar', 2.0);
144 | * $doc->addField('foo', 'baz', 3.0);
145 | *
146 | * // resultant field boost will be 6!
147 | * echo $doc->getFieldBoost('foo');
148 | *
149 | *
150 | * @param string $key
151 | * @param mixed $value
152 | * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
153 | */
154 | public function addField($key, $value, $boost = false)
155 | {
156 | if (!isset($this->_fields[$key]))
157 | {
158 | // create holding array if this is the first value
159 | $this->_fields[$key] = array();
160 | }
161 | else if (!is_array($this->_fields[$key]))
162 | {
163 | // move existing value into array if it is not already an array
164 | $this->_fields[$key] = array($this->_fields[$key]);
165 | }
166 |
167 | if ($this->getFieldBoost($key) === false)
168 | {
169 | // boost not already set, set it now
170 | $this->setFieldBoost($key, $boost);
171 | }
172 | else if ((float) $boost > 0.0)
173 | {
174 | // multiply passed boost with current field boost - similar to SolrJ implementation
175 | $this->_fieldBoosts[$key] *= (float) $boost;
176 | }
177 |
178 | // add value to array
179 | $this->_fields[$key][] = $value;
180 | }
181 |
182 | /**
183 | * Handle the array manipulation for a multi-valued field
184 | *
185 | * @param string $key
186 | * @param string $value
187 | * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
188 | *
189 | * @deprecated Use addField(...) instead
190 | */
191 | public function setMultiValue($key, $value, $boost = false)
192 | {
193 | $this->addField($key, $value, $boost);
194 | }
195 |
196 | /**
197 | * Get field information
198 | *
199 | * @param string $key
200 | * @return mixed associative array of info if field exists, false otherwise
201 | */
202 | public function getField($key)
203 | {
204 | if (isset($this->_fields[$key]))
205 | {
206 | return array(
207 | 'name' => $key,
208 | 'value' => $this->_fields[$key],
209 | 'boost' => $this->getFieldBoost($key)
210 | );
211 | }
212 |
213 | return false;
214 | }
215 |
216 | /**
217 | * Set a field value. Multi-valued fields should be set as arrays
218 | * or instead use the addField(...) function which will automatically
219 | * make sure the field is an array.
220 | *
221 | * @param string $key
222 | * @param mixed $value
223 | * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
224 | */
225 | public function setField($key, $value, $boost = false)
226 | {
227 | $this->_fields[$key] = $value;
228 | $this->setFieldBoost($key, $boost);
229 | }
230 |
231 | /**
232 | * Get the currently set field boost for a document field
233 | *
234 | * @param string $key
235 | * @return float currently set field boost, false if one is not set
236 | */
237 | public function getFieldBoost($key)
238 | {
239 | return isset($this->_fieldBoosts[$key]) ? $this->_fieldBoosts[$key] : false;
240 | }
241 |
242 | /**
243 | * Set the field boost for a document field
244 | *
245 | * @param string $key field name for the boost
246 | * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
247 | */
248 | public function setFieldBoost($key, $boost)
249 | {
250 | $boost = (float) $boost;
251 |
252 | if ($boost > 0.0)
253 | {
254 | $this->_fieldBoosts[$key] = $boost;
255 | }
256 | else
257 | {
258 | $this->_fieldBoosts[$key] = false;
259 | }
260 | }
261 |
262 | /**
263 | * Return current field boosts, indexed by field name
264 | *
265 | * @return array
266 | */
267 | public function getFieldBoosts()
268 | {
269 | return $this->_fieldBoosts;
270 | }
271 |
272 | /**
273 | * Get the names of all fields in this document
274 | *
275 | * @return array
276 | */
277 | public function getFieldNames()
278 | {
279 | return array_keys($this->_fields);
280 | }
281 |
282 | /**
283 | * Get the values of all fields in this document
284 | *
285 | * @return array
286 | */
287 | public function getFieldValues()
288 | {
289 | return array_values($this->_fields);
290 | }
291 |
292 | /**
293 | * IteratorAggregate implementation function. Allows usage:
294 | *
295 | *
296 | * foreach ($document as $key => $value)
297 | * {
298 | * ...
299 | * }
300 | *
301 | */
302 | public function getIterator()
303 | {
304 | $arrayObject = new ArrayObject($this->_fields);
305 |
306 | return $arrayObject->getIterator();
307 | }
308 |
309 | /**
310 | * Magic get for field values
311 | *
312 | * @param string $key
313 | * @return mixed
314 | */
315 | public function __get($key)
316 | {
317 | if (isset($this->_fields[$key]))
318 | {
319 | return $this->_fields[$key];
320 | }
321 |
322 | return null;
323 | }
324 |
325 | /**
326 | * Magic set for field values. Multi-valued fields should be set as arrays
327 | * or instead use the addField(...) function which will automatically
328 | * make sure the field is an array.
329 | *
330 | * @param string $key
331 | * @param mixed $value
332 | */
333 | public function __set($key, $value)
334 | {
335 | $this->setField($key, $value);
336 | }
337 |
338 | /**
339 | * Magic isset for fields values. Do not call directly. Allows usage:
340 | *
341 | *
342 | * isset($document->some_field);
343 | *
344 | *
345 | * @param string $key
346 | * @return boolean
347 | */
348 | public function __isset($key)
349 | {
350 | return isset($this->_fields[$key]);
351 | }
352 |
353 | /**
354 | * Magic unset for field values. Do not call directly. Allows usage:
355 | *
356 | *
357 | * unset($document->some_field);
358 | *
359 | *
360 | * @param string $key
361 | */
362 | public function __unset($key)
363 | {
364 | unset($this->_fields[$key]);
365 | unset($this->_fieldBoosts[$key]);
366 | }
367 | }
--------------------------------------------------------------------------------
/tests/Apache/Solr/DocumentTest.php:
--------------------------------------------------------------------------------
1 |
36 | */
37 |
38 | /**
39 | * Apache_Solr_Document Unit Test
40 | */
41 | class Apache_Solr_DocumentTest extends PHPUnit_Framework_TestCase
42 | {
43 | /**
44 | * Fixture used for testing
45 | *
46 | * @var Apache_Solr_Document
47 | */
48 | private $_fixture;
49 |
50 | /**
51 | * Setup for the fixture before each unit test - part of test case API
52 | */
53 | protected function setup()
54 | {
55 | $this->_fixture = new Apache_Solr_Document();
56 | }
57 |
58 | /**
59 | * Teardown after each unit test - part of test case API
60 | */
61 | protected function tearDown()
62 | {
63 | unset($this->_fixture);
64 | }
65 |
66 | public function testDefaultStateAfterConstructor()
67 | {
68 | // document boost should be false
69 | $this->assertFalse($this->_fixture->getBoost());
70 |
71 | // document fields should be empty
72 | $this->assertEquals(0, count($this->_fixture->getFieldNames()));
73 | $this->assertEquals(0, count($this->_fixture->getFieldValues()));
74 | $this->assertEquals(0, count($this->_fixture->getFieldBoosts()));
75 |
76 | // document iterator should be empty
77 | $this->assertEquals(0, iterator_count($this->_fixture));
78 | }
79 |
80 | public function testSetAndGetField()
81 | {
82 | $field = 'field';
83 | $value = 'value';
84 | $boost = 0.5;
85 |
86 | // set the field
87 | $this->_fixture->setField($field, $value, $boost);
88 |
89 | $result = $this->_fixture->getField($field);
90 |
91 | // check the array values
92 | $this->assertTrue(is_array($result));
93 | $this->assertEquals($field, $result['name']);
94 | $this->assertEquals($value, $result['value']);
95 | $this->assertEquals($boost, $result['boost']);
96 | }
97 |
98 | public function testGetFieldReturnsFalseForNonExistentField()
99 | {
100 | $this->assertFalse($this->_fixture->getField('field'));
101 | }
102 |
103 | public function testMagicGetForFieldValues()
104 | {
105 | $field = 'field';
106 | $value = 'value';
107 |
108 | $this->_fixture->setField($field, $value);
109 |
110 | // test the __get value
111 | $this->assertEquals($value, $this->_fixture->{$field});
112 | }
113 |
114 | /**
115 | * Added for issue #48 (http://code.google.com/p/solr-php-client/issues/detail?id=48)
116 | */
117 | public function testMagicGetReturnsNullForNonExistentField()
118 | {
119 | $this->assertNull($this->_fixture->nonExistent);
120 | }
121 |
122 | public function testMagicSetForFieldValues()
123 | {
124 | $field = 'field';
125 | $value = 'value';
126 |
127 | // set field value with magic __set
128 | $this->_fixture->{$field} = $value;
129 |
130 | $fieldArray = $this->_fixture->getField($field);
131 |
132 | // set values
133 | $this->assertEquals($field, $fieldArray['name']);
134 | $this->assertEquals($value, $fieldArray['value']);
135 | $this->assertTrue($fieldArray['boost'] === false);
136 | }
137 |
138 | public function testMagicIssetForNonExistentField()
139 | {
140 | $this->assertFalse(isset($this->_fixture->field));
141 | }
142 |
143 | public function testMagicIssetForExistingField()
144 | {
145 | $field = 'field';
146 | $this->_fixture->{$field} = 'value';
147 | $this->assertTrue(isset($this->_fixture->{$field}));
148 | }
149 |
150 | public function testMagicUnsetForExistingField()
151 | {
152 | $field = 'field';
153 |
154 | $this->_fixture->{$field} = 'value';
155 |
156 | // now unset the field
157 | unset($this->_fixture->{$field});
158 |
159 | // now test that its unset
160 | $this->assertFalse(isset($this->_fixture->{$field}));
161 | }
162 |
163 | public function testMagicUnsetForNonExistingField()
164 | {
165 | $field = 'field';
166 | unset($this->_fixture->{$field});
167 |
168 | // now test that it still does not exist
169 | $this->assertFalse(isset($this->_fixture->{$field}));
170 | }
171 |
172 | public function testSetAndGetFieldBoostWithPositiveNumberSetsBoost()
173 | {
174 | $field = 'field';
175 | $boost = 0.5;
176 |
177 | $this->_fixture->setFieldBoost($field, $boost);
178 |
179 | // test the field boost
180 | $this->assertEquals($boost, $this->_fixture->getFieldBoost($field));
181 | }
182 |
183 | public function testSetAndGetFieldBoostWithZeroRemovesBoost()
184 | {
185 | $field = 'field';
186 | $boost = 0;
187 |
188 | $this->_fixture->setFieldBoost($field, $boost);
189 |
190 | // test the field boost
191 | $this->assertTrue($this->_fixture->getFieldBoost($field) === false);
192 | }
193 |
194 | public function testSetAndGetFieldBoostWithNegativeNumberRemovesBoost()
195 | {
196 | $field = 'field';
197 | $boost = -1;
198 |
199 | $this->_fixture->setFieldBoost($field, $boost);
200 |
201 | // test the field boost
202 | $this->assertTrue($this->_fixture->getFieldBoost($field) === false);
203 | }
204 |
205 | public function testSetAndGetFieldBoostWithNonNumberRemovesBoost()
206 | {
207 | $field = 'field';
208 | $boost = "i am not a number";
209 |
210 | $this->_fixture->setFieldBoost($field, $boost);
211 |
212 | // test the field boost
213 | $this->assertTrue($this->_fixture->getFieldBoost($field) === false);
214 | }
215 |
216 | public function testSetAndGetBoostWithPositiveNumberSetsBoost()
217 | {
218 | $boost = 0.5;
219 | $this->_fixture->setBoost($boost);
220 |
221 | // the boost should now be set
222 | $this->assertEquals($boost, $this->_fixture->getBoost());
223 | }
224 |
225 | public function testSetAndGetBoostWithZeroRemovesBoost()
226 | {
227 | $this->_fixture->setBoost(0);
228 |
229 | // should be boolean false
230 | $this->assertTrue($this->_fixture->getBoost() === false);
231 | }
232 |
233 | public function testSetAndGetBoostWithNegativeNumberRemovesBoost()
234 | {
235 | $this->_fixture->setBoost(-1);
236 |
237 | // should be boolean false
238 | $this->assertTrue($this->_fixture->getBoost() === false);
239 | }
240 |
241 | public function testSetAndGetBoostWithNonNumberRemovesBoost()
242 | {
243 | $this->_fixture->setBoost("i am not a number");
244 |
245 | // should be boolean false
246 | $this->assertTrue($this->_fixture->getBoost() === false);
247 | }
248 |
249 | public function testAddFieldCreatesMultiValueWhenFieldDoesNotExist()
250 | {
251 | $field = 'field';
252 | $value = 'value';
253 |
254 | $this->_fixture->addField($field, $value);
255 |
256 | // check that value is an array with correct values
257 | $fieldValue = $this->_fixture->{$field};
258 |
259 | $this->assertTrue(is_array($fieldValue));
260 | $this->assertEquals(1, count($fieldValue));
261 | $this->assertEquals($value, $fieldValue[0]);
262 | }
263 |
264 | /**
265 | * setMultiValue has been deprecated and defers to addField
266 | *
267 | * @deprecated
268 | */
269 | public function testSetMultiValueCreateMultiValueWhenFieldDoesNotExist()
270 | {
271 | $field = 'field';
272 | $value = 'value';
273 |
274 | $this->_fixture->setMultiValue($field, $value);
275 |
276 | // check that value is an array with correct values
277 | $fieldValue = $this->_fixture->{$field};
278 |
279 | $this->assertTrue(is_array($fieldValue));
280 | $this->assertEquals(1, count($fieldValue));
281 | $this->assertEquals($value, $fieldValue[0]);
282 | }
283 |
284 | public function testAddFieldCreatesMultiValueWhenFieldDoesExistAsSingleValue()
285 | {
286 | $field = 'field';
287 | $value1 = 'value1';
288 | $value2 = 'value2';
289 |
290 | // set first value as singular value
291 | $this->_fixture->{$field} = $value1;
292 |
293 | // add a second value with addField
294 | $this->_fixture->addField($field, $value2);
295 |
296 | // check that value is an array with correct values
297 | $fieldValue = $this->_fixture->{$field};
298 |
299 | $this->assertTrue(is_array($fieldValue));
300 | $this->assertEquals(2, count($fieldValue));
301 | $this->assertEquals($value1, $fieldValue[0]);
302 | $this->assertEquals($value2, $fieldValue[1]);
303 | }
304 |
305 | /**
306 | * setMultiValue has been deprecated and defers to addField
307 | *
308 | * @deprecated
309 | */
310 | public function testSetMultiValueCreatesMultiValueWhenFieldDoesExistAsSingleValue()
311 | {
312 | $field = 'field';
313 | $value1 = 'value1';
314 | $value2 = 'value2';
315 |
316 | // set first value as singular value
317 | $this->_fixture->{$field} = $value1;
318 |
319 | // add a second value with addField
320 | $this->_fixture->setMultiValue($field, $value2);
321 |
322 | // check that value is an array with correct values
323 | $fieldValue = $this->_fixture->{$field};
324 |
325 | $this->assertTrue(is_array($fieldValue));
326 | $this->assertEquals(2, count($fieldValue));
327 | $this->assertEquals($value1, $fieldValue[0]);
328 | $this->assertEquals($value2, $fieldValue[1]);
329 | }
330 |
331 | public function testAddFieldWithBoostSetsFieldBoost()
332 | {
333 | $field = 'field';
334 | $boost = 0.5;
335 |
336 | $this->_fixture->addField($field, 'value', $boost);
337 |
338 | // check the field boost
339 | $this->assertEquals($boost, $this->_fixture->getFieldBoost($field));
340 | }
341 |
342 | public function testAddFieldWithBoostMultipliesWithAPreexistingBoost()
343 | {
344 | $field = 'field';
345 | $boost = 0.5;
346 |
347 | // set a field with a boost
348 | $this->_fixture->setField($field, 'value1', $boost);
349 |
350 | // now add another value with the same boost
351 | $this->_fixture->addField($field, 'value2', $boost);
352 |
353 | // new boost should be $boost * $boost
354 | $this->assertEquals($boost * $boost, $this->_fixture->getFieldBoost($field));
355 | }
356 |
357 | public function testGetFieldNamesIsInitiallyEmpty()
358 | {
359 | $fieldNames = $this->_fixture->getFieldNames();
360 |
361 | $this->assertTrue(empty($fieldNames));
362 | }
363 |
364 | public function testGetFieldNamesAfterFieldIsSetIsNotEmpty()
365 | {
366 | $field = 'field';
367 |
368 | $this->_fixture->{$field} = 'value';
369 | $fieldNames = $this->_fixture->getFieldNames();
370 |
371 | $this->assertTrue(!empty($fieldNames));
372 | $this->assertEquals(1, count($fieldNames));
373 | $this->assertEquals($field, $fieldNames[0]);
374 | }
375 |
376 | public function testGetFieldValuesIsInitiallyEmpty()
377 | {
378 | $fieldValues = $this->_fixture->getFieldValues();
379 |
380 | $this->assertTrue(empty($fieldValues));
381 | }
382 |
383 | public function testGetFieldValuessAfterFieldIsSetIsNotEmpty()
384 | {
385 | $value = 'value';
386 |
387 | $this->_fixture->field = $value;
388 | $fieldValues = $this->_fixture->getFieldValues();
389 |
390 | $this->assertTrue(!empty($fieldValues));
391 | $this->assertEquals(1, count($fieldValues));
392 | $this->assertEquals($value, $fieldValues[0]);
393 | }
394 |
395 | public function testGetIteratorAfterFieldValueIsSet()
396 | {
397 | $field = 'field';
398 | $value = 'value';
399 |
400 | $this->_fixture->{$field} = $value;
401 |
402 | $itemCount = 0;
403 |
404 | foreach ($this->_fixture as $iteratedField => $iteratedValue)
405 | {
406 | ++$itemCount;
407 |
408 | // test field and value
409 | $this->assertEquals($field, $iteratedField);
410 | $this->assertEquals($value, $iteratedValue);
411 | }
412 |
413 | // test number of iterations is 1
414 | $this->assertEquals(1, $itemCount);
415 | }
416 |
417 | public function testClearReturnsDocumentToDefaultState()
418 | {
419 | // set the document boost
420 | $this->_fixture->setBoost(0.5);
421 |
422 | // set a field
423 | $this->_fixture->someField = "some value";
424 |
425 | // clear the document to remove boost and fields
426 | $this->_fixture->clear();
427 |
428 | // document boost should now be false
429 | $this->assertFalse($this->_fixture->getBoost());
430 |
431 | // document fields should now be empty
432 | $this->assertEquals(0, count($this->_fixture->getFieldNames()));
433 | $this->assertEquals(0, count($this->_fixture->getFieldValues()));
434 | $this->assertEquals(0, count($this->_fixture->getFieldBoosts()));
435 |
436 | // document iterator should now be empty
437 | $this->assertEquals(0, iterator_count($this->_fixture));
438 | }
439 | }
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "hash": "422be6f08003663225b1b5c913ab3bbe",
3 | "packages": [
4 |
5 | ],
6 | "packages-dev": [
7 | {
8 | "name": "phpunit/php-code-coverage",
9 | "version": "1.2.3",
10 | "source": {
11 | "type": "git",
12 | "url": "git://github.com/sebastianbergmann/php-code-coverage.git",
13 | "reference": "1.2.3"
14 | },
15 | "dist": {
16 | "type": "zip",
17 | "url": "https://github.com/sebastianbergmann/php-code-coverage/zipball/1.2.3",
18 | "reference": "1.2.3",
19 | "shasum": ""
20 | },
21 | "require": {
22 | "php": ">=5.3.3",
23 | "phpunit/php-file-iterator": ">=1.3.0@stable",
24 | "phpunit/php-token-stream": ">=1.1.3@stable",
25 | "phpunit/php-text-template": ">=1.1.1@stable"
26 | },
27 | "suggest": {
28 | "ext-dom": "*",
29 | "ext-reflection": "*",
30 | "ext-spl": "*",
31 | "ext-xdebug": ">=2.0.5"
32 | },
33 | "time": "2012-10-05 00:00:00",
34 | "type": "library",
35 | "installation-source": "dist",
36 | "autoload": {
37 | "classmap": [
38 | "PHP/"
39 | ]
40 | },
41 | "include-path": [
42 | ""
43 | ],
44 | "license": [
45 | "BSD-3-Clause"
46 | ],
47 | "authors": [
48 | {
49 | "name": "Sebastian Bergmann",
50 | "email": "sb@sebastian-bergmann.de",
51 | "role": "lead"
52 | }
53 | ],
54 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
55 | "homepage": "http://www.phpunit.de/",
56 | "keywords": [
57 | "testing",
58 | "coverage",
59 | "xunit"
60 | ]
61 | },
62 | {
63 | "name": "phpunit/php-file-iterator",
64 | "version": "1.3.3",
65 | "source": {
66 | "type": "git",
67 | "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
68 | "reference": "1.3.3"
69 | },
70 | "dist": {
71 | "type": "zip",
72 | "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
73 | "reference": "1.3.3",
74 | "shasum": ""
75 | },
76 | "require": {
77 | "php": ">=5.2.7"
78 | },
79 | "time": "2012-10-05 09:06:25",
80 | "type": "library",
81 | "installation-source": "dist",
82 | "autoload": {
83 | "classmap": [
84 | "File/"
85 | ]
86 | },
87 | "include-path": [
88 | ""
89 | ],
90 | "license": [
91 | "BSD-3-Clause"
92 | ],
93 | "authors": [
94 | {
95 | "name": "Sebastian Bergmann",
96 | "email": "sb@sebastian-bergmann.de",
97 | "role": "lead"
98 | }
99 | ],
100 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
101 | "homepage": "http://www.phpunit.de/",
102 | "keywords": [
103 | "filesystem",
104 | "iterator"
105 | ]
106 | },
107 | {
108 | "name": "phpunit/php-text-template",
109 | "version": "1.1.3",
110 | "source": {
111 | "type": "git",
112 | "url": "git://github.com/sebastianbergmann/php-text-template.git",
113 | "reference": "1.1.3"
114 | },
115 | "dist": {
116 | "type": "zip",
117 | "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.3",
118 | "reference": "1.1.3",
119 | "shasum": ""
120 | },
121 | "require": {
122 | "php": ">=5.2.7"
123 | },
124 | "time": "2012-10-05 09:17:21",
125 | "type": "library",
126 | "installation-source": "dist",
127 | "autoload": {
128 | "classmap": [
129 | "Text/"
130 | ]
131 | },
132 | "include-path": [
133 | ""
134 | ],
135 | "license": [
136 | "BSD-3-Clause"
137 | ],
138 | "authors": [
139 | {
140 | "name": "Sebastian Bergmann",
141 | "email": "sb@sebastian-bergmann.de",
142 | "role": "lead"
143 | }
144 | ],
145 | "description": "Simple template engine.",
146 | "homepage": "http://www.phpunit.de/",
147 | "keywords": [
148 | "template"
149 | ]
150 | },
151 | {
152 | "name": "phpunit/php-timer",
153 | "version": "1.0.4",
154 | "source": {
155 | "type": "git",
156 | "url": "git://github.com/sebastianbergmann/php-timer.git",
157 | "reference": "1.0.4"
158 | },
159 | "dist": {
160 | "type": "zip",
161 | "url": "https://github.com/sebastianbergmann/php-timer/zipball/1.0.4",
162 | "reference": "1.0.4",
163 | "shasum": ""
164 | },
165 | "require": {
166 | "php": ">=5.2.7"
167 | },
168 | "time": "2012-10-05 09:09:13",
169 | "type": "library",
170 | "installation-source": "dist",
171 | "autoload": {
172 | "classmap": [
173 | "PHP/"
174 | ]
175 | },
176 | "include-path": [
177 | ""
178 | ],
179 | "license": [
180 | "BSD-3-Clause"
181 | ],
182 | "authors": [
183 | {
184 | "name": "Sebastian Bergmann",
185 | "email": "sb@sebastian-bergmann.de",
186 | "role": "lead"
187 | }
188 | ],
189 | "description": "Utility class for timing",
190 | "homepage": "http://www.phpunit.de/",
191 | "keywords": [
192 | "timer"
193 | ]
194 | },
195 | {
196 | "name": "phpunit/php-token-stream",
197 | "version": "1.1.5",
198 | "source": {
199 | "type": "git",
200 | "url": "git://github.com/sebastianbergmann/php-token-stream.git",
201 | "reference": "1.1.5"
202 | },
203 | "dist": {
204 | "type": "zip",
205 | "url": "https://github.com/sebastianbergmann/php-token-stream/zipball/1.1.5",
206 | "reference": "1.1.5",
207 | "shasum": ""
208 | },
209 | "require": {
210 | "php": ">=5.2.7",
211 | "ext-tokenizer": "*"
212 | },
213 | "time": "2012-10-05 09:17:52",
214 | "type": "library",
215 | "installation-source": "dist",
216 | "autoload": {
217 | "classmap": [
218 | "PHP/"
219 | ]
220 | },
221 | "include-path": [
222 | ""
223 | ],
224 | "license": [
225 | "BSD-3-Clause"
226 | ],
227 | "authors": [
228 | {
229 | "name": "Sebastian Bergmann",
230 | "email": "sb@sebastian-bergmann.de",
231 | "role": "lead"
232 | }
233 | ],
234 | "description": "Wrapper around PHP's tokenizer extension.",
235 | "homepage": "http://www.phpunit.de/",
236 | "keywords": [
237 | "tokenizer"
238 | ]
239 | },
240 | {
241 | "name": "phpunit/phpunit",
242 | "version": "3.7.6",
243 | "source": {
244 | "type": "git",
245 | "url": "git://github.com/sebastianbergmann/phpunit.git",
246 | "reference": "3.7.6"
247 | },
248 | "dist": {
249 | "type": "zip",
250 | "url": "https://github.com/sebastianbergmann/phpunit/zipball/3.7.6",
251 | "reference": "3.7.6",
252 | "shasum": ""
253 | },
254 | "require": {
255 | "php": ">=5.3.3",
256 | "phpunit/php-file-iterator": ">=1.3.1",
257 | "phpunit/php-text-template": ">=1.1.1",
258 | "phpunit/php-code-coverage": ">=1.2.1",
259 | "phpunit/php-timer": ">=1.0.2",
260 | "phpunit/phpunit-mock-objects": ">=1.2.0",
261 | "symfony/yaml": ">=2.1.0",
262 | "ext-dom": "*",
263 | "ext-pcre": "*",
264 | "ext-reflection": "*",
265 | "ext-spl": "*"
266 | },
267 | "suggest": {
268 | "phpunit/php-invoker": ">=1.1.0",
269 | "ext-json": "*",
270 | "ext-simplexml": "*",
271 | "ext-tokenizer": "*"
272 | },
273 | "time": "2012-10-06 23:46:25",
274 | "bin": [
275 | "composer/bin/phpunit"
276 | ],
277 | "type": "library",
278 | "extra": {
279 | "branch-alias": {
280 | "dev-master": "3.7.x-dev"
281 | }
282 | },
283 | "installation-source": "dist",
284 | "autoload": {
285 | "classmap": [
286 | "PHPUnit/"
287 | ]
288 | },
289 | "include-path": [
290 | "",
291 | "../../symfony/yaml/"
292 | ],
293 | "license": [
294 | "BSD-3-Clause"
295 | ],
296 | "authors": [
297 | {
298 | "name": "Sebastian Bergmann",
299 | "email": "sebastian@phpunit.de",
300 | "role": "lead"
301 | }
302 | ],
303 | "description": "The PHP Unit Testing framework.",
304 | "homepage": "http://www.phpunit.de/",
305 | "keywords": [
306 | "testing",
307 | "phpunit",
308 | "xunit"
309 | ]
310 | },
311 | {
312 | "name": "phpunit/phpunit-mock-objects",
313 | "version": "1.2.1",
314 | "source": {
315 | "type": "git",
316 | "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
317 | "reference": "1.2.1"
318 | },
319 | "dist": {
320 | "type": "zip",
321 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/zipball/1.2.1",
322 | "reference": "1.2.1",
323 | "shasum": ""
324 | },
325 | "require": {
326 | "php": ">=5.3.3",
327 | "phpunit/php-text-template": ">=1.1.1@stable",
328 | "ext-reflection": "*",
329 | "ext-spl": "*"
330 | },
331 | "suggest": {
332 | "ext-soap": "*"
333 | },
334 | "time": "2012-10-05 00:00:00",
335 | "type": "library",
336 | "installation-source": "dist",
337 | "autoload": {
338 | "classmap": [
339 | "PHPUnit/"
340 | ]
341 | },
342 | "include-path": [
343 | ""
344 | ],
345 | "license": [
346 | "BSD-3-Clause"
347 | ],
348 | "authors": [
349 | {
350 | "name": "Sebastian Bergmann",
351 | "email": "sb@sebastian-bergmann.de",
352 | "role": "lead"
353 | }
354 | ],
355 | "description": "Mock Object library for PHPUnit",
356 | "homepage": "http://www.phpunit.de/",
357 | "keywords": [
358 | "mock",
359 | "xunit"
360 | ]
361 | },
362 | {
363 | "name": "symfony/yaml",
364 | "version": "v2.1.2",
365 | "target-dir": "Symfony/Component/Yaml",
366 | "source": {
367 | "type": "git",
368 | "url": "https://github.com/symfony/Yaml",
369 | "reference": "v2.1.0-RC2"
370 | },
371 | "dist": {
372 | "type": "zip",
373 | "url": "https://github.com/symfony/Yaml/zipball/v2.1.0-RC2",
374 | "reference": "v2.1.0-RC2",
375 | "shasum": ""
376 | },
377 | "require": {
378 | "php": ">=5.3.3"
379 | },
380 | "time": "2012-08-22 13:48:41",
381 | "type": "library",
382 | "extra": {
383 | "branch-alias": {
384 | "dev-master": "2.1-dev"
385 | }
386 | },
387 | "installation-source": "dist",
388 | "autoload": {
389 | "psr-0": {
390 | "Symfony\\Component\\Yaml": ""
391 | }
392 | },
393 | "license": [
394 | "MIT"
395 | ],
396 | "authors": [
397 | {
398 | "name": "Fabien Potencier",
399 | "email": "fabien@symfony.com"
400 | },
401 | {
402 | "name": "Symfony Community",
403 | "homepage": "http://symfony.com/contributors"
404 | }
405 | ],
406 | "description": "Symfony Yaml Component",
407 | "homepage": "http://symfony.com"
408 | }
409 | ],
410 | "aliases": [
411 |
412 | ],
413 | "minimum-stability": "stable",
414 | "stability-flags": [
415 |
416 | ]
417 | }
418 |
--------------------------------------------------------------------------------
/Apache/Solr/Service/Balancer.php:
--------------------------------------------------------------------------------
1 | , Dan Wolfe
37 | */
38 |
39 | /**
40 | * Reference Implementation for using multiple Solr services in a distribution. Functionality
41 | * includes:
42 | * routing of read / write operations
43 | * failover (on selection) for multiple read servers
44 | */
45 | class Apache_Solr_Service_Balancer
46 | {
47 | /**
48 | * SVN Revision meta data for this class
49 | */
50 | const SVN_REVISION = '$Revision$';
51 |
52 | /**
53 | * SVN ID meta data for this class
54 | */
55 | const SVN_ID = '$Id$';
56 |
57 | protected $_createDocuments = true;
58 |
59 | protected $_readableServices = array();
60 | protected $_writeableServices = array();
61 |
62 | protected $_currentReadService = null;
63 | protected $_currentWriteService = null;
64 |
65 | protected $_readPingTimeout = 2;
66 | protected $_writePingTimeout = 4;
67 |
68 | // Configuration for server selection backoff intervals
69 | protected $_useBackoff = false; // Set to true to use more resillient write server selection
70 | protected $_backoffLimit = 600; // 10 minute default maximum
71 | protected $_backoffEscalation = 2.0; // Rate at which to increase backoff period
72 | protected $_defaultBackoff = 2.0; // Default backoff interval
73 |
74 | /**
75 | * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
76 | *
77 | * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
78 | *
79 | * @param string $value
80 | * @return string
81 | */
82 | static public function escape($value)
83 | {
84 | return Apache_Solr_Service::escape($value);
85 | }
86 |
87 | /**
88 | * Escape a value meant to be contained in a phrase for special query characters
89 | *
90 | * @param string $value
91 | * @return string
92 | */
93 | static public function escapePhrase($value)
94 | {
95 | return Apache_Solr_Service::escapePhrase($value);
96 | }
97 |
98 | /**
99 | * Convenience function for creating phrase syntax from a value
100 | *
101 | * @param string $value
102 | * @return string
103 | */
104 | static public function phrase($value)
105 | {
106 | return Apache_Solr_Service::phrase($value);
107 | }
108 |
109 | /**
110 | * Constructor. Takes arrays of read and write service instances or descriptions
111 | *
112 | * @param array $readableServices
113 | * @param array $writeableServices
114 | */
115 | public function __construct($readableServices = array(), $writeableServices = array())
116 | {
117 | //setup readable services
118 | foreach ($readableServices as $service)
119 | {
120 | $this->addReadService($service);
121 | }
122 |
123 | //setup writeable services
124 | foreach ($writeableServices as $service)
125 | {
126 | $this->addWriteService($service);
127 | }
128 | }
129 |
130 | public function setReadPingTimeout($timeout)
131 | {
132 | $this->_readPingTimeout = $timeout;
133 | }
134 |
135 | public function setWritePingTimeout($timeout)
136 | {
137 | $this->_writePingTimeout = $timeout;
138 | }
139 |
140 | public function setUseBackoff($enable)
141 | {
142 | $this->_useBackoff = $enable;
143 | }
144 |
145 | /**
146 | * Generates a service ID
147 | *
148 | * @param string $host
149 | * @param integer $port
150 | * @param string $path
151 | * @return string
152 | */
153 | protected function _getServiceId($host, $port, $path)
154 | {
155 | return $host . ':' . $port . $path;
156 | }
157 |
158 | /**
159 | * Adds a service instance or service descriptor (if it is already
160 | * not added)
161 | *
162 | * @param mixed $service
163 | *
164 | * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
165 | */
166 | public function addReadService($service)
167 | {
168 | if ($service instanceof Apache_Solr_Service)
169 | {
170 | $id = $this->_getServiceId($service->getHost(), $service->getPort(), $service->getPath());
171 |
172 | $this->_readableServices[$id] = $service;
173 | }
174 | else if (is_array($service))
175 | {
176 | if (isset($service['host']) && isset($service['port']) && isset($service['path']))
177 | {
178 | $id = $this->_getServiceId((string)$service['host'], (int)$service['port'], (string)$service['path']);
179 |
180 | $this->_readableServices[$id] = $service;
181 | }
182 | else
183 | {
184 | throw new Apache_Solr_InvalidArgumentException('A Readable Service description array does not have all required elements of host, port, and path');
185 | }
186 | }
187 | }
188 |
189 | /**
190 | * Removes a service instance or descriptor from the available services
191 | *
192 | * @param mixed $service
193 | *
194 | * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
195 | */
196 | public function removeReadService($service)
197 | {
198 | $id = '';
199 |
200 | if ($service instanceof Apache_Solr_Service)
201 | {
202 | $id = $this->_getServiceId($service->getHost(), $service->getPort(), $service->getPath());
203 | }
204 | else if (is_array($service))
205 | {
206 | if (isset($service['host']) && isset($service['port']) && isset($service['path']))
207 | {
208 | $id = $this->_getServiceId((string)$service['host'], (int)$service['port'], (string)$service['path']);
209 | }
210 | else
211 | {
212 | throw new Apache_Solr_InvalidArgumentException('A Readable Service description array does not have all required elements of host, port, and path');
213 | }
214 | }
215 | else if (is_string($service))
216 | {
217 | $id = $service;
218 | }
219 |
220 | if ($id && isset($this->_readableServices[$id]))
221 | {
222 | unset($this->_readableServices[$id]);
223 | }
224 | }
225 |
226 | /**
227 | * Adds a service instance or service descriptor (if it is already
228 | * not added)
229 | *
230 | * @param mixed $service
231 | *
232 | * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
233 | */
234 | public function addWriteService($service)
235 | {
236 | if ($service instanceof Apache_Solr_Service)
237 | {
238 | $id = $this->_getServiceId($service->getHost(), $service->getPort(), $service->getPath());
239 |
240 | $this->_writeableServices[$id] = $service;
241 | }
242 | else if (is_array($service))
243 | {
244 | if (isset($service['host']) && isset($service['port']) && isset($service['path']))
245 | {
246 | $id = $this->_getServiceId((string)$service['host'], (int)$service['port'], (string)$service['path']);
247 |
248 | $this->_writeableServices[$id] = $service;
249 | }
250 | else
251 | {
252 | throw new Apache_Solr_InvalidArgumentException('A Writeable Service description array does not have all required elements of host, port, and path');
253 | }
254 | }
255 | }
256 |
257 | /**
258 | * Removes a service instance or descriptor from the available services
259 | *
260 | * @param mixed $service
261 | *
262 | * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
263 | */
264 | public function removeWriteService($service)
265 | {
266 | $id = '';
267 |
268 | if ($service instanceof Apache_Solr_Service)
269 | {
270 | $id = $this->_getServiceId($service->getHost(), $service->getPort(), $service->getPath());
271 | }
272 | else if (is_array($service))
273 | {
274 | if (isset($service['host']) && isset($service['port']) && isset($service['path']))
275 | {
276 | $id = $this->_getServiceId((string)$service['host'], (int)$service['port'], (string)$service['path']);
277 | }
278 | else
279 | {
280 | throw new Apache_Solr_InvalidArgumentException('A Readable Service description array does not have all required elements of host, port, and path');
281 | }
282 | }
283 | else if (is_string($service))
284 | {
285 | $id = $service;
286 | }
287 |
288 | if ($id && isset($this->_writeableServices[$id]))
289 | {
290 | unset($this->_writeableServices[$id]);
291 | }
292 | }
293 |
294 | /**
295 | * Iterate through available read services and select the first with a ping
296 | * that satisfies configured timeout restrictions (or the default)
297 | *
298 | * @return Apache_Solr_Service
299 | *
300 | * @throws Apache_Solr_NoServiceAvailableException If there are no read services that meet requirements
301 | */
302 | protected function _selectReadService($forceSelect = false)
303 | {
304 | if (!$this->_currentReadService || !isset($this->_readableServices[$this->_currentReadService]) || $forceSelect)
305 | {
306 | if ($this->_currentReadService && isset($this->_readableServices[$this->_currentReadService]) && $forceSelect)
307 | {
308 | // we probably had a communication error, ping the current read service, remove it if it times out
309 | if ($this->_readableServices[$this->_currentReadService]->ping($this->_readPingTimeout) === false)
310 | {
311 | $this->removeReadService($this->_currentReadService);
312 | }
313 | }
314 |
315 | if (count($this->_readableServices))
316 | {
317 | // select one of the read services at random
318 | $ids = array_keys($this->_readableServices);
319 |
320 | $id = $ids[rand(0, count($ids) - 1)];
321 | $service = $this->_readableServices[$id];
322 |
323 | if (is_array($service))
324 | {
325 | //convert the array definition to a client object
326 | $service = new Apache_Solr_Service($service['host'], $service['port'], $service['path']);
327 | $this->_readableServices[$id] = $service;
328 | }
329 |
330 | $service->setCreateDocuments($this->_createDocuments);
331 | $this->_currentReadService = $id;
332 | }
333 | else
334 | {
335 | throw new Apache_Solr_NoServiceAvailableException('No read services were available');
336 | }
337 | }
338 |
339 | return $this->_readableServices[$this->_currentReadService];
340 | }
341 |
342 | /**
343 | * Iterate through available write services and select the first with a ping
344 | * that satisfies configured timeout restrictions (or the default)
345 | *
346 | * @return Apache_Solr_Service
347 | *
348 | * @throws Apache_Solr_NoServiceAvailableException If there are no write services that meet requirements
349 | */
350 | protected function _selectWriteService($forceSelect = false)
351 | {
352 | if($this->_useBackoff)
353 | {
354 | return $this->_selectWriteServiceSafe($forceSelect);
355 | }
356 |
357 | if (!$this->_currentWriteService || !isset($this->_writeableServices[$this->_currentWriteService]) || $forceSelect)
358 | {
359 | if ($this->_currentWriteService && isset($this->_writeableServices[$this->_currentWriteService]) && $forceSelect)
360 | {
361 | // we probably had a communication error, ping the current read service, remove it if it times out
362 | if ($this->_writeableServices[$this->_currentWriteService]->ping($this->_writePingTimeout) === false)
363 | {
364 | $this->removeWriteService($this->_currentWriteService);
365 | }
366 | }
367 |
368 | if (count($this->_writeableServices))
369 | {
370 | // select one of the read services at random
371 | $ids = array_keys($this->_writeableServices);
372 |
373 | $id = $ids[rand(0, count($ids) - 1)];
374 | $service = $this->_writeableServices[$id];
375 |
376 | if (is_array($service))
377 | {
378 | //convert the array definition to a client object
379 | $service = new Apache_Solr_Service($service['host'], $service['port'], $service['path']);
380 | $this->_writeableServices[$id] = $service;
381 | }
382 |
383 | $this->_currentWriteService = $id;
384 | }
385 | else
386 | {
387 | throw new Apache_Solr_NoServiceAvailableException('No write services were available');
388 | }
389 | }
390 |
391 | return $this->_writeableServices[$this->_currentWriteService];
392 | }
393 |
394 | /**
395 | * Iterate through available write services and select the first with a ping
396 | * that satisfies configured timeout restrictions (or the default). The
397 | * timeout period will increase until a connection is made or the limit is
398 | * reached. This will allow for increased reliability with heavily loaded
399 | * server(s).
400 | *
401 | * @return Apache_Solr_Service
402 | *
403 | * @throws Apache_Solr_NoServiceAvailableException If there are no write services that meet requirements
404 | */
405 |
406 | protected function _selectWriteServiceSafe($forceSelect = false)
407 | {
408 | if (!$this->_currentWriteService || !isset($this->_writeableServices[$this->_currentWriteService]) || $forceSelect)
409 | {
410 | if (count($this->_writeableServices))
411 | {
412 | $backoff = $this->_defaultBackoff;
413 |
414 | do {
415 | // select one of the read services at random
416 | $ids = array_keys($this->_writeableServices);
417 |
418 | $id = $ids[rand(0, count($ids) - 1)];
419 | $service = $this->_writeableServices[$id];
420 |
421 | if (is_array($service))
422 | {
423 | //convert the array definition to a client object
424 | $service = new Apache_Solr_Service($service['host'], $service['port'], $service['path']);
425 | $this->_writeableServices[$id] = $service;
426 | }
427 |
428 | $this->_currentWriteService = $id;
429 |
430 | $backoff *= $this->_backoffEscalation;
431 |
432 | if($backoff > $this->_backoffLimit)
433 | {
434 | throw new Apache_Solr_NoServiceAvailableException('No write services were available. All timeouts exceeded.');
435 | }
436 |
437 | } while($this->_writeableServices[$this->_currentWriteService]->ping($backoff) === false);
438 | }
439 | else
440 | {
441 | throw new Apache_Solr_NoServiceAvailableException('No write services were available');
442 | }
443 | }
444 |
445 | return $this->_writeableServices[$this->_currentWriteService];
446 | }
447 |
448 | /**
449 | * Set the create documents flag. This determines whether {@link Apache_Solr_Response} objects will
450 | * parse the response and create {@link Apache_Solr_Document} instances in place.
451 | *
452 | * @param boolean $createDocuments
453 | */
454 | public function setCreateDocuments($createDocuments)
455 | {
456 | $this->_createDocuments = (bool) $createDocuments;
457 |
458 | // set on current read service
459 | if ($this->_currentReadService)
460 | {
461 | $service = $this->_selectReadService();
462 | $service->setCreateDocuments($createDocuments);
463 | }
464 | }
465 |
466 | /**
467 | * Get the current state of teh create documents flag.
468 | *
469 | * @return boolean
470 | */
471 | public function getCreateDocuments()
472 | {
473 | return $this->_createDocuments;
474 | }
475 |
476 | /**
477 | * Raw Add Method. Takes a raw post body and sends it to the update service. Post body
478 | * should be a complete and well formed "add" xml document.
479 | *
480 | * @param string $rawPost
481 | * @return Apache_Solr_Response
482 | *
483 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
484 | */
485 | public function add($rawPost)
486 | {
487 | $service = $this->_selectWriteService();
488 |
489 | do
490 | {
491 | try
492 | {
493 | return $service->add($rawPost);
494 | }
495 | catch (Apache_Solr_HttpTransportException $e)
496 | {
497 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
498 | {
499 | throw $e;
500 | }
501 | }
502 |
503 | $service = $this->_selectWriteService(true);
504 | } while ($service);
505 |
506 | return false;
507 | }
508 |
509 | /**
510 | * Add a Solr Document to the index
511 | *
512 | * @param Apache_Solr_Document $document
513 | * @param boolean $allowDups
514 | * @param boolean $overwritePending
515 | * @param boolean $overwriteCommitted
516 | * @return Apache_Solr_Response
517 | *
518 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
519 | */
520 | public function addDocument(Apache_Solr_Document $document, $allowDups = false, $overwritePending = true, $overwriteCommitted = true)
521 | {
522 | $service = $this->_selectWriteService();
523 |
524 | do
525 | {
526 | try
527 | {
528 | return $service->addDocument($document, $allowDups, $overwritePending, $overwriteCommitted);
529 | }
530 | catch (Apache_Solr_HttpTransportException $e)
531 | {
532 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
533 | {
534 | throw $e;
535 | }
536 | }
537 |
538 | $service = $this->_selectWriteService(true);
539 | } while ($service);
540 |
541 | return false;
542 | }
543 |
544 | /**
545 | * Add an array of Solr Documents to the index all at once
546 | *
547 | * @param array $documents Should be an array of Apache_Solr_Document instances
548 | * @param boolean $allowDups
549 | * @param boolean $overwritePending
550 | * @param boolean $overwriteCommitted
551 | * @return Apache_Solr_Response
552 | *
553 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
554 | */
555 | public function addDocuments($documents, $allowDups = false, $overwritePending = true, $overwriteCommitted = true)
556 | {
557 | $service = $this->_selectWriteService();
558 |
559 | do
560 | {
561 | try
562 | {
563 | return $service->addDocuments($documents, $allowDups, $overwritePending, $overwriteCommitted);
564 | }
565 | catch (Apache_Solr_HttpTransportException $e)
566 | {
567 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
568 | {
569 | throw $e;
570 | }
571 | }
572 |
573 | $service = $this->_selectWriteService(true);
574 | } while ($service);
575 |
576 | return false;
577 | }
578 |
579 | /**
580 | * Send a commit command. Will be synchronous unless both wait parameters are set
581 | * to false.
582 | *
583 | * @param boolean $waitFlush
584 | * @param boolean $waitSearcher
585 | * @return Apache_Solr_Response
586 | *
587 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
588 | */
589 | public function commit($optimize = true, $waitFlush = true, $waitSearcher = true, $timeout = 3600)
590 | {
591 | $service = $this->_selectWriteService();
592 |
593 | do
594 | {
595 | try
596 | {
597 | return $service->commit($optimize, $waitFlush, $waitSearcher, $timeout);
598 | }
599 | catch (Apache_Solr_HttpTransportException $e)
600 | {
601 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
602 | {
603 | throw $e;
604 | }
605 | }
606 |
607 | $service = $this->_selectWriteService(true);
608 | } while ($service);
609 |
610 | return false;
611 | }
612 |
613 | /**
614 | * Raw Delete Method. Takes a raw post body and sends it to the update service. Body should be
615 | * a complete and well formed "delete" xml document
616 | *
617 | * @param string $rawPost
618 | * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
619 | * @return Apache_Solr_Response
620 | *
621 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
622 | */
623 | public function delete($rawPost, $timeout = 3600)
624 | {
625 | $service = $this->_selectWriteService();
626 |
627 | do
628 | {
629 | try
630 | {
631 | return $service->delete($rawPost, $timeout);
632 | }
633 | catch (Apache_Solr_HttpTransportException $e)
634 | {
635 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
636 | {
637 | throw $e;
638 | }
639 | }
640 |
641 | $service = $this->_selectWriteService(true);
642 | } while ($service);
643 |
644 | return false;
645 | }
646 |
647 | /**
648 | * Create a delete document based on document ID
649 | *
650 | * @param string $id
651 | * @param boolean $fromPending
652 | * @param boolean $fromCommitted
653 | * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
654 | * @return Apache_Solr_Response
655 | *
656 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
657 | */
658 | public function deleteById($id, $fromPending = true, $fromCommitted = true, $timeout = 3600)
659 | {
660 | $service = $this->_selectWriteService();
661 |
662 | do
663 | {
664 | try
665 | {
666 | return $service->deleteById($id, $fromPending, $fromCommitted, $timeout);
667 | }
668 | catch (Apache_Solr_HttpTransportException $e)
669 | {
670 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
671 | {
672 | throw $e;
673 | }
674 | }
675 |
676 | $service = $this->_selectWriteService(true);
677 | } while ($service);
678 |
679 | return false;
680 | }
681 |
682 | /**
683 | * Create and post a delete document based on multiple document IDs.
684 | *
685 | * @param array $ids Expected to be utf-8 encoded strings
686 | * @param boolean $fromPending
687 | * @param boolean $fromCommitted
688 | * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
689 | * @return Apache_Solr_Response
690 | *
691 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
692 | */
693 | public function deleteByMultipleIds($ids, $fromPending = true, $fromCommitted = true, $timeout = 3600)
694 | {
695 | $service = $this->_selectWriteService();
696 |
697 | do
698 | {
699 | try
700 | {
701 | return $service->deleteByMultipleId($ids, $fromPending, $fromCommitted, $timeout);
702 | }
703 | catch (Apache_Solr_HttpTransportException $e)
704 | {
705 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
706 | {
707 | throw $e;
708 | }
709 | }
710 |
711 | $service = $this->_selectWriteService(true);
712 | } while ($service);
713 |
714 | return false;
715 | }
716 |
717 | /**
718 | * Create a delete document based on a query and submit it
719 | *
720 | * @param string $rawQuery
721 | * @param boolean $fromPending
722 | * @param boolean $fromCommitted
723 | * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
724 | * @return Apache_Solr_Response
725 | *
726 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
727 | */
728 | public function deleteByQuery($rawQuery, $fromPending = true, $fromCommitted = true, $timeout = 3600)
729 | {
730 | $service = $this->_selectWriteService();
731 |
732 | do
733 | {
734 | try
735 | {
736 | return $service->deleteByQuery($rawQuery, $fromPending, $fromCommitted, $timeout);
737 | }
738 | catch (Apache_Solr_HttpTransportException $e)
739 | {
740 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
741 | {
742 | throw $e;
743 | }
744 | }
745 |
746 | $service = $this->_selectWriteService(true);
747 | } while ($service);
748 |
749 | return false;
750 | }
751 |
752 | /**
753 | * Use Solr Cell to extract document contents. See {@link http://wiki.apache.org/solr/ExtractingRequestHandler} for information on how
754 | * to use Solr Cell and what parameters are available.
755 | *
756 | * NOTE: when passing an Apache_Solr_Document instance, field names and boosts will automatically be prepended by "literal." and "boost."
757 | * as appropriate. Any keys from the $params array will NOT be treated this way. Any mappings from the document will overwrite key / value
758 | * pairs in the params array if they have the same name (e.g. you pass a "literal.id" key and value in your $params array but you also
759 | * pass in a document isntance with an "id" field" - the document's value(s) will take precedence).
760 | *
761 | * @param string $file Path to file to extract data from
762 | * @param array $params optional array of key value pairs that will be sent with the post (see Solr Cell documentation)
763 | * @param Apache_Solr_Document $document optional document that will be used to generate post parameters (literal.* and boost.* params)
764 | * @param string $mimetype optional mimetype specification (for the file being extracted)
765 | *
766 | * @return Apache_Solr_Response
767 | *
768 | * @throws Apache_Solr_InvalidArgumentException if $file, $params, or $document are invalid.
769 | */
770 | public function extract($file, $params = array(), $document = null, $mimetype = 'application/octet-stream')
771 | {
772 | $service = $this->_selectWriteService();
773 |
774 | do
775 | {
776 | try
777 | {
778 | return $service->extract($file, $params, $document, $mimetype);
779 | }
780 | catch (Apache_Solr_HttpTransportException $e)
781 | {
782 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
783 | {
784 | throw $e;
785 | }
786 | }
787 |
788 | $service = $this->_selectWriteService(true);
789 | } while ($service);
790 |
791 | return false;
792 | }
793 |
794 | /**
795 | * Use Solr Cell to extract document contents. See {@link http://wiki.apache.org/solr/ExtractingRequestHandler} for information on how
796 | * to use Solr Cell and what parameters are available.
797 | *
798 | * NOTE: when passing an Apache_Solr_Document instance, field names and boosts will automatically be prepended by "literal." and "boost."
799 | * as appropriate. Any keys from the $params array will NOT be treated this way. Any mappings from the document will overwrite key / value
800 | * pairs in the params array if they have the same name (e.g. you pass a "literal.id" key and value in your $params array but you also
801 | * pass in a document isntance with an "id" field" - the document's value(s) will take precedence).
802 | *
803 | * @param string $data Data that will be passed to Solr Cell
804 | * @param array $params optional array of key value pairs that will be sent with the post (see Solr Cell documentation)
805 | * @param Apache_Solr_Document $document optional document that will be used to generate post parameters (literal.* and boost.* params)
806 | * @param string $mimetype optional mimetype specification (for the file being extracted)
807 | *
808 | * @return Apache_Solr_Response
809 | *
810 | * @throws Apache_Solr_InvalidArgumentException if $file, $params, or $document are invalid.
811 | *
812 | * @todo Should be using multipart/form-data to post parameter values, but I could not get my implementation to work. Needs revisisted.
813 | */
814 | public function extractFromString($data, $params = array(), $document = null, $mimetype = 'application/octet-stream')
815 | {
816 | $service = $this->_selectWriteService();
817 |
818 | do
819 | {
820 | try
821 | {
822 | return $service->extractFromString($data, $params, $document, $mimetype);
823 | }
824 | catch (Apache_Solr_HttpTransportException $e)
825 | {
826 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
827 | {
828 | throw $e;
829 | }
830 | }
831 |
832 | $service = $this->_selectWriteService(true);
833 | } while ($service);
834 |
835 | return false;
836 | }
837 |
838 | /**
839 | * Send an optimize command. Will be synchronous unless both wait parameters are set
840 | * to false.
841 | *
842 | * @param boolean $waitFlush
843 | * @param boolean $waitSearcher
844 | * @param float $timeout Maximum expected duration of the optimize operation on the server (otherwise, will throw a communication exception)
845 | * @return Apache_Solr_Response
846 | *
847 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
848 | */
849 | public function optimize($waitFlush = true, $waitSearcher = true, $timeout = 3600)
850 | {
851 | $service = $this->_selectWriteService();
852 |
853 | do
854 | {
855 | try
856 | {
857 | return $service->optimize($waitFlush, $waitSearcher, $timeout);
858 | }
859 | catch (Apache_Solr_HttpTransportException $e)
860 | {
861 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
862 | {
863 | throw $e;
864 | }
865 | }
866 |
867 | $service = $this->_selectWriteService(true);
868 | } while ($service);
869 |
870 | return false;
871 | }
872 |
873 | /**
874 | * Simple Search interface
875 | *
876 | * @param string $query The raw query string
877 | * @param int $offset The starting offset for result documents
878 | * @param int $limit The maximum number of result documents to return
879 | * @param array $params key / value pairs for query parameters, use arrays for multivalued parameters
880 | * @param string $method The HTTP method (Apache_Solr_Service::METHOD_GET or Apache_Solr_Service::METHOD::POST)
881 | * @return Apache_Solr_Response
882 | *
883 | * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
884 | */
885 | public function search($query, $offset = 0, $limit = 10, $params = array(), $method = Apache_Solr_Service::METHOD_GET)
886 | {
887 | $service = $this->_selectReadService();
888 |
889 | do
890 | {
891 | try
892 | {
893 | return $service->search($query, $offset, $limit, $params, $method);
894 | }
895 | catch (Apache_Solr_HttpTransportException $e)
896 | {
897 | if ($e->getCode() != 0) //IF NOT COMMUNICATION ERROR
898 | {
899 | throw $e;
900 | }
901 | }
902 |
903 | $service = $this->_selectReadService(true);
904 | } while ($service);
905 |
906 | return false;
907 | }
908 | }
909 |
--------------------------------------------------------------------------------