Skip to content

Commit 1fd77a1

Browse files
committed
Merge pull request #424
2 parents 61bbc90 + a267e05 commit 1fd77a1

20 files changed

+678
-13
lines changed

php_phongo.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,49 @@ void php_phongo_read_concern_to_zval(zval *retval, const mongoc_read_concern_t *
823823
}
824824
} /* }}} */
825825

826+
/* Prepare tagSets for BSON encoding by converting each array in the set to an
827+
* object. This ensures that empty arrays will serialize as empty documents.
828+
*
829+
* php_phongo_read_preference_tags_are_valid() handles actual validation of the
830+
* tag set structure. */
831+
void php_phongo_read_preference_prep_tagsets(zval *tagSets TSRMLS_DC) /* {{{ */
832+
{
833+
HashTable *ht_data;
834+
835+
if (Z_TYPE_P(tagSets) != IS_ARRAY) {
836+
return;
837+
}
838+
839+
ht_data = HASH_OF(tagSets);
840+
841+
#if PHP_VERSION_ID >= 70000
842+
{
843+
zval *tagSet;
844+
845+
ZEND_HASH_FOREACH_VAL(ht_data, tagSet) {
846+
if (Z_TYPE_P(tagSet) == IS_ARRAY) {
847+
convert_to_object(tagSet);
848+
}
849+
} ZEND_HASH_FOREACH_END();
850+
}
851+
#else
852+
{
853+
HashPosition pos;
854+
zval **tagSet;
855+
856+
for (zend_hash_internal_pointer_reset_ex(ht_data, &pos);
857+
zend_hash_get_current_data_ex(ht_data, (void **) &tagSet, &pos) == SUCCESS;
858+
zend_hash_move_forward_ex(ht_data, &pos)) {
859+
if (Z_TYPE_PP(tagSet) == IS_ARRAY) {
860+
convert_to_object(*tagSet);
861+
}
862+
}
863+
}
864+
#endif
865+
866+
return;
867+
} /* }}} */
868+
826869
/* Checks if tags is valid to set on a mongoc_read_prefs_t. It may be null or an
827870
* array of one or more documents. */
828871
bool php_phongo_read_preference_tags_are_valid(const bson_t *tags) /* {{{ */
@@ -864,10 +907,10 @@ void php_phongo_read_preference_to_zval(zval *retval, const mongoc_read_prefs_t
864907
}
865908

866909
if (!bson_empty0(tags)) {
910+
/* Use PHONGO_TYPEMAP_NATIVE_ARRAY for the root type since tags is an
911+
* array; however, inner documents and arrays can use the default. */
867912
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
868-
/* Use native arrays for debugging output */
869913
state.map.root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
870-
state.map.document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
871914

872915
phongo_bson_to_zval_ex(bson_get_data(tags), tags->len, &state);
873916
#if PHP_VERSION_ID >= 70000

php_phongo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ const mongoc_write_concern_t* phongo_write_concern_from_zval (zval *zwrite_conc
128128

129129
php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t *sd);
130130

131+
void php_phongo_read_preference_prep_tagsets(zval *tagSets TSRMLS_DC);
131132
bool php_phongo_read_preference_tags_are_valid(const bson_t *tags);
132133

133134
void php_phongo_server_to_zval(zval *retval, mongoc_server_description_t *sd);

src/MongoDB/Manager.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,67 @@ static bool php_phongo_manager_merge_context_options(zval *zdriverOptions TSRMLS
100100
return true;
101101
}
102102

103+
/* Prepare tagSets for BSON encoding by converting each array in the set to an
104+
* object. This ensures that empty arrays will serialize as empty documents.
105+
*
106+
* php_phongo_read_preference_tags_are_valid() handles actual validation of the
107+
* tag set structure. */
108+
static void php_phongo_manager_prep_tagsets(zval *options TSRMLS_DC)
109+
{
110+
HashTable *ht_data;
111+
112+
if (Z_TYPE_P(options) != IS_ARRAY) {
113+
return;
114+
}
115+
116+
ht_data = HASH_OF(options);
117+
118+
#if PHP_VERSION_ID >= 70000
119+
{
120+
zend_string *string_key = NULL;
121+
zend_ulong num_key = 0;
122+
zval *tagSets;
123+
124+
ZEND_HASH_FOREACH_KEY_VAL(ht_data, num_key, string_key, tagSets) {
125+
if (!string_key) {
126+
continue;
127+
}
128+
129+
/* php_phongo_make_uri() and php_phongo_apply_rp_options_to_uri()
130+
* are both case-insensitive, so we need to be as well. */
131+
if (!strcasecmp(ZSTR_VAL(string_key), "readpreferencetags")) {
132+
php_phongo_read_preference_prep_tagsets(tagSets TSRMLS_CC);
133+
}
134+
} ZEND_HASH_FOREACH_END();
135+
}
136+
#else
137+
{
138+
HashPosition pos;
139+
zval **tagSets;
140+
141+
for (zend_hash_internal_pointer_reset_ex(ht_data, &pos);
142+
zend_hash_get_current_data_ex(ht_data, (void **) &tagSets, &pos) == SUCCESS;
143+
zend_hash_move_forward_ex(ht_data, &pos)) {
144+
char *string_key = NULL;
145+
uint string_key_len = 0;
146+
ulong num_key = 0;
147+
148+
if (HASH_KEY_IS_STRING != zend_hash_get_current_key_ex(ht_data, &string_key, &string_key_len, &num_key, 0, &pos)) {
149+
continue;
150+
}
151+
152+
/* php_phongo_make_uri() and php_phongo_apply_rp_options_to_uri()
153+
* are both case-insensitive, so we need to be as well. */
154+
if (!strcasecmp(string_key, "readpreferencetags")) {
155+
php_phongo_read_preference_prep_tagsets(*tagSets TSRMLS_CC);
156+
}
157+
}
158+
}
159+
#endif
160+
161+
return;
162+
} /* }}} */
163+
103164
/* {{{ proto void Manager::__construct([string $uri = "mongodb://127.0.0.1/"[, array $options = array()[, array $driverOptions = array()]]])
104165
Constructs a new Manager */
105166
PHP_METHOD(Manager, __construct)
@@ -124,6 +185,10 @@ PHP_METHOD(Manager, __construct)
124185
}
125186
zend_restore_error_handling(&error_handling TSRMLS_CC);
126187

188+
if (options) {
189+
php_phongo_manager_prep_tagsets(options TSRMLS_CC);
190+
}
191+
127192
if (driverOptions && !php_phongo_manager_merge_context_options(driverOptions TSRMLS_CC)) {
128193
/* Exception should already have been thrown */
129194
return;

src/MongoDB/ReadConcern.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ PHP_METHOD(ReadConcern, bsonSerialize)
112112
}
113113

114114
php_phongo_read_concern_to_zval(return_value, read_concern);
115+
convert_to_object(return_value);
115116
}
116117
/* }}} */
117118

src/MongoDB/ReadPreference.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ PHP_METHOD(ReadPreference, __construct)
8686
if (tagSets) {
8787
bson_t *tags = bson_new();
8888

89+
php_phongo_read_preference_prep_tagsets(tagSets TSRMLS_CC);
8990
phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t *)tags, NULL TSRMLS_CC);
9091

9192
if (!php_phongo_read_preference_tags_are_valid(tags)) {
@@ -211,6 +212,7 @@ PHP_METHOD(ReadPreference, bsonSerialize)
211212
}
212213

213214
php_phongo_read_preference_to_zval(return_value, read_preference);
215+
convert_to_object(return_value);
214216
}
215217
/* }}} */
216218

src/MongoDB/WriteConcern.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ PHP_METHOD(WriteConcern, bsonSerialize)
193193
}
194194

195195
php_phongo_write_concern_to_zval(return_value, write_concern);
196+
convert_to_object(return_value);
196197
}
197198
/* }}} */
198199

tests/manager/manager-ctor-read_preference-001.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
3333
["tags"]=>
3434
array(2) {
3535
[0]=>
36-
array(1) {
36+
object(stdClass)#%d (%d) {
3737
["tag"]=>
3838
string(3) "one"
3939
}
4040
[1]=>
41-
array(0) {
41+
object(stdClass)#%d (%d) {
4242
}
4343
}
4444
}
@@ -58,12 +58,12 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
5858
["tags"]=>
5959
array(2) {
6060
[0]=>
61-
array(1) {
61+
object(stdClass)#%d (%d) {
6262
["tag"]=>
6363
string(3) "one"
6464
}
6565
[1]=>
66-
array(0) {
66+
object(stdClass)#%d (%d) {
6767
}
6868
}
6969
}

tests/manager/manager-ctor-read_preference-003.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
2929
["tags"]=>
3030
array(1) {
3131
[0]=>
32-
array(1) {
32+
object(stdClass)#%d (%d) {
3333
["tag"]=>
3434
string(3) "one"
3535
}

tests/manager/manager-getreadpreference-001.phpt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
5252
["tags"]=>
5353
array(2) {
5454
[0]=>
55-
array(2) {
55+
object(stdClass)#%d (%d) {
5656
["dc"]=>
5757
string(2) "ny"
5858
["use"]=>
5959
string(7) "reports"
6060
}
6161
[1]=>
62-
array(0) {
62+
object(stdClass)#%d (%d) {
6363
}
6464
}
6565
}
@@ -69,14 +69,14 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
6969
["tags"]=>
7070
array(2) {
7171
[0]=>
72-
array(2) {
72+
object(stdClass)#%d (%d) {
7373
["dc"]=>
7474
string(2) "ny"
7575
["use"]=>
7676
string(7) "reports"
7777
}
7878
[1]=>
79-
array(0) {
79+
object(stdClass)#%d (%d) {
8080
}
8181
}
8282
}
@@ -86,7 +86,7 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
8686
["tags"]=>
8787
array(1) {
8888
[0]=>
89-
array(1) {
89+
object(stdClass)#%d (%d) {
9090
["dc"]=>
9191
string(2) "ca"
9292
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
MongoDB\Driver\ReadConcern::bsonSerialize()
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
$tests = [
9+
new MongoDB\Driver\ReadConcern(),
10+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LINEARIZABLE),
11+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL),
12+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY),
13+
];
14+
15+
foreach ($tests as $test) {
16+
echo toJSON(fromPHP($test)), "\n";
17+
}
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECT--
23+
{ }
24+
{ "level" : "linearizable" }
25+
{ "level" : "local" }
26+
{ "level" : "majority" }
27+
===DONE===
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
MongoDB\Driver\ReadConcern::bsonSerialize() returns an object
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
$tests = [
9+
new MongoDB\Driver\ReadConcern(),
10+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LINEARIZABLE),
11+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL),
12+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY),
13+
];
14+
15+
foreach ($tests as $test) {
16+
var_dump($test->bsonSerialize());
17+
}
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECTF--
23+
object(stdClass)#%d (%d) {
24+
}
25+
object(stdClass)#%d (%d) {
26+
["level"]=>
27+
string(12) "linearizable"
28+
}
29+
object(stdClass)#%d (%d) {
30+
["level"]=>
31+
string(5) "local"
32+
}
33+
object(stdClass)#%d (%d) {
34+
["level"]=>
35+
string(8) "majority"
36+
}
37+
===DONE===

tests/readConcern/readconcern-constants.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ MongoDB\Driver\ReadConcern constants
66
<?php
77
require_once __DIR__ . "/../utils/basic.inc";
88

9+
var_dump(MongoDB\Driver\ReadConcern::LINEARIZABLE);
910
var_dump(MongoDB\Driver\ReadConcern::LOCAL);
1011
var_dump(MongoDB\Driver\ReadConcern::MAJORITY);
1112

1213
?>
1314
===DONE===
1415
<?php exit(0); ?>
1516
--EXPECTF--
17+
string(12) "linearizable"
1618
string(5) "local"
1719
string(8) "majority"
1820
===DONE===
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
MongoDB\Driver\ReadConcern debug output
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
$tests = [
9+
new MongoDB\Driver\ReadConcern(),
10+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LINEARIZABLE),
11+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::LOCAL),
12+
new MongoDB\Driver\ReadConcern(MongoDB\Driver\ReadConcern::MAJORITY),
13+
];
14+
15+
foreach ($tests as $test) {
16+
var_dump($test);
17+
}
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECTF--
23+
object(MongoDB\Driver\ReadConcern)#%d (%d) {
24+
}
25+
object(MongoDB\Driver\ReadConcern)#%d (%d) {
26+
["level"]=>
27+
string(12) "linearizable"
28+
}
29+
object(MongoDB\Driver\ReadConcern)#%d (%d) {
30+
["level"]=>
31+
string(5) "local"
32+
}
33+
object(MongoDB\Driver\ReadConcern)#%d (%d) {
34+
["level"]=>
35+
string(8) "majority"
36+
}
37+
===DONE===

0 commit comments

Comments
 (0)