Skip to content

Commit 2691047

Browse files
committed
PHPC-120: BSON\toArray should support classmap to unserialize as
1 parent 3fa8cc8 commit 2691047

File tree

5 files changed

+52
-27
lines changed

5 files changed

+52
-27
lines changed

php_phongo.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ zend_bool phongo_writeconcernerror_init(zval *return_value, bson_t *bson TSRMLS_
273273
if (bson_iter_init_find(&iter, bson, "errInfo") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
274274
uint32_t len;
275275
const uint8_t *data;
276-
php_phongo_bson_state state = {NULL, NULL, 0};
276+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
277277

278278
bson_iter_document(&iter, &len, &data);
279279

@@ -1202,7 +1202,7 @@ static void phongo_cursor_it_get_current_data(zend_object_iterator *iter, zval *
12021202

12031203
static void phongo_cursor_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
12041204
{
1205-
php_phongo_bson_state state = {NULL, NULL, 0};
1205+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
12061206
phongo_cursor_it *cursor_it = (phongo_cursor_it *)iter;
12071207
const bson_t *doc;
12081208

@@ -1236,7 +1236,7 @@ static void phongo_cursor_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
12361236

12371237
static void phongo_cursor_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
12381238
{
1239-
php_phongo_bson_state state = {NULL, NULL, 0};
1239+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
12401240
phongo_cursor_it *cursor_it = (phongo_cursor_it *)iter;
12411241

12421242
/* firstBatch is empty when the query simply didn't return any results */

php_phongo_classes.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,20 @@ typedef struct {
3030
bson_t *bson;
3131
} php_phongo_command_t;
3232

33+
typedef struct {
34+
struct {
35+
char *classname;
36+
int classname_len;
37+
} document;
38+
struct {
39+
char *classname;
40+
int classname_len;
41+
} array;
42+
} php_phongo_bson_typemap;
43+
3344
typedef struct {
3445
zval *zchild;
35-
char *classname;
36-
int classname_len;
46+
php_phongo_bson_typemap map;
3747
} php_phongo_bson_state;
3848

3949
typedef struct {

src/MongoDB/CommandResult.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ PHP_METHOD(CommandResult, getResponseDocument)
150150

151151

152152
if (intern->result.firstBatch) {
153-
php_phongo_bson_state state = {NULL, NULL, 0};
153+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
154154

155155
state.zchild = return_value;
156156
bson_to_zval(bson_get_data(intern->result.firstBatch), intern->result.firstBatch->len, &state);

src/bson.c

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
/* Our stuffz */
3737
#include "php_phongo.h"
3838
#include "php_bson.h"
39+
#include "php_array.h"
3940

4041

4142
#define BSON_APPEND_INT32(b,key,val) \
@@ -453,17 +454,16 @@ bool php_phongo_bson_visit_document(const bson_iter_t *iter __attribute__((unuse
453454
TSRMLS_FETCH();
454455

455456
if (bson_iter_init(&child, v_document)) {
456-
php_phongo_bson_state state = {NULL, NULL, 0};
457+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
457458

458-
state.classname = ((php_phongo_bson_state *)data)->classname;
459-
state.classname_len = ((php_phongo_bson_state *)data)->classname_len;
459+
state.map = ((php_phongo_bson_state *)data)->map;
460460

461461
MAKE_STD_ZVAL(state.zchild);
462462
array_init(state.zchild);
463463

464464
if (!bson_iter_visit_all(&child, &php_bson_visitors, &state)) {
465-
if (state.classname_len) {
466-
ce = zend_fetch_class(state.classname, state.classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
465+
if (state.map.document.classname_len) {
466+
ce = zend_fetch_class(state.map.document.classname, state.map.document.classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
467467
if (ce->type == ZEND_INTERNAL_CLASS && ce->constructor) {
468468
zval tmp_val = *state.zchild;
469469

@@ -490,25 +490,23 @@ bool php_phongo_bson_visit_document(const bson_iter_t *iter __attribute__((unuse
490490

491491
bool php_phongo_bson_visit_array(const bson_iter_t *iter __attribute__((unused)), const char *key, const bson_t *v_array, void *data)
492492
{
493-
php_phongo_bson_state *parent_state = data;
494-
zval *retval = parent_state->zchild;
493+
zval *retval = ((php_phongo_bson_state *)data)->zchild;
495494
zend_class_entry *ce = zend_standard_class_def;
496495
bson_iter_t child;
497496
TSRMLS_FETCH();
498497

499498
if (bson_iter_init(&child, v_array)) {
500-
php_phongo_bson_state state = {NULL, NULL, 0};
499+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
501500

502-
state.classname = parent_state->classname;
503-
state.classname_len = parent_state->classname_len;
501+
state.map = ((php_phongo_bson_state *)data)->map;
504502

505503
MAKE_STD_ZVAL(state.zchild);
506504
array_init(state.zchild);
507505

508506
if (!bson_iter_visit_all(&child, &php_bson_visitors, &state)) {
509507

510-
if (state.classname_len) {
511-
ce = zend_fetch_class(state.classname, state.classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
508+
if (state.map.array.classname_len) {
509+
ce = zend_fetch_class(state.map.array.classname, state.map.array.classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
512510
if (ce->type == ZEND_INTERNAL_CLASS && ce->constructor) {
513511
zval tmp_val = *state.zchild;
514512

@@ -840,26 +838,43 @@ PHP_FUNCTION(fromArray)
840838
}
841839
/* }}} */
842840

843-
/* {{{ proto string BSON\toArray(string data)
844-
Returns the PHP representation of a BSON value */
841+
/* {{{ proto string BSON\toArray(string data [, array $typemap = array()])
842+
Returns the PHP representation of a BSON value, optionally converting them into custom types/classes */
845843
PHP_FUNCTION(toArray)
846844
{
847-
char *data, *classname = NULL;
848-
int data_len, classname_len = 0;
849-
php_phongo_bson_state state = {NULL, NULL, 0};
845+
char *data, *document_classname, *array_classname;
846+
int data_len, document_classname_len, array_classname_len;
847+
zval *typemap = NULL;
848+
zend_bool document_classname_free = 0, array_classname_free = 0;
849+
php_phongo_bson_state state = {NULL, {{NULL, 0}, {NULL, 0}}};
850850

851851
(void)return_value_ptr; (void)this_ptr; (void)return_value_used; /* We don't use these */
852852

853-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &data, &data_len, &classname, &classname_len) == FAILURE) {
853+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!", &data, &data_len, &typemap) == FAILURE) {
854854
return;
855855
}
856856

857-
state.classname_len = classname_len;
858-
state.classname = classname;
857+
if (typemap) {
858+
array_classname = php_array_fetchl_string(typemap, "array", sizeof("array")-1, &array_classname_len, &array_classname_free);
859+
if (array_classname_len) {
860+
state.map.array.classname_len = array_classname_len;
861+
state.map.array.classname = array_classname;
862+
}
863+
864+
document_classname = php_array_fetchl_string(typemap, "document", sizeof("document")-1, &document_classname_len, &document_classname_free);
865+
if (document_classname_len) {
866+
state.map.document.classname_len = document_classname_len;
867+
state.map.document.classname = document_classname;
868+
}
869+
}
859870
state.zchild = return_value;
860871
if (!bson_to_zval((const unsigned char *)data, data_len, &state)) {
861872
RETURN_NULL();
862873
}
874+
875+
if (document_classname_free) {
876+
efree(document_classname);
877+
}
863878
}
864879
/* }}} */
865880

tests/bson/bson-decode-002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ $tests = array(
1818
foreach($tests as $n => $test) {
1919
$s = BSON\fromArray($test);
2020
echo "Test#{$n} ", BSON\toJSON($s), "\n";
21-
$val = BSON\toArray($s, "ArrayObject");
21+
$val = BSON\toArray($s, array("document"=> "ArrayObject", "array" => "ArrayObject"));
2222
var_dump($val);
2323
}
2424
?>

0 commit comments

Comments
 (0)