1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: |
14 | Israel Ekpo <iekpo@php.net> |
15 | Omar Shaban <omars@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "php_solr.h"
20
21 /** ************************************************************************ **/
22 /** DEFINITIONS FOR SOLR INPUT DOCUMENT METHODS **/
23 /** ************************************************************************ **/
24
25 /* {{{ proto void SolrInputDocument::__construct()
26 SolrInputDocument constructor */
PHP_METHOD(SolrInputDocument,__construct)27 PHP_METHOD(SolrInputDocument, __construct)
28 {
29 zval *objptr = getThis();
30 if (solr_input_doc_ctor(objptr) == NULL)
31 {
32 return;
33 }
34 }
35
36 /* }}} */
37
38 /* {{{ proto void SolrInputDocument::__destruct(void)
39 Destructor for SolrInputDocument */
PHP_METHOD(SolrInputDocument,__destruct)40 PHP_METHOD(SolrInputDocument, __destruct)
41 {
42 solr_document_t *doc_entry = NULL;
43
44 /* Retrieve the document entry for this SolrDocument */
45 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
46
47 zend_hash_index_del(SOLR_GLOBAL(documents), doc_entry->document_index);
48
49 /* Keep track of how many SolrDocument instances we currently have */
50 SOLR_GLOBAL(document_count)--;
51
52 return ;
53 }
54 }
55 /* }}} */
56
57 /* {{{ proto void SolrInputDocument::__clone(void)
58 Clones the current object. Not to be called directly. */
PHP_METHOD(SolrInputDocument,__clone)59 PHP_METHOD(SolrInputDocument, __clone)
60 {
61 RETURN_NULL();
62 }
63 /* }}} */
64
65 /* {{{ proto void SolrInputDocument::__sleep(void)
66 Should not be called directly. Serialization is not supported. */
PHP_METHOD(SolrInputDocument,__sleep)67 PHP_METHOD(SolrInputDocument, __sleep)
68 {
69 solr_throw_exception_ex(solr_ce_SolrIllegalOperationException, SOLR_ERROR_1005, SOLR_FILE_LINE_FUNC, SOLR_ERROR_1005_MSG);
70 }
71 /* }}} */
72
73 /* {{{ proto void SolrInputDocument::__wakeup(void)
74 Should not be called directly. Serialization is not supported. */
PHP_METHOD(SolrInputDocument,__wakeup)75 PHP_METHOD(SolrInputDocument, __wakeup)
76 {
77 solr_throw_exception_ex(solr_ce_SolrIllegalOperationException, SOLR_ERROR_1005, SOLR_FILE_LINE_FUNC, SOLR_ERROR_1005_MSG);
78 }
79 /* }}} */
80
81 /* {{{ proto bool SolrInputDocument::setBoost(float document_boost)
82 Sets the boost for the document. */
PHP_METHOD(SolrInputDocument,setBoost)83 PHP_METHOD(SolrInputDocument, setBoost)
84 {
85 double boost_value = 0.0f;
86 solr_document_t *doc_entry = NULL;
87
88 if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", &boost_value) == FAILURE) {
89
90 RETURN_FALSE;
91 }
92
93 /* If the submitted boost_value is negative. */
94 if (boost_value < 0.0) {
95
96 RETURN_FALSE;
97 }
98
99 /* Retrieve the document entry for this SolrDocument */
100 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
101
102 doc_entry->document_boost = boost_value;
103
104 RETURN_TRUE;
105 }
106
107 RETURN_FALSE;
108 }
109 /* }}} */
110
111 /* {{{ proto float SolrInputDocument::getBoost(void)
112 Retrieves the boost for the document. */
PHP_METHOD(SolrInputDocument,getBoost)113 PHP_METHOD(SolrInputDocument, getBoost)
114 {
115 solr_document_t *doc_entry = NULL;
116
117 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
118
119 RETURN_DOUBLE(doc_entry->document_boost);
120 }
121
122 RETURN_FALSE;
123 }
124 /* }}} */
125
126 /* {{{ proto bool SolrInputDocument::clear(void)
127 Discards all the fields and resets the document boost to zero. */
PHP_METHOD(SolrInputDocument,clear)128 PHP_METHOD(SolrInputDocument, clear)
129 {
130 solr_document_t *doc_entry = NULL;
131
132 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
133
134 doc_entry->document_boost = 0.0;
135 doc_entry->field_count = 0L;
136
137 zend_hash_clean(doc_entry->fields);
138
139 RETURN_TRUE;
140 }
141
142 RETURN_FALSE;
143 }
144 /* }}} */
145
146 /* {{{ proto bool SolrInputDocument::addField(string field_name, field_value [, float field_boost])
147 Adds a field to the document. Can be called multiple times. */
PHP_METHOD(SolrInputDocument,addField)148 PHP_METHOD(SolrInputDocument, addField)
149 {
150 solr_char_t *field_name = NULL, *field_value = NULL;
151 COMPAT_ARG_SIZE_T field_name_length = 0, field_value_length = 0;
152 solr_document_t *doc_entry = NULL;
153 double field_boost = 0.0;
154
155
156 /* Process the parameters passed to the method */
157 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|d", &field_name,
158 &field_name_length, &field_value, &field_value_length, &field_boost) == FAILURE) {
159 RETURN_FALSE;
160 }
161
162 if (!field_name_length) {
163 RETURN_FALSE;
164 }
165
166 /* Retrieve the document entry for the SolrDocument instance */
167 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS)
168 {
169 solr_field_list_t *field_values = NULL;
170
171 /* If the field already exists in the SolrDocument instance append the value to the field list queue */
172 if ((field_values = (solr_field_list_t *)zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) != NULL) {
173 if (solr_document_insert_field_value(field_values, (solr_char_t *)field_value, field_boost) == FAILURE) {
174 RETURN_FALSE;
175 }
176 } else {
177
178 /* Otherwise, create a new one and add it to the hash table */
179 field_values = (solr_field_list_t *) pemalloc(sizeof(solr_field_list_t), SOLR_DOCUMENT_FIELD_PERSISTENT);
180
181 memset(field_values, 0, sizeof(solr_field_list_t));
182
183 field_values->count = 0L;
184 field_values->field_boost = 0.0;
185 field_values->field_name = (solr_char_t *) pestrdup((char *)field_name, SOLR_DOCUMENT_FIELD_PERSISTENT);
186 field_values->head = NULL;
187 field_values->last = NULL;
188
189 if (solr_document_insert_field_value(field_values, field_value, field_boost) == FAILURE) {
190 solr_destroy_field_list(field_values);
191 RETURN_FALSE;
192 }
193
194 if (zend_hash_str_add_ptr(doc_entry->fields, field_name, field_name_length,(void *) field_values) == NULL) {
195 solr_destroy_field_list(field_values);
196 RETURN_FALSE;
197 }
198
199 /* Increment field count only when HEAD is added */
200 doc_entry->field_count++;
201 }
202
203 RETURN_TRUE;
204 }
205
206 RETURN_FALSE;
207 }
208 /* }}} */
209
210 /* {{{ proto bool SolrInputDocument::updateField(string fieldName, int modifier, string value) */
PHP_METHOD(SolrInputDocument,updateField)211 PHP_METHOD(SolrInputDocument, updateField)
212 {
213 solr_char_t *field_name = NULL, *field_value = NULL;
214 COMPAT_ARG_SIZE_T field_name_length = 0, field_value_len = 0;
215 solr_document_t *doc_entry;
216 solr_field_list_t *field;
217
218 long modifier = 0L;
219
220 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sls", &field_name, &field_name_length, &modifier, &field_value, &field_value_len) == FAILURE) {
221 return;
222 }
223
224 if (!field_name_length || !field_value_len) {
225 RETURN_FALSE;
226 }
227
228 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) {
229 return;
230 }
231
232 switch (modifier) {
233 case SOLR_FIELD_VALUE_MOD_ADD:
234 case SOLR_FIELD_VALUE_MOD_REMOVE:
235 case SOLR_FIELD_VALUE_MOD_REMOVEREGEX:
236 case SOLR_FIELD_VALUE_MOD_SET:
237 case SOLR_FIELD_VALUE_MOD_INC:
238 break;
239
240 default:
241 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4003, SOLR_FILE_LINE_FUNC, SOLR_ERROR_4003_MSG);
242 RETURN_FALSE;
243 }
244
245 if ((field = zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) == NULL){
246 field = (solr_field_list_t *)pemalloc(sizeof(solr_field_list_t), SOLR_DOCUMENT_FIELD_PERSISTENT);
247 memset(field, 0, sizeof(solr_field_list_t));
248 field->field_name = pestrdup(field_name, SOLR_DOCUMENT_FIELD_PERSISTENT);
249 field->count = 1;
250 field->head = NULL;
251 field->last = NULL;
252 if (modifier > 0) {
253 field->modified = 1;
254 }
255 doc_entry->field_count++;
256 if (zend_hash_str_add_ptr(doc_entry->fields, field_name, field_name_length, field) == NULL) {
257 RETURN_FALSE;
258 }
259 } else if (field->modified == 0) {
260 solr_throw_exception_ex(solr_ce_SolrIllegalOperationException, SOLR_ERROR_4004, SOLR_FILE_LINE_FUNC, SOLR_ERROR_4004_MSG);
261 RETURN_FALSE;
262 }
263
264 solr_document_insert_field_value_ex(field, field_value, 0.0, modifier);
265 }
266
267 /* }}} */
268 /* {{{ proto bool SolrInputDocument::setFieldBoost(string fieldname, float boost_value)
269 Sets the boost for the specified field. */
PHP_METHOD(SolrInputDocument,setFieldBoost)270 PHP_METHOD(SolrInputDocument, setFieldBoost)
271 {
272 solr_char_t *field_name = NULL;
273 COMPAT_ARG_SIZE_T field_name_length = 0;
274 double field_boost = 0.0;
275 solr_document_t *doc_entry = NULL;
276
277 /* Process the parameters passed to the default constructor */
278 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sd", &field_name, &field_name_length, &field_boost) == FAILURE) {
279
280 RETURN_FALSE;
281 }
282
283 if (!field_name_length) {
284 RETURN_FALSE;
285 }
286
287 if (field_boost < 0.0) {
288 RETURN_FALSE;
289 }
290
291 /* Retrieve the document entry for the SolrDocument instance */
292 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
293
294 solr_field_list_t *field_values = NULL;
295
296 /* If the field already exists in the SolrDocument instance append the value to the field list queue */
297 if ((field_values = zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) != NULL) {
298 field_values->field_boost = field_boost;
299 RETURN_TRUE;
300 }
301
302 RETURN_FALSE;
303 }
304
305 RETURN_FALSE;
306 }
307 /* }}} */
308
309 /**
310 * {{{ proto bool SolrInputDocument::setVersion(int version)
311 * Enable optimistic concurrency using assertions */
PHP_METHOD(SolrInputDocument,setVersion)312 PHP_METHOD(SolrInputDocument, setVersion)
313 {
314 long version = 0;
315 solr_document_t *doc_entry = NULL;
316 solr_field_list_t *field = NULL;
317 solr_char_t *field_name = "_version_";
318 COMPAT_ARG_SIZE_T field_name_length = sizeof("_version_");
319 char version_str[80];
320 zend_error_handling error_handling;
321
322 zend_replace_error_handling(EH_THROW, solr_ce_SolrIllegalArgumentException, &error_handling);
323 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &version) == FAILURE) {
324 zend_restore_error_handling(&error_handling);
325 return;
326 }
327 zend_restore_error_handling(&error_handling);
328
329 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) {
330 return;
331 }
332
333 if (zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) {
334 zend_hash_str_del(doc_entry->fields, field_name, field_name_length);
335 }
336
337 field = pemalloc(sizeof(solr_field_list_t), SOLR_DOCUMENT_FIELD_PERSISTENT);
338
339 field->count = 0L;
340 field->field_boost = 0.0f;
341 field->field_name = pestrdup(field_name, SOLR_DOCUMENT_FIELD_PERSISTENT);
342 field->head = field->last = NULL;
343
344 snprintf(version_str, 80, "%ld", version);
345
346 solr_document_insert_field_value(field, version_str, 0.0);
347
348 if (zend_hash_str_update_ptr(doc_entry->fields, field_name, field_name_length, field) == NULL) {
349 solr_throw_exception_ex(solr_ce_SolrException, SOLR_ERROR_1008, SOLR_FILE_LINE_FUNC, SOLR_ERROR_1008_MSG);
350 solr_destroy_field_list(field);
351 return;
352 }
353
354 RETURN_TRUE;
355 }
356 /* }}} */
357
358 /* {{{ proto int SolrInputDocument::getVersion( void ) */
PHP_METHOD(SolrInputDocument,getVersion)359 PHP_METHOD(SolrInputDocument, getVersion)
360 {
361 solr_document_t *doc_entry = NULL;
362 solr_char_t *field_name = "_version_";
363 COMPAT_ARG_SIZE_T field_name_length = sizeof("_version_");
364 solr_field_list_t *field = NULL;
365
366 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) {
367 RETURN_NULL();
368 }
369 if ((field = zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) != NULL) {
370 RETURN_LONG(atol(field->head->field_value));
371 }
372 RETURN_NULL();
373 }
374 /* }}} */
375
376 /* {{{ proto float SolrInputDocument::getFieldBoost(string fieldname)
377 Returns the boost value for the specified field. */
PHP_METHOD(SolrInputDocument,getFieldBoost)378 PHP_METHOD(SolrInputDocument, getFieldBoost)
379 {
380 solr_char_t *field_name = NULL;
381 COMPAT_ARG_SIZE_T field_name_length = 0;
382 solr_document_t *doc_entry = NULL;
383
384 /* Process the parameters passed to the default constructor */
385 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
386 RETURN_FALSE;
387 }
388
389 if (!field_name_length) {
390 RETURN_FALSE;
391 }
392
393 /* Retrieve the document entry for the SolrDocument instance */
394 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
395
396 solr_field_list_t *field_values = NULL;
397
398 if ((field_values = zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) != NULL) {
399 RETURN_DOUBLE(field_values->field_boost);
400 }
401 RETURN_FALSE;
402 }
403
404 RETURN_FALSE;
405 }
406 /* }}} */
407
408 /* {{{ proto array SolrInputDocument::getFieldNames(void)
409 Returns an array of all the field names in the document. */
PHP_METHOD(SolrInputDocument,getFieldNames)410 PHP_METHOD(SolrInputDocument, getFieldNames)
411 {
412 solr_document_get_field_names(INTERNAL_FUNCTION_PARAM_PASSTHRU);
413 }
414 /* }}} */
415
416 /* {{{ proto int SolrInputDocument::getFieldCount(void)
417 Returns the number of fields in document. Multivalued fields are only counted once. */
PHP_METHOD(SolrInputDocument,getFieldCount)418 PHP_METHOD(SolrInputDocument, getFieldCount)
419 {
420 solr_document_t *doc_entry = NULL;
421
422 /* Retrieve the document entry for the SolrDocument instance */
423 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS)
424 {
425 RETURN_LONG(zend_hash_num_elements(doc_entry->fields));
426 }
427
428 RETURN_FALSE;
429 }
430 /* }}} */
431
432 /* {{{ proto SolrDocumentField SolrInputDocument::getField(string fieldname)
433 Returns the requested field. */
PHP_METHOD(SolrInputDocument,getField)434 PHP_METHOD(SolrInputDocument, getField)
435 {
436 solr_char_t *field_name = NULL;
437 COMPAT_ARG_SIZE_T field_name_length = 0;
438 solr_document_t *doc_entry = NULL;
439 zend_string *field_str = NULL;
440
441 /* Process the parameters passed to the default constructor */
442 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
443
444 RETURN_FALSE;
445 }
446
447 if (!field_name_length) {
448 RETURN_FALSE;
449 }
450
451 field_str = zend_string_init(field_name, field_name_length, SOLR_DOCUMENT_FIELD_PERSISTENT);
452
453 /* Retrieve the document entry for the SolrDocument instance */
454 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS)
455 {
456 solr_field_list_t *field_values = NULL;
457
458 if ((field_values = zend_hash_find_ptr(doc_entry->fields, field_str)) != NULL)
459 {
460 solr_create_document_field_object(field_values, &return_value);
461 /* The field was retrieved, so we're done here */
462 zend_string_release(field_str);
463 return ;
464 }
465 goto return_false;
466 }
467 return_false:
468 zend_string_release(field_str);
469 RETURN_FALSE;
470 }
471 /* }}} */
472
473 /* {{{ proto array SolrInputDocument::toArray(void)
474 Returns an array representation of the object. */
PHP_METHOD(SolrInputDocument,toArray)475 PHP_METHOD(SolrInputDocument, toArray)
476 {
477 solr_document_t *doc_entry = NULL;
478 zval fields_array;
479
480 /* Retrieve the document entry for the SolrDocument instance */
481 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS)
482 {
483 HashTable *fields_ht;
484 array_init(return_value);
485 array_init(&fields_array);
486 zend_hash_init(Z_ARRVAL(fields_array), zend_hash_num_elements(doc_entry->fields), NULL, ZVAL_PTR_DTOR, 0);
487
488 add_assoc_double(return_value, "document_boost", doc_entry->document_boost);
489 add_assoc_long(return_value, "field_count", doc_entry->field_count);
490 add_assoc_zval(return_value, "fields", &fields_array);
491
492 fields_ht = doc_entry->fields;
493
494 SOLR_HASHTABLE_FOR_LOOP(fields_ht)
495 {
496 solr_field_list_t *field = NULL;
497 zval current_field;
498 zval *current_field_ptr = ¤t_field;
499
500 field = zend_hash_get_current_data_ptr(fields_ht);
501 /* create SolrDocumentField */
502 solr_create_document_field_object(field, ¤t_field_ptr);
503 /* create SolrDocumentField to the fields HT */
504 add_next_index_zval(&fields_array, current_field_ptr);
505 }
506 /* We are done */
507 return;
508 }
509
510 RETURN_FALSE;
511 }
512 /* }}} */
513
514 /* {{{ proto bool SolrInputDocument::fieldExists(string field_name)
515 Checks if the field name exists in the document. */
PHP_METHOD(SolrInputDocument,fieldExists)516 PHP_METHOD(SolrInputDocument, fieldExists)
517 {
518 solr_char_t *field_name = NULL;
519 COMPAT_ARG_SIZE_T field_name_length = 0;
520 solr_document_t *doc_entry = NULL;
521
522 /* Process the parameters passed to the default constructor */
523 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
524 RETURN_FALSE;
525 }
526
527 if (!field_name_length) {
528 RETURN_FALSE;
529 }
530
531 /* Retrieve the document entry for the SolrDocument instance */
532 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
533 if (zend_hash_str_exists(doc_entry->fields, field_name, field_name_length)) {
534 RETURN_TRUE;
535 } else {
536 RETURN_FALSE;
537 }
538 }
539
540 RETURN_FALSE;
541 }
542 /* }}} */
543
544 /* {{{ proto bool SolrInputDocument::deleteField(string field_name)
545 Removes the request field from the document. */
PHP_METHOD(SolrInputDocument,deleteField)546 PHP_METHOD(SolrInputDocument, deleteField)
547 {
548 solr_document_t *doc_entry = NULL;
549 char *field_name;
550 COMPAT_ARG_SIZE_T field_name_len = 0;
551
552 /* Process the parameters passed to the default constructor */
553 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_len) == FAILURE) {
554 RETURN_FALSE;
555 }
556
557 if (!field_name_len) {
558 RETURN_FALSE;
559 }
560
561 /* Retrieve the document entry for the SolrDocument instance */
562 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) {
563 if (zend_hash_str_del(doc_entry->fields, field_name, field_name_len) == SUCCESS) {
564 doc_entry->field_count--;
565 RETURN_TRUE;
566 }
567 RETURN_FALSE;
568 }
569 RETURN_FALSE;
570 }
571 /* }}} */
572
573 /* {{{ proto bool SolrInputDocument::sort(int sort_criterion [, int sort_direction])
574 Sorts the document fields by the specified criterion. */
PHP_METHOD(SolrInputDocument,sort)575 PHP_METHOD(SolrInputDocument, sort)
576 {
577 long int order_by = 0L;
578 long int sort_direction = SOLR_SORT_ASC;
579 solr_document_t *doc_entry = NULL;
580 int renumber = 0;
581
582 /* The pointer to the comparison function used by zend_qsort */
583 #if PHP_VERSION_ID < 80000
584 compare_func_t comparison_function = NULL;
585 #else
586 bucket_compare_func_t comparison_function = NULL;
587 #endif
588
589 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &order_by, &sort_direction) == FAILURE) {
590 RETURN_FALSE;
591 }
592
593 /* Retrieve the document entry for the SolrDocument instance */
594 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) {
595 RETURN_FALSE;
596 }
597
598 /* {{{ Select the appropriate comparison function */
599 switch(order_by)
600 {
601 case SOLR_SORT_FIELD_NAME : /* Sorting by field name */
602 {
603 switch(sort_direction)
604 {
605 case SOLR_SORT_ASC :
606 comparison_function = solr_compare_field_name;
607 break;
608
609 case SOLR_SORT_DESC :
610 comparison_function = solr_rcompare_field_name;
611 break;
612 }
613 }
614 break; /* case SOLR_SORT_FIELD_NAME */
615
616 case SOLR_SORT_FIELD_VALUE_COUNT : /* Sorting by number of values per field */
617 {
618 switch(sort_direction)
619 {
620 case SOLR_SORT_ASC :
621 comparison_function = solr_compare_field_value_count;
622 break;
623
624 case SOLR_SORT_DESC :
625 comparison_function = solr_rcompare_field_value_count;
626 break;
627 }
628 }
629 break; /* case SOLR_SORT_FIELD_VALUE_COUNT */
630
631 case SOLR_SORT_FIELD_BOOST_VALUE : /* Sorting by field boost values */
632 {
633 switch(sort_direction)
634 {
635 case SOLR_SORT_ASC :
636 comparison_function = solr_compare_field_boost_value;
637 break;
638
639 case SOLR_SORT_DESC :
640 comparison_function = solr_rcompare_field_boost_value;
641 break;
642 }
643 }
644 break; /* case SOLR_SORT_FIELD_BOOST_VALUE */
645
646 default : /* Undefined sort criteria */
647
648 RETURN_FALSE;
649
650 break;
651
652 } /* }}} switch(order_by) */
653
654 /* Undefined sort direction. It was not ASC or DESC */
655 if (!comparison_function) {
656
657 RETURN_FALSE;
658 }
659
660 zend_hash_sort(doc_entry->fields, comparison_function, renumber);
661
662 RETURN_TRUE;
663 }
664 /* }}} */
665
666 /* {{{ proto bool SolrInputDocument::merge(SolrInputDocument source [, bool override])
667 Merges the source document to the current object. */
PHP_METHOD(SolrInputDocument,merge)668 PHP_METHOD(SolrInputDocument, merge)
669 {
670 solr_document_t *destination_document = NULL;
671 solr_document_t *source_document = NULL;
672
673 /* The destination SolrDocument instance */
674 zval * destination_document_zval = getThis();
675
676 /* The source SolrDocument instance */
677 zval *source_document_zval = NULL;
678
679 /* Should we skip fields that already exist in destination */
680 zend_bool overwrite = (zend_bool) 0;
681
682 copy_ctor_func_t p_copy_ctor = (copy_ctor_func_t) field_copy_constructor;
683
684 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &source_document_zval, solr_ce_SolrInputDocument, &overwrite) == FAILURE) {
685
686 RETURN_FALSE;
687 }
688
689 if (solr_fetch_document_entry(OBJ_FOR_PROP(source_document_zval), &source_document) == FAILURE) {
690
691 RETURN_FALSE;
692 }
693
694 if (solr_fetch_document_entry(OBJ_FOR_PROP(destination_document_zval), &destination_document) == FAILURE) {
695
696 RETURN_FALSE;
697 }
698
699 if (zend_hash_num_elements(source_document->fields) == 0) {
700
701 php_error_docref(NULL, E_WARNING, "Source SolrInputDocument has no fields. Source documentId");
702
703 RETURN_FALSE;
704 }
705
706 /* Copy the fields in the source HashTable to the destination HashTable */
707 zend_hash_merge(destination_document->fields, source_document->fields, p_copy_ctor, overwrite);
708
709 /* Update the field count */
710 destination_document->field_count = (uint32_t) zend_hash_num_elements(destination_document->fields);
711
712 RETURN_TRUE;
713 }
714 /* }}} */
715
716 /* {{{ proto void SolrInputDocument::addChildDocument(SolrInputDocument child)
717 Adds a child document */
PHP_METHOD(SolrInputDocument,addChildDocument)718 PHP_METHOD(SolrInputDocument, addChildDocument)
719 {
720 zval *child_obj = NULL;
721 solr_document_t *solr_doc = NULL, *child_doc_entry = NULL;
722
723 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &child_obj, solr_ce_SolrInputDocument) == FAILURE)
724 {
725 RETURN_FALSE;
726 }
727
728 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc) == FAILURE)
729 {
730 solr_throw_exception_ex(solr_ce_SolrException, SOLR_ERROR_1008, SOLR_FILE_LINE_FUNC, "Internal Error: Unable to fetch document_entry.");
731 return;
732 }
733
734 if (solr_fetch_document_entry(OBJ_FOR_PROP(child_obj), &child_doc_entry) == FAILURE)
735 {
736 solr_throw_exception_ex(solr_ce_SolrException, SOLR_ERROR_1008, SOLR_FILE_LINE_FUNC, "Internal Error: Unable to fetch document_entry for child document.");
737 return;
738 }
739
740 /* SolrInputDocument must contain at least one field */
741 if (0 == zend_hash_num_elements(child_doc_entry->fields)) {
742 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "Child document has no fields");
743 return;
744 }
745
746 if (zend_hash_next_index_insert(solr_doc->children, child_obj) == NULL) {
747 solr_throw_exception_ex(solr_ce_SolrException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "Internal Error: Unable to add child to the hashtable.");
748 } else {
749 Z_ADDREF_P(child_obj);
750 }
751 }
752 /* }}} */
753
754 /* {{{ proto void SolrInputDocument::addChildDocuments(array)
755 Adds a child documents */
PHP_METHOD(SolrInputDocument,addChildDocuments)756 PHP_METHOD(SolrInputDocument, addChildDocuments)
757 {
758 HashTable *solr_input_docs;
759 solr_document_t *solr_doc = NULL;
760 zval *docs_array = NULL;
761 int num_input_docs = 0, curr_pos = 0;
762 size_t pos = 0U;
763 zval **input_docs = NULL, *current_input_doc = NULL;
764
765 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &docs_array) == FAILURE) {
766 return;
767 }
768
769 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc) == FAILURE)
770 {
771 solr_throw_exception_ex(solr_ce_SolrException, SOLR_ERROR_1008, SOLR_FILE_LINE_FUNC, "Internal Error: Unable to fetch document_entry.");
772 }
773
774 solr_input_docs = Z_ARRVAL_P(docs_array);
775 num_input_docs = zend_hash_num_elements(solr_input_docs);
776
777 if(!num_input_docs)
778 {
779 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "The array parameter passed is empty");
780 return;
781 }
782
783 /* This should be released if there is an error */
784 input_docs = (zval **) pemalloc((sizeof(zval *) * (num_input_docs + 1)), SOLR_DOCUMENT_PERSISTENT);
785
786 memset(input_docs, 0, sizeof(zval *) * (num_input_docs + 1));
787
788 /* Please check all the SolrInputDocument instances passed via the array */
789 SOLR_HASHTABLE_FOR_LOOP(solr_input_docs)
790 {
791 zval *solr_input_doc = NULL;
792 solr_document_t *doc_entry = NULL;
793 HashTable *document_fields;
794
795 solr_input_doc = zend_hash_get_current_data(solr_input_docs);
796
797 if (Z_TYPE_P(solr_input_doc) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(solr_input_doc), solr_ce_SolrInputDocument))
798 {
799 SOLR_FREE_DOC_ENTRIES(input_docs);
800
801 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "SolrInputDocument number %u is not a valid SolrInputDocument instance", (curr_pos + 1U));
802
803 return;
804 }
805
806 if (solr_fetch_document_entry(OBJ_FOR_PROP(solr_input_doc), &doc_entry) == FAILURE) {
807
808 SOLR_FREE_DOC_ENTRIES(input_docs);
809
810 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "SolrInputDocument number %u is not valid. Object not present in HashTable", (curr_pos + 1U));
811
812 return;
813 }
814
815 document_fields = doc_entry->fields;
816
817 /* SolrInputDocument must contain at least one field */
818 if (0 == zend_hash_num_elements(document_fields)) {
819
820 SOLR_FREE_DOC_ENTRIES(input_docs);
821
822 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "SolrInputDocument number %u has no fields", (curr_pos + 1U));
823
824 return;
825 }
826 input_docs[curr_pos] = solr_input_doc;
827
828 curr_pos++;
829 }
830
831 /* Grab the first (solr_document_t *) pointer */
832 current_input_doc = input_docs[pos];
833
834 while(current_input_doc != NULL)
835 {
836 if (zend_hash_next_index_insert(solr_doc->children, current_input_doc) == NULL)
837 {
838 solr_throw_exception_ex(solr_ce_SolrIllegalArgumentException, SOLR_ERROR_4000, SOLR_FILE_LINE_FUNC, "SolrInputDocument number %u has no fields", (pos + 1U));
839 SOLR_FREE_DOC_ENTRIES(input_docs);
840 return;
841 }
842 /* todo possible leak */
843 Z_ADDREF_P(current_input_doc);
844 pos++;
845
846 current_input_doc = input_docs[pos];
847 }
848
849 SOLR_FREE_DOC_ENTRIES(input_docs);
850 }
851 /* }}} */
852
853 /* {{{ proto array SolrInputDocument::getChildDocuments( void )
854 Returns child documents or null if none */
PHP_METHOD(SolrInputDocument,getChildDocuments)855 PHP_METHOD(SolrInputDocument, getChildDocuments)
856 {
857 solr_document_t *solr_doc = NULL;
858
859 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc) == FAILURE)
860 {
861 php_error_docref(NULL, E_ERROR, "Unable to fetch document entry for current object");
862 }
863
864 if (zend_hash_num_elements(solr_doc->children) > 0)
865 {
866 array_init(return_value);
867 zend_hash_init(Z_ARRVAL_P(return_value), zend_hash_num_elements(solr_doc->children), NULL, ZVAL_PTR_DTOR, 0);
868 zend_hash_copy(Z_ARRVAL_P(return_value), solr_doc->children, (copy_ctor_func_t)zval_add_ref);
869 }
870 }
871 /* }}} */
872
873 /* {{{ proto bool SolrInputDocument::hasChildDocuments (void)
874 Checks whether this document has got child documents */
PHP_METHOD(SolrInputDocument,hasChildDocuments)875 PHP_METHOD(SolrInputDocument, hasChildDocuments)
876 {
877 solr_document_t *solr_doc = NULL;
878
879 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc))
880 {
881 php_error_docref(NULL, E_ERROR, "Unable to fetch document entry for current object");
882 }
883
884 if (zend_hash_num_elements(solr_doc->children) > 0)
885 {
886 RETURN_TRUE;
887 } else {
888 RETURN_FALSE;
889 }
890 }
891 /* }}} */
892
893 /* {{{ proto int SolrInputDocument::getChildDocumentsCount (void)
894 Returns the number of child documents */
PHP_METHOD(SolrInputDocument,getChildDocumentsCount)895 PHP_METHOD(SolrInputDocument, getChildDocumentsCount)
896 {
897 solr_document_t *solr_doc = NULL;
898
899 if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc))
900 {
901 php_error_docref(NULL, E_ERROR, "Unable to fetch document entry for current object");
902 }
903
904 ZVAL_LONG(return_value, zend_hash_num_elements(solr_doc->children));
905 }
906 /* }}} */
907
908 /*
909 * Local variables:
910 * tab-width: 4
911 * c-basic-offset: 4
912 * indent-tabs-mode: t
913 * End:
914 * vim600: fdm=marker
915 * vim: noet sw=4 ts=4
916 */
917