@@ -908,9 +908,9 @@ public function prepareSortOrProjection(array $fields)
908
908
*/
909
909
public function prepareFieldName ($ fieldName )
910
910
{
911
- list ( $ fieldName ) = $ this ->prepareQueryElement ($ fieldName , null , null , false );
911
+ $ fieldNames = $ this ->prepareQueryElement ($ fieldName , null , null , false );
912
912
913
- return $ fieldName ;
913
+ return $ fieldNames [ 0 ][ 0 ] ;
914
914
}
915
915
916
916
/**
@@ -991,11 +991,12 @@ public function prepareQueryOrNewObj(array $query)
991
991
continue ;
992
992
}
993
993
994
- list ($ key , $ value ) = $ this ->prepareQueryElement ($ key , $ value , null , true );
995
-
996
- $ preparedQuery [$ key ] = is_array ($ value )
997
- ? array_map ('\Doctrine\ODM\MongoDB\Types\Type::convertPHPToDatabaseValue ' , $ value )
998
- : Type::convertPHPToDatabaseValue ($ value );
994
+ $ preparedQueryElements = $ this ->prepareQueryElement ($ key , $ value , null , true );
995
+ foreach ($ preparedQueryElements as list ($ preparedKey , $ preparedValue )) {
996
+ $ preparedQuery [$ preparedKey ] = is_array ($ preparedValue )
997
+ ? array_map ('\Doctrine\ODM\MongoDB\Types\Type::convertPHPToDatabaseValue ' , $ preparedValue )
998
+ : Type::convertPHPToDatabaseValue ($ preparedValue );
999
+ }
999
1000
}
1000
1001
1001
1002
return $ preparedQuery ;
@@ -1011,7 +1012,7 @@ public function prepareQueryOrNewObj(array $query)
1011
1012
* @param mixed $value
1012
1013
* @param ClassMetadata $class Defaults to $this->class
1013
1014
* @param boolean $prepareValue Whether or not to prepare the value
1014
- * @return array Prepared field name and value
1015
+ * @return array An array of tuples containing prepared field names and values
1015
1016
*/
1016
1017
private function prepareQueryElement ($ fieldName , $ value = null , $ class = null , $ prepareValue = true )
1017
1018
{
@@ -1025,18 +1026,18 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1025
1026
$ fieldName = $ mapping ['name ' ];
1026
1027
1027
1028
if ( ! $ prepareValue ) {
1028
- return array ( $ fieldName , $ value) ;
1029
+ return [[ $ fieldName , $ value]] ;
1029
1030
}
1030
1031
1031
1032
// Prepare mapped, embedded objects
1032
1033
if ( ! empty ($ mapping ['embedded ' ]) && is_object ($ value ) &&
1033
1034
! $ this ->dm ->getMetadataFactory ()->isTransient (get_class ($ value ))) {
1034
- return array ( $ fieldName , $ this ->pb ->prepareEmbeddedDocumentValue ($ mapping , $ value )) ;
1035
+ return [[ $ fieldName , $ this ->pb ->prepareEmbeddedDocumentValue ($ mapping , $ value )]] ;
1035
1036
}
1036
1037
1037
1038
if (! empty ($ mapping ['reference ' ]) && is_object ($ value ) && ! ($ value instanceof \MongoId)) {
1038
1039
try {
1039
- return array ( $ fieldName , $ this ->dm -> createDBRef ( $ value , $ mapping) );
1040
+ return $ this ->prepareDbRefElement ( $ fieldName , $ value , $ mapping );
1040
1041
} catch (MappingException $ e ) {
1041
1042
// do nothing in case passed object is not mapped document
1042
1043
}
@@ -1046,47 +1047,47 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1046
1047
// We can't have expressions in empty() with PHP < 5.5, so store it in a variable
1047
1048
$ arrayValue = (array ) $ value ;
1048
1049
if (empty ($ mapping ['reference ' ]) || $ mapping ['storeAs ' ] !== ClassMetadataInfo::REFERENCE_STORE_AS_ID || empty ($ arrayValue )) {
1049
- return array ( $ fieldName , $ value) ;
1050
+ return [[ $ fieldName , $ value]] ;
1050
1051
}
1051
1052
1052
1053
// Additional preparation for one or more simple reference values
1053
1054
$ targetClass = $ this ->dm ->getClassMetadata ($ mapping ['targetDocument ' ]);
1054
1055
1055
1056
if ( ! is_array ($ value )) {
1056
- return array ( $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )) ;
1057
+ return [[ $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )]] ;
1057
1058
}
1058
1059
1059
1060
// Objects without operators or with DBRef fields can be converted immediately
1060
1061
if ( ! $ this ->hasQueryOperators ($ value ) || $ this ->hasDBRefFields ($ value )) {
1061
- return array ( $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )) ;
1062
+ return [[ $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )]] ;
1062
1063
}
1063
1064
1064
- return array ( $ fieldName , $ this ->prepareQueryExpression ($ value , $ targetClass )) ;
1065
+ return [[ $ fieldName , $ this ->prepareQueryExpression ($ value , $ targetClass )]] ;
1065
1066
}
1066
1067
1067
1068
// Process identifier fields
1068
1069
if (($ class ->hasField ($ fieldName ) && $ class ->isIdentifier ($ fieldName )) || $ fieldName === '_id ' ) {
1069
1070
$ fieldName = '_id ' ;
1070
1071
1071
1072
if ( ! $ prepareValue ) {
1072
- return array ( $ fieldName , $ value) ;
1073
+ return [[ $ fieldName , $ value]] ;
1073
1074
}
1074
1075
1075
1076
if ( ! is_array ($ value )) {
1076
- return array ( $ fieldName , $ class ->getDatabaseIdentifierValue ($ value )) ;
1077
+ return [[ $ fieldName , $ class ->getDatabaseIdentifierValue ($ value )]] ;
1077
1078
}
1078
1079
1079
1080
// Objects without operators or with DBRef fields can be converted immediately
1080
1081
if ( ! $ this ->hasQueryOperators ($ value ) || $ this ->hasDBRefFields ($ value )) {
1081
- return array ( $ fieldName , $ class ->getDatabaseIdentifierValue ($ value )) ;
1082
+ return [[ $ fieldName , $ class ->getDatabaseIdentifierValue ($ value )]] ;
1082
1083
}
1083
1084
1084
- return array ( $ fieldName , $ this ->prepareQueryExpression ($ value , $ class )) ;
1085
+ return [[ $ fieldName , $ this ->prepareQueryExpression ($ value , $ class )]] ;
1085
1086
}
1086
1087
1087
1088
// No processing for unmapped, non-identifier, non-dotted field names
1088
1089
if (strpos ($ fieldName , '. ' ) === false ) {
1089
- return array ( $ fieldName , $ value) ;
1090
+ return [[ $ fieldName , $ value]] ;
1090
1091
}
1091
1092
1092
1093
/* Process "fieldName.objectProperty" queries (on arrays or objects).
@@ -1099,7 +1100,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1099
1100
1100
1101
// No further processing for unmapped fields
1101
1102
if ( ! isset ($ class ->fieldMappings [$ e [0 ]])) {
1102
- return array ( $ fieldName , $ value) ;
1103
+ return [[ $ fieldName , $ value]] ;
1103
1104
}
1104
1105
1105
1106
$ mapping = $ class ->fieldMappings [$ e [0 ]];
@@ -1109,7 +1110,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1109
1110
if ($ mapping ['type ' ] === Type::HASH || $ mapping ['type ' ] === Type::RAW ) {
1110
1111
$ fieldName = implode ('. ' , $ e );
1111
1112
1112
- return array ( $ fieldName , $ value) ;
1113
+ return [[ $ fieldName , $ value]] ;
1113
1114
}
1114
1115
1115
1116
if ($ mapping ['type ' ] == 'many ' && CollectionHelper::isHash ($ mapping ['strategy ' ])
@@ -1130,7 +1131,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1130
1131
} else {
1131
1132
$ fieldName = $ e [0 ] . '. ' . $ e [1 ];
1132
1133
1133
- return array ( $ fieldName , $ value) ;
1134
+ return [[ $ fieldName , $ value]] ;
1134
1135
}
1135
1136
1136
1137
// No further processing for fields without a targetDocument mapping
@@ -1139,7 +1140,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1139
1140
$ fieldName .= '. ' .$ nextObjectProperty ;
1140
1141
}
1141
1142
1142
- return array ( $ fieldName , $ value) ;
1143
+ return [[ $ fieldName , $ value]] ;
1143
1144
}
1144
1145
1145
1146
$ targetClass = $ this ->dm ->getClassMetadata ($ mapping ['targetDocument ' ]);
@@ -1150,7 +1151,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1150
1151
$ fieldName .= '. ' .$ nextObjectProperty ;
1151
1152
}
1152
1153
1153
- return array ( $ fieldName , $ value) ;
1154
+ return [[ $ fieldName , $ value]] ;
1154
1155
}
1155
1156
1156
1157
$ targetMapping = $ targetClass ->getFieldMapping ($ objectProperty );
@@ -1164,19 +1165,19 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1164
1165
// Process targetDocument identifier fields
1165
1166
if ($ objectPropertyIsId ) {
1166
1167
if ( ! $ prepareValue ) {
1167
- return array ( $ fieldName , $ value) ;
1168
+ return [[ $ fieldName , $ value]] ;
1168
1169
}
1169
1170
1170
1171
if ( ! is_array ($ value )) {
1171
- return array ( $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )) ;
1172
+ return [[ $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )]] ;
1172
1173
}
1173
1174
1174
1175
// Objects without operators or with DBRef fields can be converted immediately
1175
1176
if ( ! $ this ->hasQueryOperators ($ value ) || $ this ->hasDBRefFields ($ value )) {
1176
- return array ( $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )) ;
1177
+ return [[ $ fieldName , $ targetClass ->getDatabaseIdentifierValue ($ value )]] ;
1177
1178
}
1178
1179
1179
- return array ( $ fieldName , $ this ->prepareQueryExpression ($ value , $ targetClass )) ;
1180
+ return [[ $ fieldName , $ this ->prepareQueryExpression ($ value , $ targetClass )]] ;
1180
1181
}
1181
1182
1182
1183
/* The property path may include a third field segment, excluding the
@@ -1189,12 +1190,16 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $
1189
1190
? $ this ->dm ->getClassMetadata ($ targetMapping ['targetDocument ' ])
1190
1191
: null ;
1191
1192
1192
- list ($ key , $ value ) = $ this ->prepareQueryElement ($ nextObjectProperty , $ value , $ nextTargetClass , $ prepareValue );
1193
+ $ fieldNames = $ this ->prepareQueryElement ($ nextObjectProperty , $ value , $ nextTargetClass , $ prepareValue );
1194
+
1195
+ return array_map (function ($ preparedTuple ) use ($ fieldName ) {
1196
+ list ($ key , $ value ) = $ preparedTuple ;
1193
1197
1194
- $ fieldName .= '. ' . $ key ;
1198
+ return [$ fieldName . '. ' . $ key , $ value ];
1199
+ }, $ fieldNames );
1195
1200
}
1196
1201
1197
- return array ( $ fieldName , $ value) ;
1202
+ return [[ $ fieldName , $ value]] ;
1198
1203
}
1199
1204
1200
1205
/**
@@ -1390,4 +1395,35 @@ private function getWriteOptions(array $options = array())
1390
1395
1391
1396
return array_merge ($ defaultOptions , $ documentOptions , $ options );
1392
1397
}
1398
+
1399
+ /**
1400
+ * @param string $fieldName
1401
+ * @param mixed $value
1402
+ * @param array $mapping
1403
+ * @return array
1404
+ */
1405
+ private function prepareDbRefElement ($ fieldName , $ value , array $ mapping )
1406
+ {
1407
+ $ dbRef = $ this ->dm ->createDBRef ($ value , $ mapping );
1408
+ $ keys = ['$ref ' => true , '$id ' => true , '$db ' => true ];
1409
+ if ($ mapping ['storeAs ' ] === ClassMetadataInfo::REFERENCE_STORE_AS_ID ) {
1410
+ unset($ keys ['$db ' ]);
1411
+ }
1412
+ if (isset ($ mapping ['targetDocument ' ])) {
1413
+ unset($ keys ['$ref ' ], $ keys ['$db ' ]);
1414
+ }
1415
+
1416
+ if ($ mapping ['storeAs ' ] === ClassMetadataInfo::REFERENCE_STORE_AS_ID ) {
1417
+ return [[$ fieldName , $ dbRef ]];
1418
+ } elseif ($ mapping ['type ' ] === 'many ' ) {
1419
+ return [[$ fieldName , ['$elemMatch ' => array_intersect_key ($ dbRef , $ keys )]]];
1420
+ } else {
1421
+ return array_map (
1422
+ function ($ key ) use ($ dbRef , $ fieldName ) {
1423
+ return [$ fieldName . '. ' . $ key , $ dbRef [$ key ]];
1424
+ },
1425
+ array_keys ($ keys )
1426
+ );
1427
+ }
1428
+ }
1393
1429
}
0 commit comments