Skip to content

Commit 4b7336e

Browse files
committed
PHPC-274: Fix zval_to_bson() encoding of BSON\Serializable objects
Previously, only BSON\Persistable objects were handled.
1 parent 68eba44 commit 4b7336e

File tree

2 files changed

+115
-46
lines changed

2 files changed

+115
-46
lines changed

src/bson.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -763,21 +763,24 @@ PHONGO_API void zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *
763763

764764
switch(Z_TYPE_P(data)) {
765765
case IS_OBJECT:
766-
if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce TSRMLS_CC)) {
767-
768-
if (flags & PHONGO_BSON_ADD_ODS) {
769-
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(data)->name, strlen(Z_OBJCE_P(data)->name));
770-
}
771-
766+
767+
if (instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce TSRMLS_CC)) {
772768
zend_call_method_with_0_params(&data, NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
773-
if(obj_data) {
774-
if (Z_TYPE_P(obj_data) == IS_ARRAY) {
775-
ht_data = HASH_OF(obj_data);
776-
} else {
769+
770+
if (obj_data) {
771+
if (Z_TYPE_P(obj_data) != IS_ARRAY) {
777772
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "%s", "Return value expected to be array");
778773
zval_ptr_dtor(&obj_data);
779774
}
780775

776+
ht_data = HASH_OF(obj_data);
777+
778+
if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce TSRMLS_CC)) {
779+
if (flags & PHONGO_BSON_ADD_ODS) {
780+
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(data)->name, strlen(Z_OBJCE_P(data)->name));
781+
}
782+
}
783+
781784
break;
782785
}
783786
}

tests/bson/bson-encode-002.phpt

Lines changed: 102 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,65 +6,130 @@ BSON encoding: Encoding objects into BSON representation
66
<?php
77
require_once __DIR__ . "/../utils/basic.inc";
88

9-
class MyClass implements BSON\Serializable, BSON\Unserializable {
10-
function bsonSerialize() {
11-
return array(
12-
"random" => "class",
13-
"data"
14-
);
9+
class AssociativeArray implements BSON\Serializable, BSON\Unserializable
10+
{
11+
function bsonSerialize()
12+
{
13+
return array("random" => "class", "data");
1514
}
16-
function bsonUnserialize(array $data) {
17-
var_dump(__METHOD__, $data);
15+
16+
function bsonUnserialize(array $data)
17+
{
18+
echo __METHOD__, "() was called with data:\n";
19+
var_dump($data);
1820
}
1921
}
20-
class MyClass2 implements BSON\Serializable, BSON\Unserializable {
21-
function bsonSerialize() {
22-
return array(
23-
1, 2, 3,
24-
);
22+
23+
class NumericArray implements BSON\Serializable, BSON\Unserializable
24+
{
25+
function bsonSerialize()
26+
{
27+
return array(1, 2, 3);
2528
}
26-
function bsonUnserialize(array $data) {
27-
var_dump(__METHOD__, $data);
29+
30+
function bsonUnserialize(array $data)
31+
{
32+
echo __METHOD__, "() was called with data:\n";
33+
var_dump($data);
2834
}
2935
}
3036

31-
$tests = array(
32-
array("stuff" => new MyClass),
33-
array("stuff" => new MyClass2),
34-
);
37+
echo "Testing top-level AssociativeArray:\n";
38+
$bson = BSON\fromArray(new AssociativeArray);
39+
echo BSON\toJSON($bson), "\n";
40+
echo "Encoded BSON:\n";
41+
hex_dump($bson);
42+
$value = BSON\toArray($bson, array("document" => 'AssociativeArray'));
43+
echo "Decoded BSON:\n";
44+
var_dump($value);
45+
46+
echo "\nTesting embedded AssociativeArray:\n";
47+
$bson = BSON\fromArray(array('embed' => new AssociativeArray));
48+
echo BSON\toJSON($bson), "\n";
49+
echo "Encoded BSON:\n";
50+
hex_dump($bson);
51+
$value = BSON\toArray($bson, array("document" => 'AssociativeArray'));
52+
echo "Decoded BSON:\n";
53+
var_dump($value);
54+
55+
echo "\nTesting top-level NumericArray:\n";
56+
$bson = BSON\fromArray(new NumericArray);
57+
echo BSON\toJSON($bson), "\n";
58+
echo "Encoded BSON:\n";
59+
hex_dump($bson);
60+
$value = BSON\toArray($bson, array("document" => 'NumericArray'));
61+
echo "Decoded BSON:\n";
62+
var_dump($value);
63+
64+
echo "\nTesting embedded NumericArray:\n";
65+
$bson = BSON\fromArray(array('embed' => new NumericArray));
66+
echo BSON\toJSON($bson), "\n";
67+
echo "Encoded BSON:\n";
68+
hex_dump($bson);
69+
$value = BSON\toArray($bson, array("document" => 'NumericArray'));
70+
echo "Decoded BSON:\n";
71+
var_dump($value);
3572

36-
foreach($tests as $n => $test) {
37-
$s = BSON\fromArray($test);
38-
echo "Test#{$n} ", BSON\toJSON($s), "\n";
39-
hex_dump($s);
40-
$obj = BSON\toArray($s, array("document" => get_class($test["stuff"])));
41-
var_dump($obj);
42-
}
4373
?>
4474
===DONE===
4575
<?php exit(0); ?>
4676
--EXPECTF--
47-
Test#0 { "stuff" : { "random" : "class", "0" : "data" } }
48-
0 : 2f 00 00 00 03 73 74 75 66 66 00 23 00 00 00 02 [/....stuff.#....]
77+
Testing top-level AssociativeArray:
78+
{ "random" : "class", "0" : "data" }
79+
Encoded BSON:
80+
0 : 23 00 00 00 02 72 61 6e 64 6f 6d 00 06 00 00 00 [#....random.....]
81+
10 : 63 6c 61 73 73 00 02 30 00 05 00 00 00 64 61 74 [class..0.....dat]
82+
20 : 61 00 00 [a..]
83+
Decoded BSON:
84+
array(2) {
85+
["random"]=>
86+
string(5) "class"
87+
[0]=>
88+
string(4) "data"
89+
}
90+
91+
Testing embedded AssociativeArray:
92+
{ "embed" : { "random" : "class", "0" : "data" } }
93+
Encoded BSON:
94+
0 : 2f 00 00 00 03 65 6d 62 65 64 00 23 00 00 00 02 [/....embed.#....]
4995
10 : 72 61 6e 64 6f 6d 00 06 00 00 00 63 6c 61 73 73 [random.....class]
5096
20 : 00 02 30 00 05 00 00 00 64 61 74 61 00 00 00 [..0.....data...]
51-
string(24) "MyClass::bsonUnserialize"
97+
AssociativeArray::bsonUnserialize() was called with data:
5298
array(2) {
5399
["random"]=>
54100
string(5) "class"
55101
[0]=>
56102
string(4) "data"
57103
}
104+
Decoded BSON:
58105
array(1) {
59-
["stuff"]=>
60-
object(MyClass)#%d (0) {
106+
["embed"]=>
107+
object(AssociativeArray)#%d (0) {
61108
}
62109
}
63-
Test#1 { "stuff" : { "0" : 1, "1" : 2, "2" : 3 } }
64-
0 : 26 00 00 00 03 73 74 75 66 66 00 1a 00 00 00 10 [&....stuff......]
110+
111+
Testing top-level NumericArray:
112+
{ "0" : 1, "1" : 2, "2" : 3 }
113+
Encoded BSON:
114+
0 : 1a 00 00 00 10 30 00 01 00 00 00 10 31 00 02 00 [.....0......1...]
115+
10 : 00 00 10 32 00 03 00 00 00 00 [...2......]
116+
Decoded BSON:
117+
array(3) {
118+
[0]=>
119+
int(1)
120+
[1]=>
121+
int(2)
122+
[2]=>
123+
int(3)
124+
}
125+
126+
Testing embedded NumericArray:
127+
{ "embed" : { "0" : 1, "1" : 2, "2" : 3 } }
128+
Encoded BSON:
129+
0 : 26 00 00 00 03 65 6d 62 65 64 00 1a 00 00 00 10 [&....embed......]
65130
10 : 30 00 01 00 00 00 10 31 00 02 00 00 00 10 32 00 [0......1......2.]
66131
20 : 03 00 00 00 00 00 [......]
67-
string(25) "MyClass2::bsonUnserialize"
132+
NumericArray::bsonUnserialize() was called with data:
68133
array(3) {
69134
[0]=>
70135
int(1)
@@ -73,9 +138,10 @@ array(3) {
73138
[2]=>
74139
int(3)
75140
}
141+
Decoded BSON:
76142
array(1) {
77-
["stuff"]=>
78-
object(MyClass2)#%d (0) {
143+
["embed"]=>
144+
object(NumericArray)#%d (0) {
79145
}
80146
}
81147
===DONE===

0 commit comments

Comments
 (0)