Skip to content

Commit 7d7a48e

Browse files
committed
PHPC-229: Support options array in second parameter of Manager ctor
1 parent 8087ab6 commit 7d7a48e

File tree

6 files changed

+250
-36
lines changed

6 files changed

+250
-36
lines changed

php_phongo.c

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "mongoc-read-prefs-private.h"
3232
#include "mongoc-bulk-operation-private.h"
3333
#include "mongoc-write-concern-private.h"
34+
#include "mongoc-uri-private.h"
3435
#include "mongoc-trace.h"
3536

3637

@@ -1495,41 +1496,62 @@ void php_phongo_cursor_to_zval(zval *retval, php_phongo_cursor_t *cursor) /* {{{
14951496
/* }}} */
14961497

14971498

1498-
mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptions TSRMLS_DC) /* {{{ */
1499+
mongoc_uri_t *php_phongo_make_uri(const char *uri_string, bson_t *options TSRMLS_DC) /* {{{ */
14991500
{
1500-
zval **tmp;
1501-
php_stream_context *ctx;
1502-
const char *mech;
1503-
const mongoc_uri_t *muri;
1504-
mongoc_client_t *client = mongoc_client_new(uri);
1505-
1501+
bson_iter_t iter;
1502+
mongoc_uri_t *uri;
15061503

1507-
ENTRY;
1504+
uri = mongoc_uri_new(uri_string);
1505+
MONGOC_DEBUG("Connection string: '%s'", uri_string);
15081506

1509-
if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "debug", strlen("debug") + 1, (void**)&tmp) == SUCCESS) {
1510-
convert_to_string(*tmp);
1507+
if (options && bson_iter_init(&iter, options)) {
1508+
while (bson_iter_next (&iter)) {
1509+
const char *key = bson_iter_key(&iter);
15111510

1512-
zend_alter_ini_entry_ex((char *)PHONGO_DEBUG_INI, sizeof(PHONGO_DEBUG_INI), Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
1513-
}
1514-
1515-
MONGOC_DEBUG("Creating Manager, phongo-%s[%s] - mongoc-%s, libbson-%s", MONGODB_VERSION_S, MONGODB_STABILITY_S, MONGOC_VERSION_S, BSON_VERSION_S);
1516-
MONGOC_DEBUG("Connecting to '%s'", uri);
1517-
1518-
if (!client) {
1519-
RETURN(false);
1511+
if (mongoc_uri_option_is_bool(key)) {
1512+
mongoc_uri_set_option_as_bool (uri, key, bson_iter_as_bool(&iter));
1513+
}
1514+
else if (mongoc_uri_option_is_int32(key) && BSON_ITER_HOLDS_INT32(&iter)) {
1515+
mongoc_uri_set_option_as_int32 (uri, key, bson_iter_int32 (&iter));
1516+
}
1517+
else if (mongoc_uri_option_is_utf8(key) && BSON_ITER_HOLDS_UTF8(&iter)) {
1518+
mongoc_uri_set_option_as_utf8(uri, key, bson_iter_utf8 (&iter, NULL));
1519+
}
1520+
else if (BSON_ITER_HOLDS_ARRAY(&iter) && !strcasecmp(key, "hosts")) {
1521+
bson_iter_t sub;
1522+
1523+
bson_iter_recurse(&iter, &sub);
1524+
while (bson_iter_next (&sub)) {
1525+
if (BSON_ITER_HOLDS_UTF8(&sub)) {
1526+
mongoc_uri_parse_host(uri, bson_iter_utf8(&sub, NULL));
1527+
}
1528+
}
1529+
}
1530+
else if (BSON_ITER_HOLDS_UTF8(&iter)) {
1531+
const char *value = bson_iter_utf8 (&iter, NULL);
1532+
1533+
if (!strcasecmp(key, "username")) {
1534+
mongoc_uri_set_username(uri, value);
1535+
} else if (!strcasecmp(key, "password")) {
1536+
mongoc_uri_set_password(uri, value);
1537+
} else if (!strcasecmp(key, "database")) {
1538+
mongoc_uri_set_database(uri, value);
1539+
} else if (!strcasecmp(key, "authsource")) {
1540+
mongoc_uri_set_auth_source(uri, value);
1541+
}
1542+
}
1543+
}
15201544
}
15211545

1522-
if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "context", strlen("context") + 1, (void**)&tmp) == SUCCESS) {
1523-
ctx = php_stream_context_from_zval(*tmp, 0);
1524-
} else {
1525-
GET_DEFAULT_CONTEXT();
1526-
}
1527-
muri = mongoc_client_get_uri(client);
1546+
return uri;
1547+
} /* }}} */
15281548

1529-
if (driverOptions && mongoc_uri_get_ssl(muri)) {
1549+
void php_phongo_populate_default_ssl_ctx(php_stream_context *ctx, zval *driverOptions) /* {{{ */
1550+
{
1551+
zval **tmp;
15301552

15311553
#define SET_STRING_CTX(name) \
1532-
if (php_array_exists(driverOptions, name)) { \
1554+
if (driverOptions && php_array_exists(driverOptions, name)) { \
15331555
zval ztmp; \
15341556
zend_bool ctmp_free; \
15351557
int ctmp_len; \
@@ -1542,7 +1564,7 @@ mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptio
15421564
#define SET_BOOL_CTX(name, defaultvalue) \
15431565
{ \
15441566
zval ztmp; \
1545-
if (php_array_exists(driverOptions, name)) { \
1567+
if (driverOptions && php_array_exists(driverOptions, name)) { \
15461568
ZVAL_BOOL(&ztmp, php_array_fetchl_bool(driverOptions, ZEND_STRL(name))); \
15471569
php_stream_context_set_option(ctx, "ssl", name, &ztmp); \
15481570
} \
@@ -1567,12 +1589,46 @@ mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptio
15671589
SET_STRING_CTX("ciphers");
15681590
#undef SET_BOOL_CTX
15691591
#undef SET_STRING_CTX
1592+
} /* }}} */
1593+
1594+
mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, zval *driverOptions TSRMLS_DC) /* {{{ */
1595+
{
1596+
zval **tmp;
1597+
php_stream_context *ctx;
1598+
const char *mech;
1599+
mongoc_client_t *client;
1600+
1601+
ENTRY;
1602+
1603+
1604+
if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "debug", strlen("debug") + 1, (void**)&tmp) == SUCCESS) {
1605+
convert_to_string(*tmp);
1606+
1607+
zend_alter_ini_entry_ex((char *)PHONGO_DEBUG_INI, sizeof(PHONGO_DEBUG_INI), Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
1608+
}
1609+
1610+
if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "context", strlen("context") + 1, (void**)&tmp) == SUCCESS) {
1611+
ctx = php_stream_context_from_zval(*tmp, 0);
1612+
} else {
1613+
GET_DEFAULT_CONTEXT();
1614+
}
1615+
1616+
if (mongoc_uri_get_ssl(uri)) {
1617+
php_phongo_populate_default_ssl_ctx(ctx, driverOptions);
15701618
}
15711619

1572-
mech = mongoc_uri_get_auth_mechanism(muri);
1620+
MONGOC_DEBUG("Creating Manager, phongo-%s[%s] - mongoc-%s, libbson-%s", MONGODB_VERSION_S, MONGODB_STABILITY_S, MONGOC_VERSION_S, BSON_VERSION_S);
1621+
client = mongoc_client_new_from_uri(uri);
1622+
1623+
if (!client) {
1624+
RETURN(false);
1625+
}
1626+
1627+
1628+
mech = mongoc_uri_get_auth_mechanism(uri);
15731629

15741630
/* Check if we are doing X509 auth, in which case extract the username (subject) from the cert if no username is provided */
1575-
if (mech && !strcasecmp(mech, "MONGODB-X509") && !mongoc_uri_get_username(muri)) {
1631+
if (mech && !strcasecmp(mech, "MONGODB-X509") && !mongoc_uri_get_username(uri)) {
15761632
zval **pem;
15771633

15781634
if (SUCCESS == php_stream_context_get_option(ctx, "ssl", "local_cert", &pem)) {

php_phongo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ void php_phongo_read_preference_to_zval(zval *retval, const mongoc_read_prefs_t
130130
void php_phongo_write_concern_to_zval(zval *retval, const mongoc_write_concern_t *write_concern);
131131
void php_phongo_cursor_to_zval(zval *retval, php_phongo_cursor_t *cursor);
132132

133-
mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptions TSRMLS_DC);
133+
mongoc_uri_t *php_phongo_make_uri(const char *uri_string, bson_t *options TSRMLS_DC);
134+
mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, zval *driverOptions TSRMLS_DC);
134135
void php_phongo_objectid_new_from_oid(zval *object, const bson_oid_t *oid TSRMLS_DC);
135136
void php_phongo_cursor_id_new_from_id(zval *object, int64_t cursorid TSRMLS_DC);
136137
void php_phongo_new_utcdatetime_from_epoch(zval *object, int64_t msec_since_epoch TSRMLS_DC);

src/MongoDB/Manager.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,40 @@ PHP_METHOD(Manager, __construct)
5858
{
5959
php_phongo_manager_t *intern;
6060
zend_error_handling error_handling;
61-
char *uri;
62-
int uri_len;
61+
mongoc_uri_t *uri;
62+
char *uri_string;
63+
int uri_string_len;
6364
zval *options = NULL;
65+
bson_t bson_options = BSON_INITIALIZER;
6466
zval *driverOptions = NULL;
6567
(void)return_value; (void)return_value_ptr; (void)return_value_used;
6668

6769

6870
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
6971
intern = (php_phongo_manager_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
7072

71-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!a!", &uri, &uri_len, &options, &driverOptions) == FAILURE) {
73+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!a!", &uri_string, &uri_string_len, &options, &driverOptions) == FAILURE) {
7274
zend_restore_error_handling(&error_handling TSRMLS_CC);
7375
return;
7476
}
7577
zend_restore_error_handling(&error_handling TSRMLS_CC);
7678

7779

78-
intern->client = php_phongo_make_mongo_client(uri, driverOptions TSRMLS_CC);
79-
if (!intern->client) {
80+
if (options) {
81+
zval_to_bson(options, PHONGO_BSON_NONE, &bson_options, NULL TSRMLS_CC);
82+
}
83+
84+
uri = php_phongo_make_uri (uri_string, &bson_options TSRMLS_CC);
85+
if (uri) {
86+
intern->client = php_phongo_make_mongo_client(uri, driverOptions TSRMLS_CC);
87+
mongoc_uri_destroy(uri);
88+
} else {
8089
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "%s", "Failed to parse MongoDB URI");
81-
return;
8290
}
91+
if (!intern->client) {
92+
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "%s", "Failed to create Manager from URI");
93+
}
94+
8395
}
8496
/* }}} */
8597
/* {{{ proto MongoDB\Driver\Cursor Manager::executeCommand(string $db, MongoDB\Driver\Command $command[, MongoDB\Driver\ReadPreference $readPreference = null])
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
Connect to MongoDB with using SSL and default options
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("STANDALONE_SSL"); ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(STANDALONE_SSL, array("ssl" => true, "serverselectiontimeoutms" => 100));
10+
11+
12+
$bulk = new MongoDB\Driver\BulkWrite;
13+
$bulk->insert(array("my" => "value"));
14+
15+
throws(function() use ($manager, $bulk) {
16+
$retval = $manager->executeBulkWrite(NS, $bulk);
17+
}, "MongoDB\Driver\Exception\SSLConnectionException");
18+
19+
20+
21+
/* Disable all CA and hostname checks */
22+
$opts = array(
23+
"ssl" => array(
24+
"verify_peer" => false,
25+
"verify_peer_name" => false,
26+
"allow_self_signed" => true,
27+
),
28+
);
29+
$context = stream_context_create($opts);
30+
31+
$uriopts = array("ssl" => true, "serverselectiontimeoutms" => 100);
32+
$ctxopts = array("context" => $context);
33+
$manager = new MongoDB\Driver\Manager(STANDALONE_SSL, $uriopts, $ctxopts);
34+
35+
36+
$bulk = new MongoDB\Driver\BulkWrite;
37+
$bulk->insert(array("my" => "value"));
38+
39+
$retval = $manager->executeBulkWrite(NS, $bulk);
40+
printf("Inserted %d documents\n", $retval->getInsertedCount());
41+
42+
43+
44+
?>
45+
===DONE===
46+
<?php exit(0); ?>
47+
--EXPECTF--
48+
OK: Got MongoDB\Driver\Exception\SSLConnectionException
49+
Inserted 1 documents
50+
===DONE===
51+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
MongoDB\Driver\Manager: Logging into MongoDB using credentials from $options
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("STANDALONE_AUTH"); ?>
5+
<?php CLEANUP(STANDALONE_AUTH) ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
$url = parse_url(STANDALONE_AUTH);
11+
parse_str($url["query"], $args);
12+
13+
14+
$dsn = sprintf("mongodb://%s:%d/", $url["host"], $url["port"]);
15+
$options = array(
16+
"username" => $url["user"],
17+
"password" => $url["pass"],
18+
) + $args;
19+
$manager = new MongoDB\Driver\Manager($dsn, $options);
20+
21+
22+
$bulk = new MongoDB\Driver\BulkWrite;
23+
24+
$bulk->insert(array("my" => "value"));
25+
$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
26+
27+
printf("Inserted: %d\n", $inserted);
28+
29+
30+
$options["username"] = "not-found-user";
31+
$manager = new MongoDB\Driver\Manager($dsn, $options);
32+
$bulk = new MongoDB\Driver\BulkWrite;
33+
34+
$bulk->insert(array("my" => "value"));
35+
throws(function() use ($manager, $bulk) {
36+
$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
37+
printf("Incorrectly inserted: %d\n", $inserted);
38+
}, "MongoDB\Driver\Exception\AuthenticationException");
39+
?>
40+
===DONE===
41+
<?php exit(0); ?>
42+
--EXPECTF--
43+
Inserted: 1
44+
OK: Got MongoDB\Driver\Exception\AuthenticationException
45+
===DONE===
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
MongoDB\Driver\Manager: Logging into MongoDB using credentials from $options
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("STANDALONE_SSL"); ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$opts = array(
10+
"ssl" => array(
11+
"verify_peer" => false,
12+
"verify_peer_name" => false,
13+
"allow_self_signed" => true,
14+
),
15+
);
16+
$context = stream_context_create($opts);
17+
18+
$options = array(
19+
"ssl" => false,
20+
"serverselectiontimeoutms" => 100,
21+
);
22+
/* The server requires SSL */
23+
$manager = new MongoDB\Driver\Manager(STANDALONE_SSL, $options, array("context" => $context));
24+
25+
$bulk = new MongoDB\Driver\BulkWrite;
26+
$bulk->insert(array("my" => "value"));
27+
throws(function() use ($manager, $bulk) {
28+
$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
29+
printf("Inserted incorrectly: %d\n", $inserted);
30+
}, "Exception");
31+
32+
33+
34+
$options = array(
35+
"ssl" => true,
36+
);
37+
$manager = new MongoDB\Driver\Manager(STANDALONE_SSL, $options, array("context" => $context));
38+
$bulk = new MongoDB\Driver\BulkWrite;
39+
40+
$bulk->insert(array("my" => "value"));
41+
$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
42+
printf("Inserted: %d\n", $inserted);
43+
?>
44+
===DONE===
45+
<?php exit(0); ?>
46+
--EXPECTF--
47+
OK: Got Exception
48+
Inserted: 1
49+
===DONE===

0 commit comments

Comments
 (0)