@@ -1512,6 +1512,18 @@ mongoc_uri_t *php_phongo_make_uri(const char *uri_string, bson_t *options TSRMLS
1512
1512
while (bson_iter_next (& iter )) {
1513
1513
const char * key = bson_iter_key (& iter );
1514
1514
1515
+ /* Skip read preference and write concern options, as those must be
1516
+ * processed after the mongoc_client_t is constructed. */
1517
+ if (!strcasecmp (key , "journal" ) ||
1518
+ !strcasecmp (key , "readpreference" ) ||
1519
+ !strcasecmp (key , "readpreferencetags" ) ||
1520
+ !strcasecmp (key , "safe" ) ||
1521
+ !strcasecmp (key , "slaveok" ) ||
1522
+ !strcasecmp (key , "w" ) ||
1523
+ !strcasecmp (key , "wtimeoutms" )) {
1524
+ continue ;
1525
+ }
1526
+
1515
1527
if (mongoc_uri_option_is_bool (key )) {
1516
1528
mongoc_uri_set_option_as_bool (uri , key , bson_iter_as_bool (& iter ));
1517
1529
}
@@ -1595,6 +1607,176 @@ void php_phongo_populate_default_ssl_ctx(php_stream_context *ctx, zval *driverOp
1595
1607
#undef SET_STRING_CTX
1596
1608
} /* }}} */
1597
1609
1610
+ bool php_phongo_apply_rp_options_to_client (mongoc_client_t * client , bson_t * options TSRMLS_DC ) /* {{{ */
1611
+ {
1612
+ bson_iter_t iter ;
1613
+ mongoc_read_prefs_t * new_rp ;
1614
+ const mongoc_read_prefs_t * old_rp ;
1615
+
1616
+ if (!(old_rp = mongoc_client_get_read_prefs (client ))) {
1617
+ phongo_throw_exception (PHONGO_ERROR_MONGOC_FAILED TSRMLS_CC , "Client does not have a read preference" );
1618
+
1619
+ return false;
1620
+ }
1621
+
1622
+ new_rp = mongoc_read_prefs_copy (old_rp );
1623
+
1624
+ if (bson_iter_init_find_case (& iter , options , "slaveok" ) && BSON_ITER_HOLDS_BOOL (& iter )) {
1625
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_SECONDARY_PREFERRED );
1626
+ }
1627
+
1628
+ if (bson_iter_init_find_case (& iter , options , "readpreference" ) && BSON_ITER_HOLDS_UTF8 (& iter )) {
1629
+ const char * str = bson_iter_utf8 (& iter , NULL );
1630
+
1631
+ if (0 == strcasecmp ("primary" , str )) {
1632
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_PRIMARY );
1633
+ } else if (0 == strcasecmp ("primarypreferred" , str )) {
1634
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_PRIMARY_PREFERRED );
1635
+ } else if (0 == strcasecmp ("secondary" , str )) {
1636
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_SECONDARY );
1637
+ } else if (0 == strcasecmp ("secondarypreferred" , str )) {
1638
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_SECONDARY_PREFERRED );
1639
+ } else if (0 == strcasecmp ("nearest" , str )) {
1640
+ mongoc_read_prefs_set_mode (new_rp , MONGOC_READ_NEAREST );
1641
+ } else {
1642
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Unsupported readPreference value: '%s'" , str );
1643
+ mongoc_read_prefs_destroy (new_rp );
1644
+
1645
+ return false;
1646
+ }
1647
+ }
1648
+
1649
+ if (bson_iter_init_find_case (& iter , options , "readpreferencetags" ) && BSON_ITER_HOLDS_ARRAY (& iter )) {
1650
+ bson_t tags ;
1651
+ uint32_t len ;
1652
+ const uint8_t * data ;
1653
+
1654
+ bson_iter_array (& iter , & len , & data );
1655
+
1656
+ if (bson_init_static (& tags , data , len )) {
1657
+ mongoc_read_prefs_set_tags (new_rp , & tags );
1658
+ }
1659
+ }
1660
+
1661
+ if (mongoc_read_prefs_get_mode (new_rp ) == MONGOC_READ_PRIMARY &&
1662
+ !bson_empty (mongoc_read_prefs_get_tags (new_rp ))) {
1663
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Primary read preference mode conflicts with tags" );
1664
+ mongoc_read_prefs_destroy (new_rp );
1665
+
1666
+ return false;
1667
+ }
1668
+
1669
+ /* This may be redundant in light of the last check (primary with tags), but
1670
+ * we'll check anyway in case additional validation is implemented. */
1671
+ if (!mongoc_read_prefs_is_valid (new_rp )) {
1672
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Read preference is not valid" );
1673
+ mongoc_read_prefs_destroy (new_rp );
1674
+
1675
+ return false;
1676
+ }
1677
+
1678
+ mongoc_client_set_read_prefs (client , new_rp );
1679
+ mongoc_read_prefs_destroy (new_rp );
1680
+
1681
+ return true;
1682
+ } /* }}} */
1683
+
1684
+ bool php_phongo_apply_wc_options_to_client (mongoc_client_t * client , bson_t * options TSRMLS_DC ) /* {{{ */
1685
+ {
1686
+ bson_iter_t iter ;
1687
+ int32_t wtimeoutms ;
1688
+ mongoc_write_concern_t * new_wc ;
1689
+ const mongoc_write_concern_t * old_wc ;
1690
+
1691
+ if (!(old_wc = mongoc_client_get_write_concern (client ))) {
1692
+ phongo_throw_exception (PHONGO_ERROR_MONGOC_FAILED TSRMLS_CC , "Client does not have a write concern" );
1693
+
1694
+ return false;
1695
+ }
1696
+
1697
+ wtimeoutms = mongoc_write_concern_get_wtimeout (old_wc );
1698
+
1699
+ new_wc = mongoc_write_concern_copy (old_wc );
1700
+
1701
+ if (bson_iter_init_find_case (& iter , options , "safe" ) && BSON_ITER_HOLDS_BOOL (& iter )) {
1702
+ mongoc_write_concern_set_w (new_wc , bson_iter_bool (& iter ) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED );
1703
+ }
1704
+
1705
+ if (bson_iter_init_find_case (& iter , options , "wtimeoutms" ) && BSON_ITER_HOLDS_INT32 (& iter )) {
1706
+ wtimeoutms = bson_iter_int32 (& iter );
1707
+ }
1708
+
1709
+ if (bson_iter_init_find_case (& iter , options , "journal" ) && BSON_ITER_HOLDS_BOOL (& iter )) {
1710
+ mongoc_write_concern_set_journal (new_wc , bson_iter_bool (& iter ));
1711
+ }
1712
+
1713
+ if (bson_iter_init_find_case (& iter , options , "w" )) {
1714
+ if (BSON_ITER_HOLDS_INT32 (& iter )) {
1715
+ int32_t value = bson_iter_int32 (& iter );
1716
+
1717
+ switch (value ) {
1718
+ case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED :
1719
+ case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED :
1720
+ mongoc_write_concern_set_w (new_wc , value );
1721
+ break ;
1722
+
1723
+ default :
1724
+ if (value > 0 ) {
1725
+ mongoc_write_concern_set_w (new_wc , value );
1726
+ break ;
1727
+ }
1728
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Unsupported w value: %d" , value );
1729
+ mongoc_write_concern_destroy (new_wc );
1730
+
1731
+ return false;
1732
+ }
1733
+ } else if (BSON_ITER_HOLDS_UTF8 (& iter )) {
1734
+ const char * str = bson_iter_utf8 (& iter , NULL );
1735
+
1736
+ if (0 == strcasecmp ("majority" , str )) {
1737
+ mongoc_write_concern_set_wmajority (new_wc , wtimeoutms );
1738
+ } else {
1739
+ mongoc_write_concern_set_wtag (new_wc , str );
1740
+ }
1741
+ }
1742
+ }
1743
+
1744
+ /* Only set wtimeout if it's still applicable; otherwise, clear it. */
1745
+ if (mongoc_write_concern_get_w (new_wc ) > 1 ||
1746
+ mongoc_write_concern_get_wmajority (new_wc ) ||
1747
+ mongoc_write_concern_get_wtag (new_wc )) {
1748
+ mongoc_write_concern_set_wtimeout (new_wc , wtimeoutms );
1749
+ } else {
1750
+ mongoc_write_concern_set_wtimeout (new_wc , 0 );
1751
+ }
1752
+
1753
+ if (mongoc_write_concern_get_journal (new_wc )) {
1754
+ int32_t w = mongoc_write_concern_get_w (new_wc );
1755
+
1756
+ if (w == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || w == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED ) {
1757
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Journal conflicts with w value: %d" , w );
1758
+ mongoc_write_concern_destroy (new_wc );
1759
+
1760
+ return false;
1761
+ }
1762
+ }
1763
+
1764
+ /* This may be redundant in light of the last check (unacknowledged w with
1765
+ journal), but we'll check anyway in case additional validation is
1766
+ implemented. */
1767
+ if (!_mongoc_write_concern_is_valid (new_wc )) {
1768
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Write concern is not valid" );
1769
+ mongoc_write_concern_destroy (new_wc );
1770
+
1771
+ return false;
1772
+ }
1773
+
1774
+ mongoc_client_set_write_concern (client , new_wc );
1775
+ mongoc_write_concern_destroy (new_wc );
1776
+
1777
+ return true;
1778
+ } /* }}} */
1779
+
1598
1780
mongoc_client_t * php_phongo_make_mongo_client (const mongoc_uri_t * uri , zval * driverOptions TSRMLS_DC ) /* {{{ */
1599
1781
{
1600
1782
zval * * tmp ;
0 commit comments