@@ -448,13 +448,66 @@ mongoc_bulk_operation_t *phongo_bulkwrite_init(zend_bool ordered) { /* {{{ */
448
448
return mongoc_bulk_operation_new (ordered );
449
449
} /* }}} */
450
450
451
- #define PHONGO_WRITECONCERN_ALLOWED 0x01
452
- #define PHONGO_READPREFERENCE_ALLOWED 0x02
451
+ static bool process_read_concern (zval * option , bson_t * mongoc_opts TSRMLS_DC )
452
+ {
453
+ if (Z_TYPE_P (option ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (option ), php_phongo_readconcern_ce TSRMLS_CC )) {
454
+ const mongoc_read_concern_t * read_concern = phongo_read_concern_from_zval (option TSRMLS_CC );
455
+
456
+ if (!mongoc_read_concern_append ((mongoc_read_concern_t * )read_concern , mongoc_opts )) {
457
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending \"%s\" option" , "readConcern" );
458
+ return false;
459
+ }
460
+ } else {
461
+ phongo_throw_exception (
462
+ PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC ,
463
+ "Expected 'readConcern' option to be 'MongoDB\\Driver\\ReadConcern', %s given" ,
464
+ zend_get_type_by_const (Z_TYPE_P (option ))
465
+ );
466
+ return false;
467
+ }
468
+ return true;
469
+ }
470
+
471
+ static uint32_t phongo_do_select_server (mongoc_client_t * client , bson_t * opts , zval * zreadPreference , int server_id TSRMLS_DC )
472
+ {
473
+ bson_error_t error ;
474
+ uint32_t selected_server_id = 0 ;
475
+
476
+ if (server_id > 0 ) {
477
+ bson_append_int32 (opts , "serverId" , -1 , server_id );
478
+ selected_server_id = server_id ;
479
+ } else {
480
+ mongoc_server_description_t * selected_server = NULL ;
453
481
454
- static int process_read_preference (zval * option , zval * * zreadPreference TSRMLS_DC )
482
+ selected_server = mongoc_client_select_server (client , false, (zreadPreference ? phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ) : mongoc_client_get_read_prefs (client )), & error );
483
+ if (selected_server ) {
484
+ selected_server_id = mongoc_server_description_id (selected_server );
485
+ bson_append_int32 (opts , "serverId" , -1 , selected_server_id );
486
+ mongoc_server_description_destroy (selected_server );
487
+ } else {
488
+ /* Check for connection related exceptions */
489
+ if (!EG (exception )) {
490
+ phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
491
+ }
492
+ }
493
+ }
494
+
495
+ return selected_server_id ;
496
+ }
497
+
498
+ static bool process_read_preference (zval * option , bson_t * mongoc_opts , zval * * zreadPreference , mongoc_client_t * client , int server_id TSRMLS_DC )
455
499
{
456
500
if (Z_TYPE_P (option ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (option ), php_phongo_readpreference_ce TSRMLS_CC )) {
457
- * zreadPreference = option ;
501
+ int selected_server_id ;
502
+
503
+ if (zreadPreference ) {
504
+ * zreadPreference = option ;
505
+ }
506
+
507
+ selected_server_id = phongo_do_select_server (client , mongoc_opts , * zreadPreference , server_id TSRMLS_CC );
508
+ if (!selected_server_id ) {
509
+ return false;
510
+ }
458
511
} else {
459
512
phongo_throw_exception (
460
513
PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC ,
@@ -466,10 +519,18 @@ static int process_read_preference(zval *option, zval **zreadPreference TSRMLS_D
466
519
return true;
467
520
}
468
521
469
- static int process_write_concern (zval * option , zval * * zwriteConcern TSRMLS_DC )
522
+ static bool process_write_concern (zval * option , bson_t * mongoc_opts , zval * * zwriteConcern TSRMLS_DC )
470
523
{
471
524
if (Z_TYPE_P (option ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (option ), php_phongo_writeconcern_ce TSRMLS_CC )) {
472
- * zwriteConcern = option ;
525
+ const mongoc_write_concern_t * write_concern = phongo_write_concern_from_zval (option TSRMLS_CC );
526
+
527
+ if (zwriteConcern ) {
528
+ * zwriteConcern = option ;
529
+ }
530
+
531
+ if (!mongoc_write_concern_append ((mongoc_write_concern_t * ) write_concern , mongoc_opts )) {
532
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending \"%s\" option" , "writeConcern" );
533
+ }
473
534
} else {
474
535
phongo_throw_exception (
475
536
PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC ,
@@ -481,26 +542,31 @@ static int process_write_concern(zval *option, zval **zwriteConcern TSRMLS_DC)
481
542
return true;
482
543
}
483
544
484
- static int phongo_execute_parse_options (zval * options , int flags , zval * * zreadPreference , zval * * zwriteConcern TSRMLS_DC )
545
+ static int phongo_execute_parse_options (mongoc_client_t * client , int server_id , zval * driver_options , int type , bson_t * mongoc_opts , zval * * zreadPreference , zval * * zwriteConcern TSRMLS_DC )
485
546
{
486
- if (options && Z_TYPE_P (options ) == IS_ARRAY ) {
487
- HashTable * ht_data = HASH_OF (options );
547
+ if (driver_options && Z_TYPE_P (driver_options ) == IS_ARRAY ) {
548
+ HashTable * ht_data = HASH_OF (driver_options );
488
549
#if PHP_VERSION_ID >= 70000
489
550
zend_string * string_key = NULL ;
490
551
zend_ulong num_key = 0 ;
491
- zval * option ;
552
+ zval * driver_option ;
492
553
493
- ZEND_HASH_FOREACH_KEY_VAL (ht_data , num_key , string_key , option ) {
554
+ ZEND_HASH_FOREACH_KEY_VAL (ht_data , num_key , string_key , driver_option ) {
494
555
if (!string_key ) {
495
556
continue ;
496
557
}
497
558
498
- if ((!strcasecmp (ZSTR_VAL (string_key ), "readPreference" )) && (flags & PHONGO_READPREFERENCE_ALLOWED )) {
499
- if (!process_read_preference (option , zreadPreference )) {
559
+ /* URI options are case-insensitive */
560
+ if ((!strcasecmp (ZSTR_VAL (string_key ), "readConcern" )) && (type & PHONGO_COMMAND_READ )) {
561
+ if (!process_read_concern (driver_option , mongoc_opts )) {
562
+ return false;
563
+ }
564
+ } else if ((!strcasecmp (ZSTR_VAL (string_key ), "readPreference" )) && (type == PHONGO_COMMAND_READ || type == PHONGO_COMMAND_RAW )) {
565
+ if (!process_read_preference (driver_option , mongoc_opts , zreadPreference , client , server_id )) {
500
566
return false;
501
567
}
502
- } else if ((!strcasecmp (ZSTR_VAL (string_key ), "writeConcern" )) && (flags & PHONGO_WRITECONCERN_ALLOWED )) {
503
- if (!process_write_concern (option , zwriteConcern )) {
568
+ } else if ((!strcasecmp (ZSTR_VAL (string_key ), "writeConcern" )) && (type & PHONGO_COMMAND_WRITE )) {
569
+ if (!process_write_concern (driver_option , mongoc_opts , zwriteConcern )) {
504
570
return false;
505
571
}
506
572
} else {
@@ -510,10 +576,10 @@ static int phongo_execute_parse_options(zval *options, int flags, zval **zreadPr
510
576
} ZEND_HASH_FOREACH_END ();
511
577
#else
512
578
HashPosition pos ;
513
- zval * * option ;
579
+ zval * * driver_option ;
514
580
515
581
for (zend_hash_internal_pointer_reset_ex (ht_data , & pos );
516
- zend_hash_get_current_data_ex (ht_data , (void * * ) & option , & pos ) == SUCCESS ;
582
+ zend_hash_get_current_data_ex (ht_data , (void * * ) & driver_option , & pos ) == SUCCESS ;
517
583
zend_hash_move_forward_ex (ht_data , & pos )) {
518
584
char * string_key = NULL ;
519
585
uint string_key_len = 0 ;
@@ -524,12 +590,16 @@ static int phongo_execute_parse_options(zval *options, int flags, zval **zreadPr
524
590
}
525
591
526
592
/* URI options are case-insensitive */
527
- if ((!strcasecmp (string_key , "readPreference " )) && (flags & PHONGO_READPREFERENCE_ALLOWED )) {
528
- if (!process_read_preference ( * option , zreadPreference TSRMLS_CC )) {
593
+ if ((!strcasecmp (string_key , "readConcern " )) && (type & PHONGO_COMMAND_READ )) {
594
+ if (!process_read_concern ( * driver_option , mongoc_opts TSRMLS_CC )) {
529
595
return false;
530
596
}
531
- } else if ((!strcasecmp (string_key , "writeConcern" )) && (flags & PHONGO_WRITECONCERN_ALLOWED )) {
532
- if (!process_write_concern (* option , zwriteConcern TSRMLS_CC )) {
597
+ } else if ((!strcasecmp (string_key , "readPreference" )) && (type == PHONGO_COMMAND_READ )) {
598
+ if (!process_read_preference (* driver_option , mongoc_opts , zreadPreference , client , server_id TSRMLS_CC )) {
599
+ return false;
600
+ }
601
+ } else if ((!strcasecmp (string_key , "writeConcern" )) && (type & PHONGO_COMMAND_WRITE )) {
602
+ if (!process_write_concern (* driver_option , mongoc_opts , zwriteConcern TSRMLS_CC )) {
533
603
return false;
534
604
}
535
605
} else {
@@ -565,7 +635,7 @@ bool phongo_execute_write(mongoc_client_t *client, const char *namespace, php_ph
565
635
/* FIXME: Legacy way of specifying the writeConcern option into this function */
566
636
if (options && Z_TYPE_P (options ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (options ), php_phongo_writeconcern_ce TSRMLS_CC )) {
567
637
zwriteConcern = options ;
568
- } else if (!phongo_execute_parse_options (options , PHONGO_WRITECONCERN_ALLOWED , NULL , & zwriteConcern TSRMLS_CC )) {
638
+ } else if (!phongo_execute_parse_options (client , server_id , options , PHONGO_COMMAND_WRITE , NULL , NULL , & zwriteConcern TSRMLS_CC )) {
569
639
return false;
570
640
}
571
641
@@ -672,7 +742,7 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, zval *z
672
742
/* FIXME: Legacy way of specifying the readPreference option into this function */
673
743
if (options && Z_TYPE_P (options ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (options ), php_phongo_readpreference_ce TSRMLS_CC )) {
674
744
zreadPreference = options ;
675
- } else if (!phongo_execute_parse_options (options , PHONGO_READPREFERENCE_ALLOWED , & zreadPreference , NULL TSRMLS_CC )) {
745
+ } else if (!phongo_execute_parse_options (client , server_id , options , PHONGO_COMMAND_READ , NULL , & zreadPreference , NULL TSRMLS_CC )) {
676
746
return false;
677
747
}
678
748
@@ -715,36 +785,7 @@ static bson_t *create_wrapped_command_envelope(const char *db, bson_t *reply)
715
785
return tmp ;
716
786
}
717
787
718
- static int phongo_do_select_server (mongoc_client_t * client , bson_t * opts , zval * zreadPreference , int server_id TSRMLS_DC )
719
- {
720
- bson_error_t error ;
721
- uint32_t selected_server_id ;
722
-
723
- if (server_id > 0 ) {
724
- bson_append_int32 (opts , "serverId" , -1 , server_id );
725
- selected_server_id = server_id ;
726
- } else {
727
- mongoc_server_description_t * selected_server = NULL ;
728
-
729
- selected_server = mongoc_client_select_server (client , false, (zreadPreference ? phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ) : mongoc_client_get_read_prefs (client )), & error );
730
- if (selected_server ) {
731
- selected_server_id = mongoc_server_description_id (selected_server );
732
- bson_append_int32 (opts , "serverId" , -1 , selected_server_id );
733
- mongoc_server_description_destroy (selected_server );
734
- } else {
735
- /* Check for connection related exceptions */
736
- if (!EG (exception )) {
737
- phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
738
- }
739
-
740
- return false;
741
- }
742
- }
743
-
744
- return selected_server_id ;
745
- }
746
-
747
- int phongo_execute_command (mongoc_client_t * client , const char * db , zval * zcommand , zval * options , int server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
788
+ int phongo_execute_command (mongoc_client_t * client , php_phongo_command_type_t type , const char * db , zval * zcommand , zval * options , int server_id , zval * return_value , int return_value_used TSRMLS_DC ) /* {{{ */
748
789
{
749
790
const php_phongo_command_t * command ;
750
791
bson_iter_t iter ;
@@ -754,6 +795,7 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, zval *zcomma
754
795
mongoc_cursor_t * cmd_cursor ;
755
796
uint32_t selected_server_id ;
756
797
zval * zreadPreference = NULL ;
798
+ int result ;
757
799
758
800
command = Z_COMMAND_OBJ_P (zcommand );
759
801
@@ -762,7 +804,7 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, zval *zcomma
762
804
/* FIXME: Legacy way of specifying the readPreference option into this function */
763
805
if (options && Z_TYPE_P (options ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (options ), php_phongo_readpreference_ce TSRMLS_CC )) {
764
806
zreadPreference = options ;
765
- } else if (!phongo_execute_parse_options (options , PHONGO_READPREFERENCE_ALLOWED , & zreadPreference , NULL TSRMLS_CC )) {
807
+ } else if (!phongo_execute_parse_options (client , server_id , options , type , opts , & zreadPreference , NULL TSRMLS_CC )) {
766
808
return false;
767
809
}
768
810
@@ -775,7 +817,27 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, zval *zcomma
775
817
/* Although "opts" already always includes the serverId option, the read
776
818
* preference is added to the command parts, which is relevant for mongos
777
819
* command construction. */
778
- if (!mongoc_client_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error )) {
820
+ switch (type ) {
821
+ case PHONGO_COMMAND_RAW :
822
+ result = mongoc_client_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error );
823
+ break ;
824
+ case PHONGO_COMMAND_READ :
825
+ result = mongoc_client_read_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error );
826
+ break ;
827
+ case PHONGO_COMMAND_WRITE :
828
+ result = mongoc_client_write_command_with_opts (client , db , command -> bson , opts , & reply , & error );
829
+ break ;
830
+ case PHONGO_COMMAND_READ_WRITE :
831
+ /* We can pass NULL as readPreference, as this argument was added historically, but has no function */
832
+ result = mongoc_client_read_write_command_with_opts (client , db , command -> bson , NULL , opts , & reply , & error );
833
+ break ;
834
+ default :
835
+ /* Should never happen, but if it does: exception */
836
+ phongo_throw_exception (PHONGO_ERROR_LOGIC TSRMLS_CC , "Type '%d' should never have been passed to phongo_execute_command, please file a bug report" , type );
837
+ bson_free (opts );
838
+ return false;
839
+ }
840
+ if (!result ) {
779
841
phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
780
842
bson_free (opts );
781
843
return false;
0 commit comments