Skip to content

Commit 3c01dd2

Browse files
committed
Extract utility function to check return types of bsonSerialize()
1 parent 1516d3b commit 3c01dd2

File tree

1 file changed

+50
-49
lines changed

1 file changed

+50
-49
lines changed

src/phongo_bson_encode.c

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,49 @@ static int php_phongo_is_array_or_document(zval* val)
9090
return IS_ARRAY;
9191
}
9292

93+
/* Checks the return type of a bsonSerialize() method. Returns true on
94+
* success; otherwise, throws an exception and returns false.
95+
*
96+
* TODO: obsolete once PHP 8.0+ is required and tentative return type is enforced.
97+
*/
98+
static inline bool phongo_check_bson_serialize_return_type(zval* retval, zend_class_entry* ce)
99+
{
100+
if (instanceof_function(ce, php_phongo_persistable_ce)) {
101+
// Instances of Persistable must return an array, stdClass, or MongoDB\BSON\Document
102+
if (
103+
Z_TYPE_P(retval) != IS_ARRAY && !(Z_TYPE_P(retval) == IS_OBJECT && (instanceof_function(Z_OBJCE_P(retval), zend_standard_class_def) || instanceof_function(Z_OBJCE_P(retval), php_phongo_document_ce)))) {
104+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE,
105+
"Expected %s::%s() to return an array, stdClass, or %s, %s given",
106+
ZSTR_VAL(ce->name),
107+
BSON_SERIALIZE_FUNC_NAME,
108+
ZSTR_VAL(php_phongo_document_ce->name),
109+
PHONGO_ZVAL_CLASS_OR_TYPE_NAME(*retval));
110+
return false;
111+
}
112+
113+
return true;
114+
}
115+
116+
if (instanceof_function(ce, php_phongo_serializable_ce)) {
117+
// Instances of Serializable must return an array, stdClass, MongoDB\BSON\Document, or MongoDB\BSON\PackedArray
118+
if (
119+
Z_TYPE_P(retval) != IS_ARRAY && !(Z_TYPE_P(retval) == IS_OBJECT && (instanceof_function(Z_OBJCE_P(retval), zend_standard_class_def) || instanceof_function(Z_OBJCE_P(retval), php_phongo_document_ce) || instanceof_function(Z_OBJCE_P(retval), php_phongo_packedarray_ce)))) {
120+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE,
121+
"Expected %s::%s() to return an array, stdClass, %s, or %s, %s given",
122+
ZSTR_VAL(ce->name),
123+
BSON_SERIALIZE_FUNC_NAME,
124+
ZSTR_VAL(php_phongo_document_ce->name),
125+
ZSTR_VAL(php_phongo_packedarray_ce->name),
126+
PHONGO_ZVAL_CLASS_OR_TYPE_NAME(*retval));
127+
return false;
128+
}
129+
130+
return true;
131+
}
132+
133+
return false;
134+
}
135+
93136
/* Appends the array or object argument to the BSON document.
94137
*
95138
* For instances of MongoDB\BSON\Document, raw BSON data is appended as document.
@@ -134,31 +177,9 @@ static void php_phongo_bson_append_object(bson_t* bson, php_phongo_field_path* f
134177
return;
135178
}
136179

137-
// TODO PHP_VERSION_ID < 80000: obsolete once the tentative return type of bsonSerialize() is enforced
138-
if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce)) {
139-
if (
140-
Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && (instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def) || instanceof_function(Z_OBJCE(obj_data), php_phongo_document_ce)))) {
141-
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE,
142-
"Expected %s::%s() to return an array, stdClass, or %s, %s given",
143-
ZSTR_VAL(Z_OBJCE_P(object)->name),
144-
BSON_SERIALIZE_FUNC_NAME,
145-
ZSTR_VAL(php_phongo_document_ce->name),
146-
PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
147-
zval_ptr_dtor(&obj_data);
148-
149-
return;
150-
}
151-
} else if (
152-
Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && (instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def) || instanceof_function(Z_OBJCE(obj_data), php_phongo_document_ce) || instanceof_function(Z_OBJCE(obj_data), php_phongo_packedarray_ce)))) {
153-
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE,
154-
"Expected %s::%s() to return an array, stdClass, %s, or %s, %s given",
155-
ZSTR_VAL(Z_OBJCE_P(object)->name),
156-
BSON_SERIALIZE_FUNC_NAME,
157-
ZSTR_VAL(php_phongo_document_ce->name),
158-
ZSTR_VAL(php_phongo_packedarray_ce->name),
159-
PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
180+
if (!phongo_check_bson_serialize_return_type(&obj_data, Z_OBJCE_P(object))) {
181+
// Exception already thrown
160182
zval_ptr_dtor(&obj_data);
161-
162183
return;
163184
}
164185

@@ -474,19 +495,12 @@ static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path*
474495
return;
475496
}
476497

477-
if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce)) {
478-
if (Z_TYPE(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE(obj_data), php_phongo_packedarray_ce)) {
479-
phongo_throw_exception(
480-
PHONGO_ERROR_UNEXPECTED_VALUE,
481-
"Expected %s::%s() to return an array, stdClass, or %s, %s given",
482-
ZSTR_VAL(Z_OBJCE_P(data)->name),
483-
BSON_SERIALIZE_FUNC_NAME,
484-
ZSTR_VAL(php_phongo_document_ce->name),
485-
PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
486-
487-
goto cleanup;
488-
}
498+
if (!phongo_check_bson_serialize_return_type(&obj_data, Z_OBJCE_P(data))) {
499+
// Exception already thrown
500+
goto cleanup;
501+
}
489502

503+
if (instanceof_function(Z_OBJCE_P(data), php_phongo_persistable_ce)) {
490504
bson_append_binary(bson, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t*) Z_OBJCE_P(data)->name->val, Z_OBJCE_P(data)->name->len);
491505
/* Ensure that we ignore an existing key with the same name
492506
* if one exists in the bsonSerialize() return value. */
@@ -500,19 +514,6 @@ static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path*
500514
goto done;
501515
}
502516

503-
if (Z_TYPE(obj_data) != IS_ARRAY && !(Z_TYPE(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE(obj_data), zend_standard_class_def))) {
504-
phongo_throw_exception(
505-
PHONGO_ERROR_UNEXPECTED_VALUE,
506-
"Expected %s::%s() to return an array, stdClass, %s, or %s, %s given",
507-
ZSTR_VAL(Z_OBJCE_P(data)->name),
508-
BSON_SERIALIZE_FUNC_NAME,
509-
ZSTR_VAL(php_phongo_document_ce->name),
510-
ZSTR_VAL(php_phongo_packedarray_ce->name),
511-
PHONGO_ZVAL_CLASS_OR_TYPE_NAME(obj_data));
512-
513-
goto cleanup;
514-
}
515-
516517
ht_data = HASH_OF(&obj_data);
517518

518519
break;

0 commit comments

Comments
 (0)