@@ -169,21 +169,60 @@ public function request() : array
169
169
$ sort = '' ;
170
170
if (array_key_exists ('sort ' , $ this ->request )) {
171
171
$ sort = $ this ->request ['sort ' ];
172
+ $ columnsData = $ this ->getTableColumns ();
172
173
173
- if (!empty ($ sort )) {
174
+ if (!empty ($ sort ) && strpos ( $ sort , ' | ' ) !== false ) {
174
175
// Get the model, column and sort order from the sent parameter.
175
- $ modelColumn = $ sort ;
176
- if (strpos ($ sort , '| ' ) !== false ) {
177
- list ($ modelColumn , $ order ) = explode ('| ' , $ sort );
178
- }
176
+ list ($ modelColumn , $ order ) = explode ('| ' , $ sort );
179
177
$ order = strtolower ($ order ) === 'asc ' ? 'ASC ' : 'DESC ' ;
180
178
181
179
$ modelColumn = preg_replace ("/[^a-zA-Z0-9_\s]/ " , '' , $ modelColumn );
182
- $ columnsData = $ this -> getTableColumns ();
180
+ // Check to see whether this is a related sorting by looking for a
183
181
if (isset ($ columnsData [$ modelColumn ])) {
184
- $ sort = " ORDER BY {$ modelColumn } {$ order }" ;
182
+ if (strpos ($ modelColumn , '. ' ) !== false ) {
183
+ // We are using a related sort.
184
+ // Get the namespace for the models from the configuration.
185
+ $ modelNamespace = \Phalcon \Di::getDefault ()->getConfig ()->namespace ->models ;
186
+ // Get the model name and the sort column from the sent parameter
187
+ list ($ model , $ column ) = explode ('. ' , $ modelColumn );
188
+ // Convert the model name into camel case.
189
+ $ modelName = str_replace (' ' , '' , ucwords (str_replace ('_ ' , ' ' , $ model )));
190
+ // Create the model name with the appended namespace.
191
+ $ modelName = $ modelNamespace . '\\' . $ modelName ;
192
+
193
+ // Make sure the model exists.
194
+ if (!class_exists ($ modelName )) {
195
+ throw new \Exception ('Related model does not exist. ' );
196
+ }
197
+
198
+ // Instance the model so we have access to the getSource() function.
199
+ $ modelObject = new $ modelName ();
200
+ // Instance meta data memory to access the primary keys for the table.
201
+ $ metaData = new \Phalcon \Mvc \Model \MetaData \Memory ();
202
+ // Get the first matching primary key.
203
+ // @TODO This will hurt on compound primary keys.
204
+ $ primaryKey = $ metaData ->getPrimaryKeyAttributes ($ modelObject )[0 ];
205
+ if ($ metaData ->hasAttribute ($ modelObject , $ column )) {
206
+ // We need the table to exist in the query in order for the related sort to work.
207
+ // Therefore we add it to comply with this by comparing the primary key to not being NULL.
208
+ $ this ->relationSearchFields [$ modelName ][] = [
209
+ $ primaryKey , ': ' , '$$ ' ,
210
+ ];
211
+
212
+ $ sort = " ORDER BY {$ modelObject ->getSource ()}. {$ column } {$ order }" ;
213
+ }
214
+ unset($ modelObject );
215
+ } else {
216
+ $ sort = " ORDER BY {$ modelColumn } {$ order }" ;
217
+ }
218
+ } else {
219
+ $ sort = null ;
220
+ }
221
+ } else {
222
+ if (isset ($ columnsData [$ sort ])) {
223
+ $ sort = " ORDER BY {$ sort } DESC " ;
185
224
} else {
186
- $ sort = '' ;
225
+ $ sort = null ;
187
226
}
188
227
}
189
228
}
0 commit comments