@@ -451,6 +451,62 @@ mongoc_bulk_operation_t *phongo_bulkwrite_init(zend_bool ordered) { /* {{{ */
451
451
#define PHONGO_WRITECONCERN_ALLOWED 0x01
452
452
#define PHONGO_READPREFERENCE_ALLOWED 0x02
453
453
454
+ /* Appends a document field for the given opts document and key. Returns true on
455
+ * success; otherwise, false is returned and an exception is thrown. */
456
+ static bool php_phongo_command_opts_append_document (bson_t * opts , const char * opts_key , zval * zarr , const char * zarr_key TSRMLS_DC ) /* {{{ */
457
+ {
458
+ zval * value = php_array_fetch (zarr , zarr_key );
459
+ bson_t b = BSON_INITIALIZER ;
460
+
461
+ if (Z_TYPE_P (value ) != IS_OBJECT && Z_TYPE_P (value ) != IS_ARRAY ) {
462
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Expected \"%s\" option to be array or object, %s given" , zarr_key , zend_get_type_by_const (Z_TYPE_P (value )));
463
+ return false;
464
+ }
465
+
466
+ php_phongo_zval_to_bson (value , PHONGO_BSON_NONE , & b , NULL TSRMLS_CC );
467
+
468
+ if (EG (exception )) {
469
+ bson_destroy (& b );
470
+ return false;
471
+ }
472
+
473
+ if (!BSON_APPEND_DOCUMENT (opts , opts_key , & b )) {
474
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC , "Error appending \"%s\" option" , opts_key );
475
+ bson_destroy (& b );
476
+ return false;
477
+ }
478
+
479
+ bson_destroy (& b );
480
+ return true;
481
+ } /* }}} */
482
+
483
+
484
+ static int process_collation (zval * option , bson_t * mongoc_opts TSRMLS_DC )
485
+ {
486
+ return php_phongo_command_opts_append_document (mongoc_opts , "collation" , option , "collation" TSRMLS_CC );
487
+ }
488
+
489
+ static int process_read_concern (zval * option , bson_t * mongoc_opts TSRMLS_DC )
490
+ {
491
+ if (Z_TYPE_P (option ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (option ), php_phongo_readconcern_ce TSRMLS_CC )) {
492
+ zval zreadConcern ;
493
+ const mongoc_read_concern_t * read_concern = phongo_read_concern_from_zval (option TSRMLS_CC );
494
+
495
+ php_phongo_read_concern_to_zval (& zreadConcern , read_concern );
496
+ convert_to_object (& zreadConcern );
497
+
498
+ return php_phongo_command_opts_append_document (mongoc_opts , "readConcern" , & zreadConcern , "readConcern" TSRMLS_CC );
499
+ } else {
500
+ phongo_throw_exception (
501
+ PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC ,
502
+ "Expected 'readConcern' option to be 'MongoDB\\Driver\\ReadPreference', %s given" ,
503
+ zend_get_type_by_const (Z_TYPE_P (option ))
504
+ );
505
+ return false;
506
+ }
507
+ return true;
508
+ }
509
+
454
510
static int process_read_preference (zval * option , zval * * zreadPreference TSRMLS_DC )
455
511
{
456
512
if (Z_TYPE_P (option ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (option ), php_phongo_readpreference_ce TSRMLS_CC )) {
@@ -481,26 +537,35 @@ static int process_write_concern(zval *option, zval **zwriteConcern TSRMLS_DC)
481
537
return true;
482
538
}
483
539
484
- static int phongo_execute_parse_options (zval * options , int flags , zval * * zreadPreference , zval * * zwriteConcern TSRMLS_DC )
540
+ static int phongo_execute_parse_options (zval * driver_options , int flags , bson_t * mongoc_opts , zval * * zreadPreference , zval * * zwriteConcern TSRMLS_DC )
485
541
{
486
- if (options && Z_TYPE_P (options ) == IS_ARRAY ) {
487
- HashTable * ht_data = HASH_OF (options );
542
+ if (driver_options && Z_TYPE_P (driver_options ) == IS_ARRAY ) {
543
+ HashTable * ht_data = HASH_OF (driver_options );
488
544
#if PHP_VERSION_ID >= 70000
489
545
zend_string * string_key = NULL ;
490
546
zend_ulong num_key = 0 ;
491
- zval * option ;
547
+ zval * driver_option ;
492
548
493
- ZEND_HASH_FOREACH_KEY_VAL (ht_data , num_key , string_key , option ) {
549
+ ZEND_HASH_FOREACH_KEY_VAL (ht_data , num_key , string_key , driver_option ) {
494
550
if (!string_key ) {
495
551
continue ;
496
552
}
497
553
498
- if ((!strcasecmp (ZSTR_VAL (string_key ), "readPreference" )) && (flags & PHONGO_READPREFERENCE_ALLOWED )) {
499
- if (!process_read_preference (option , zreadPreference )) {
554
+ /* URI options are case-insensitive */
555
+ if (!strcasecmp (ZSTR_VAL (string_key ), "collation" )) {
556
+ if (!process_collation (driver_option , mongoc_opts )) {
557
+ return false;
558
+ }
559
+ } else if (!strcasecmp (ZSTR_VAL (string_key ), "readConcern" )) {
560
+ if (!process_read_concern (driver_option , mongoc_opts )) {
561
+ return false;
562
+ }
563
+ } else if ((!strcasecmp (ZSTR_VAL (string_key ), "readPreference" )) && (flags & PHONGO_READPREFERENCE_ALLOWED )) {
564
+ if (!process_read_preference (driver_option , zreadPreference )) {
500
565
return false;
501
566
}
502
567
} else if ((!strcasecmp (ZSTR_VAL (string_key ), "writeConcern" )) && (flags & PHONGO_WRITECONCERN_ALLOWED )) {
503
- if (!process_write_concern (option , zwriteConcern )) {
568
+ if (!process_write_concern (driver_option , zwriteConcern )) {
504
569
return false;
505
570
}
506
571
} else {
@@ -510,10 +575,10 @@ static int phongo_execute_parse_options(zval *options, int flags, zval **zreadPr
510
575
} ZEND_HASH_FOREACH_END ();
511
576
#else
512
577
HashPosition pos ;
513
- zval * * option ;
578
+ zval * * driver_option ;
514
579
515
580
for (zend_hash_internal_pointer_reset_ex (ht_data , & pos );
516
- zend_hash_get_current_data_ex (ht_data , (void * * ) & option , & pos ) == SUCCESS ;
581
+ zend_hash_get_current_data_ex (ht_data , (void * * ) & driver_option , & pos ) == SUCCESS ;
517
582
zend_hash_move_forward_ex (ht_data , & pos )) {
518
583
char * string_key = NULL ;
519
584
uint string_key_len = 0 ;
@@ -524,12 +589,20 @@ static int phongo_execute_parse_options(zval *options, int flags, zval **zreadPr
524
589
}
525
590
526
591
/* URI options are case-insensitive */
527
- if ((!strcasecmp (string_key , "readPreference" )) && (flags & PHONGO_READPREFERENCE_ALLOWED )) {
528
- if (!process_read_preference (* option , zreadPreference TSRMLS_CC )) {
592
+ if (!strcasecmp (string_key , "collation" )) {
593
+ if (!process_collation (* driver_option , mongoc_opts )) {
594
+ return false;
595
+ }
596
+ } else if (!strcasecmp (string_key , "readConcern" )) {
597
+ if (!process_read_concern (* driver_option , mongoc_opts )) {
598
+ return false;
599
+ }
600
+ } else if ((!strcasecmp (string_key , "readPreference" )) && (flags & PHONGO_READPREFERENCE_ALLOWED )) {
601
+ if (!process_read_preference (* driver_option , zreadPreference TSRMLS_CC )) {
529
602
return false;
530
603
}
531
604
} else if ((!strcasecmp (string_key , "writeConcern" )) && (flags & PHONGO_WRITECONCERN_ALLOWED )) {
532
- if (!process_write_concern (* option , zwriteConcern TSRMLS_CC )) {
605
+ if (!process_write_concern (* driver_option , zwriteConcern TSRMLS_CC )) {
533
606
return false;
534
607
}
535
608
} else {
@@ -565,7 +638,7 @@ bool phongo_execute_write(mongoc_client_t *client, const char *namespace, php_ph
565
638
/* FIXME: Legacy way of specifying the writeConcern option into this function */
566
639
if (options && Z_TYPE_P (options ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (options ), php_phongo_writeconcern_ce TSRMLS_CC )) {
567
640
zwriteConcern = options ;
568
- } else if (!phongo_execute_parse_options (options , PHONGO_WRITECONCERN_ALLOWED , NULL , & zwriteConcern TSRMLS_CC )) {
641
+ } else if (!phongo_execute_parse_options (options , PHONGO_WRITECONCERN_ALLOWED , NULL , NULL , & zwriteConcern TSRMLS_CC )) {
569
642
return false;
570
643
}
571
644
@@ -672,7 +745,7 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, zval *z
672
745
/* FIXME: Legacy way of specifying the readPreference option into this function */
673
746
if (options && Z_TYPE_P (options ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (options ), php_phongo_readpreference_ce TSRMLS_CC )) {
674
747
zreadPreference = options ;
675
- } else if (!phongo_execute_parse_options (options , PHONGO_READPREFERENCE_ALLOWED , & zreadPreference , NULL TSRMLS_CC )) {
748
+ } else if (!phongo_execute_parse_options (options , PHONGO_READPREFERENCE_ALLOWED , NULL , & zreadPreference , NULL TSRMLS_CC )) {
676
749
return false;
677
750
}
678
751
@@ -744,7 +817,7 @@ static int phongo_do_select_server(mongoc_client_t *client, bson_t *opts, zval *
744
817
return selected_server_id ;
745
818
}
746
819
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 ) /* {{{ */
820
+ 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
821
{
749
822
const php_phongo_command_t * command ;
750
823
bson_iter_t iter ;
@@ -754,6 +827,7 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, zval *zcomma
754
827
mongoc_cursor_t * cmd_cursor ;
755
828
uint32_t selected_server_id ;
756
829
zval * zreadPreference = NULL ;
830
+ int result ;
757
831
758
832
command = Z_COMMAND_OBJ_P (zcommand );
759
833
@@ -762,7 +836,7 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, zval *zcomma
762
836
/* FIXME: Legacy way of specifying the readPreference option into this function */
763
837
if (options && Z_TYPE_P (options ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (options ), php_phongo_readpreference_ce TSRMLS_CC )) {
764
838
zreadPreference = options ;
765
- } else if (!phongo_execute_parse_options (options , PHONGO_READPREFERENCE_ALLOWED , & zreadPreference , NULL TSRMLS_CC )) {
839
+ } else if (!phongo_execute_parse_options (options , PHONGO_READPREFERENCE_ALLOWED , opts , & zreadPreference , NULL TSRMLS_CC )) {
766
840
return false;
767
841
}
768
842
@@ -775,7 +849,24 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, zval *zcomma
775
849
/* Although "opts" already always includes the serverId option, the read
776
850
* preference is added to the command parts, which is relevant for mongos
777
851
* command construction. */
778
- if (!mongoc_client_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error )) {
852
+ switch (type ) {
853
+ case PHONGO_COMMAND_RAW :
854
+ result = mongoc_client_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error );
855
+ break ;
856
+ case PHONGO_COMMAND_READ :
857
+ result = mongoc_client_read_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error );
858
+ break ;
859
+ case PHONGO_COMMAND_WRITE :
860
+ result = mongoc_client_write_command_with_opts (client , db , command -> bson , opts , & reply , & error );
861
+ break ;
862
+ case PHONGO_COMMAND_READ_WRITE :
863
+ result = mongoc_client_read_write_command_with_opts (client , db , command -> bson , phongo_read_preference_from_zval (zreadPreference TSRMLS_CC ), opts , & reply , & error );
864
+ break ;
865
+ default :
866
+ /* Should never happen, but if it does: abort */
867
+ assert (false);
868
+ }
869
+ if (!result ) {
779
870
phongo_throw_exception_from_bson_error_t (& error TSRMLS_CC );
780
871
bson_free (opts );
781
872
return false;
0 commit comments