@@ -90,6 +90,49 @@ static int php_phongo_is_array_or_document(zval* val)
90
90
return IS_ARRAY ;
91
91
}
92
92
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
+
93
136
/* Appends the array or object argument to the BSON document.
94
137
*
95
138
* 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
134
177
return ;
135
178
}
136
179
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
160
182
zval_ptr_dtor (& obj_data );
161
-
162
183
return ;
163
184
}
164
185
@@ -474,19 +495,12 @@ static void php_phongo_zval_to_bson_internal(zval* data, php_phongo_field_path*
474
495
return ;
475
496
}
476
497
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
+ }
489
502
503
+ if (instanceof_function (Z_OBJCE_P (data ), php_phongo_persistable_ce )) {
490
504
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 );
491
505
/* Ensure that we ignore an existing key with the same name
492
506
* 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*
500
514
goto done ;
501
515
}
502
516
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
-
516
517
ht_data = HASH_OF (& obj_data );
517
518
518
519
break ;
0 commit comments