From 178404ac1363eec5ec88de0995a7579013bc84da Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Thu, 16 Apr 2026 13:52:08 +0200 Subject: [PATCH 1/3] PHPC-2699: Add readonly properties to WriteConcernError class --- src/MongoDB/WriteConcernError.c | 26 +++++++------------ src/MongoDB/WriteConcernError.stub.php | 6 +++++ src/MongoDB/WriteConcernError_arginfo.h | 16 +++++++++++- .../writeconcernerror-getcode-001.phpt | 2 ++ .../writeconcernerror-getinfo-001.phpt | 12 +++++++++ .../writeconcernerror-getmessage-001.phpt | 2 ++ 6 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/MongoDB/WriteConcernError.c b/src/MongoDB/WriteConcernError.c index 869dbaa07..527a6e891 100644 --- a/src/MongoDB/WriteConcernError.c +++ b/src/MongoDB/WriteConcernError.c @@ -92,25 +92,16 @@ static zend_object* phongo_writeconcernerror_create_object(zend_class_entry* cla return &intern->std; } -static HashTable* phongo_writeconcernerror_get_debug_info(zend_object* object, int* is_temp) +static void phongo_writeconcernerror_update_properties(phongo_writeconcernerror_t* intern) { - PHONGO_INTERN_FROM_Z_OBJ(writeconcernerror, object); - - zval retval = ZVAL_STATIC_INIT; - - *is_temp = 1; + zend_update_property_string(phongo_writeconcernerror_ce, &intern->std, ZEND_STRL("message"), intern->message ? intern->message : ""); + zend_update_property_long(phongo_writeconcernerror_ce, &intern->std, ZEND_STRL("code"), intern->code); - array_init_size(&retval, 3); - ADD_ASSOC_STRING(&retval, "message", intern->message ? intern->message : ""); - ADD_ASSOC_LONG_EX(&retval, "code", intern->code); if (!Z_ISUNDEF(intern->info)) { - Z_ADDREF(intern->info); - ADD_ASSOC_ZVAL_EX(&retval, "info", &intern->info); + zend_update_property(phongo_writeconcernerror_ce, &intern->std, ZEND_STRL("info"), &intern->info); } else { - ADD_ASSOC_NULL_EX(&retval, "info"); + zend_update_property_null(phongo_writeconcernerror_ce, &intern->std, ZEND_STRL("info")); } - - return Z_ARRVAL(retval); } void phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS) @@ -119,9 +110,8 @@ void phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS) phongo_writeconcernerror_ce->create_object = phongo_writeconcernerror_create_object; memcpy(&phongo_handler_writeconcernerror, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - phongo_handler_writeconcernerror.get_debug_info = phongo_writeconcernerror_get_debug_info; - phongo_handler_writeconcernerror.free_obj = phongo_writeconcernerror_free_object; - phongo_handler_writeconcernerror.offset = XtOffsetOf(phongo_writeconcernerror_t, std); + phongo_handler_writeconcernerror.free_obj = phongo_writeconcernerror_free_object; + phongo_handler_writeconcernerror.offset = XtOffsetOf(phongo_writeconcernerror_t, std); } /* Initializes a new WriteConcernError in return_value using the BSON document. @@ -166,5 +156,7 @@ bool phongo_writeconcernerror_init(zval* return_value, const bson_t* bson) } } + phongo_writeconcernerror_update_properties(intern); + return true; } diff --git a/src/MongoDB/WriteConcernError.stub.php b/src/MongoDB/WriteConcernError.stub.php index cfbbe3ffa..467f8854a 100644 --- a/src/MongoDB/WriteConcernError.stub.php +++ b/src/MongoDB/WriteConcernError.stub.php @@ -12,6 +12,12 @@ final class WriteConcernError { final private function __construct() {} + public readonly string $message; + + public readonly int $code; + + public readonly object|null $info; + final public function getCode(): int {} final public function getInfo(): ?object {} diff --git a/src/MongoDB/WriteConcernError_arginfo.h b/src/MongoDB/WriteConcernError_arginfo.h index f7cc409d2..78c77d7ec 100644 --- a/src/MongoDB/WriteConcernError_arginfo.h +++ b/src/MongoDB/WriteConcernError_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c924ca635d5f5a97ca918b59ca313ac77aae075c */ + * Stub hash: f215bf4fccd5214875964d0f557ff2e923b61812 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_MongoDB_Driver_WriteConcernError___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -38,5 +38,19 @@ static zend_class_entry *register_class_MongoDB_Driver_WriteConcernError(void) class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NOT_SERIALIZABLE; #endif + zval property_message_default_value; + ZVAL_UNDEF(&property_message_default_value); + zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_MESSAGE), &property_message_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + + zval property_code_default_value; + ZVAL_UNDEF(&property_code_default_value); + zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_CODE), &property_code_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + + zval property_info_default_value; + ZVAL_UNDEF(&property_info_default_value); + zend_string *property_info_name = zend_string_init("info", sizeof("info") - 1, 1); + zend_declare_typed_property(class_entry, property_info_name, &property_info_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_OBJECT|MAY_BE_NULL)); + zend_string_release(property_info_name); + return class_entry; } diff --git a/tests/writeConcernError/writeconcernerror-getcode-001.phpt b/tests/writeConcernError/writeconcernerror-getcode-001.phpt index fb4c682e9..5a74763f6 100644 --- a/tests/writeConcernError/writeconcernerror-getcode-001.phpt +++ b/tests/writeConcernError/writeconcernerror-getcode-001.phpt @@ -18,6 +18,7 @@ try { $manager->executeBulkWrite(NS, $bulk, ['writeConcern' => new MongoDB\Driver\WriteConcern(12)]); } catch(MongoDB\Driver\Exception\BulkWriteException $e) { var_dump($e->getWriteResult()->getWriteConcernError()->getCode()); + var_dump($e->getWriteResult()->getWriteConcernError()->code); } ?> @@ -25,4 +26,5 @@ try { --EXPECT-- int(100) +int(100) ===DONE=== diff --git a/tests/writeConcernError/writeconcernerror-getinfo-001.phpt b/tests/writeConcernError/writeconcernerror-getinfo-001.phpt index d65966b79..8d947d8c9 100644 --- a/tests/writeConcernError/writeconcernerror-getinfo-001.phpt +++ b/tests/writeConcernError/writeconcernerror-getinfo-001.phpt @@ -45,6 +45,7 @@ try { $server->executeBulkWrite(NS, $bulk); } catch (MongoDB\Driver\Exception\BulkWriteException $e) { var_dump($e->getWriteResult()->getWriteConcernError()->getInfo()); + var_dump($e->getWriteResult()->getWriteConcernError()->info); } ?> @@ -61,4 +62,15 @@ object(stdClass)#%d (%d) { string(14) "clientSupplied" } } +object(stdClass)#%d (%d) { + ["writeConcern"]=> + object(stdClass)#%d (%d) { + ["w"]=> + int(2) + ["wtimeout"]=> + int(0) + ["provenance"]=> + string(14) "clientSupplied" + } +} ===DONE=== diff --git a/tests/writeConcernError/writeconcernerror-getmessage-001.phpt b/tests/writeConcernError/writeconcernerror-getmessage-001.phpt index 27d4e16c1..7b59e9f93 100644 --- a/tests/writeConcernError/writeconcernerror-getmessage-001.phpt +++ b/tests/writeConcernError/writeconcernerror-getmessage-001.phpt @@ -18,6 +18,7 @@ try { $manager->executeBulkWrite(NS, $bulk, ['writeConcern' => new MongoDB\Driver\WriteConcern(12)]); } catch(MongoDB\Driver\Exception\BulkWriteException $e) { var_dump($e->getWriteResult()->getWriteConcernError()->getMessage()); + var_dump($e->getWriteResult()->getWriteConcernError()->message); } ?> @@ -25,4 +26,5 @@ try { --EXPECT-- string(29) "Not enough data-bearing nodes" +string(29) "Not enough data-bearing nodes" ===DONE=== From 9f872bdc526e5c21666af77c338cf387b0cdaacf Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Thu, 16 Apr 2026 14:00:09 +0200 Subject: [PATCH 2/3] Use properties for classes in test utils --- tests/utils/tools.php | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/utils/tools.php b/tests/utils/tools.php index 1889b228d..091361d9f 100644 --- a/tests/utils/tools.php +++ b/tests/utils/tools.php @@ -713,21 +713,21 @@ function printWriteResult(WriteResult $result, $details = true) { printServer($result->getServer()); - printf("insertedCount: %d\n", $result->getInsertedCount()); - printf("matchedCount: %d\n", $result->getMatchedCount()); - printf("modifiedCount: %d\n", $result->getModifiedCount()); - printf("upsertedCount: %d\n", $result->getUpsertedCount()); - printf("deletedCount: %d\n", $result->getDeletedCount()); + printf("insertedCount: %d\n", $result->insertedCount); + printf("matchedCount: %d\n", $result->matchedCount); + printf("modifiedCount: %d\n", $result->modifiedCount); + printf("upsertedCount: %d\n", $result->upsertedCount); + printf("deletedCount: %d\n", $result->deletedCount); - foreach ($result->getUpsertedIds() as $index => $id) { + foreach ($result->upsertedIds as $index => $id) { printf("upsertedId[%d]: ", $index); var_dump($id); } - $writeConcernError = $result->getWriteConcernError(); + $writeConcernError = $result->writeConcernError; printWriteConcernError($writeConcernError ? $writeConcernError : null, $details); - foreach ($result->getWriteErrors() as $writeError) { + foreach ($result->writeErrors as $writeError) { printWriteError($writeError); } } @@ -737,38 +737,38 @@ function printWriteConcernError(?WriteConcernError $error = null, $details = nul if ($error) { /* This stuff is generated by the server, no need for us to test it */ if (!$details) { - printf("writeConcernError: %s (%d)\n", $error->getMessage(), $error->getCode()); + printf("writeConcernError: %s (%d)\n", $error->message, $error->code); return; } var_dump($error); - printf("writeConcernError.message: %s\n", $error->getMessage()); - printf("writeConcernError.code: %d\n", $error->getCode()); + printf("writeConcernError.message: %s\n", $error->message); + printf("writeConcernError.code: %d\n", $error->code); printf("writeConcernError.info: "); - var_dump($error->getInfo()); + var_dump($error->info); } } function printWriteError(WriteError $error) { var_dump($error); - printf("writeError[%d].message: %s\n", $error->getIndex(), $error->getMessage()); - printf("writeError[%d].code: %d\n", $error->getIndex(), $error->getCode()); + printf("writeError[%d].message: %s\n", $error->index, $error->message); + printf("writeError[%d].code: %d\n", $error->index, $error->code); } function getInsertCount($retval) { - return $retval->getInsertedCount(); + return $retval->insertedCount; } function getModifiedCount($retval) { - return $retval->getModifiedCount(); + return $retval->modifiedCount; } function getDeletedCount($retval) { - return $retval->getDeletedCount(); + return $retval->deletedCount; } function getUpsertedCount($retval) { - return $retval->getUpsertedCount(); + return $retval->usertedCount; } function getWriteErrors($retval) { - return (array)$retval->getWriteErrors(); + return $retval->writeErrors; } function def($arr) { From bac57339e9410d6b34991904834622d5fc45c46b Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Thu, 16 Apr 2026 14:05:35 +0200 Subject: [PATCH 3/3] Update tests/utils/tools.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/utils/tools.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/tools.php b/tests/utils/tools.php index 091361d9f..7906695df 100644 --- a/tests/utils/tools.php +++ b/tests/utils/tools.php @@ -765,7 +765,7 @@ function getDeletedCount($retval) { return $retval->deletedCount; } function getUpsertedCount($retval) { - return $retval->usertedCount; + return $retval->upsertedCount; } function getWriteErrors($retval) { return $retval->writeErrors;