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 DOCUMENT METHODS                                    **/
23 /** ************************************************************************ **/
24 
25 /* {{{ static int solr_document_set_field(zval *objptr, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length, solr_char_t *field_value, COMPAT_ARG_SIZE_T field_value_length) */
solr_document_set_field(zval * objptr,solr_char_t * field_name,COMPAT_ARG_SIZE_T field_name_length,solr_char_t * field_value,COMPAT_ARG_SIZE_T field_value_length)26 static int solr_document_set_field(zval *objptr, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length, solr_char_t *field_value, COMPAT_ARG_SIZE_T field_value_length)
27 {
28 	double field_boost = 0.0f;
29 
30 	solr_document_t *doc_entry = NULL;
31 
32 	if (!field_name_length) {
33 
34 		return FAILURE;
35 	}
36 
37 	if (!field_value_length)
38 	{
39 		return FAILURE;
40 	}
41 
42 	/* Retrieve the document entry for the SolrDocument instance */
43 	if (solr_fetch_document_entry(OBJ_FOR_PROP(objptr), &doc_entry) == SUCCESS)
44 	{
45 		solr_field_list_t *field_values      = NULL;
46 		zval *tmp;
47 
48 		/* If the field already exists in the SolrDocument instance append the value to the field list queue */
49 		if ((field_values = zend_hash_str_find_ptr(doc_entry->fields, field_name, field_name_length)) != NULL) {
50 			if (solr_document_insert_field_value(field_values, field_value, field_boost) == FAILURE) {
51 
52 				return FAILURE;
53 			}
54 
55 		} else {
56 
57 			/* Otherwise, create a new one and add it to the hash table */
58 			field_values = (solr_field_list_t *)  pemalloc(sizeof(solr_field_list_t), SOLR_DOCUMENT_FIELD_PERSISTENT);
59 
60 			memset(field_values, 0, sizeof(solr_field_list_t));
61 
62 			field_values->count       = 0L;
63 			field_values->field_boost = 0.0;
64 			field_values->field_name  = (solr_char_t *) pestrdup(field_name,SOLR_DOCUMENT_FIELD_PERSISTENT);
65 			field_values->head        = NULL;
66 			field_values->last        = NULL;
67 
68 			if (solr_document_insert_field_value(field_values, field_value, field_boost) == FAILURE) {
69 
70 				solr_destroy_field_list(field_values);
71 
72 				return FAILURE;
73 			}
74 			if ((tmp = zend_hash_str_add_ptr(doc_entry->fields, field_name, field_name_length, field_values)) == NULL) {
75 
76 				solr_destroy_field_list(field_values);
77 
78 				return FAILURE;
79 			}
80 
81 			/* Increment field count only when HEAD is added */
82 			doc_entry->field_count++;
83 		}
84 
85 		return SUCCESS;
86 	}
87 
88 	return FAILURE;
89 }
90 /* }}} */
91 
92 /* {{{ static int solr_document_get_field(zval *objptr, zval *return_value, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length) */
solr_document_get_field(zval * objptr,zval * return_value,solr_char_t * field_name,COMPAT_ARG_SIZE_T field_name_length)93 static int solr_document_get_field(zval *objptr, zval *return_value, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length)
94 {
95 	solr_document_t *doc_entry = NULL;
96 
97 	if (!field_name_length) {
98 
99 		return FAILURE;
100 	}
101 
102 	/* Retrieve the document entry for the SolrDocument instance */
103 	if (solr_fetch_document_entry(OBJ_FOR_PROP(objptr), &doc_entry) == SUCCESS)
104 	{
105 		solr_field_list_t *field_values = NULL;
106 
107 		if ((field_values = zend_hash_str_find_ptr(doc_entry->fields, (char *)field_name, field_name_length)) != NULL)
108 		{
109 			solr_create_document_field_object(field_values, &return_value);
110 
111 			/* The field was retrieved, so we're done here */
112 			return SUCCESS;
113 		}
114 
115 		return FAILURE;
116 	}
117 
118 	return FAILURE;
119 }
120 /* }}} */
121 
122 /* {{{ static int solr_document_remove_field(zval *objptr, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length) */
solr_document_remove_field(zval * objptr,solr_char_t * field_name,COMPAT_ARG_SIZE_T field_name_length)123 static int solr_document_remove_field(zval *objptr, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length)
124 {
125 	solr_document_t *doc_entry = NULL;
126 
127 	if (!field_name_length) {
128 
129 		return FAILURE;
130 	}
131 
132 	/* Retrieve the document entry for the SolrDocument instance */
133 	if (solr_fetch_document_entry(OBJ_FOR_PROP(objptr), &doc_entry) == SUCCESS) {
134 
135 		if (zend_hash_str_del(doc_entry->fields, field_name, field_name_length) == SUCCESS) {
136 
137 			doc_entry->field_count--;
138 
139 			return SUCCESS;
140 		}
141 
142 		return FAILURE;
143 	}
144 
145 	return FAILURE;
146 }
147 /* }}} */
148 
149 /* {{{ static int solr_document_field_exists(zval *objptr, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length) */
solr_document_field_exists(zval * objptr,solr_char_t * field_name,COMPAT_ARG_SIZE_T field_name_length)150 static int solr_document_field_exists(zval *objptr, solr_char_t *field_name, COMPAT_ARG_SIZE_T field_name_length)
151 {
152 	solr_document_t *doc_entry = NULL;
153 
154 	if (!field_name_length) {
155 
156 		return FAILURE;
157 	}
158 
159 	/* Retrieve the document entry for the SolrDocument instance */
160 	if (solr_fetch_document_entry(OBJ_FOR_PROP(objptr), &doc_entry) == SUCCESS) {
161 
162 		if (zend_hash_str_exists(doc_entry->fields, field_name, field_name_length)) {
163 
164 			return SUCCESS;
165 
166 		} else {
167 
168 			return FAILURE;
169 		}
170 	}
171 
172 	return FAILURE;
173 }
174 /* }}} */
175 
176 /* {{{ static void solr_serialize_document_object(HashTable *document_fields, xmlChar **buffer, int *size) */
solr_serialize_document_object(HashTable * document_fields,xmlChar ** buffer,int * size)177 static void solr_serialize_document_object(HashTable *document_fields, xmlChar **buffer, int *size)
178 {
179 	xmlNode *root_node = NULL, *fields_node = NULL;
180 	xmlDoc *doc_ptr = NULL;
181 	int format = 1;
182 
183 	if(!buffer)
184 	{
185 		return;
186 	}
187 
188 	doc_ptr = solr_xml_create_xml_doc((xmlChar *) "solr_document", &root_node);
189 	fields_node = xmlNewChild(root_node, NULL, (xmlChar *) "fields", NULL);
190 
191 	SOLR_HASHTABLE_FOR_LOOP(document_fields)
192 	{
193 		solr_field_list_t *field = NULL;
194 		solr_char_t *doc_field_name = NULL;
195 		solr_field_value_t *doc_field_value = NULL;
196 		xmlNode *field_node = NULL;
197 
198 		field = zend_hash_get_current_data_ptr(document_fields);
199 		doc_field_name = field->field_name;
200 		doc_field_value = field->head;
201 
202 		field_node = xmlNewChild(fields_node, NULL, (xmlChar *) "field", NULL);
203 
204 		xmlNewProp(field_node, (xmlChar *) "name", (xmlChar *) doc_field_name);
205 
206 		/* Loop through all the values for this field */
207 		while(doc_field_value != NULL)
208 		{
209 			xmlChar *escaped_field_value = xmlEncodeEntitiesReentrant(doc_ptr, (xmlChar *) doc_field_value->field_value);
210 
211 			xmlNewChild(field_node, NULL, (xmlChar *) "field_value", escaped_field_value);
212 
213 			/* Release the memory allocated by xmlEncodeEntitiesReentrant */
214 			xmlFree(escaped_field_value);
215 
216 			/* Grab the next value for this field if any */
217 			doc_field_value = doc_field_value->next;
218 
219 		} /* while(doc_field_value != NULL) */
220 
221 	} /* SOLR_HASHTABLE_FOR_LOOP(document_fields) */
222 
223 	xmlIndentTreeOutput = 1;
224 
225 	xmlDocDumpFormatMemoryEnc(doc_ptr, buffer, size, "UTF-8", format);
226 
227 	xmlFreeDoc(doc_ptr);
228 }
229 /* }}} */
230 
231 /* {{{ static void solr_unserialize_document_field(HashTable *document_fields, xmlNode *field_node) */
solr_unserialize_document_field(HashTable * document_fields,xmlNode * field_node)232 static void solr_unserialize_document_field(HashTable *document_fields, xmlNode *field_node)
233 {
234 	solr_char_t *field_name = NULL;
235 	xmlNode *xml_curr_value = NULL;
236 	solr_field_list_t *field_values = (solr_field_list_t *) pemalloc(sizeof(solr_field_list_t), SOLR_DOCUMENT_FIELD_PERSISTENT);
237 	zend_string *field_str;
238 
239 	memset(field_values, 0, sizeof(solr_field_list_t));
240 
241 	field_name = (solr_char_t *) solr_xml_get_node_contents(field_node->properties);
242 
243 	field_values->count       = 0L;
244 	field_values->field_boost = 0.0f;
245 	field_values->field_name  = (solr_char_t *) pestrdup(field_name, SOLR_DOCUMENT_FIELD_PERSISTENT);
246 	field_values->head        = NULL;
247 	field_values->last        = NULL;
248 
249 	/* Grab the first field node */
250 	xml_curr_value = field_node->children;
251 
252 	/* Looping through all the field_value nodes */
253 	while(xml_curr_value != NULL)
254 	{
255 		/* No assumptions. It must be the field value nodes */
256 		if (xml_curr_value->type == XML_ELEMENT_NODE && solr_xml_match_node(xml_curr_value, "field_value"))
257 		{
258 			solr_char_t *field_value = (solr_char_t *) solr_xml_get_node_contents(xml_curr_value);
259 
260 			/* Add this value to the list of values */
261 			if (solr_document_insert_field_value(field_values, field_value, 0.0f) == FAILURE) {
262 
263 				php_error_docref(NULL, E_WARNING, "Error adding field value during SolrDocument unserialization");
264 			}
265 		}
266 
267 		/* Move to the next field_value */
268 		xml_curr_value = xml_curr_value->next;
269 	}
270 
271 	field_str = zend_string_init(field_name, strlen(field_name), SOLR_DOCUMENT_FIELD_PERSISTENT);
272 
273 	/* All the values have been retrieved for this field. Now let's drop the field in the HashTable */
274 	if ((field_values = zend_hash_add_new_ptr(document_fields, field_str, (void *) field_values)) == NULL) {
275 
276 		zend_string_release(field_str);
277 		solr_destroy_field_list(field_values);
278 
279 		php_error_docref(NULL, E_WARNING, "Error adding field values to HashTable during SolrDocument unserialization");
280 		return;
281 	}
282 	zend_string_release(field_str);
283 }
284 /* }}} */
285 
286 /* {{{ static int solr_unserialize_child_documents(xmlDoc *doc, solr_document_t *doc_entry)
287  * 1. retrieve doc hashes
288  * 2. base64_decode
289  * 3. unserialize (call php method)
290  * 4. add child to solr_doc_t.children
291  */
solr_unserialize_child_documents(xmlDoc * doc,solr_document_t * doc_entry)292 static int solr_unserialize_child_documents(xmlDoc *doc, solr_document_t *doc_entry)
293 {
294 
295     xmlXPathContext *xp_ctx = NULL;
296     xmlXPathObject *xp_obj = NULL;
297     xmlNodeSet *result = NULL;
298     xmlChar *hash, *xp_expression;
299     int num_nodes = 0, idx = 0;
300 
301     /* unserialize vars */
302     php_unserialize_data_t var_hash;
303 
304     zval solr_doc_zv;
305 
306     xp_expression = (xmlChar *)"/solr_document/child_docs/dochash";
307 
308     xp_ctx = xmlXPathNewContext(doc);
309     xp_obj = xmlXPathEvalExpression(xp_expression, xp_ctx);
310 
311     result = xp_obj->nodesetval;
312     num_nodes = result->nodeNr;
313 
314     if (num_nodes > 0)
315     {
316         for (;idx < num_nodes; idx++)
317         {
318             zend_string *sdoc_str; /* serialized document string */
319             unsigned char *sdoc_copy, *str_end;
320             hash = result->nodeTab[idx]->children->content;
321             sdoc_str = (zend_string *)php_base64_decode((const unsigned char*)hash, strlen((char *)hash));
322             memset(&var_hash, 0, sizeof(php_unserialize_data_t));
323             PHP_VAR_UNSERIALIZE_INIT(var_hash);
324             sdoc_copy = (unsigned char *)sdoc_str->val;
325             str_end = (unsigned char *) (sdoc_copy + strlen((const char *)sdoc_copy));
326 
327             if (!php_var_unserialize(&solr_doc_zv, (const unsigned char **)&sdoc_copy, str_end, &var_hash)){
328                 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
329                 php_error_docref(NULL, E_ERROR, "Unable to unserialize child document");
330 
331                 xmlXPathFreeContext(xp_ctx);
332                 xmlXPathFreeObject(xp_obj);
333                 zend_string_release(sdoc_str);
334                 return FAILURE;
335             }
336             zend_string_release(sdoc_str);
337             if (zend_hash_next_index_insert(doc_entry->children, &solr_doc_zv) == NULL)
338             {
339                 php_error_docref(NULL, E_ERROR, "Unable to add child document to parent document post-unserialize");
340             }
341             PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
342         }
343     }
344     xmlXPathFreeContext(xp_ctx);
345     xmlXPathFreeObject(xp_obj);
346 
347     return SUCCESS;
348 }
349 /* }}} */
350 
solr_unserialize_document_fields(xmlDoc * doc,HashTable * document_fields)351 static int solr_unserialize_document_fields(xmlDoc *doc, HashTable *document_fields)
352 {
353     xmlXPathContext *xpathctxt = NULL;
354     xmlChar *xpath_expression = NULL;
355     xmlXPathObject *xpathObj = NULL;
356     xmlNodeSet *result = NULL;
357 
358     register size_t num_nodes = 0U;
359 
360     register size_t i = 0U;
361     xpathctxt = xmlXPathNewContext(doc);
362 
363     if (!xpathctxt)
364     {
365         xmlFreeDoc(doc);
366 
367         php_error_docref(NULL, E_WARNING, "A valid XML xpath context could not be created");
368 
369         return FAILURE;
370     }
371 
372     xpath_expression = (xmlChar *) "/solr_document/fields/field/@name";
373 
374     xpathObj = xmlXPathEval(xpath_expression, xpathctxt);
375 
376     if (!xpathObj)
377     {
378         xmlXPathFreeContext(xpathctxt);
379 
380         xmlFreeDoc(doc);
381 
382         php_error_docref(NULL, E_WARNING, "A valid XML xpath object could not be created from the expression");
383 
384         return FAILURE;
385     }
386 
387     result = xpathObj->nodesetval;
388 
389     if (!result)
390     {
391         xmlXPathFreeContext(xpathctxt);
392 
393         xmlXPathFreeObject(xpathObj);
394 
395         xmlFreeDoc(doc);
396 
397         php_error_docref(NULL, E_WARNING, "Document has no fields");
398 
399         return FAILURE;
400     }
401 
402     num_nodes = result->nodeNr;
403 
404     i = 0U;
405 
406     if (!num_nodes)
407     {
408         xmlXPathFreeContext(xpathctxt);
409 
410         xmlXPathFreeObject(xpathObj);
411 
412         xmlFreeDoc(doc);
413 
414         php_error_docref(NULL, E_WARNING, "Document has no fields");
415 
416         return FAILURE;
417     }
418 
419     for (i = 0U; i < num_nodes; i++)
420     {
421         xmlNode *currNode = result->nodeTab[i];
422 
423         /* Absolutely No assumptions. I have to make sure that this is the name attribute */
424         if (currNode->type == XML_ATTRIBUTE_NODE && solr_xml_match_node(currNode, "name"))
425         {
426             /* Get the field node */
427             xmlNode *field_xml_node = currNode->parent;
428 
429             /* Retrieve all the values for this field and put them in the HashTable */
430             solr_unserialize_document_field(document_fields, field_xml_node);
431         }
432     }
433 
434     xmlXPathFreeContext(xpathctxt);
435 
436     xmlXPathFreeObject(xpathObj);
437     return SUCCESS;
438 }
439 
440 /* {{{ static int solr_unserialize_document_object(HashTable *document_fields, char *serialized, int size) */
solr_unserialize_document_object(solr_document_t * doc_entry,char * serialized,int size)441 static int solr_unserialize_document_object(solr_document_t *doc_entry, char *serialized, int size)
442 {
443 	xmlDoc *doc = NULL;
444 
445 	doc = xmlReadMemory(serialized, size, NULL, "UTF-8", 0);
446 
447 	if (!doc)
448 	{
449 		php_error_docref(NULL, E_WARNING, "The serialized document string is invalid");
450 		return FAILURE;
451 	}
452 
453 	if (solr_unserialize_document_fields(doc, doc_entry->fields) == FAILURE)
454 	{
455 	    php_error_docref(NULL, E_WARNING, "Unable to unserialize document fields");
456 	    return FAILURE;
457 	}
458 
459 	if (solr_unserialize_child_documents(doc, doc_entry) == FAILURE)
460 	{
461 	    php_error_docref(NULL, E_WARNING, "Unable to unserialize document fields");
462 	    return FAILURE;
463 	}
464 
465 	xmlFreeDoc(doc);
466 
467 	return SUCCESS;
468 }
469 /* }}} */
470 
471 /* {{{ proto void SolrDocument::__construct(void)
472 	SolrDocument constructor */
PHP_METHOD(SolrDocument,__construct)473 PHP_METHOD(SolrDocument, __construct)
474 {
475 	zval *objptr = getThis();
476 	zend_ulong document_index = SOLR_UNIQUE_DOCUMENT_INDEX();
477 
478 	if (solr_init_document(document_index) == NULL)
479 	{
480 	    return;
481 	}
482 
483 	/* Set the value of the internal id property */
484 	zend_update_property_long(solr_ce_SolrDocument, OBJ_FOR_PROP(objptr), SOLR_INDEX_PROPERTY_NAME, sizeof(SOLR_INDEX_PROPERTY_NAME) - 1, document_index);
485 
486 	/* Overriding the default object handlers */
487 	Z_OBJ_HT_P(objptr) = &solr_input_document_object_handlers;
488 }
489 
490 /* }}} */
491 
492 /* {{{ proto void SolrDocument::__destruct(void)
493 	Destructor for SolrDocument */
PHP_METHOD(SolrDocument,__destruct)494 PHP_METHOD(SolrDocument, __destruct)
495 {
496 	solr_document_t *doc_entry = NULL;
497 
498 	/* Retrieve the document entry for this SolrDocument */
499 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) 	{
500 
501 		zend_hash_index_del(SOLR_GLOBAL(documents), doc_entry->document_index);
502 
503 		/* Keep track of how many SolrDocument instances we currently have */
504 		SOLR_GLOBAL(document_count)--;
505 
506 		return ;
507 	}
508 }
509 /* }}} */
510 
511 /* {{{ proto SolrDocument::__clone(void)
512    Clone method for SolrDocument */
PHP_METHOD(SolrDocument,__clone)513 PHP_METHOD(SolrDocument, __clone)
514 {
515     RETURN_NULL();
516 }
517 /* }}} */
518 
519 /* {{{ proto SolrDocument::__set(string fieldname, string field_value)
520    Magic method for setting field names. */
PHP_METHOD(SolrDocument,__set)521 PHP_METHOD(SolrDocument, __set)
522 {
523 	solr_char_t *field_name = NULL;
524 	COMPAT_ARG_SIZE_T field_name_length  = 0;
525 
526 	solr_char_t *field_value = NULL;
527 	COMPAT_ARG_SIZE_T field_value_length = 0;
528 
529 	/* Process the parameters passed to the method */
530 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &field_name,
531 			&field_name_length, &field_value,
532 			&field_value_length) == FAILURE) {
533 
534 		RETURN_FALSE;
535 	}
536 
537 	if (solr_document_set_field(getThis(), field_name, field_name_length, field_value, field_value_length) == SUCCESS)
538 	{
539 		RETURN_TRUE;
540 	}
541 
542 	RETURN_FALSE;
543 }
544 /* }}} */
545 
546 /* {{{ proto SolrDocumentField SolrDocument::__get(string fieldname)
547    Magic method for getting a field. */
PHP_METHOD(SolrDocument,__get)548 PHP_METHOD(SolrDocument, __get)
549 {
550 	solr_char_t *field_name = NULL;
551 	COMPAT_ARG_SIZE_T field_name_length   = 0;
552 
553 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
554 
555 		RETURN_FALSE;
556 	}
557 
558 	if (solr_document_get_field(getThis(), return_value, field_name, field_name_length) == FAILURE) {
559 
560 		RETURN_NULL();
561 	}
562 }
563 /* }}} */
564 
565 /* {{{ proto bool SolrDocument::__isset(string field_name)
566    Checks if a field exists */
PHP_METHOD(SolrDocument,__isset)567 PHP_METHOD(SolrDocument, __isset)
568 {
569 	solr_char_t *field_name = NULL;
570 	COMPAT_ARG_SIZE_T field_name_length  = 0;
571 
572 	/* Process the parameters passed to the default constructor */
573 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
574 
575 		RETURN_FALSE;
576 	}
577 
578 	if (solr_document_field_exists(getThis(), field_name, field_name_length) == SUCCESS)
579 	{
580 		RETURN_TRUE;
581 	}
582 
583 	RETURN_FALSE;
584 }
585 /* }}} */
586 
587 /* {{{ proto bool SolrDocument::__unset(string fieldname)
588    Removes a field from the document. */
PHP_METHOD(SolrDocument,__unset)589 PHP_METHOD(SolrDocument, __unset)
590 {
591 	solr_char_t *field_name = NULL;
592 	COMPAT_ARG_SIZE_T field_name_length  = 0;
593 
594 	/* Process the parameters passed to the default constructor */
595 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
596 
597 		RETURN_FALSE;
598 	}
599 
600 	if (solr_document_remove_field(getThis(), field_name, field_name_length) == SUCCESS)
601 	{
602 		RETURN_TRUE;
603 	}
604 
605 	RETURN_FALSE;
606 }
607 /* }}} */
608 
609 /* {{{ proto void SolrDocument::offsetSet(string field_name, string field_value)
610     Sets the specified field in the document */
PHP_METHOD(SolrDocument,offsetSet)611 PHP_METHOD(SolrDocument, offsetSet)
612 {
613 	solr_char_t *field_name = NULL;
614 	COMPAT_ARG_SIZE_T field_name_length  = 0;
615 
616 	solr_char_t *field_value = NULL;
617 	COMPAT_ARG_SIZE_T field_value_length = 0;
618 
619 	/* Process the parameters passed to the method */
620 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &field_name,
621 			&field_name_length, &field_value,
622 			&field_value_length) == FAILURE) {
623 
624 		return;
625 	}
626 
627 	if (solr_document_set_field(getThis(), field_name, field_name_length, field_value, field_value_length) == SUCCESS)
628 	{
629 		return;
630 	}
631 }
632 /* }}} */
633 
634 /* {{{ proto SolrDocumentField SolrDocument::offsetGet(string field_name)
635    Returns the request field. */
PHP_METHOD(SolrDocument,offsetGet)636 PHP_METHOD(SolrDocument, offsetGet)
637 {
638 	solr_char_t *field_name = NULL;
639 	COMPAT_ARG_SIZE_T field_name_length   = 0;
640 
641 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
642 
643 		RETURN_FALSE;
644 	}
645 
646 	if (solr_document_get_field(getThis(), return_value, field_name, field_name_length) == FAILURE) {
647 
648 		RETURN_NULL();
649 	}
650 }
651 /* }}} */
652 
653 /* {{{ proto bool SolrDocument::offsetExists(string fieldname)
654    Checks if the request field exists in the document */
PHP_METHOD(SolrDocument,offsetExists)655 PHP_METHOD(SolrDocument, offsetExists)
656 {
657 	solr_char_t *field_name = NULL;
658 	COMPAT_ARG_SIZE_T field_name_length  = 0;
659 
660 	/* Process the parameters passed to the default constructor */
661 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
662 
663 		RETURN_FALSE;
664 	}
665 
666 	if (solr_document_field_exists(getThis(), field_name, field_name_length) == SUCCESS)
667 	{
668 		RETURN_TRUE;
669 	}
670 
671 	RETURN_FALSE;
672 }
673 /* }}} */
674 
675 /* {{{ proto void SolrDocument::offsetUnset(string fieldname)
676    Removes the specified field from the document */
PHP_METHOD(SolrDocument,offsetUnset)677 PHP_METHOD(SolrDocument, offsetUnset)
678 {
679 	solr_char_t *field_name = NULL;
680 	COMPAT_ARG_SIZE_T field_name_length  = 0;
681 
682 	/* Process the parameters passed to the default constructor */
683 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
684 
685 		return;
686 	}
687 
688 	if (solr_document_remove_field(getThis(), field_name, field_name_length) == SUCCESS)
689 	{
690 		return;
691 	}
692 }
693 /* }}} */
694 
695 /* {{{ proto void SolrDocument::rewind(void)
696    Resets the internal pointer. */
PHP_METHOD(SolrDocument,rewind)697 PHP_METHOD(SolrDocument, rewind)
698 {
699 	solr_document_t *doc_entry = NULL;
700 	HashTable *doc_fields = NULL;
701 
702 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) 	{
703 
704 		return;
705 	}
706 
707 	doc_fields = doc_entry->fields;
708 
709 	zend_hash_internal_pointer_reset(doc_fields);
710 }
711 /* }}} */
712 
713 /* {{{ proto SolrDocumentField SolrDocument::current(void)
714    Retrieves the current field. */
PHP_METHOD(SolrDocument,current)715 PHP_METHOD(SolrDocument, current)
716 {
717 	solr_document_t *doc_entry = NULL;
718 	HashTable *doc_fields = NULL;
719 	solr_field_list_t *field_values = NULL;
720 
721 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) 	{
722 		return;
723 	}
724 
725 	doc_fields = doc_entry->fields;
726 
727 	field_values = zend_hash_get_current_data_ptr(doc_fields);
728 
729 	if(field_values && field_values ) {
730 		solr_create_document_field_object(field_values, &return_value);
731 		return;
732 	}
733 
734 	RETURN_NULL();
735 }
736 /* }}} */
737 
738 /* {{{ proto string SolrDocument::key(void)
739    Retrieves the current key. */
PHP_METHOD(SolrDocument,key)740 PHP_METHOD(SolrDocument, key)
741 {
742 	solr_document_t *doc_entry = NULL;
743 	zend_ulong num_index = 0L;
744 	HashTable *doc_fields = NULL;
745 	zend_string *field_name_str;
746 
747 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) 	{
748 
749 		return;
750 	}
751 
752 	doc_fields = doc_entry->fields;
753 
754 	if (zend_hash_get_current_key(doc_fields, &field_name_str, &num_index))
755 	{
756 	    RETURN_STR_COPY(field_name_str);
757 	}
758 }
759 /* }}} */
760 
761 /* {{{ proto void SolrDocument::next(void)
762   Moves the internal pointer to the next field. */
PHP_METHOD(SolrDocument,next)763 PHP_METHOD(SolrDocument, next)
764 {
765 	solr_document_t *doc_entry = NULL;
766 	HashTable *doc_fields = NULL;
767 
768 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) 	{
769 
770 		return;
771 	}
772 
773 	doc_fields = doc_entry->fields;
774 
775 	zend_hash_move_forward(doc_fields);
776 }
777 /* }}} */
778 
779 /* {{{ proto bool SolrDocument::valid(void)
780   Checks if the current internal pointer position is still valid. */
PHP_METHOD(SolrDocument,valid)781 PHP_METHOD(SolrDocument, valid)
782 {
783 	solr_document_t *doc_entry = NULL;
784 	HashTable *doc_fields = NULL;
785 	zend_bool is_valid = 0;
786 
787 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) 	{
788 
789 		return;
790 	}
791 
792 	doc_fields = doc_entry->fields;
793 	is_valid = (zend_bool) ( SUCCESS == zend_hash_has_more_elements(doc_fields) );
794 
795 	RETURN_BOOL(is_valid);
796 }
797 /* }}} */
798 
799 /* {{{ proto string SolrDocument::serialize(void)
800    Custom SolrDocument serializer. Returns an XML document string representing the object. */
PHP_METHOD(SolrDocument,serialize)801 PHP_METHOD(SolrDocument, serialize)
802 {
803 	solr_document_t *doc_entry = NULL;
804 	HashTable *doc_fields = NULL;
805 	char *serialized = NULL;
806 	int size = 0;
807 
808 	/* Retrieve the document entry for the SolrDocument instance */
809 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE)
810 	{
811 	    /* todo error here */
812 		RETURN_NULL();
813 	}
814 
815 	doc_fields = doc_entry->fields;
816 
817 	solr_serialize_document_object(doc_fields, (xmlChar **) &serialized, &size);
818 
819 	if (size)
820 	{
821 		RETVAL_STRINGL(serialized, size);
822 
823 		xmlFree(serialized);
824 
825 		return;
826 	}
827 
828 	RETURN_NULL();
829 }
830 /* }}} */
831 
832 /* {{{ proto void SolrDocument::unserialize(string serialized_xml)
833    Custom SolrDocument unserializer. Brings the object back to life. */
PHP_METHOD(SolrDocument,unserialize)834 PHP_METHOD(SolrDocument, unserialize)
835 {
836 	solr_char_t *serialized = NULL;
837 	COMPAT_ARG_SIZE_T serialized_length  = 0;
838 	zval *objptr = getThis();
839 	zend_ulong document_index = SOLR_UNIQUE_DOCUMENT_INDEX();
840 	solr_document_t *doc_entry = NULL;
841 
842 	/* Process the parameters passed to the default constructor */
843 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized, &serialized_length) == FAILURE) {
844 
845 		RETURN_FALSE;
846 	}
847 
848 	doc_entry = solr_init_document(document_index);
849 
850 	/* Set the value of the internal id property */
851 	zend_update_property_long(solr_ce_SolrDocument, OBJ_FOR_PROP(objptr), SOLR_INDEX_PROPERTY_NAME, sizeof(SOLR_INDEX_PROPERTY_NAME) - 1, document_index);
852 
853 	/* Overriding the default object handlers */
854 	Z_OBJ_HT_P(objptr) = &solr_input_document_object_handlers;
855 
856 	if (solr_unserialize_document_object(doc_entry, serialized, serialized_length) == FAILURE)
857 	{
858 		return;
859 	}
860 
861 	doc_entry->field_count = zend_hash_num_elements(doc_entry->fields);
862 }
863 /* }}} */
864 
865 /* {{{ proto bool SolrDocument::clear(void)
866    Resets the current object. Discards all the fields and resets the document boost to zero. */
PHP_METHOD(SolrDocument,clear)867 PHP_METHOD(SolrDocument, clear)
868 {
869 	solr_document_t *doc_entry = NULL;
870 
871 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS) 	{
872 
873 		doc_entry->document_boost = 0.0;
874 		doc_entry->field_count = 0L;
875 
876 		zend_hash_clean(doc_entry->fields);
877 
878 		RETURN_TRUE;
879 	}
880 
881 	RETURN_FALSE;
882 }
883 /* }}} */
884 
885 /* {{{ proto bool SolrDocument::addField(string fieldname, string value)
886    Adds a field to the document */
PHP_METHOD(SolrDocument,addField)887 PHP_METHOD(SolrDocument, addField)
888 {
889 	solr_char_t *field_name = NULL;
890 	COMPAT_ARG_SIZE_T field_name_length  = 0;
891 	solr_char_t *field_value = NULL;
892 	COMPAT_ARG_SIZE_T field_value_length = 0;
893 
894 	/* Process the parameters passed to the method */
895 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &field_name,
896 			&field_name_length, &field_value,
897 			&field_value_length) == FAILURE) {
898 
899 		RETURN_FALSE;
900 	}
901 
902 	if (solr_document_set_field(getThis(), field_name, field_name_length, field_value, field_value_length) == SUCCESS)
903 	{
904 		RETURN_TRUE;
905 	}
906 
907 	RETURN_FALSE;
908 }
909 /* }}} */
910 
911 /* {{{ proto array SolrDocument::getFieldNames(void)
912    Returns an array of fields names in the document. */
PHP_METHOD(SolrDocument,getFieldNames)913 PHP_METHOD(SolrDocument, getFieldNames)
914 {
915     solr_document_get_field_names(INTERNAL_FUNCTION_PARAM_PASSTHRU);
916 }
917 /* }}} */
918 
919 /* {{{ proto int SolrDocument::getFieldCount(void)
920    Returns the number of fields in this document. Multi-value fields are only counted once. */
PHP_METHOD(SolrDocument,getFieldCount)921 PHP_METHOD(SolrDocument, getFieldCount)
922 {
923 	solr_document_t *doc_entry = NULL;
924 
925 	/* Retrieve the document entry for the SolrDocument instance */
926 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS)
927 	{
928 		RETURN_LONG(zend_hash_num_elements(doc_entry->fields));
929 	}
930 
931 	RETURN_FALSE;
932 }
933 /* }}} */
934 
935 /* {{{ proto SolrDocumentField SolrDocument::getField(string fieldname)
936    Retrieves the requested field */
PHP_METHOD(SolrDocument,getField)937 PHP_METHOD(SolrDocument, getField)
938 {
939 	solr_char_t *field_name = NULL;
940 	COMPAT_ARG_SIZE_T field_name_length  = 0;
941 
942 	/* Process the parameters passed to the default constructor */
943 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
944 
945 		RETURN_FALSE;
946 	}
947 
948 	if (solr_document_get_field(getThis(), return_value, field_name, field_name_length) == FAILURE) {
949 
950 		RETURN_FALSE;
951 	}
952 }
953 /* }}} */
954 
955 /* {{{ proto array SolrDocument::toArray(void)
956    Returns an array representation of the SolrDocument object. */
PHP_METHOD(SolrDocument,toArray)957 PHP_METHOD(SolrDocument, toArray)
958 {
959 	solr_document_t *doc_entry = NULL;
960 	zval arr_tmp;
961 	zval *fields_array = &arr_tmp;
962 
963 	/* Retrieve the document entry for the SolrDocument instance */
964 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == SUCCESS)
965 	{
966 		HashTable *fields_ht;
967 #ifndef PHP_7
968 		MAKE_STD_ZVAL(fields_array);
969 #endif
970 		array_init(return_value);
971 		array_init(fields_array);
972 
973 		add_assoc_double(return_value, "document_boost", doc_entry->document_boost);
974 		add_assoc_long(return_value,   "field_count", doc_entry->field_count);
975 		add_assoc_zval(return_value,   "fields", fields_array);
976 
977 		fields_ht = doc_entry->fields;
978 
979 		SOLR_HASHTABLE_FOR_LOOP(fields_ht)
980 		{
981 			solr_field_list_t *field = NULL;
982 			zval current_field_tmp;
983 			zval *current_field = &current_field_tmp;
984 #ifndef PHP_7
985 			MAKE_STD_ZVAL(current_field);
986 #endif
987 			field = zend_hash_get_current_data_ptr(fields_ht);
988 
989 			solr_create_document_field_object(field, &current_field);
990 
991 			add_next_index_zval(fields_array, current_field);
992 		}
993 
994 		/* We are done */
995 		return;
996 	}
997 
998 	RETURN_FALSE;
999 }
1000 /* }}} */
1001 
1002 /* {{{ proto bool SolrDocument::fieldExists(string fieldname)
1003    Checks if the field exists. */
PHP_METHOD(SolrDocument,fieldExists)1004 PHP_METHOD(SolrDocument, fieldExists)
1005 {
1006 	solr_char_t *field_name = NULL;
1007 	COMPAT_ARG_SIZE_T field_name_length = 0;
1008 
1009 	/* Process the parameters passed to the default constructor */
1010 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
1011 
1012 		RETURN_FALSE;
1013 	}
1014 
1015 	if (solr_document_field_exists(getThis(), field_name, field_name_length) == SUCCESS)
1016 	{
1017 		RETURN_TRUE;
1018 	}
1019 
1020 	RETURN_FALSE;
1021 }
1022 /* }}} */
1023 
1024 /* {{{ proto bool SolrDocument::deleteField(string field_name)
1025    Removes the requested field. */
PHP_METHOD(SolrDocument,deleteField)1026 PHP_METHOD(SolrDocument, deleteField)
1027 {
1028 	solr_char_t *field_name = NULL;
1029 	COMPAT_ARG_SIZE_T field_name_length  = 0;
1030 
1031 	/* Process the parameters passed to the default constructor */
1032 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &field_name, &field_name_length) == FAILURE) {
1033 
1034 		RETURN_FALSE;
1035 	}
1036 
1037 	if (solr_document_remove_field(getThis(), field_name, field_name_length) == SUCCESS)
1038 	{
1039 		RETURN_TRUE;
1040 	}
1041 
1042 	RETURN_FALSE;
1043 }
1044 /* }}} */
1045 
1046 /* {{{ proto bool SolrDocument::sort(int sort_criterion [, int sort_direction])
1047    Sorts the fields in the document */
PHP_METHOD(SolrDocument,sort)1048 PHP_METHOD(SolrDocument, sort)
1049 {
1050 	long int order_by = 0L;
1051 	long int sort_direction = SOLR_SORT_ASC;
1052 	solr_document_t *doc_entry = NULL;
1053 	int renumber = 0;
1054 
1055 	/* The pointer to the comparison function used by zend_qsort */
1056 #if PHP_VERSION_ID < 80000
1057 	compare_func_t comparison_function = NULL;
1058 #else
1059 	bucket_compare_func_t comparison_function = NULL;
1060 #endif
1061 
1062 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &order_by, &sort_direction) == FAILURE) {
1063 
1064 		RETURN_FALSE;
1065 	}
1066 
1067 	/* Retrieve the document entry for the SolrDocument instance */
1068 	if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &doc_entry) == FAILURE) {
1069 
1070 		RETURN_FALSE;
1071 	}
1072 
1073 	/*  {{{ Select the appropriate comparison function */
1074 	switch(order_by)
1075 	{
1076 		case  SOLR_SORT_FIELD_NAME : /* Sorting by field name */
1077 		{
1078 			switch(sort_direction)
1079 			{
1080 				case SOLR_SORT_ASC :
1081 					comparison_function = solr_compare_field_name;
1082 				break;
1083 
1084 				case SOLR_SORT_DESC :
1085 					comparison_function = solr_rcompare_field_name;
1086 				break;
1087 			}
1088 		}
1089 		break; /* case  SOLR_SORT_FIELD_NAME */
1090 
1091 		case  SOLR_SORT_FIELD_VALUE_COUNT : /* Sorting by number of values per field */
1092 		{
1093 			switch(sort_direction)
1094 			{
1095 				case SOLR_SORT_ASC :
1096 					comparison_function = solr_compare_field_value_count;
1097 				break;
1098 
1099 				case SOLR_SORT_DESC :
1100 					comparison_function = solr_rcompare_field_value_count;
1101 				break;
1102 			}
1103 		}
1104 		break; /* case  SOLR_SORT_FIELD_VALUE_COUNT */
1105 
1106 		case  SOLR_SORT_FIELD_BOOST_VALUE : /* Sorting by field boost values */
1107 		{
1108 			switch(sort_direction)
1109 			{
1110 				case SOLR_SORT_ASC :
1111 					comparison_function = solr_compare_field_boost_value;
1112 				break;
1113 
1114 				case SOLR_SORT_DESC :
1115 					comparison_function = solr_rcompare_field_boost_value;
1116 				break;
1117 			}
1118 		}
1119 		break; /* case  SOLR_SORT_FIELD_BOOST_VALUE */
1120 
1121 		default : /* Undefined sort criteria */
1122 
1123 			RETURN_FALSE;
1124 
1125 		break;
1126 
1127 	} /* }}} switch(order_by) */
1128 
1129 	/* Undefined sort direction. It was not ASC or DESC */
1130 	if (!comparison_function) {
1131 
1132 		RETURN_FALSE;
1133 	}
1134 
1135 	zend_hash_sort(doc_entry->fields, comparison_function, renumber);
1136 
1137 	RETURN_TRUE;
1138 }
1139 /* }}} */
1140 
1141 /* {{{ proto bool SolrDocument::merge(SolrDocument source [, bool override])
1142    Merges source to the current SolrDocument. */
PHP_METHOD(SolrDocument,merge)1143 PHP_METHOD(SolrDocument, merge)
1144 {
1145 	solr_document_t *destination_document = NULL;
1146 	solr_document_t *source_document = NULL;
1147 
1148 	copy_ctor_func_t p_copy_ctor = (copy_ctor_func_t) field_copy_constructor;
1149 
1150 	/* The destination SolrDocument instance */
1151 	zval *destination_document_zval = getThis();
1152 
1153 	/* The source SolrDocument instance */
1154 	zval *source_document_zval = NULL;
1155 
1156 	/* Should we skip fields that already exist in destination */
1157 	zend_bool overwrite = (zend_bool) 0;
1158 
1159 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &source_document_zval, solr_ce_SolrDocument, &overwrite) == FAILURE) {
1160 
1161 		RETURN_FALSE;
1162 	}
1163 
1164 	if (solr_fetch_document_entry(OBJ_FOR_PROP(source_document_zval), &source_document) == FAILURE) {
1165 
1166 		RETURN_FALSE;
1167 	}
1168 
1169 	if (solr_fetch_document_entry(OBJ_FOR_PROP(destination_document_zval), &destination_document) == FAILURE) {
1170 
1171 		RETURN_FALSE;
1172 	}
1173 
1174 	if (zend_hash_num_elements(source_document->fields) == 0)
1175 	{
1176 		php_error_docref(NULL, E_WARNING, "Source SolrDocument has no fields. Source");
1177 
1178 		RETURN_FALSE;
1179 	}
1180 
1181 	/* TODO child documents */
1182 	/* Copy the fields in the source HashTable to the destination HashTable */
1183 	zend_hash_merge(destination_document->fields, source_document->fields, p_copy_ctor, (int) overwrite);
1184 
1185 	/* Update the field count */
1186 	destination_document->field_count = (uint32_t) zend_hash_num_elements(destination_document->fields);
1187 
1188 	RETURN_TRUE;
1189 }
1190 /* }}} */
1191 
1192 
solr_add_child_input_documents_from_documents(HashTable * children,solr_document_t * new_doc_entry)1193 static void solr_add_child_input_documents_from_documents(HashTable * children, solr_document_t *new_doc_entry)
1194 {
1195     SOLR_HASHTABLE_FOR_LOOP(children)
1196     {
1197         zval solr_input_doc;
1198         zval *solr_doc = zend_hash_get_current_data(children);
1199 
1200         zend_call_method_with_0_params(OBJ_FOR_PROP(solr_doc), Z_OBJCE_P(solr_doc), NULL, "getinputdocument", &solr_input_doc);
1201 
1202         if (zend_hash_next_index_insert(new_doc_entry->children, &solr_input_doc) == NULL)
1203         {
1204             php_error_docref(NULL, E_ERROR, "Unable to convert child SolrDocument to SolrInputDocument");
1205         }
1206     }
1207 }
1208 
1209 /* {{{ proto SolrInputDocument SolrDocument::getInputDocument(void)
1210    Returns a SolrInputDocument equivalent of the object. */
PHP_METHOD(SolrDocument,getInputDocument)1211 PHP_METHOD(SolrDocument, getInputDocument)
1212 {
1213 	zval *objptr = getThis();
1214 	solr_document_t new_solr_doc;
1215 	solr_document_t *new_doc_entry = NULL, *old_doc_entry = NULL;
1216 
1217 	memset(&new_solr_doc, 0, sizeof(solr_document_t));
1218 
1219 	new_doc_entry = &new_solr_doc;
1220 
1221 	/* Retrieve the document entry for the original SolrDocument */
1222 	if (solr_fetch_document_entry(OBJ_FOR_PROP(objptr), &old_doc_entry) == FAILURE) {
1223 
1224 		php_error_docref(NULL, E_ERROR, "SolrDocument could not be fetched.");
1225 
1226 		return;
1227 	}
1228 
1229 	object_init_ex(return_value, solr_ce_SolrInputDocument);
1230 
1231 	if ((new_doc_entry = solr_input_doc_ctor(return_value))== NULL)
1232 	{
1233 	    php_error_docref(NULL, E_ERROR, "SolrInputDocument could not be created.");
1234 	}
1235 
1236 	/* Duplicate the doc_entry contents */
1237 	new_doc_entry->field_count = old_doc_entry->field_count;
1238 	new_doc_entry->document_boost = old_doc_entry->document_boost;
1239 
1240 	/* Initializing the hash table used for storing fields in this SolrDocument */
1241 	/* Copy the contents of the old fields HashTable to the new SolrDocument */
1242 	zend_hash_copy(new_doc_entry->fields, old_doc_entry->fields, (copy_ctor_func_t) field_copy_constructor);
1243 
1244         /* call getInputDocument on each child SolrDocument and store children */
1245 	if (zend_hash_num_elements(old_doc_entry->children) > 0)
1246 	{
1247 	    solr_add_child_input_documents_from_documents(old_doc_entry->children, new_doc_entry);
1248 	}
1249 }
1250 /* }}} */
1251 
1252 
1253 /* {{{ proto array SolrInputDocument::getChildDocuments( void )
1254      Returns child documents or null if none */
PHP_METHOD(SolrDocument,getChildDocuments)1255 PHP_METHOD(SolrDocument, getChildDocuments)
1256 {
1257     solr_document_t *solr_doc = NULL;
1258 
1259     if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc) == FAILURE)
1260     {
1261         php_error_docref(NULL, E_ERROR, "Unable to fetch document entry for current object");
1262         return;
1263     }
1264 
1265     if (zend_hash_num_elements(solr_doc->children) > 0)
1266     {
1267         array_init(return_value);
1268         zend_hash_init(Z_ARRVAL_P(return_value), zend_hash_num_elements(solr_doc->children), NULL, ZVAL_PTR_DTOR, 0);
1269         zend_hash_copy(Z_ARRVAL_P(return_value), solr_doc->children, (copy_ctor_func_t)zval_add_ref);
1270     }
1271 }
1272 /* }}} */
1273 
1274 /* {{{ proto bool SolrInputDocument::hasChildDocuments( void )
1275      Checks whether this document has child documents */
PHP_METHOD(SolrDocument,hasChildDocuments)1276 PHP_METHOD(SolrDocument, hasChildDocuments)
1277 {
1278     solr_document_t *solr_doc = NULL;
1279 
1280     if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc) == FAILURE)
1281     {
1282         php_error_docref(NULL, E_ERROR, "Unable to fetch document entry for current object");
1283         return;
1284     }
1285 
1286     if (zend_hash_num_elements(solr_doc->children) > 0)
1287     {
1288         RETURN_TRUE;
1289     } else {
1290         RETURN_FALSE;
1291     }
1292 }
1293 /* }}} */
1294 
1295 /* {{{ proto int SolrInputDocument::getChildDocumentsCount( void )
1296      Returns the number of child documents */
PHP_METHOD(SolrDocument,getChildDocumentsCount)1297 PHP_METHOD(SolrDocument, getChildDocumentsCount)
1298 {
1299     solr_document_t *solr_doc = NULL;
1300 
1301     if (solr_fetch_document_entry(OBJ_FOR_PROP(getThis()), &solr_doc) == FAILURE)
1302     {
1303         php_error_docref(NULL, E_ERROR, "Unable to fetch document entry for current object");
1304         return;
1305     }
1306 
1307     ZVAL_LONG(return_value, zend_hash_num_elements(solr_doc->children));
1308 }
1309 /* }}} */
1310 
1311 
1312 /* {{{ proto SolrDocumentField::__construct(void)
1313    Constructor */
PHP_METHOD(SolrDocumentField,__construct)1314 PHP_METHOD(SolrDocumentField, __construct)
1315 {
1316 	Z_OBJ_HT_P(getThis()) = &solr_document_field_handlers;
1317 }
1318 /* }}} */
1319 
1320 /* {{{ proto SolrDocumentField::__destruct(void)
1321    Destructor */
PHP_METHOD(SolrDocumentField,__destruct)1322 PHP_METHOD(SolrDocumentField, __destruct)
1323 {
1324 
1325 }
1326 /* }}} */
1327 
1328 /* {{{ PHP_SOLR_API void solr_document_field_write_property(zval *object, zval *member, zval *value) */
1329 #if PHP_VERSION_ID < 70400
solr_document_field_write_property(zval * object,zval * member,zval * value,void ** cache_slot)1330 PHP_SOLR_API void  solr_document_field_write_property(zval *object, zval *member, zval *value, void **cache_slot)
1331 #elif PHP_VERSION_ID < 80000
1332 PHP_SOLR_API zval *solr_document_field_write_property(zval *object, zval *member, zval *value, void **cache_slot)
1333 #else
1334 PHP_SOLR_API zval *solr_document_field_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot)
1335 #endif
1336 
1337 {
1338 	solr_throw_exception(solr_ce_SolrIllegalOperationException, SOLR_ERROR_1007_MSG, SOLR_ERROR_1007, SOLR_FILE_LINE_FUNC);
1339 /*
1340 	if (Z_TYPE_P(member) == IS_STRING)
1341 	{
1342 		php_error_docref(NULL, E_WARNING, "Attempting to set value for [%s] property in a SolrDocumentField instance", Z_STRVAL_P(member));
1343 	}
1344 */
1345 #if PHP_VERSION_ID >= 70400
1346 	return value;
1347 #endif
1348 }
1349 /* }}} */
1350 
1351 /* {{{ PHP_SOLR_API void solr_document_field_unset_property(zval *object, zval *member) */
1352 #if PHP_VERSION_ID < 80000
solr_document_field_unset_property(zval * object,zval * member,void ** cache_slot)1353 PHP_SOLR_API void solr_document_field_unset_property(zval *object, zval *member, void ** cache_slot)
1354 #else
1355 PHP_SOLR_API void solr_document_field_unset_property(zend_object *object, zend_string *member, void ** cache_slot)
1356 #endif
1357 {
1358 	solr_throw_exception(solr_ce_SolrIllegalOperationException, SOLR_ERROR_1007_MSG, SOLR_ERROR_1007, SOLR_FILE_LINE_FUNC);
1359 
1360 /*
1361 	if (Z_TYPE_P(member) == IS_STRING)
1362 	{
1363 		php_error_docref(NULL, E_WARNING, "Attempting to remove [%s] property in a SolrDocumentField instance", Z_STRVAL_P(member));
1364 	}
1365 */
1366 }
1367 /* }}} */
1368 
1369 /*
1370  * Local variables:
1371  * tab-width: 4
1372  * c-basic-offset: 4
1373  * indent-tabs-mode: t
1374  * End:
1375  * vim600: fdm=marker
1376  * vim: noet sw=4 ts=4
1377  */
1378