Skip to content

Commit 8050b14

Browse files
committed
PHPC-779: Switch UTCDateTime from O to C type serialization
1 parent d6b095a commit 8050b14

File tree

5 files changed

+114
-9
lines changed

5 files changed

+114
-9
lines changed

src/BSON/UTCDateTime.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
#include <ext/date/php_date.h>
3737
#include <ext/spl/spl_iterators.h>
3838
#include <ext/date/php_date.h>
39+
#include <ext/standard/php_var.h>
40+
#if PHP_VERSION_ID >= 70000
41+
# include <zend_smart_str.h>
42+
#else
43+
# include <ext/standard/php_smart_str.h>
44+
#endif
3945
/* Our Compatability header */
4046
#include "phongo_compat.h"
4147

@@ -287,6 +293,97 @@ PHP_METHOD(UTCDateTime, toDateTime)
287293
}
288294
/* }}} */
289295

296+
/* {{{ proto string UTCDateTime::serialize()
297+
*/
298+
PHP_METHOD(UTCDateTime, serialize)
299+
{
300+
php_phongo_utcdatetime_t *intern;
301+
#if PHP_VERSION_ID >= 70000
302+
zval retval;
303+
#else
304+
zval *retval;
305+
#endif
306+
php_serialize_data_t var_hash;
307+
smart_str buf = { 0 };
308+
char s_milliseconds[24];
309+
int s_milliseconds_len;
310+
311+
intern = Z_UTCDATETIME_OBJ_P(getThis());
312+
313+
if (zend_parse_parameters_none() == FAILURE) {
314+
return;
315+
}
316+
317+
s_milliseconds_len = snprintf(s_milliseconds, sizeof(s_milliseconds), "%" PRId64, intern->milliseconds);
318+
319+
#if PHP_VERSION_ID >= 70000
320+
array_init_size(&retval, 2);
321+
ADD_ASSOC_STRINGL(&retval, "milliseconds", s_milliseconds, s_milliseconds_len);
322+
#else
323+
ALLOC_INIT_ZVAL(retval);
324+
array_init_size(retval, 2);
325+
ADD_ASSOC_STRINGL(retval, "milliseconds", s_milliseconds, s_milliseconds_len);
326+
#endif
327+
328+
PHP_VAR_SERIALIZE_INIT(var_hash);
329+
php_var_serialize(&buf, &retval, &var_hash TSRMLS_CC);
330+
smart_str_0(&buf);
331+
PHP_VAR_SERIALIZE_DESTROY(var_hash);
332+
333+
PHONGO_RETVAL_SMART_STR(buf);
334+
335+
smart_str_free(&buf);
336+
zval_ptr_dtor(&retval);
337+
}
338+
/* }}} */
339+
340+
/* {{{ proto string UTCDateTime::unserialize(string $serialized)
341+
*/
342+
PHP_METHOD(UTCDateTime, unserialize)
343+
{
344+
php_phongo_utcdatetime_t *intern;
345+
zend_error_handling error_handling;
346+
char *serialized;
347+
phongo_zpp_char_len serialized_len;
348+
#if PHP_VERSION_ID >= 70000
349+
zval props;
350+
#else
351+
zval *props;
352+
#endif
353+
php_unserialize_data_t var_hash;
354+
355+
intern = Z_UTCDATETIME_OBJ_P(getThis());
356+
357+
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
358+
359+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &serialized_len) == FAILURE) {
360+
zend_restore_error_handling(&error_handling TSRMLS_CC);
361+
return;
362+
}
363+
zend_restore_error_handling(&error_handling TSRMLS_CC);
364+
365+
#if PHP_VERSION_ID < 70000
366+
ALLOC_INIT_ZVAL(props);
367+
#endif
368+
PHP_VAR_UNSERIALIZE_INIT(var_hash);
369+
if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char *) serialized + serialized_len, &var_hash TSRMLS_CC)) {
370+
zval_ptr_dtor(&props);
371+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "%s unserialization failed", ZSTR_VAL(php_phongo_utcdatetime_ce->name));
372+
373+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
374+
return;
375+
}
376+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
377+
378+
#if PHP_VERSION_ID >= 70000
379+
php_phongo_utcdatetime_init_from_hash(intern, HASH_OF(&props) TSRMLS_CC);
380+
#else
381+
php_phongo_utcdatetime_init_from_hash(intern, HASH_OF(props) TSRMLS_CC);
382+
#endif
383+
zval_ptr_dtor(&props);
384+
}
385+
/* }}} */
386+
290387

291388
/* {{{ BSON\UTCDateTime */
292389

@@ -298,6 +395,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime___set_state, 0, 0, 1)
298395
ZEND_ARG_ARRAY_INFO(0, properties, 0)
299396
ZEND_END_ARG_INFO()
300397

398+
ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime_unserialize, 0, 0, 1)
399+
ZEND_ARG_INFO(0, serialized)
400+
ZEND_END_ARG_INFO()
401+
301402
ZEND_BEGIN_ARG_INFO_EX(ai_UTCDateTime_void, 0, 0, 0)
302403
ZEND_END_ARG_INFO()
303404

@@ -307,6 +408,8 @@ static zend_function_entry php_phongo_utcdatetime_me[] = {
307408
PHP_ME(UTCDateTime, __set_state, ai_UTCDateTime___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
308409
PHP_ME(UTCDateTime, __toString, ai_UTCDateTime_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
309410
PHP_ME(UTCDateTime, __wakeup, ai_UTCDateTime_void, ZEND_ACC_PUBLIC)
411+
PHP_ME(UTCDateTime, serialize, ai_UTCDateTime_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
412+
PHP_ME(UTCDateTime, unserialize, ai_UTCDateTime_unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
310413
PHP_ME(UTCDateTime, toDateTime, ai_UTCDateTime_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
311414
PHP_FE_END
312415
};
@@ -399,6 +502,8 @@ PHP_MINIT_FUNCTION(UTCDateTime)
399502
PHONGO_CE_FINAL(php_phongo_utcdatetime_ce);
400503

401504
zend_class_implements(php_phongo_utcdatetime_ce TSRMLS_CC, 1, php_phongo_type_ce);
505+
zend_class_implements(php_phongo_utcdatetime_ce TSRMLS_CC, 1, zend_ce_serializable);
506+
402507
memcpy(&php_phongo_handler_utcdatetime, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
403508
php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties;
404509
#if PHP_VERSION_ID >= 70000

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ object(MongoDB\BSON\UTCDateTime)#%d (%d) {
2424
["milliseconds"]=>
2525
string(1) "0"
2626
}
27-
string(64) "O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:1:"0";}"
27+
string(71) "C:24:"MongoDB\BSON\UTCDateTime":34:{a:1:{s:12:"milliseconds";s:1:"0";}}"
2828
object(MongoDB\BSON\UTCDateTime)#%d (%d) {
2929
["milliseconds"]=>
3030
string(1) "0"
@@ -34,7 +34,7 @@ object(MongoDB\BSON\UTCDateTime)#%d (%d) {
3434
["milliseconds"]=>
3535
string(14) "-1416445411987"
3636
}
37-
string(78) "O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:14:"-1416445411987";}"
37+
string(85) "C:24:"MongoDB\BSON\UTCDateTime":48:{a:1:{s:12:"milliseconds";s:14:"-1416445411987";}}"
3838
object(MongoDB\BSON\UTCDateTime)#%d (%d) {
3939
["milliseconds"]=>
4040
string(14) "-1416445411987"
@@ -44,7 +44,7 @@ object(MongoDB\BSON\UTCDateTime)#%d (%d) {
4444
["milliseconds"]=>
4545
string(13) "1416445411987"
4646
}
47-
string(77) "O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:13:"1416445411987";}"
47+
string(84) "C:24:"MongoDB\BSON\UTCDateTime":47:{a:1:{s:12:"milliseconds";s:13:"1416445411987";}}"
4848
object(MongoDB\BSON\UTCDateTime)#%d (%d) {
4949
["milliseconds"]=>
5050
string(13) "1416445411987"

tests/bson/bson-utcdatetime-serialization-002.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ $tests = [
1212
];
1313

1414
foreach ($tests as $milliseconds) {
15-
$s = sprintf('O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:%d:"%s";}', strlen($milliseconds), $milliseconds);
15+
$s = sprintf('C:24:"MongoDB\BSON\UTCDateTime":%d:{a:1:{s:12:"milliseconds";s:%d:"%s";}}', 32 + strlen($milliseconds) + strlen(strlen($milliseconds)), strlen($milliseconds), $milliseconds);
1616

1717
var_dump($s);
1818
var_dump(unserialize($s));
@@ -23,19 +23,19 @@ foreach ($tests as $milliseconds) {
2323
===DONE===
2424
<?php exit(0); ?>
2525
--EXPECTF--
26-
string(64) "O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:1:"0";}"
26+
string(71) "C:24:"MongoDB\BSON\UTCDateTime":34:{a:1:{s:12:"milliseconds";s:1:"0";}}"
2727
object(MongoDB\BSON\UTCDateTime)#%d (%d) {
2828
["milliseconds"]=>
2929
string(1) "0"
3030
}
3131

32-
string(78) "O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:14:"-1416445411987";}"
32+
string(85) "C:24:"MongoDB\BSON\UTCDateTime":48:{a:1:{s:12:"milliseconds";s:14:"-1416445411987";}}"
3333
object(MongoDB\BSON\UTCDateTime)#%d (%d) {
3434
["milliseconds"]=>
3535
string(14) "-1416445411987"
3636
}
3737

38-
string(77) "O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:13:"1416445411987";}"
38+
string(84) "C:24:"MongoDB\BSON\UTCDateTime":47:{a:1:{s:12:"milliseconds";s:13:"1416445411987";}}"
3939
object(MongoDB\BSON\UTCDateTime)#%d (%d) {
4040
["milliseconds"]=>
4141
string(13) "1416445411987"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ MongoDB\BSON\UTCDateTime unserialization requires "milliseconds" integer or nume
66
require_once __DIR__ . '/../utils/tools.php';
77

88
echo throws(function() {
9-
unserialize('O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";d:1;}');
9+
unserialize('C:24:"MongoDB\BSON\UTCDateTime":30:{a:1:{s:12:"milliseconds";d:1;}}');
1010
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1111

1212
?>

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

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

88
echo throws(function() {
9-
unserialize('O:24:"MongoDB\BSON\UTCDateTime":1:{s:12:"milliseconds";s:7:"INVALID";}');
9+
unserialize('C:24:"MongoDB\BSON\UTCDateTime":40:{a:1:{s:12:"milliseconds";s:7:"INVALID";}}');
1010
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1111

1212
/* TODO: Add tests for out-of-range values once CDRIVER-1377 is resolved */

0 commit comments

Comments
 (0)