Skip to content

Commit c780a27

Browse files
committed
PHPC-1027: Introduce classes for deprecated BSON types (Undefined)
1 parent a081085 commit c780a27

17 files changed

+344
-67
lines changed

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ if test "$MONGODB" != "no"; then
174174
src/BSON/Timestamp.c \
175175
src/BSON/TimestampInterface.c \
176176
src/BSON/Type.c \
177+
src/BSON/Undefined.c \
177178
src/BSON/Unserializable.c \
178179
src/BSON/UTCDateTime.c \
179180
src/BSON/UTCDateTimeInterface.c \

config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ if (PHP_MONGODB != "no") {
8484

8585
EXTENSION("mongodb", "php_phongo.c phongo_compat.c", null, PHP_MONGODB_CFLAGS);
8686
ADD_SOURCES(configure_module_dirname + "/src", "bson.c bson-encode.c", "mongodb");
87-
ADD_SOURCES(configure_module_dirname + "/src/BSON", "Binary.c BinaryInterface.c Decimal128.c Decimal128Interface.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Timestamp.c TimestampInterface.c Type.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c", "mongodb");
87+
ADD_SOURCES(configure_module_dirname + "/src/BSON", "Binary.c BinaryInterface.c Decimal128.c Decimal128Interface.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c", "mongodb");
8888
ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "BulkWrite.c Command.c Cursor.c CursorId.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c", "mongodb");
8989
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c ConnectionException.c ConnectionTimeoutException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c", "mongodb");
9090
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c Subscriber.c functions.c", "mongodb");

php_phongo.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,7 @@ PHP_MINIT_FUNCTION(mongodb)
26552655
php_phongo_persistable_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26562656
php_phongo_regex_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26572657
php_phongo_timestamp_init_ce(INIT_FUNC_ARGS_PASSTHRU);
2658+
php_phongo_undefined_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26582659
php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26592660

26602661
php_phongo_bulkwrite_init_ce(INIT_FUNC_ARGS_PASSTHRU);

php_phongo_classes.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ static inline php_phongo_regex_t* php_regex_fetch_object(zend_object *obj) {
8888
static inline php_phongo_timestamp_t* php_timestamp_fetch_object(zend_object *obj) {
8989
return (php_phongo_timestamp_t *)((char *)obj - XtOffsetOf(php_phongo_timestamp_t, std));
9090
}
91+
static inline php_phongo_undefined_t* php_undefined_fetch_object(zend_object *obj) {
92+
return (php_phongo_undefined_t *)((char *)obj - XtOffsetOf(php_phongo_undefined_t, std));
93+
}
9194
static inline php_phongo_utcdatetime_t* php_utcdatetime_fetch_object(zend_object *obj) {
9295
return (php_phongo_utcdatetime_t *)((char *)obj - XtOffsetOf(php_phongo_utcdatetime_t, std));
9396
}
@@ -122,6 +125,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
122125
# define Z_OBJECTID_OBJ_P(zv) (php_objectid_fetch_object(Z_OBJ_P(zv)))
123126
# define Z_REGEX_OBJ_P(zv) (php_regex_fetch_object(Z_OBJ_P(zv)))
124127
# define Z_TIMESTAMP_OBJ_P(zv) (php_timestamp_fetch_object(Z_OBJ_P(zv)))
128+
# define Z_UNDEFINED_OBJ_P(zv) (php_undefined_fetch_object(Z_OBJ_P(zv)))
125129
# define Z_UTCDATETIME_OBJ_P(zv) (php_utcdatetime_fetch_object(Z_OBJ_P(zv)))
126130
# define Z_COMMANDFAILEDEVENT_OBJ_P(zv) (php_commandfailedevent_fetch_object(Z_OBJ_P(zv)))
127131
# define Z_COMMANDSTARTEDEVENT_OBJ_P(zv) (php_commandstartedevent_fetch_object(Z_OBJ_P(zv)))
@@ -148,6 +152,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
148152
# define Z_OBJ_OBJECTID(zo) (php_objectid_fetch_object(zo))
149153
# define Z_OBJ_REGEX(zo) (php_regex_fetch_object(zo))
150154
# define Z_OBJ_TIMESTAMP(zo) (php_timestamp_fetch_object(zo))
155+
# define Z_OBJ_UNDEFINED(zo) (php_undefined_fetch_object(zo))
151156
# define Z_OBJ_UTCDATETIME(zo) (php_utcdatetime_fetch_object(zo))
152157
# define Z_OBJ_COMMANDFAILEDEVENT(zo) (php_commandfailedevent_fetch_object(zo))
153158
# define Z_OBJ_COMMANDSTARTEDEVENT(zo) (php_commandstartedevent_fetch_object(zo))
@@ -176,6 +181,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
176181
# define Z_OBJECTID_OBJ_P(zv) ((php_phongo_objectid_t *)zend_object_store_get_object(zv TSRMLS_CC))
177182
# define Z_REGEX_OBJ_P(zv) ((php_phongo_regex_t *)zend_object_store_get_object(zv TSRMLS_CC))
178183
# define Z_TIMESTAMP_OBJ_P(zv) ((php_phongo_timestamp_t *)zend_object_store_get_object(zv TSRMLS_CC))
184+
# define Z_UNDEFINED_OBJ_P(zv) ((php_phongo_undefined_t *)zend_object_store_get_object(zv TSRMLS_CC))
179185
# define Z_UTCDATETIME_OBJ_P(zv) ((php_phongo_utcdatetime_t *)zend_object_store_get_object(zv TSRMLS_CC))
180186
# define Z_COMMANDFAILEDEVENT_OBJ_P(zv) ((php_phongo_commandfailedevent_t *)zend_object_store_get_object(zv TSRMLS_CC))
181187
# define Z_COMMANDSTARTEDEVENT_OBJ_P(zv) ((php_phongo_commandstartedevent_t *)zend_object_store_get_object(zv TSRMLS_CC))
@@ -202,6 +208,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
202208
# define Z_OBJ_OBJECTID(zo) ((php_phongo_objectid_t *)zo)
203209
# define Z_OBJ_REGEX(zo) ((php_phongo_regex_t *)zo)
204210
# define Z_OBJ_TIMESTAMP(zo) ((php_phongo_timestamp_t *)zo)
211+
# define Z_OBJ_UNDEFINED(zo) ((php_phongo_undefined_t *)zo)
205212
# define Z_OBJ_UTCDATETIME(zo) ((php_phongo_utcdatetime_t *)zo)
206213
# define Z_OBJ_COMMANDFAILEDEVENT(zo) ((php_phongo_commandfailedevent_t *)zo)
207214
# define Z_OBJ_COMMANDSTARTEDEVENT(zo) ((php_phongo_commandstartedevent_t *)zo)
@@ -254,6 +261,7 @@ extern zend_class_entry *php_phongo_minkey_ce;
254261
extern zend_class_entry *php_phongo_objectid_ce;
255262
extern zend_class_entry *php_phongo_regex_ce;
256263
extern zend_class_entry *php_phongo_timestamp_ce;
264+
extern zend_class_entry *php_phongo_undefined_ce;
257265
extern zend_class_entry *php_phongo_utcdatetime_ce;
258266

259267
extern zend_class_entry *php_phongo_binary_interface_ce;
@@ -283,8 +291,9 @@ extern void php_phongo_regex_init_ce(INIT_FUNC_ARGS);
283291
extern void php_phongo_serializable_init_ce(INIT_FUNC_ARGS);
284292
extern void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS);
285293
extern void php_phongo_type_init_ce(INIT_FUNC_ARGS);
286-
extern void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS);
294+
extern void php_phongo_undefined_init_ce(INIT_FUNC_ARGS);
287295
extern void php_phongo_unserializable_init_ce(INIT_FUNC_ARGS);
296+
extern void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS);
288297

289298
extern void php_phongo_binary_interface_init_ce(INIT_FUNC_ARGS);
290299
extern void php_phongo_decimal128_interface_init_ce(INIT_FUNC_ARGS);

php_phongo_structs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ typedef struct {
201201
PHONGO_ZEND_OBJECT_POST
202202
} php_phongo_timestamp_t;
203203

204+
typedef struct {
205+
PHONGO_ZEND_OBJECT_PRE
206+
PHONGO_ZEND_OBJECT_POST
207+
} php_phongo_undefined_t;
208+
204209
typedef struct {
205210
PHONGO_ZEND_OBJECT_PRE
206211
bool initialized;

src/BSON/Undefined.c

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright 2014-2017 MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifdef HAVE_CONFIG_H
18+
# include "config.h"
19+
#endif
20+
21+
#include <php.h>
22+
#include <Zend/zend_interfaces.h>
23+
#include <ext/standard/php_var.h>
24+
#if PHP_VERSION_ID >= 70000
25+
# include <zend_smart_str.h>
26+
#else
27+
# include <ext/standard/php_smart_str.h>
28+
#endif
29+
30+
#include "phongo_compat.h"
31+
#include "php_phongo.h"
32+
33+
zend_class_entry *php_phongo_undefined_ce;
34+
35+
/* {{{ proto string MongoDB\BSON\Undefined::__toString()
36+
Return the empty string. */
37+
static PHP_METHOD(Undefined, __toString)
38+
{
39+
PHONGO_RETURN_STRINGL("", 0);
40+
} /* }}} */
41+
42+
/* {{{ proto array MongoDB\BSON\Undefined::jsonSerialize()
43+
*/
44+
static PHP_METHOD(Undefined, jsonSerialize)
45+
{
46+
if (zend_parse_parameters_none() == FAILURE) {
47+
return;
48+
}
49+
50+
array_init_size(return_value, 1);
51+
ADD_ASSOC_BOOL_EX(return_value, "$undefined", 1);
52+
} /* }}} */
53+
54+
/* {{{ proto string MongoDB\BSON\Undefined::serialize()
55+
*/
56+
static PHP_METHOD(Undefined, serialize)
57+
{
58+
PHONGO_RETURN_STRING("");
59+
} /* }}} */
60+
61+
/* {{{ proto void MongoDB\BSON\Undefined::unserialize(string $serialized)
62+
*/
63+
static PHP_METHOD(Undefined, unserialize)
64+
{
65+
zend_error_handling error_handling;
66+
char *serialized;
67+
phongo_zpp_char_len serialized_len;
68+
69+
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
70+
71+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &serialized_len) == FAILURE) {
72+
zend_restore_error_handling(&error_handling TSRMLS_CC);
73+
return;
74+
}
75+
zend_restore_error_handling(&error_handling TSRMLS_CC);
76+
} /* }}} */
77+
78+
/* {{{ MongoDB\BSON\Undefined function entries */
79+
ZEND_BEGIN_ARG_INFO_EX(ai_Undefined_unserialize, 0, 0, 1)
80+
ZEND_ARG_INFO(0, serialized)
81+
ZEND_END_ARG_INFO()
82+
83+
ZEND_BEGIN_ARG_INFO_EX(ai_Undefined_void, 0, 0, 0)
84+
ZEND_END_ARG_INFO()
85+
86+
static zend_function_entry php_phongo_undefined_me[] = {
87+
/* __set_state intentionally missing */
88+
PHP_ME(Undefined, __toString, ai_Undefined_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
89+
PHP_ME(Undefined, jsonSerialize, ai_Undefined_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
90+
PHP_ME(Undefined, serialize, ai_Undefined_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
91+
PHP_ME(Undefined, unserialize, ai_Undefined_unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
92+
ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Undefined_void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
93+
PHP_FE_END
94+
};
95+
/* }}} */
96+
97+
/* {{{ MongoDB\BSON\Undefined object handlers */
98+
static zend_object_handlers php_phongo_handler_undefined;
99+
100+
static void php_phongo_undefined_free_object(phongo_free_object_arg *object TSRMLS_DC) /* {{{ */
101+
{
102+
php_phongo_undefined_t *intern = Z_OBJ_UNDEFINED(object);
103+
104+
zend_object_std_dtor(&intern->std TSRMLS_CC);
105+
106+
#if PHP_VERSION_ID < 70000
107+
efree(intern);
108+
#endif
109+
} /* }}} */
110+
111+
static phongo_create_object_retval php_phongo_undefined_create_object(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
112+
{
113+
php_phongo_undefined_t *intern = NULL;
114+
115+
intern = PHONGO_ALLOC_OBJECT_T(php_phongo_undefined_t, class_type);
116+
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
117+
object_properties_init(&intern->std, class_type);
118+
119+
#if PHP_VERSION_ID >= 70000
120+
intern->std.handlers = &php_phongo_handler_undefined;
121+
122+
return &intern->std;
123+
#else
124+
{
125+
zend_object_value retval;
126+
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, php_phongo_undefined_free_object, NULL TSRMLS_CC);
127+
retval.handlers = &php_phongo_handler_undefined;
128+
129+
return retval;
130+
}
131+
#endif
132+
} /* }}} */
133+
/* }}} */
134+
135+
void php_phongo_undefined_init_ce(INIT_FUNC_ARGS) /* {{{ */
136+
{
137+
zend_class_entry ce;
138+
139+
INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Undefined", php_phongo_undefined_me);
140+
php_phongo_undefined_ce = zend_register_internal_class(&ce TSRMLS_CC);
141+
php_phongo_undefined_ce->create_object = php_phongo_undefined_create_object;
142+
PHONGO_CE_FINAL(php_phongo_undefined_ce);
143+
144+
zend_class_implements(php_phongo_undefined_ce TSRMLS_CC, 1, php_phongo_json_serializable_ce);
145+
zend_class_implements(php_phongo_undefined_ce TSRMLS_CC, 1, php_phongo_type_ce);
146+
zend_class_implements(php_phongo_undefined_ce TSRMLS_CC, 1, zend_ce_serializable);
147+
148+
memcpy(&php_phongo_handler_undefined, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
149+
#if PHP_VERSION_ID >= 70000
150+
php_phongo_handler_undefined.free_obj = php_phongo_undefined_free_object;
151+
php_phongo_handler_undefined.offset = XtOffsetOf(php_phongo_undefined_t, std);
152+
#endif
153+
} /* }}} */
154+
155+
/*
156+
* Local variables:
157+
* tab-width: 4
158+
* c-basic-offset: 4
159+
* End:
160+
* vim600: noet sw=4 ts=4 fdm=marker
161+
* vim<600: noet sw=4 ts=4
162+
*/

src/bson-encode.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,13 @@ static void php_phongo_bson_append_object(bson_t *bson, php_phongo_bson_flags_t
270270
return;
271271
}
272272

273+
/* Deprecated types */
274+
if (instanceof_function(Z_OBJCE_P(object), php_phongo_undefined_ce TSRMLS_CC)) {
275+
mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding Undefined");
276+
bson_append_undefined(bson, key, key_len);
277+
return;
278+
}
279+
273280
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Unexpected %s instance: %s", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(object)->name));
274281
return;
275282
} else {

src/bson.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,30 @@ static bool php_phongo_bson_visit_binary(const bson_iter_t *iter ARG_UNUSED, con
131131

132132
static bool php_phongo_bson_visit_undefined(const bson_iter_t *iter, const char *key, void *data) /* {{{ */
133133
{
134-
mongoc_log(MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_DOMAIN, "Detected unsupported BSON type 0x06 (undefined) for fieldname \"%s\"", key);
134+
zval *retval = PHONGO_BSON_STATE_ZCHILD(data);
135+
#if PHP_VERSION_ID >= 70000
136+
zval zchild;
137+
138+
object_init_ex(&zchild, php_phongo_undefined_ce);
139+
140+
if (((php_phongo_bson_state *)data)->is_visiting_array) {
141+
add_next_index_zval(retval, &zchild);
142+
} else {
143+
ADD_ASSOC_ZVAL(retval, key, &zchild);
144+
}
145+
#else
146+
zval *zchild = NULL;
147+
TSRMLS_FETCH();
148+
149+
MAKE_STD_ZVAL(zchild);
150+
object_init_ex(zchild, php_phongo_undefined_ce);
151+
152+
if (((php_phongo_bson_state *)data)->is_visiting_array) {
153+
add_next_index_zval(retval, zchild);
154+
} else {
155+
ADD_ASSOC_ZVAL(retval, key, zchild);
156+
}
157+
#endif
135158

136159
return false;
137160
} /* }}} */

tests/bson/bson-toPHP_error-005.phpt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ MongoDB\BSON\toPHP(): BSON decoding ignores unsupported BSON types
33
--FILE--
44
<?php
55
$tests = [
6-
pack('VCa*xx', 10, 0x06, 'foo'), // undefined
76
pack('VCa*xVa*xx12x', 37, 0x0C, 'foo', 11, 'collection'), // DBPointer
87
pack('VCa*xVa*xx', 18, 0x0E, 'foo', 4, 'bar'), // symbol
98
];
@@ -18,9 +17,6 @@ ini_set('mongodb.debug', 'off');
1817
===DONE===
1918
<?php exit(0); ?>
2019
--EXPECTF--
21-
[%s] PHONGO-BSON: WARNING > Detected unsupported BSON type 0x06 (undefined) for fieldname "foo"
22-
object(stdClass)#%d (%d) {
23-
}
2420
[%s] PHONGO-BSON: WARNING > Detected unsupported BSON type 0x0C (DBPointer) for fieldname "foo"
2521
object(stdClass)#%d (%d) {
2622
}

tests/bson/bson-toPHP_error-006.phpt

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)