Skip to content

Commit f4a574e

Browse files
committed
PHPC-121: Use BSON\Serialize::bsonSerialize() during serialization
1 parent e82b1d0 commit f4a574e

File tree

2 files changed

+113
-12
lines changed

2 files changed

+113
-12
lines changed

src/bson.c

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,33 @@ void object_to_bson(zval *object, const char *key, long key_len, bson_t *bson TS
569569
}
570570

571571
if (instanceof_function(Z_OBJCE_P(object), php_phongo_type_ce TSRMLS_CC)) {
572+
if (instanceof_function(Z_OBJCE_P(object), php_phongo_serializable_ce TSRMLS_CC)) {
573+
zval *retval = NULL;
574+
575+
zend_call_method_with_0_params(&object, NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &retval);
576+
if (retval) {
577+
bson_t child;
578+
HashTable *tmp_ht;
579+
580+
convert_to_array_ex(&retval);
581+
tmp_ht = HASH_OF(retval);
582+
583+
if (tmp_ht) {
584+
tmp_ht->nApplyCount++;
585+
}
586+
587+
bson_append_array_begin(bson, key, key_len, &child);
588+
zval_to_bson(retval, PHONGO_BSON_NONE, &child, NULL TSRMLS_CC);
589+
bson_append_array_end(bson, &child);
590+
591+
if (tmp_ht) {
592+
tmp_ht->nApplyCount--;
593+
}
594+
zval_ptr_dtor(&retval);
595+
}
596+
return;
597+
}
598+
572599
if (instanceof_function(Z_OBJCE_P(object), php_phongo_objectid_ce TSRMLS_CC)) {
573600
bson_oid_t oid;
574601

@@ -831,22 +858,26 @@ void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *ma
831858
zend_class_entry *array_ce = NULL, *document_ce = NULL;
832859

833860
classname = php_array_fetchl_string(typemap, "array", sizeof("array")-1, &classname_len, &classname_free);
834-
array_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
861+
if (classname_len) {
862+
array_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
835863

836-
if (instanceof_function(array_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
837-
map->array = array_ce;
838-
}
839-
if (classname_free) {
840-
efree(classname);
864+
if (instanceof_function(array_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
865+
map->array = array_ce;
866+
}
867+
if (classname_free) {
868+
efree(classname);
869+
}
841870
}
842871

843872
classname = php_array_fetchl_string(typemap, "document", sizeof("document")-1, &classname_len, &classname_free);
844-
document_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
845-
if (instanceof_function(document_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
846-
map->document = document_ce;
847-
}
848-
if (classname_free) {
849-
efree(classname);
873+
if (classname_len) {
874+
document_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
875+
if (instanceof_function(document_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
876+
map->document = document_ce;
877+
}
878+
if (classname_free) {
879+
efree(classname);
880+
}
850881
}
851882
}
852883
}

tests/bson/bson-encode-002.phpt

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
--TEST--
2+
BSON encoding: Encoding objects into BSON representation
3+
--SKIPIF--
4+
<?php require "tests/utils/basic-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once "tests/utils/basic.inc";
8+
9+
class MyClass implements BSON\Serializable, BSON\Unserializable, BSON\Type {
10+
function bsonSerialize() {
11+
return array(
12+
"random" => "class",
13+
"data"
14+
);
15+
}
16+
function bsonUnserialize(array $data) {
17+
var_dump(__METHOD__, $data);
18+
}
19+
}
20+
class MyClass2 implements BSON\Serializable, BSON\Unserializable, BSON\Type {
21+
function bsonSerialize() {
22+
return array(
23+
1, 2, 3,
24+
);
25+
}
26+
function bsonUnserialize(array $data) {
27+
var_dump(__METHOD__, $data);
28+
}
29+
}
30+
31+
$tests = array(
32+
array("stuff" => new MyClass),
33+
array("stuff" => new MyClass2),
34+
);
35+
36+
foreach($tests as $n => $test) {
37+
$s = BSON\fromArray($test);
38+
echo "Test#{$n} ", BSON\toJSON($s), "\n";
39+
hex_dump($s);
40+
BSON\toArray($s, array("array" => get_class($test["stuff"])));
41+
}
42+
?>
43+
===DONE===
44+
<?php exit(0); ?>
45+
--EXPECT--
46+
Test#0 { "stuff" : [ "class", "data" ] }
47+
0 : 2f 00 00 00 04 73 74 75 66 66 00 23 00 00 00 02 [/....stuff.#....]
48+
10 : 72 61 6e 64 6f 6d 00 06 00 00 00 63 6c 61 73 73 [random.....class]
49+
20 : 00 02 30 00 05 00 00 00 64 61 74 61 00 00 00 [..0.....data...]
50+
string(24) "MyClass::bsonUnserialize"
51+
array(2) {
52+
["random"]=>
53+
string(5) "class"
54+
[0]=>
55+
string(4) "data"
56+
}
57+
Test#1 { "stuff" : [ 1, 2, 3 ] }
58+
0 : 26 00 00 00 04 73 74 75 66 66 00 1a 00 00 00 10 [&....stuff......]
59+
10 : 30 00 01 00 00 00 10 31 00 02 00 00 00 10 32 00 [0......1......2.]
60+
20 : 03 00 00 00 00 00 [......]
61+
string(25) "MyClass2::bsonUnserialize"
62+
array(3) {
63+
[0]=>
64+
int(1)
65+
[1]=>
66+
int(2)
67+
[2]=>
68+
int(3)
69+
}
70+
===DONE===

0 commit comments

Comments
 (0)