@@ -123,8 +123,18 @@ class Builder extends BaseBuilder
123123 */
124124 public $ options = [];
125125
126+ public const TRANSFORM_QUERY_DATE = 1 << 0 ;
127+ public const TRANSFORM_RESULT_DATE = 1 << 1 ;
128+ public const TRANSFORM_RENAME_QUERY_ROOT_ID = 1 << 2 ;
129+ public const TRANSFORM_RENAME_RESULT_ROOT_ID = 1 << 3 ;
130+ public const TRANSFORM_RENAME_QUERY_EMBED_ID = 1 << 4 ;
131+ public const TRANSFORM_RENAME_RESULT_EMBED_ID = 1 << 5 ;
132+
133+ /** @var int-mask-of<self::TRANSFORM_* */
134+ private int $ transformations = -1 ;
135+
126136 /**
127- * All of the available clause operators.
137+ * All the available clause operators.
128138 *
129139 * @var array
130140 */
@@ -575,6 +585,27 @@ public function generateCacheKey()
575585 return md5 (serialize (array_values ($ key )));
576586 }
577587
588+ public function disableDateTransformation (): static
589+ {
590+ $ this ->transformations &= ~self ::TRANSFORM_QUERY_DATE & ~self ::TRANSFORM_RESULT_DATE ;
591+
592+ return $ this ;
593+ }
594+
595+ public function disableRootIdTransformation (): static
596+ {
597+ $ this ->transformations &= ~self ::TRANSFORM_RENAME_QUERY_ROOT_ID & ~self ::TRANSFORM_RENAME_RESULT_ROOT_ID ;
598+
599+ return $ this ;
600+ }
601+
602+ public function disableEmbedIdTransformation (): static
603+ {
604+ $ this ->transformations &= ~self ::TRANSFORM_RENAME_QUERY_EMBED_ID & ~self ::TRANSFORM_RENAME_RESULT_EMBED_ID ;
605+
606+ return $ this ;
607+ }
608+
578609 /** @return ($function is null ? AggregationBuilder : mixed) */
579610 public function aggregate ($ function = null , $ columns = ['* ' ])
580611 {
@@ -1763,9 +1794,12 @@ public function orWhereIntegerNotInRaw($column, $values, $boolean = 'and')
17631794 throw new BadMethodCallException ('This method is not supported by MongoDB ' );
17641795 }
17651796
1766- private function aliasIdForQuery (array $ values ): array
1797+ private function aliasIdForQuery (array $ values, bool $ root = true ): array
17671798 {
1768- if (array_key_exists ('id ' , $ values )) {
1799+ if (
1800+ ($ root && $ this ->transformations & self ::TRANSFORM_RENAME_QUERY_ROOT_ID || ! $ root && $ this ->transformations & self ::TRANSFORM_RENAME_QUERY_EMBED_ID )
1801+ && array_key_exists ('id ' , $ values )
1802+ ) {
17691803 if (array_key_exists ('_id ' , $ values ) && $ values ['id ' ] !== $ values ['_id ' ]) {
17701804 throw new InvalidArgumentException ('Cannot have both "id" and "_id" fields. ' );
17711805 }
@@ -1792,7 +1826,10 @@ private function aliasIdForQuery(array $values): array
17921826 }
17931827
17941828 // ".id" subfield are alias for "._id"
1795- if (str_ends_with ($ key , '.id ' )) {
1829+ if (
1830+ $ this ->transformations & self ::TRANSFORM_RENAME_QUERY_EMBED_ID
1831+ && str_ends_with ($ key , '.id ' )
1832+ ) {
17961833 $ newkey = substr ($ key , 0 , -3 ) . '._id ' ;
17971834 if (array_key_exists ($ newkey , $ values ) && $ value !== $ values [$ newkey ]) {
17981835 throw new InvalidArgumentException (sprintf ('Cannot have both "%s" and "%s" fields. ' , $ key , $ newkey ));
@@ -1805,8 +1842,8 @@ private function aliasIdForQuery(array $values): array
18051842
18061843 foreach ($ values as &$ value ) {
18071844 if (is_array ($ value )) {
1808- $ value = $ this ->aliasIdForQuery ($ value );
1809- } elseif ($ value instanceof DateTimeInterface) {
1845+ $ value = $ this ->aliasIdForQuery ($ value, false );
1846+ } elseif ($ this -> transformations & self :: TRANSFORM_QUERY_DATE && $ value instanceof DateTimeInterface) {
18101847 $ value = new UTCDateTime ($ value );
18111848 }
18121849 }
@@ -1817,42 +1854,49 @@ private function aliasIdForQuery(array $values): array
18171854 /**
18181855 * @internal
18191856 *
1857+ * @param bool $embed True when applied to a sub-document
18201858 * @psalm-param T $values
18211859 *
18221860 * @psalm-return T
18231861 *
18241862 * @template T of array|object
18251863 */
1826- public function aliasIdForResult (array |object $ values ): array |object
1864+ public function aliasIdForResult (array |object $ values, bool $ root = false ): array |object
18271865 {
18281866 if (is_array ($ values )) {
1829- if (array_key_exists ('_id ' , $ values ) && ! array_key_exists ('id ' , $ values )) {
1867+ if (
1868+ ($ root && $ this ->transformations & self ::TRANSFORM_RENAME_RESULT_ROOT_ID || ! $ root && $ this ->transformations & self ::TRANSFORM_RENAME_QUERY_EMBED_ID )
1869+ && array_key_exists ('_id ' , $ values ) && ! array_key_exists ('id ' , $ values )
1870+ ) {
18301871 $ values ['id ' ] = $ values ['_id ' ];
18311872 unset($ values ['_id ' ]);
18321873 }
18331874
18341875 foreach ($ values as $ key => $ value ) {
1835- if ($ value instanceof UTCDateTime) {
1876+ if ($ this -> transformations & self :: TRANSFORM_RESULT_DATE && $ value instanceof UTCDateTime) {
18361877 $ values [$ key ] = Date::instance ($ value ->toDateTime ())
18371878 ->setTimezone (new DateTimeZone (date_default_timezone_get ()));
18381879 } elseif (is_array ($ value ) || is_object ($ value )) {
1839- $ values [$ key ] = $ this ->aliasIdForResult ($ value );
1880+ $ values [$ key ] = $ this ->aliasIdForResult ($ value, true );
18401881 }
18411882 }
18421883 }
18431884
18441885 if ($ values instanceof stdClass) {
1845- if (property_exists ($ values , '_id ' ) && ! property_exists ($ values , 'id ' )) {
1886+ if (
1887+ ($ root && $ this ->transformations & self ::TRANSFORM_RENAME_RESULT_ROOT_ID || ! $ root && $ this ->transformations & self ::TRANSFORM_RENAME_QUERY_EMBED_ID )
1888+ && property_exists ($ values , '_id ' ) && ! property_exists ($ values , 'id ' )
1889+ ) {
18461890 $ values ->id = $ values ->_id ;
18471891 unset($ values ->_id );
18481892 }
18491893
18501894 foreach (get_object_vars ($ values ) as $ key => $ value ) {
1851- if ($ value instanceof UTCDateTime) {
1895+ if ($ this -> transformations & self :: TRANSFORM_RESULT_DATE && $ value instanceof UTCDateTime) {
18521896 $ values ->{$ key } = Date::instance ($ value ->toDateTime ())
18531897 ->setTimezone (new DateTimeZone (date_default_timezone_get ()));
18541898 } elseif (is_array ($ value ) || is_object ($ value )) {
1855- $ values ->{$ key } = $ this ->aliasIdForResult ($ value );
1899+ $ values ->{$ key } = $ this ->aliasIdForResult ($ value, true );
18561900 }
18571901 }
18581902 }
0 commit comments