Skip to content

Commit 8ee86a1

Browse files
committed
PHPC-779: Switch ObjectID from O to C type serialization
1 parent 9ccbea5 commit 8ee86a1

File tree

5 files changed

+105
-5
lines changed

5 files changed

+105
-5
lines changed

src/BSON/ObjectID.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
#include <ext/standard/info.h>
3535
#include <Zend/zend_interfaces.h>
3636
#include <ext/spl/spl_iterators.h>
37+
#include <ext/standard/php_var.h>
38+
#if PHP_VERSION_ID >= 70000
39+
# include <zend_smart_str.h>
40+
#else
41+
# include <ext/standard/php_smart_str.h>
42+
#endif
3743
/* Our Compatability header */
3844
#include "phongo_compat.h"
3945

@@ -209,6 +215,93 @@ PHP_METHOD(ObjectID, __wakeup)
209215
}
210216
/* }}} */
211217

218+
/* {{{ proto string ObjectID::serialize()
219+
*/
220+
PHP_METHOD(ObjectID, serialize)
221+
{
222+
php_phongo_objectid_t *intern;
223+
#if PHP_VERSION_ID >= 70000
224+
zval retval;
225+
#else
226+
zval *retval;
227+
#endif
228+
php_serialize_data_t var_hash;
229+
smart_str buf = { 0 };
230+
231+
intern = Z_OBJECTID_OBJ_P(getThis());
232+
233+
if (zend_parse_parameters_none() == FAILURE) {
234+
return;
235+
}
236+
237+
#if PHP_VERSION_ID >= 70000
238+
array_init_size(&retval, 2);
239+
ADD_ASSOC_STRINGL(&retval, "oid", intern->oid, 24);
240+
#else
241+
ALLOC_INIT_ZVAL(retval);
242+
array_init_size(retval, 2);
243+
ADD_ASSOC_STRINGL(retval, "oid", intern->oid, 24);
244+
#endif
245+
246+
PHP_VAR_SERIALIZE_INIT(var_hash);
247+
php_var_serialize(&buf, &retval, &var_hash TSRMLS_CC);
248+
smart_str_0(&buf);
249+
PHP_VAR_SERIALIZE_DESTROY(var_hash);
250+
251+
PHONGO_RETVAL_SMART_STR(buf);
252+
253+
smart_str_free(&buf);
254+
zval_ptr_dtor(&retval);
255+
}
256+
/* }}} */
257+
258+
/* {{{ proto string ObjectID::unserialize(string $serialized)
259+
*/
260+
PHP_METHOD(ObjectID, unserialize)
261+
{
262+
php_phongo_objectid_t *intern;
263+
zend_error_handling error_handling;
264+
char *serialized;
265+
phongo_zpp_char_len serialized_len;
266+
#if PHP_VERSION_ID >= 70000
267+
zval props;
268+
#else
269+
zval *props;
270+
#endif
271+
php_unserialize_data_t var_hash;
272+
273+
intern = Z_OBJECTID_OBJ_P(getThis());
274+
275+
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
276+
277+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &serialized_len) == FAILURE) {
278+
zend_restore_error_handling(&error_handling TSRMLS_CC);
279+
return;
280+
}
281+
zend_restore_error_handling(&error_handling TSRMLS_CC);
282+
283+
#if PHP_VERSION_ID < 70000
284+
ALLOC_INIT_ZVAL(props);
285+
#endif
286+
PHP_VAR_UNSERIALIZE_INIT(var_hash);
287+
if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char *) serialized + serialized_len, &var_hash TSRMLS_CC)) {
288+
zval_ptr_dtor(&props);
289+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "%s unserialization failed", ZSTR_VAL(php_phongo_objectid_ce->name));
290+
291+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
292+
return;
293+
}
294+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
295+
296+
#if PHP_VERSION_ID >= 70000
297+
php_phongo_objectid_init_from_hash(intern, HASH_OF(&props) TSRMLS_CC);
298+
#else
299+
php_phongo_objectid_init_from_hash(intern, HASH_OF(props) TSRMLS_CC);
300+
#endif
301+
zval_ptr_dtor(&props);
302+
}
303+
/* }}} */
304+
212305
/* {{{ BSON\ObjectID */
213306

214307
ZEND_BEGIN_ARG_INFO_EX(ai_ObjectID___construct, 0, 0, 0)
@@ -219,6 +312,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_ObjectID___set_state, 0, 0, 1)
219312
ZEND_ARG_ARRAY_INFO(0, properties, 0)
220313
ZEND_END_ARG_INFO()
221314

315+
ZEND_BEGIN_ARG_INFO_EX(ai_ObjectID_unserialize, 0, 0, 1)
316+
ZEND_ARG_INFO(0, serialized)
317+
ZEND_END_ARG_INFO()
318+
222319
ZEND_BEGIN_ARG_INFO_EX(ai_ObjectID_void, 0, 0, 0)
223320
ZEND_END_ARG_INFO()
224321

@@ -228,6 +325,8 @@ static zend_function_entry php_phongo_objectid_me[] = {
228325
PHP_ME(ObjectID, __set_state, ai_ObjectID___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
229326
PHP_ME(ObjectID, __toString, ai_ObjectID_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
230327
PHP_ME(ObjectID, __wakeup, ai_ObjectID_void, ZEND_ACC_PUBLIC)
328+
PHP_ME(ObjectID, serialize, ai_ObjectID_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
329+
PHP_ME(ObjectID, unserialize, ai_ObjectID_unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
231330
PHP_FE_END
232331
};
233332

@@ -326,6 +425,7 @@ PHP_MINIT_FUNCTION(ObjectID)
326425
PHONGO_CE_FINAL(php_phongo_objectid_ce);
327426

328427
zend_class_implements(php_phongo_objectid_ce TSRMLS_CC, 1, php_phongo_type_ce);
428+
zend_class_implements(php_phongo_objectid_ce TSRMLS_CC, 1, zend_ce_serializable);
329429

330430
memcpy(&php_phongo_handler_objectid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
331431
php_phongo_handler_objectid.compare_objects = php_phongo_objectid_compare_objects;

tests/bson/bson-javascript-serialization-001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ object(MongoDB\BSON\Javascript)#%d (%d) {
8585
}
8686
}
8787
}
88-
string(206) "C:23:"MongoDB\BSON\Javascript":169:{a:2:{s:4:"code";s:29:"function foo() { return id; }";s:5:"scope";O:8:"stdClass":1:{s:2:"id";O:21:"MongoDB\BSON\ObjectID":1:{s:3:"oid";s:24:"53e2a1c40640fd72175d4603";}}}}"
88+
string(213) "C:23:"MongoDB\BSON\Javascript":176:{a:2:{s:4:"code";s:29:"function foo() { return id; }";s:5:"scope";O:8:"stdClass":1:{s:2:"id";C:21:"MongoDB\BSON\ObjectID":48:{a:1:{s:3:"oid";s:24:"53e2a1c40640fd72175d4603";}}}}}"
8989
object(MongoDB\BSON\Javascript)#%d (%d) {
9090
["code"]=>
9191
string(29) "function foo() { return id; }"

tests/bson/bson-objectid-serialization-001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ object(MongoDB\BSON\ObjectID)#%d (%d) {
1515
["oid"]=>
1616
string(24) "576c25db6118fd406e6e6471"
1717
}
18-
string(75) "O:21:"MongoDB\BSON\ObjectID":1:{s:3:"oid";s:24:"576c25db6118fd406e6e6471";}"
18+
string(82) "C:21:"MongoDB\BSON\ObjectID":48:{a:1:{s:3:"oid";s:24:"576c25db6118fd406e6e6471";}}"
1919
object(MongoDB\BSON\ObjectID)#%d (%d) {
2020
["oid"]=>
2121
string(24) "576c25db6118fd406e6e6471"

tests/bson/bson-objectid-serialization_error-001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ MongoDB\BSON\ObjectID unserialization requires "oid" string field
66
require_once __DIR__ . '/../utils/tools.php';
77

88
echo throws(function() {
9-
unserialize('O:21:"MongoDB\BSON\ObjectID":1:{s:3:"oid";i:0;}');
9+
unserialize('C:21:"MongoDB\BSON\ObjectID":20:{a:1:{s:3:"oid";i:0;}}');
1010
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1111

1212
?>

tests/bson/bson-objectid-serialization_error-002.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ MongoDB\BSON\ObjectID unserialization requires valid hex string
66
require_once __DIR__ . '/../utils/tools.php';
77

88
echo throws(function() {
9-
unserialize('O:21:"MongoDB\BSON\ObjectID":1:{s:3:"oid";s:24:"0123456789abcdefghijklmn";}');
9+
unserialize('C:21:"MongoDB\BSON\ObjectID":48:{a:1:{s:3:"oid";s:24:"0123456789abcdefghijklmn";}}');
1010
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1111

1212
echo throws(function() {
13-
unserialize('O:21:"MongoDB\BSON\ObjectID":1:{s:3:"oid";s:7:"INVALID";}');
13+
unserialize('C:21:"MongoDB\BSON\ObjectID":30:{a:1:{s:3:"oid";s:7:"INVALID";}}');
1414
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1515

1616
?>

0 commit comments

Comments
 (0)