@@ -75,18 +75,27 @@ private function __construct(array $schema, array $request_params)
7575
7676 private function getSQLFieldForProperty (string $ prop_name ): string
7777 {
78- $ prop = $ this ->flattened_properties [$ prop_name ];
79- $ is_join = str_contains ($ prop_name , '. ' );
80- $ sql_field = $ prop ['x-field ' ] ?? $ prop_name ;
78+ $ real_prop_name = str_replace (chr (0x1F ), '. ' , $ prop_name );
79+ $ prop = $ this ->flattened_properties [$ real_prop_name ];
80+ $ is_join = str_contains ($ real_prop_name , '. ' );
81+ $ sql_field = $ prop ['x-field ' ] ?? $ real_prop_name ;
8182 if (!$ is_join ) {
8283 // Only add the _. prefix if it isn't a join
8384 $ sql_field = "_. $ sql_field " ;
84- } else if ($ prop_name !== $ sql_field ) {
85+ } else if ($ real_prop_name !== $ sql_field ) {
8586 // If the property name is different from the SQL field name, we will need to add/change the table alias
8687 // $prop_name is a join where the part before the dot is the join alias (also the property on the main item), and the part after the dot is the property on the joined item
87- $ join_alias = explode ('. ' , $ prop_name )[0 ];
88+ $ parts = explode ('. ' , $ prop_name );
89+ array_pop ($ parts ); // Get rid of the field
90+ $ join_alias = implode ('. ' , $ parts );
8891 $ sql_field = "{$ join_alias }. {$ sql_field }" ;
8992 }
93+ $ parts = explode ('. ' , $ sql_field );
94+ if (count ($ parts ) > 2 ) {
95+ $ field = array_pop ($ parts );
96+ $ table = implode (chr (0x1F ), $ parts );
97+ $ sql_field = "{$ table }. {$ field }" ;
98+ }
9099 return $ sql_field ;
91100 }
92101
@@ -98,6 +107,7 @@ private function getSelectCriteriaForProperty(string $prop_name, bool $distinct_
98107 {
99108 global $ DB ;
100109
110+ $ prop_name = str_replace (chr (0x1F ), '. ' , $ prop_name );
101111 $ prop = $ this ->flattened_properties [$ prop_name ];
102112 if ($ prop ['x-writeonly ' ] ?? false ) {
103113 // Do not expose write-only fields
@@ -157,6 +167,7 @@ private static function getJoins(string $join_alias, array $join_definition): ar
157167 if (!isset ($ joins [$ join_type ])) {
158168 $ joins [$ join_type ] = [];
159169 }
170+ $ join_alias = str_replace ('. ' , chr (0x1F ), $ join_alias );
160171 $ join_table = $ join ['table ' ] . ' AS ' . $ join_alias ;
161172 $ join_parent = (isset ($ join ['ref_join ' ]) && $ join ['ref_join ' ]) ? "{$ join_alias }_ref " : '_ ' ;
162173 if (isset ($ join ['ref_join ' ])) {
@@ -304,6 +315,7 @@ private function getMatchingRecords($ignore_pagination = false): array
304315 $ criteria ['GROUPBY ' ] = ['_itemtype ' , '_.id ' ];
305316 } else {
306317 foreach ($ this ->joins as $ join_alias => $ join ) {
318+ $ join_alias = str_replace ('. ' , chr (0x1F ), $ join_alias );
307319 $ s = $ this ->getSelectCriteriaForProperty ("$ join_alias.id " , true );
308320 if ($ s !== null ) {
309321 $ criteria ['SELECT ' ][] = $ s ;
@@ -409,6 +421,11 @@ private function hydrateRecords(array $records): array
409421 }
410422 } else {
411423 foreach ($ this ->joins as $ join_alias => $ join ) {
424+ $ parts = explode (chr (0x1F ), $ fkey );
425+ if (count ($ parts ) > 1 ) {
426+ $ field = array_pop ($ parts );
427+ $ fkey = implode ('. ' , $ parts ) . chr (0x1F ) . $ field ;
428+ }
412429 if ($ fkey === $ join_alias . chr (0x1F ) . 'id ' ) {
413430 $ fkey_tables [$ fkey ] = $ join ['table ' ];
414431 break ;
@@ -454,17 +471,20 @@ private function hydrateRecords(array $records): array
454471 $ criteria ['SELECT ' ][] = new QueryExpression ($ DB ::quoteValue ($ schema_name ), '_itemtype ' );
455472 }
456473 } else {
457- $ join_name = explode (chr (0x1F ), $ fkey )[0 ];
458- $ props_to_use = array_filter ($ this ->flattened_properties , static function ($ prop_name ) use ($ join_name ) {
459- return str_starts_with ($ prop_name , $ join_name . '. ' );
474+ $ join_name_parts = explode (chr (0x1F ), $ fkey );
475+ array_pop ($ join_name_parts );
476+ $ join_name = implode (chr (0x1F ), $ join_name_parts );
477+ $ join_name_dotted = str_replace (chr (0x1F ), '. ' , $ join_name );
478+ $ props_to_use = array_filter ($ this ->flattened_properties , static function ($ prop_name ) use ($ join_name_dotted ) {
479+ return str_starts_with ($ prop_name , $ join_name_dotted . '. ' );
460480 }, ARRAY_FILTER_USE_KEY );
461481
462482 $ criteria ['FROM ' ] = "$ table AS " . $ DB ::quoteName ($ join_name );
463483 $ id_field = $ join_name . '.id ' ;
464484 }
465485 $ criteria ['WHERE ' ] = [$ id_field => $ ids_to_fetch ];
466486 foreach ($ props_to_use as $ prop_name => $ prop ) {
467- if ($ prop ['x-writeonly ' ] ?? false ) {
487+ if ($ prop ['x-writeonly ' ] ?? false || isset ( $ prop [ ' x-mapped-from ' ]) ) {
468488 continue ;
469489 }
470490 $ criteria ['SELECT ' ][] = $ this ->getSQLFieldForProperty ($ prop_name ) . ' AS ' . str_replace ('. ' , chr (0x1F ), $ prop_name );
0 commit comments