Skip to content

Commit c2b2dcd

Browse files
committed
Merge pull request #56
2 parents 48e921a + 1edcd14 commit c2b2dcd

File tree

80 files changed

+400
-286
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+400
-286
lines changed

php_bson.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ typedef struct {
5656
zend_class_entry *document;
5757
php_phongo_bson_typemap_types array_type;
5858
zend_class_entry *array;
59+
php_phongo_bson_typemap_types root_type;
60+
zend_class_entry *root;
5961
} php_phongo_bson_typemap;
6062

6163
typedef struct {
@@ -64,14 +66,14 @@ typedef struct {
6466
zend_class_entry *odm;
6567
} php_phongo_bson_state;
6668

67-
#define PHONGO_BSON_STATE_INITIALIZER {NULL, { PHONGO_TYPEMAP_NONE, NULL, PHONGO_TYPEMAP_NONE, NULL}, NULL}
69+
#define PHONGO_BSON_STATE_INITIALIZER {NULL, { PHONGO_TYPEMAP_NONE, NULL, PHONGO_TYPEMAP_NONE, NULL, PHONGO_TYPEMAP_NONE, NULL}, NULL}
6870

6971
PHONGO_API void zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson, bson_t **bson_out TSRMLS_DC);
7072
PHONGO_API int bson_to_zval(const unsigned char *data, int data_len, php_phongo_bson_state *state);
7173
PHONGO_API void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *map TSRMLS_DC);
7274

73-
PHP_FUNCTION(toArray);
74-
PHP_FUNCTION(fromArray);
75+
PHP_FUNCTION(toPHP);
76+
PHP_FUNCTION(fromPHP);
7577
PHP_FUNCTION(toJSON);
7678
PHP_FUNCTION(fromJSON);
7779

php_phongo.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,13 +1346,19 @@ void php_phongo_server_to_zval(zval *retval, const mongoc_server_description_t *
13461346
}
13471347
if (sd->tags.len) {
13481348
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
1349+
/* Use native arrays for debugging output */
1350+
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
1351+
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
13491352

13501353
MAKE_STD_ZVAL(state.zchild);
13511354
bson_to_zval(bson_get_data(&sd->tags), sd->tags.len, &state);
13521355
add_assoc_zval_ex(retval, ZEND_STRS("tags"), state.zchild);
13531356
}
13541357
{
13551358
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
1359+
/* Use native arrays for debugging output */
1360+
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
1361+
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
13561362

13571363
MAKE_STD_ZVAL(state.zchild);
13581364
bson_to_zval(bson_get_data(&sd->last_is_master), sd->last_is_master.len, &state);
@@ -1370,6 +1376,9 @@ void php_phongo_read_preference_to_zval(zval *retval, const mongoc_read_prefs_t
13701376
add_assoc_long_ex(retval, ZEND_STRS("mode"), read_prefs->mode);
13711377
if (read_prefs->tags.len) {
13721378
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
1379+
/* Use native arrays for debugging output */
1380+
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
1381+
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
13731382

13741383
MAKE_STD_ZVAL(state.zchild);
13751384
bson_to_zval(bson_get_data(&read_prefs->tags), read_prefs->tags.len, &state);
@@ -1432,6 +1441,9 @@ void php_phongo_cursor_to_zval(zval *retval, php_phongo_cursor_t *cursor) /* {{{
14321441
_ADD_BOOL(zcursor, has_fields);
14331442
#undef _ADD_BOOL
14341443

1444+
/* Avoid using PHONGO_TYPEMAP_NATIVE_ARRAY for decoding query, selector,
1445+
* and current documents so that users can differentiate BSON arrays
1446+
* and documents. */
14351447
{
14361448
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
14371449

@@ -2063,11 +2075,11 @@ PHP_MINFO_FUNCTION(mongodb)
20632075

20642076
/* {{{ mongodb_functions[]
20652077
*/
2066-
ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromArray, 0, 0, 1)
2067-
ZEND_ARG_INFO(0, array)
2078+
ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromPHP, 0, 0, 1)
2079+
ZEND_ARG_INFO(0, value)
20682080
ZEND_END_ARG_INFO();
20692081

2070-
ZEND_BEGIN_ARG_INFO_EX(ai_bson_toArray, 0, 0, 1)
2082+
ZEND_BEGIN_ARG_INFO_EX(ai_bson_toPHP, 0, 0, 1)
20712083
ZEND_ARG_INFO(0, bson)
20722084
ZEND_END_ARG_INFO();
20732085

@@ -2080,8 +2092,8 @@ ZEND_BEGIN_ARG_INFO_EX(ai_bson_fromJSON, 0, 0, 1)
20802092
ZEND_END_ARG_INFO();
20812093

20822094
const zend_function_entry mongodb_functions[] = {
2083-
ZEND_NS_FE(BSON_NAMESPACE, fromArray, ai_bson_fromArray)
2084-
ZEND_NS_FE(BSON_NAMESPACE, toArray, ai_bson_toArray)
2095+
ZEND_NS_FE(BSON_NAMESPACE, fromPHP, ai_bson_fromPHP)
2096+
ZEND_NS_FE(BSON_NAMESPACE, toPHP, ai_bson_toPHP)
20852097
ZEND_NS_FE(BSON_NAMESPACE, toJSON, ai_bson_toJSON)
20862098
ZEND_NS_FE(BSON_NAMESPACE, fromJSON, ai_bson_fromJSON)
20872099
PHP_FE_END

src/MongoDB/Query.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ HashTable *php_phongo_query_get_debug_info(zval *object, int *is_temp TSRMLS_DC)
133133

134134
array_init_size(&retval, 6);
135135

136+
/* Avoid using PHONGO_TYPEMAP_NATIVE_ARRAY for decoding query and selector
137+
* documents so that users can differentiate BSON arrays and documents. */
136138
if (intern->query) {
137139
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
138140

src/MongoDB/Server.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ PHP_METHOD(Server, getTags)
164164

165165
if ((sd = mongoc_topology_description_server_by_id(&intern->client->topology->description, intern->server_id))) {
166166
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
167+
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
168+
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
167169

168170
MAKE_STD_ZVAL(state.zchild);
169171
bson_to_zval(bson_get_data(&sd->tags), sd->tags.len, &state);
@@ -191,6 +193,8 @@ PHP_METHOD(Server, getInfo)
191193

192194
if ((sd = mongoc_topology_description_server_by_id(&intern->client->topology->description, intern->server_id))) {
193195
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
196+
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
197+
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
194198

195199
MAKE_STD_ZVAL(state.zchild);
196200
bson_to_zval(bson_get_data(&sd->last_is_master), sd->last_is_master.len, &state);

src/MongoDB/WriteResult.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ PHP_METHOD(WriteResult, getUpsertedIds)
235235
}
236236
}
237237
/* }}} */
238-
/* {{{ proto WriteConcernError[] WriteResult::getWriteConcernError()
238+
/* {{{ proto WriteConcernError WriteResult::getWriteConcernError()
239239
Return any write concern error that occurred */
240240
PHP_METHOD(WriteResult, getWriteConcernError)
241241
{
@@ -444,6 +444,10 @@ HashTable *php_phongo_writeresult_get_debug_info(zval *object, int *is_temp TSRM
444444
add_assoc_long_ex(&retval, ZEND_STRS("nRemoved"), intern->write_result.nRemoved);
445445
add_assoc_long_ex(&retval, ZEND_STRS("nUpserted"), intern->write_result.nUpserted);
446446

447+
/* Use native arrays for debugging output */
448+
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
449+
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
450+
447451
MAKE_STD_ZVAL(state.zchild);
448452
bson_to_zval(bson_get_data(&intern->write_result.upserted), intern->write_result.upserted.len, &state);
449453
add_assoc_zval_ex(&retval, ZEND_STRS("upsertedIds"), state.zchild);

src/bson.c

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -896,17 +896,40 @@ int bson_to_zval(const unsigned char *data, int data_len, php_phongo_bson_state
896896
return 0;
897897
}
898898

899+
/* We initialize an array because it will either be returned as-is (native
900+
* array in type map), passed to bsonUnserialize() (ODM class), or used to
901+
* initialize a stdClass object (native object in type map). */
899902
array_init(state->zchild);
900903
bson_iter_visit_all(&iter, &php_bson_visitors, state);
901-
if ((state->map.array || state->odm) && instanceof_function(state->odm ? state->odm : state->map.array, php_phongo_unserializable_ce TSRMLS_CC)) {
902-
zval *obj = NULL;
903-
904-
MAKE_STD_ZVAL(obj);
905-
object_init_ex(obj, state->odm ? state->odm : state->map.array);
906-
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state->zchild);
907-
SEPARATE_ZVAL(&state->zchild);
908-
zval_dtor(state->zchild);
909-
ZVAL_ZVAL(state->zchild, obj, 1, 1);
904+
905+
/* If php_phongo_bson_visit_binary() finds an ODM class, it supersedes our
906+
* document type. */
907+
if (state->odm) {
908+
state->map.root_type = PHONGO_TYPEMAP_CLASS;
909+
}
910+
911+
switch (state->map.root_type) {
912+
case PHONGO_TYPEMAP_NATIVE_ARRAY:
913+
/* Nothing to do here */
914+
break;
915+
916+
case PHONGO_TYPEMAP_CLASS:
917+
/* If the class implements Unserializable, initialize the object
918+
* from our array data; otherwise, fall through to native object. */
919+
if (instanceof_function(state->odm ? state->odm : state->map.root, php_phongo_unserializable_ce TSRMLS_CC)) {
920+
zval *obj = NULL;
921+
922+
MAKE_STD_ZVAL(obj);
923+
object_init_ex(obj, state->odm ? state->odm : state->map.root);
924+
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state->zchild);
925+
zval_ptr_dtor(&state->zchild);
926+
state->zchild = obj;
927+
break;
928+
}
929+
930+
case PHONGO_TYPEMAP_NATIVE_OBJECT:
931+
default:
932+
object_and_properties_init(state->zchild, zend_standard_class_def, Z_ARRVAL_P(state->zchild));
910933
}
911934

912935
if (bson_reader_read(reader, &eof) || !eof) {
@@ -920,9 +943,9 @@ int bson_to_zval(const unsigned char *data, int data_len, php_phongo_bson_state
920943
return 1;
921944
}
922945

923-
/* {{{ proto string BSON\fromArray(array|object data)
924-
Returns the BSON representation of a value */
925-
PHP_FUNCTION(fromArray)
946+
/* {{{ proto string BSON\fromPHP(array|object $value)
947+
Returns the BSON representation of a PHP value */
948+
PHP_FUNCTION(fromPHP)
926949
{
927950
zval *data;
928951
bson_t *bson;
@@ -947,7 +970,6 @@ void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *ma
947970
char *classname;
948971
int classname_len;
949972
zend_bool classname_free = 0;
950-
zend_class_entry *array_ce = NULL, *document_ce = NULL;
951973

952974
classname = php_array_fetchl_string(typemap, "array", sizeof("array")-1, &classname_len, &classname_free);
953975
if (classname_len) {
@@ -956,8 +978,8 @@ void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *ma
956978
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
957979
map->array_type = PHONGO_TYPEMAP_NATIVE_OBJECT;
958980
} else {
981+
zend_class_entry *array_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
959982
map->array_type = PHONGO_TYPEMAP_CLASS;
960-
array_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
961983

962984
if (instanceof_function(array_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
963985
map->array = array_ce;
@@ -975,8 +997,8 @@ void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *ma
975997
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
976998
map->document_type = PHONGO_TYPEMAP_NATIVE_OBJECT;
977999
} else {
1000+
zend_class_entry *document_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
9781001
map->document_type = PHONGO_TYPEMAP_CLASS;
979-
document_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
9801002

9811003
if (instanceof_function(document_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
9821004
map->document = document_ce;
@@ -986,11 +1008,30 @@ void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *ma
9861008
efree(classname);
9871009
}
9881010
}
1011+
1012+
classname = php_array_fetchl_string(typemap, "root", sizeof("root")-1, &classname_len, &classname_free);
1013+
if (classname_len) {
1014+
if (!strcasecmp(classname, "array")) {
1015+
map->root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
1016+
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
1017+
map->root_type = PHONGO_TYPEMAP_NATIVE_OBJECT;
1018+
} else {
1019+
zend_class_entry *root_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
1020+
map->root_type = PHONGO_TYPEMAP_CLASS;
1021+
1022+
if (instanceof_function(root_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
1023+
map->root = root_ce;
1024+
}
1025+
}
1026+
if (classname_free) {
1027+
efree(classname);
1028+
}
1029+
}
9891030
}
9901031
}
991-
/* {{{ proto string BSON\toArray(string data [, array $typemap = array()])
992-
Returns the PHP representation of a BSON value, optionally converting them into custom types/classes */
993-
PHP_FUNCTION(toArray)
1032+
/* {{{ proto array|object BSON\toPHP(string $bson [, array $typemap = array()])
1033+
Returns the PHP representation of a BSON value, optionally converting it into a custom class */
1034+
PHP_FUNCTION(toPHP)
9941035
{
9951036
char *data;
9961037
int data_len;
@@ -1014,7 +1055,7 @@ PHP_FUNCTION(toArray)
10141055
}
10151056
/* }}} */
10161057

1017-
/* {{{ proto BSON\toJSON BSON\toJSON(string data)
1058+
/* {{{ proto string BSON\toJSON(string $bson)
10181059
Returns the JSON representation of a BSON value */
10191060
PHP_FUNCTION(toJSON)
10201061
{
@@ -1045,7 +1086,7 @@ PHP_FUNCTION(toJSON)
10451086
}
10461087
/* }}} */
10471088

1048-
/* {{{ proto string BSON\fromJSON(string data)
1089+
/* {{{ proto string BSON\fromJSON(string $json)
10491090
Returns the BSON representation of a JSON value */
10501091
PHP_FUNCTION(fromJSON)
10511092
{

tests/bson/bson-binary-001.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ throws(function() use($classname) {
3333

3434

3535
foreach($tests as $n => $test) {
36-
$s = fromArray($test);
36+
$s = fromPHP($test);
3737
echo "Test#{$n} ", $json = toJSON($s), "\n";
3838
$bson = fromJSON($json);
39-
$testagain = toArray($bson);
40-
var_dump(toJSON(fromArray($test)), toJSON(fromArray($testagain)));
39+
$testagain = toPHP($bson);
40+
var_dump(toJSON(fromPHP($test)), toJSON(fromPHP($testagain)));
4141
var_dump((object)$test == (object)$testagain);
4242
}
4343

tests/bson/bson-decode-001.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ $tests = array(
4141
);
4242

4343
foreach($tests as $n => $test) {
44-
$s = fromArray($test);
44+
$s = fromPHP($test);
4545
echo "Test#{$n} ", toJSON($s), "\n";
46-
$val = toArray($s);
47-
if ($val == $test) {
46+
$val = toPHP($s);
47+
if ($val == (object) $test) {
4848
echo "OK\n";
4949
} else {
5050
var_dump($val, $test);

tests/bson/bson-decode-002.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ $tests = array(
2323
);
2424

2525
foreach($tests as $n => $test) {
26-
$s = BSON\fromArray($test);
27-
echo "Test#{$n} ", BSON\toJSON($s), "\n";
28-
$val = BSON\toArray($s, array("document"=> "MyArrayObject", "array" => "MyArrayObject"));
26+
$s = fromPHP($test);
27+
echo "Test#{$n} ", toJSON($s), "\n";
28+
$val = toPHP($s, array("root"=> "MyArrayObject", "document"=> "MyArrayObject", "array" => "MyArrayObject"));
2929
var_dump($val);
3030
}
3131
?>

tests/bson/bson-encode-001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ $tests = array(
3535
);
3636

3737
foreach($tests as $n => $test) {
38-
$s = fromArray($test);
38+
$s = fromPHP($test);
3939
echo "Test#{$n} ", toJSON($s), "\n";
4040
hex_dump($s);
4141
}

0 commit comments

Comments
 (0)