Skip to content

Commit b03d171

Browse files
committed
PHPC-1206: Add __set_state() support for WriteConcern
1 parent 4a568e3 commit b03d171

File tree

4 files changed

+288
-1
lines changed

4 files changed

+288
-1
lines changed

src/MongoDB/WriteConcern.c

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,121 @@
2626

2727
zend_class_entry* php_phongo_writeconcern_ce;
2828

29+
/* Initialize the object from a HashTable and return whether it was successful.
30+
* An exception will be thrown on error. */
31+
static bool php_phongo_writeconcern_init_from_hash(php_phongo_writeconcern_t* intern, HashTable* props TSRMLS_DC) /* {{{ */
32+
{
33+
#if PHP_VERSION_ID >= 70000
34+
zval *w, *wtimeout, *j;
35+
36+
intern->write_concern = mongoc_write_concern_new();
37+
38+
if ((w = zend_hash_str_find(props, "w", sizeof("w") - 1))) {
39+
if (Z_TYPE_P(w) == IS_LONG) {
40+
if (Z_LVAL_P(w) < -3) {
41+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"w\" integer field to be >= -3", ZSTR_VAL(php_phongo_writeconcern_ce->name));
42+
goto failure;
43+
}
44+
mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_P(w));
45+
} else if (Z_TYPE_P(w) == IS_STRING) {
46+
if (strcmp(Z_STRVAL_P(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) {
47+
mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY);
48+
} else {
49+
mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_P(w));
50+
}
51+
} else {
52+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"w\" field to be integer or string", ZSTR_VAL(php_phongo_writeconcern_ce->name));
53+
goto failure;
54+
}
55+
}
56+
57+
if ((wtimeout = zend_hash_str_find(props, "wtimeout", sizeof("wtimeout") - 1))) {
58+
if (Z_TYPE_P(wtimeout) == IS_LONG) {
59+
if (Z_LVAL_P(wtimeout) < 0) {
60+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"wtimeout\" integer field to be >= 0", ZSTR_VAL(php_phongo_writeconcern_ce->name));
61+
goto failure;
62+
}
63+
if (Z_LVAL_P(wtimeout) > INT32_MAX) {
64+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"wtimeout\" integer field to be <= %" PRId32, ZSTR_VAL(php_phongo_writeconcern_ce->name), INT32_MAX);
65+
goto failure;
66+
}
67+
68+
mongoc_write_concern_set_wtimeout(intern->write_concern, Z_LVAL_P(wtimeout));
69+
} else {
70+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"wtimeout\" field to be integer", ZSTR_VAL(php_phongo_writeconcern_ce->name));
71+
goto failure;
72+
}
73+
}
74+
75+
if ((j = zend_hash_str_find(props, "j", sizeof("j") - 1))) {
76+
if (Z_TYPE_P(j) == IS_TRUE || Z_TYPE_P(j) == IS_FALSE) {
77+
mongoc_write_concern_set_journal(intern->write_concern, zend_is_true(j));
78+
} else {
79+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"j\" field to be boolean", ZSTR_VAL(php_phongo_writeconcern_ce->name));
80+
goto failure;
81+
}
82+
}
83+
#else
84+
zval **w, **wtimeout, **j;
85+
86+
intern->write_concern = mongoc_write_concern_new();
87+
88+
if (zend_hash_find(props, "w", sizeof("w"), (void**) &w) == SUCCESS) {
89+
if (Z_TYPE_PP(w) == IS_LONG) {
90+
if (Z_LVAL_PP(w) < -3) {
91+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"w\" integer field to be >= -3", ZSTR_VAL(php_phongo_writeconcern_ce->name));
92+
goto failure;
93+
}
94+
mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_PP(w));
95+
} else if (Z_TYPE_PP(w) == IS_STRING) {
96+
if (strcmp(Z_STRVAL_PP(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) {
97+
mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY);
98+
} else {
99+
mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_PP(w));
100+
}
101+
} else {
102+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"w\" field to be integer or string", ZSTR_VAL(php_phongo_writeconcern_ce->name));
103+
goto failure;
104+
}
105+
}
106+
107+
if (zend_hash_find(props, "wtimeout", sizeof("wtimeout"), (void**) &wtimeout) == SUCCESS) {
108+
if (Z_TYPE_PP(wtimeout) == IS_LONG) {
109+
if (Z_LVAL_PP(wtimeout) < 0) {
110+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"wtimeout\" integer field to be >= 0", ZSTR_VAL(php_phongo_writeconcern_ce->name));
111+
goto failure;
112+
}
113+
if (Z_LVAL_PP(wtimeout) > INT32_MAX) {
114+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"wtimeout\" integer field to be <= %" PRId32, ZSTR_VAL(php_phongo_writeconcern_ce->name), INT32_MAX);
115+
goto failure;
116+
}
117+
118+
mongoc_write_concern_set_wtimeout(intern->write_concern, Z_LVAL_PP(wtimeout));
119+
} else {
120+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"wtimeout\" field to be integer", ZSTR_VAL(php_phongo_writeconcern_ce->name));
121+
goto failure;
122+
}
123+
}
124+
125+
if (zend_hash_find(props, "j", sizeof("j"), (void**) &j) == SUCCESS) {
126+
if (Z_TYPE_PP(j) == IS_BOOL) {
127+
mongoc_write_concern_set_journal(intern->write_concern, Z_BVAL_PP(j));
128+
} else {
129+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires \"j\" field to be boolean", ZSTR_VAL(php_phongo_writeconcern_ce->name));
130+
goto failure;
131+
}
132+
}
133+
134+
#endif
135+
136+
return true;
137+
138+
failure:
139+
mongoc_write_concern_destroy(intern->write_concern);
140+
intern->write_concern = NULL;
141+
return false;
142+
} /* }}} */
143+
29144
/* {{{ proto void MongoDB\Driver\WriteConcern::__construct(integer|string $w[, integer $wtimeout[, boolean $journal]])
30145
Constructs a new WriteConcern */
31146
static PHP_METHOD(WriteConcern, __construct)
@@ -88,6 +203,26 @@ static PHP_METHOD(WriteConcern, __construct)
88203
}
89204
} /* }}} */
90205

206+
/* {{{ proto void MongoDB\BSON\WriteConcern::__set_state(array $properties)
207+
*/
208+
static PHP_METHOD(WriteConcern, __set_state)
209+
{
210+
php_phongo_writeconcern_t* intern;
211+
HashTable* props;
212+
zval* array;
213+
214+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
215+
RETURN_FALSE;
216+
}
217+
218+
object_init_ex(return_value, php_phongo_writeconcern_ce);
219+
220+
intern = Z_WRITECONCERN_OBJ_P(return_value);
221+
props = Z_ARRVAL_P(array);
222+
223+
php_phongo_writeconcern_init_from_hash(intern, props TSRMLS_CC);
224+
} /* }}} */
225+
91226
/* {{{ proto string|integer|null MongoDB\Driver\WriteConcern::getW()
92227
Returns the WriteConcern "w" option */
93228
static PHP_METHOD(WriteConcern, getW)
@@ -274,12 +409,17 @@ ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___construct, 0, 0, 1)
274409
ZEND_ARG_INFO(0, journal)
275410
ZEND_END_ARG_INFO()
276411

412+
ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern___set_state, 0, 0, 1)
413+
ZEND_ARG_ARRAY_INFO(0, properties, 0)
414+
ZEND_END_ARG_INFO()
415+
277416
ZEND_BEGIN_ARG_INFO_EX(ai_WriteConcern_void, 0, 0, 0)
278417
ZEND_END_ARG_INFO()
279418

280419
static zend_function_entry php_phongo_writeconcern_me[] = {
281420
/* clang-format off */
282421
PHP_ME(WriteConcern, __construct, ai_WriteConcern___construct, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
422+
PHP_ME(WriteConcern, __set_state, ai_WriteConcern___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
283423
PHP_ME(WriteConcern, getW, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
284424
PHP_ME(WriteConcern, getWtimeout, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
285425
PHP_ME(WriteConcern, getJournal, ai_WriteConcern_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
@@ -329,7 +469,7 @@ static phongo_create_object_retval php_phongo_writeconcern_create_object(zend_cl
329469
#else
330470
{
331471
zend_object_value retval;
332-
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, php_phongo_writeconcern_free_object, NULL TSRMLS_CC);
472+
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, php_phongo_writeconcern_free_object, NULL TSRMLS_CC);
333473
retval.handlers = &php_phongo_handler_writeconcern;
334474

335475
return retval;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
--TEST--
2+
MongoDB\Driver\WriteConcern::__set_state()
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
$tests = [
9+
[ 'w' => -3 ],
10+
[ 'w' => -2 ], // -2 is default
11+
[ 'w' => -1 ],
12+
[ 'w' => 0 ],
13+
[ 'w' => 1 ],
14+
[ 'w' => 'majority' ],
15+
[ 'w' => 'tag' ],
16+
[ 'w' => 1, 'j' => false ],
17+
[ 'w' => 1, 'wtimeout' => 1000 ],
18+
[ 'w' => 1, 'j' => true, 'wtimeout' => 1000 ],
19+
[ 'j' => true ],
20+
[ 'wtimeout' => 1000 ],
21+
];
22+
23+
foreach ($tests as $fields) {
24+
var_export(MongoDB\Driver\WriteConcern::__set_state($fields));
25+
echo "\n\n";
26+
}
27+
28+
?>
29+
===DONE===
30+
<?php exit(0); ?>
31+
--EXPECT--
32+
MongoDB\Driver\WriteConcern::__set_state(array(
33+
'w' => 'majority',
34+
))
35+
36+
MongoDB\Driver\WriteConcern::__set_state(array(
37+
))
38+
39+
MongoDB\Driver\WriteConcern::__set_state(array(
40+
'w' => -1,
41+
))
42+
43+
MongoDB\Driver\WriteConcern::__set_state(array(
44+
'w' => 0,
45+
))
46+
47+
MongoDB\Driver\WriteConcern::__set_state(array(
48+
'w' => 1,
49+
))
50+
51+
MongoDB\Driver\WriteConcern::__set_state(array(
52+
'w' => 'majority',
53+
))
54+
55+
MongoDB\Driver\WriteConcern::__set_state(array(
56+
'w' => 'tag',
57+
))
58+
59+
MongoDB\Driver\WriteConcern::__set_state(array(
60+
'w' => 1,
61+
'j' => false,
62+
))
63+
64+
MongoDB\Driver\WriteConcern::__set_state(array(
65+
'w' => 1,
66+
'wtimeout' => 1000,
67+
))
68+
69+
MongoDB\Driver\WriteConcern::__set_state(array(
70+
'w' => 1,
71+
'j' => true,
72+
'wtimeout' => 1000,
73+
))
74+
75+
MongoDB\Driver\WriteConcern::__set_state(array(
76+
'j' => true,
77+
))
78+
79+
MongoDB\Driver\WriteConcern::__set_state(array(
80+
'wtimeout' => 1000,
81+
))
82+
83+
===DONE===
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
MongoDB\Driver\WriteConcern::__set_state() requires correct data types and values
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
echo throws(function() {
9+
MongoDB\Driver\WriteConcern::__set_state(['w' => -4]);
10+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
11+
12+
echo throws(function() {
13+
MongoDB\Driver\WriteConcern::__set_state(['w' => M_PI]);
14+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
15+
16+
17+
echo throws(function() {
18+
MongoDB\Driver\WriteConcern::__set_state(['wtimeout' => -1]);
19+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
20+
21+
echo throws(function() {
22+
MongoDB\Driver\WriteConcern::__set_state(['wtimeout' => 'failure']);
23+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
24+
25+
26+
echo throws(function() {
27+
MongoDB\Driver\WriteConcern::__set_state(['j' => 'failure']);
28+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
29+
30+
?>
31+
===DONE===
32+
<?php exit(0); ?>
33+
--EXPECT--
34+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
35+
MongoDB\Driver\WriteConcern initialization requires "w" integer field to be >= -3
36+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
37+
MongoDB\Driver\WriteConcern initialization requires "w" field to be integer or string
38+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
39+
MongoDB\Driver\WriteConcern initialization requires "wtimeout" integer field to be >= 0
40+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
41+
MongoDB\Driver\WriteConcern initialization requires "wtimeout" field to be integer
42+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
43+
MongoDB\Driver\WriteConcern initialization requires "j" field to be boolean
44+
===DONE===
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
MongoDB\Driver\WriteConcern::__set_state() requires correct data types and values
3+
--SKIPIF--
4+
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
5+
--FILE--
6+
<?php
7+
8+
require_once __DIR__ . '/../utils/tools.php';
9+
10+
echo throws(function() {
11+
MongoDB\Driver\WriteConcern::__set_state(['wtimeout' => pow(2, 32) + 1]);
12+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
13+
14+
?>
15+
===DONE===
16+
<?php exit(0); ?>
17+
--EXPECT--
18+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
19+
MongoDB\Driver\WriteConcern initialization requires "wtimeout" integer field to be <= 2147483647
20+
===DONE===

0 commit comments

Comments
 (0)