diff --git a/php_phongo_structs.h b/php_phongo_structs.h index f0090e8d3..044ceb5d1 100644 --- a/php_phongo_structs.h +++ b/php_phongo_structs.h @@ -64,7 +64,9 @@ typedef struct { } php_phongo_cursor_t; typedef struct { + bool initialized; int64_t id; + HashTable* properties; zend_object std; } php_phongo_cursorid_t; diff --git a/src/MongoDB/Cursor.c b/src/MongoDB/Cursor.c index 3415840f0..aa05b7082 100644 --- a/src/MongoDB/Cursor.c +++ b/src/MongoDB/Cursor.c @@ -124,8 +124,9 @@ static void php_phongo_cursor_id_new_from_id(zval* object, int64_t cursorid) /* object_init_ex(object, php_phongo_cursorid_ce); - intern = Z_CURSORID_OBJ_P(object); - intern->id = cursorid; + intern = Z_CURSORID_OBJ_P(object); + intern->id = cursorid; + intern->initialized = true; } /* }}} */ /* {{{ proto array MongoDB\Driver\Cursor::toArray() diff --git a/src/MongoDB/CursorId.c b/src/MongoDB/CursorId.c index 16e872e96..d0bd3f5a6 100644 --- a/src/MongoDB/CursorId.c +++ b/src/MongoDB/CursorId.c @@ -39,7 +39,8 @@ static bool php_phongo_cursorid_init_from_string(php_phongo_cursorid_t* intern, return false; } - intern->id = id; + intern->id = id; + intern->initialized = true; return true; } /* }}} */ @@ -57,6 +58,61 @@ static bool php_phongo_cursorid_init_from_hash(php_phongo_cursorid_t* intern, Ha return false; } /* }}} */ +static HashTable* php_phongo_cursorid_get_properties_hash(phongo_compat_object_handler_type* object, bool is_debug) /* {{{ */ +{ + php_phongo_cursorid_t* intern; + HashTable* props; + + intern = Z_OBJ_CURSORID(PHONGO_COMPAT_GET_OBJ(object)); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2); + + if (!intern->initialized) { + return props; + } + + { + zval value; + + if (is_debug) { +#if SIZEOF_ZEND_LONG == 4 + ZVAL_INT64_STRING(&value, intern->id); +#else + ZVAL_LONG(&value, intern->id); +#endif + } else { + ZVAL_INT64_STRING(&value, intern->id); + } + zend_hash_str_update(props, "id", sizeof("id") - 1, &value); + } + + return props; +} /* }}} */ + +/* {{{ proto MongoDB\Driver\CursorId MongoDB\Driver\CursorId::__set_state(array $properties) +*/ +static PHP_METHOD(CursorId, __set_state) +{ + zend_error_handling error_handling; + php_phongo_cursorid_t* intern; + HashTable* props; + zval* array; + + zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) { + zend_restore_error_handling(&error_handling); + return; + } + zend_restore_error_handling(&error_handling); + + object_init_ex(return_value, php_phongo_cursorid_ce); + + intern = Z_CURSORID_OBJ_P(return_value); + props = Z_ARRVAL_P(array); + + php_phongo_cursorid_init_from_hash(intern, props); +} /* }}} */ + /* {{{ proto string MongoDB\Driver\CursorId::__toString() Returns the string representation of the CursorId */ static PHP_METHOD(CursorId, __toString) @@ -148,6 +204,10 @@ static PHP_METHOD(CursorId, unserialize) } /* }}} */ /* {{{ MongoDB\Driver\CursorId function entries */ +ZEND_BEGIN_ARG_INFO_EX(ai_CursorId___set_state, 0, 0, 1) + ZEND_ARG_ARRAY_INFO(0, properties, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(ai_CursorId_unserialize, 0, 0, 1) ZEND_ARG_INFO(0, serialized) ZEND_END_ARG_INFO() @@ -157,6 +217,7 @@ ZEND_END_ARG_INFO() static zend_function_entry php_phongo_cursorid_me[] = { /* clang-format off */ + PHP_ME(CursorId, __set_state, ai_CursorId___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(CursorId, __toString, ai_CursorId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) PHP_ME(CursorId, serialize, ai_CursorId_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) PHP_ME(CursorId, unserialize, ai_CursorId_unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) @@ -175,6 +236,11 @@ static void php_phongo_cursorid_free_object(zend_object* object) /* {{{ */ php_phongo_cursorid_t* intern = Z_OBJ_CURSORID(object); zend_object_std_dtor(&intern->std); + + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } } /* }}} */ static zend_object* php_phongo_cursorid_create_object(zend_class_entry* class_type) /* {{{ */ @@ -193,24 +259,16 @@ static zend_object* php_phongo_cursorid_create_object(zend_class_entry* class_ty static HashTable* php_phongo_cursorid_get_debug_info(phongo_compat_object_handler_type* object, int* is_temp) /* {{{ */ { - php_phongo_cursorid_t* intern; - zval retval = ZVAL_STATIC_INIT; - *is_temp = 1; - intern = Z_OBJ_CURSORID(PHONGO_COMPAT_GET_OBJ(object)); - - array_init(&retval); - -#if SIZEOF_ZEND_LONG == 4 - ADD_ASSOC_INT64_AS_STRING(&retval, "id", intern->id); -#else - ADD_ASSOC_LONG_EX(&retval, "id", intern->id); -#endif - - return Z_ARRVAL(retval); + return php_phongo_cursorid_get_properties_hash(object, true); } /* }}} */ /* }}} */ +static HashTable* php_phongo_cursorid_get_properties(phongo_compat_object_handler_type* object) /* {{{ */ +{ + return php_phongo_cursorid_get_properties_hash(object, false); +} /* }}} */ + void php_phongo_cursorid_init_ce(INIT_FUNC_ARGS) /* {{{ */ { zend_class_entry ce; @@ -224,6 +282,7 @@ void php_phongo_cursorid_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_cursorid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_cursorid.get_debug_info = php_phongo_cursorid_get_debug_info; + php_phongo_handler_cursorid.get_properties = php_phongo_cursorid_get_properties; php_phongo_handler_cursorid.free_obj = php_phongo_cursorid_free_object; php_phongo_handler_cursorid.offset = XtOffsetOf(php_phongo_cursorid_t, std); } /* }}} */ diff --git a/tests/cursorid/cursorid-001.phpt b/tests/cursorid/cursorid-001.phpt index e1643490e..34cfbbc3e 100644 --- a/tests/cursorid/cursorid-001.phpt +++ b/tests/cursorid/cursorid-001.phpt @@ -1,5 +1,5 @@ --TEST-- -MongoDB\Driver\CursorID BSON serialization +MongoDB\Driver\CursorId BSON serialization --SKIPIF-- diff --git a/tests/cursorid/cursorid-002.phpt b/tests/cursorid/cursorid-002.phpt index 7143a756f..1ca48ad39 100644 --- a/tests/cursorid/cursorid-002.phpt +++ b/tests/cursorid/cursorid-002.phpt @@ -1,5 +1,5 @@ --TEST-- -MongoDB\Driver\CursorID BSON serialization for killCursors command +MongoDB\Driver\CursorId BSON serialization for killCursors command --SKIPIF-- diff --git a/tests/cursorid/cursorid-debug-001.phpt b/tests/cursorid/cursorid-debug-001.phpt new file mode 100644 index 000000000..c08c99cff --- /dev/null +++ b/tests/cursorid/cursorid-debug-001.phpt @@ -0,0 +1,20 @@ +--TEST-- +MongoDB\Driver\CursorId debug output +--FILE-- + +===DONE=== + +--EXPECTF-- +object(MongoDB\Driver\CursorId)#%d (%d) { + ["id"]=> + %rint\(|string\(19\) "|%r7250031947823432848%r"|\)%r +} +===DONE=== diff --git a/tests/cursorid/cursorid-debug-002.phpt b/tests/cursorid/cursorid-debug-002.phpt new file mode 100644 index 000000000..6591a22ca --- /dev/null +++ b/tests/cursorid/cursorid-debug-002.phpt @@ -0,0 +1,22 @@ +--TEST-- +MongoDB\Driver\CursorId debug output on 32-bit platform +--SKIPIF-- + +--FILE-- + +===DONE=== + +--EXPECTF-- +object(MongoDB\Driver\CursorId)#%d (%d) { + ["id"]=> + string(19) "7250031947823432848" +} +===DONE=== diff --git a/tests/cursorid/cursorid-debug-003.phpt b/tests/cursorid/cursorid-debug-003.phpt new file mode 100644 index 000000000..2ff1b6448 --- /dev/null +++ b/tests/cursorid/cursorid-debug-003.phpt @@ -0,0 +1,22 @@ +--TEST-- +MongoDB\Driver\CursorId debug output on 64-bit platform +--SKIPIF-- + +--FILE-- + +===DONE=== + +--EXPECTF-- +object(MongoDB\Driver\CursorId)#%d (%d) { + ["id"]=> + int(7250031947823432848) +} +===DONE=== diff --git a/tests/cursorid/cursorid-serialization-001.phpt b/tests/cursorid/cursorid-serialization-001.phpt index 4bd6b291c..d1fb6668a 100644 --- a/tests/cursorid/cursorid-serialization-001.phpt +++ b/tests/cursorid/cursorid-serialization-001.phpt @@ -1,5 +1,5 @@ --TEST-- -MongoDB\Driver\CursorID serialization +MongoDB\Driver\CursorId serialization --FILE-- '7250031947823432848', +])); +echo "\n"; + +?> +===DONE=== + +--EXPECT-- +MongoDB\Driver\CursorId::__set_state(array( + 'id' => '7250031947823432848', +)) +===DONE=== diff --git a/tests/cursorid/cursorid-set_state_error-001.phpt b/tests/cursorid/cursorid-set_state_error-001.phpt new file mode 100644 index 000000000..863940589 --- /dev/null +++ b/tests/cursorid/cursorid-set_state_error-001.phpt @@ -0,0 +1,18 @@ +--TEST-- +MongoDB\Driver\CursorId::__set_state() requires "id" string field +--FILE-- + 0]); +}, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n"; + +?> +===DONE=== + +--EXPECT-- +OK: Got MongoDB\Driver\Exception\InvalidArgumentException +MongoDB\Driver\CursorId initialization requires "id" string field +===DONE=== diff --git a/tests/cursorid/cursorid-tostring-001.phpt b/tests/cursorid/cursorid-tostring-001.phpt new file mode 100644 index 000000000..7625f3d58 --- /dev/null +++ b/tests/cursorid/cursorid-tostring-001.phpt @@ -0,0 +1,15 @@ +--TEST-- +MongoDB\Driver\CursorId::__toString() +--FILE-- + +===DONE=== + +--EXPECT-- +string(19) "7250031947823432848" +===DONE=== diff --git a/tests/cursorid/cursorid-var_export-001.phpt b/tests/cursorid/cursorid-var_export-001.phpt new file mode 100644 index 000000000..e4ba0b817 --- /dev/null +++ b/tests/cursorid/cursorid-var_export-001.phpt @@ -0,0 +1,19 @@ +--TEST-- +MongoDB\Driver\CursorId: var_export() +--FILE-- + +===DONE=== + +--EXPECT-- +MongoDB\Driver\CursorId::__set_state(array( + 'id' => '7250031947823432848', +)) +===DONE===