Skip to content

Commit e147fd3

Browse files
committed
PHPC-245: executeUpdate() converts objects to arrays
Multiple things here -- we shouldn't be injecting __pclass every time we serialize an object -- only when we are preparing it to be inserted. Otherwise, for example when executing an update, it will be injected into the update document too -- which b0rks the update statement. We also need to bail out when we don't get an array from the serialize callback -- and rather then pretend the return array from the callback is the data we got passed in in the get-go, keep the original zval intact so we don't accidentally convert it to array
1 parent 2154934 commit e147fd3

File tree

6 files changed

+280
-18
lines changed

6 files changed

+280
-18
lines changed

php_bson.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030
#include "php_phongo.h"
3131

3232
typedef enum {
33-
PHONGO_BSON_NONE = 0x00,
34-
PHONGO_BSON_ADD_ID = 0x01,
33+
PHONGO_BSON_NONE = 0x00,
34+
PHONGO_BSON_ADD_ID = 0x01,
3535
PHONGO_BSON_RETURN_ID = 0x02,
36+
PHONGO_BSON_ADD_ODS = 0x04,
3637
} phongo_bson_flags_t;
3738

3839
PHONGO_API void zval_to_bson(zval *data, phongo_bson_flags_t flags, bson_t *bson, bson_t **bson_out TSRMLS_DC);

src/MongoDB/BulkWrite.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ PHP_METHOD(BulkWrite, insert)
9797
if (return_value_used) {
9898
bson_flags |= PHONGO_BSON_RETURN_ID;
9999
}
100+
bson_flags |= PHONGO_BSON_ADD_ODS;
100101

101102
bson = bson_new();
102103
zval_to_bson(document, bson_flags, bson, &bson_out TSRMLS_CC);

src/MongoDB/Manager.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ PHP_METHOD(Manager, executeInsert)
172172

173173

174174
bson = bson_new();
175-
zval_to_bson(document, PHONGO_BSON_NONE, bson, NULL TSRMLS_CC);
175+
zval_to_bson(document, PHONGO_BSON_ADD_ODS, bson, NULL TSRMLS_CC);
176176
phongo_execute_single_insert(intern->client, namespace, bson, phongo_write_concern_from_zval(zwrite_concern TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC);
177177
bson_clear(&bson);
178178
}

src/bson.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -561,14 +561,14 @@ int php_phongo_is_array_or_document(zval **val TSRMLS_DC) /* {{{ */
561561
return IS_ARRAY;
562562
}
563563
/* }}} */
564-
void object_to_bson(zval *object, const char *key, long key_len, bson_t *bson TSRMLS_DC)
564+
void object_to_bson(zval *object, phongo_bson_flags_t flags, const char *key, long key_len, bson_t *bson TSRMLS_DC)
565565
{
566566
bson_t child;
567567

568568
if (Z_TYPE_P(object) != IS_OBJECT || instanceof_function(Z_OBJCE_P(object), zend_standard_class_def TSRMLS_CC)) {
569569
mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding as-if was stdclass");
570570
bson_append_document_begin(bson, key, key_len, &child);
571-
zval_to_bson(object, PHONGO_BSON_NONE, &child, NULL TSRMLS_CC);
571+
zval_to_bson(object, flags, &child, NULL TSRMLS_CC);
572572
bson_append_document_end(bson, &child);
573573
return;
574574
}
@@ -591,9 +591,11 @@ void object_to_bson(zval *object, const char *key, long key_len, bson_t *bson TS
591591

592592
bson_append_document_begin(bson, key, key_len, &child);
593593
if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce TSRMLS_CC)) {
594-
bson_append_binary(&child, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(object)->name, strlen(Z_OBJCE_P(object)->name));
594+
if (flags & PHONGO_BSON_ADD_ODS) {
595+
bson_append_binary(&child, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(object)->name, strlen(Z_OBJCE_P(object)->name));
596+
}
595597
}
596-
zval_to_bson(retval, PHONGO_BSON_NONE, &child, NULL TSRMLS_CC);
598+
zval_to_bson(retval, flags, &child, NULL TSRMLS_CC);
597599
bson_append_document_end(bson, &child);
598600

599601
if (tmp_ht) {
@@ -665,7 +667,7 @@ void object_to_bson(zval *object, const char *key, long key_len, bson_t *bson TS
665667
}
666668
}
667669
}
668-
void phongo_bson_append(bson_t *bson, const char *key, long key_len, int entry_type, zval *entry TSRMLS_DC)
670+
void phongo_bson_append(bson_t *bson, phongo_bson_flags_t flags, const char *key, long key_len, int entry_type, zval *entry TSRMLS_DC)
669671
{
670672
switch (entry_type)
671673
{
@@ -704,7 +706,7 @@ void phongo_bson_append(bson_t *bson, const char *key, long key_len, int entry_t
704706
}
705707

706708
bson_append_array_begin(bson, key, key_len, &child);
707-
zval_to_bson(entry, PHONGO_BSON_NONE, &child, NULL TSRMLS_CC);
709+
zval_to_bson(entry, flags, &child, NULL TSRMLS_CC);
708710
bson_append_array_end(bson, &child);
709711

710712
if (tmp_ht) {
@@ -714,7 +716,7 @@ void phongo_bson_append(bson_t *bson, const char *key, long key_len, int entry_t
714716
}
715717
/* break intentionally omitted */
716718
case IS_OBJECT:
717-
object_to_bson(entry, key, key_len, bson TSRMLS_CC);
719+
object_to_bson(entry, flags, key, key_len, bson TSRMLS_CC);
718720
break;
719721

720722
default:
@@ -727,18 +729,26 @@ PHONGO_API void zval_to_bson(zval *data, phongo_bson_flags_t flags, bson_t *bson
727729
{
728730
HashPosition pos;
729731
HashTable *ht_data;
732+
zval *obj_data = NULL;
730733

731734
switch(Z_TYPE_P(data)) {
732735
case IS_OBJECT:
733736
if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce TSRMLS_CC)) {
734-
zval *retval;
735737

736-
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(data)->name, strlen(Z_OBJCE_P(data)->name));
738+
if (flags & PHONGO_BSON_ADD_ODS) {
739+
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(data)->name, strlen(Z_OBJCE_P(data)->name));
740+
}
741+
742+
zend_call_method_with_0_params(&data, NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
743+
if(obj_data) {
744+
if (Z_TYPE_P(obj_data) == IS_ARRAY) {
745+
ht_data = HASH_OF(obj_data);
746+
} else {
747+
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "%s", "Return value expected to be array");
748+
zval_ptr_dtor(&obj_data);
749+
}
737750

738-
zend_call_method_with_0_params(&data, NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &retval);
739-
if(retval) {
740-
ZVAL_ZVAL(data, retval, 0, 1);
741-
convert_to_array(data);
751+
break;
742752
}
743753
}
744754
/* break intentionally omitted */
@@ -752,6 +762,9 @@ PHONGO_API void zval_to_bson(zval *data, phongo_bson_flags_t flags, bson_t *bson
752762
}
753763

754764
if (ht_data && ht_data->nApplyCount > 1) {
765+
if (obj_data) {
766+
zval_ptr_dtor(&obj_data);
767+
}
755768
return;
756769
}
757770

@@ -794,7 +807,7 @@ PHONGO_API void zval_to_bson(zval *data, phongo_bson_flags_t flags, bson_t *bson
794807
key_len = bson_uint32_to_string(index, (const char **)&key, numbuf, sizeof(numbuf));
795808
}
796809

797-
phongo_bson_append(bson, key, key_len, Z_TYPE_PP(entry), *entry TSRMLS_CC);
810+
phongo_bson_append(bson, flags, key, key_len, Z_TYPE_PP(entry), *entry TSRMLS_CC);
798811
}
799812

800813
if (flags & PHONGO_BSON_ADD_ID) {
@@ -810,6 +823,9 @@ PHONGO_API void zval_to_bson(zval *data, phongo_bson_flags_t flags, bson_t *bson
810823
}
811824
}
812825
}
826+
if (obj_data) {
827+
zval_ptr_dtor(&obj_data);
828+
}
813829
}
814830

815831
/* }}} */
@@ -873,7 +889,7 @@ PHP_FUNCTION(fromArray)
873889
}
874890

875891
bson = bson_new();
876-
zval_to_bson(data, PHONGO_BSON_NONE, bson, NULL TSRMLS_CC);
892+
zval_to_bson(data, PHONGO_BSON_ADD_ODS, bson, NULL TSRMLS_CC);
877893

878894
RETVAL_STRINGL((const char *) bson_get_data(bson), bson->len, 1);
879895
bson_destroy(bson);

tests/bson/bson-ods-001.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class Person implements BSON\Persistable {
8181
$updated['$set'] = array($k => $v);
8282
}
8383
}
84+
return $updated;
8485
}
8586

8687
function getName() {

0 commit comments

Comments
 (0)