@@ -144,6 +144,16 @@ protected function getFeatures(): array {
144144 }
145145 return $ features ;
146146 }
147+
148+ /**
149+ * Get features based on DBA model features
150+ *
151+ * @param string $dbaClass is the dba class to get the features from
152+ */
153+ //TODO doesnt retrieve features based on form fields, could be done by adding api class in relationship objects
154+ final protected function getFeaturesOther (string $ dbaClass ): array {
155+ return call_user_func ($ dbaClass . '::getFeatures ' );
156+ }
147157
148158 protected function getUpdateHandlers ($ id , $ current_user ): array {
149159 return [];
@@ -174,6 +184,11 @@ public function getAliasedFeatures(): array {
174184 $ features = $ this ->getFeatures ();
175185 return $ this ->mapFeatures ($ features );
176186 }
187+
188+ public function getAliasedFeaturesOther ($ dbaClass ): array {
189+ $ features = $ this ->getFeaturesOther ($ dbaClass );
190+ return $ this ->mapFeatures ($ features );
191+ }
177192
178193 final protected function mapFeatures ($ features ): array {
179194 $ mappedFeatures = [];
@@ -183,6 +198,18 @@ final protected function mapFeatures($features): array {
183198 }
184199 return $ mappedFeatures ;
185200 }
201+
202+ public static function getToOneRelationships (): array {
203+ return [];
204+ }
205+
206+ public static function getToManyRelationships (): array {
207+ return [];
208+ }
209+
210+ public function getAllRelationships (): array {
211+ return array_merge ($ this ->getToOneRelationships (), $ this ->getToManyRelationships ());
212+ }
186213
187214 /**
188215 * Retrieve currently logged-in user
@@ -1145,19 +1172,39 @@ protected function makeOrderFilterTemplates(Request $request, array $features, s
11451172 $ orderings = $ this ->getQueryParameterAsList ($ request , 'sort ' );
11461173 $ contains_primary_key = false ;
11471174 foreach ($ orderings as $ order ) {
1148- if (preg_match ('/^(?P<operator>[-])?(?P<key>[_a-zA-Z]+)$/ ' , $ order , $ matches )) {
1175+ $ factory = null ;
1176+ $ joinKey = null ;
1177+ $ features_sort = $ features ;
1178+ if (preg_match ('/^(?P<operator>[-])?(?P<key>[_a-zA-Z.]+)$/ ' , $ order , $ matches )) {
11491179 // Special filtering of _id to use for uniform access to model primary key
11501180 $ cast_key = $ matches ['key ' ] == 'id ' ? $ this ->getPrimaryKey () : $ matches ['key ' ];
11511181 if ($ cast_key == $ this ->getPrimaryKey ()) {
11521182 $ contains_primary_key = true ;
11531183 }
1154- if (array_key_exists ($ cast_key , $ features )) {
1155- $ remappedKey = $ features [$ cast_key ]['dbname ' ];
1184+ if (strpos ($ cast_key , ". " )) {
1185+ $ parts = explode (". " , $ cast_key );
1186+ if (count ($ parts ) == 2 ) { // Only relations of 1 deep allowed ex. task.keyspace
1187+ $ relationString = $ parts [0 ];
1188+ //currently getting all relationships, but its probably only possible to sort on 1 to 1 relations
1189+ $ relations = $ this ->getAllRelationships ();
1190+ if (array_key_exists ($ relationString , $ relations )) {
1191+ $ relationClass = $ relations [$ relationString ]['relationType ' ];
1192+ $ relationFeatures = $ this ->getAliasedFeaturesOther ($ relationClass );
1193+ $ factory = $ this ->getModelFactory ($ relationClass );
1194+ $ joinKey = $ relations [$ relationString ]['relationKey ' ];
1195+ $ key = $ relations [$ relationString ]['key ' ];
1196+ $ features_sort = $ relationFeatures ;
1197+ $ cast_key = $ parts [1 ];
1198+ }
1199+ }
1200+ }
1201+ if (array_key_exists ($ cast_key , $ features_sort )) {
1202+ $ remappedKey = $ features_sort [$ cast_key ]['dbname ' ];
11561203 $ type = ($ matches ['operator ' ] == '- ' ) ? "DESC " : "ASC " ;
11571204 if ($ reverseSort ) {
11581205 $ type = ($ type == "ASC " ) ? "DESC " : "ASC " ;
11591206 }
1160- $ orderTemplates [] = ['by ' => $ remappedKey , 'type ' => $ type ];
1207+ $ orderTemplates [] = ['by ' => $ remappedKey , 'type ' => $ type, ' factory ' => $ factory , ' joinKey ' => $ joinKey , ' key ' => $ key ];
11611208 }
11621209 else {
11631210 throw new HttpForbidden ("Ordering parameter ' " . $ order . "' is not valid " );
@@ -1170,7 +1217,7 @@ protected function makeOrderFilterTemplates(Request $request, array $features, s
11701217
11711218 //when no primary key has been added in the sort parameter, add the default case of sorting on primary key as last sort
11721219 if (!$ contains_primary_key ) {
1173- $ orderTemplates [] = ['by ' => $ this ->getPrimaryKey (), 'type ' => $ defaultSort ];
1220+ $ orderTemplates [] = ['by ' => $ this ->getPrimaryKey (), 'type ' => $ defaultSort, ' factory ' => null , ' joinKey ' => null ];
11741221 }
11751222
11761223 return $ orderTemplates ;
0 commit comments