diff options
| author | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2024-10-29 13:47:36 +0000 |
|---|---|---|
| committer | Jan-Hendrik Willms <tleilax+github@gmail.com> | 2024-10-29 14:49:35 +0100 |
| commit | 39720acf9a5242bf208bc9f3f7777016c7cb64be (patch) | |
| tree | 903f8ced9ac65549b3932234201e8ea16dfc872b /lib/models/SimpleORMap.class.php | |
| parent | c6a3494a08f0f45edede344d11651549c2848988 (diff) | |
allow sorm relations to be explicitely ordered in php on the collection and use that for CourseDate::statusgruppen relation, fixes #4776
Closes #4776
Merge request studip/studip!3569
Diffstat (limited to 'lib/models/SimpleORMap.class.php')
| -rw-r--r-- | lib/models/SimpleORMap.class.php | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/lib/models/SimpleORMap.class.php b/lib/models/SimpleORMap.class.php index a42a792..eaed70c 100644 --- a/lib/models/SimpleORMap.class.php +++ b/lib/models/SimpleORMap.class.php @@ -682,8 +682,12 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate $db_table = static::db_table(); $sql = "SELECT `$db_table`.* FROM `$thru_table` - INNER JOIN `$db_table` ON `$thru_table`.`$thru_assoc_key` = `$db_table`.`$assoc_foreign_key` - WHERE `$thru_table`.`$thru_key` = ? " . ($options['order_by'] ?? ''); + JOIN `$db_table` ON `$thru_table`.`$thru_assoc_key` = `$db_table`.`$assoc_foreign_key` + WHERE `$thru_table`.`$thru_key` = ? "; + if (empty($options['order_by_php']) && !empty($options['order_by'])) { + $sql .= $options['order_by']; + } + $st = DBManager::get()->prepare($sql); $st->execute([$foreign_key_value]); @@ -1180,11 +1184,17 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate * or callback to invoke before record gets deleted * 'on_store': contains simply 'store' to indicate that related records should be stored * or callback to invoke after record gets stored + * 'order_by': optional ordering of relation items + * 'order_by_php': optional order performed on the collection and not in sql + * this may either be a string containing the columns and directions (e.g. 'foo desc, bar') + * or an array with the described string and a sort option flag (e.g. ['foo', SORT_NUMERIC]) + * + * Note: Defining order_by_php will disable any set order_by option. * * @param string $relation name of relation * @return array assoc array containing options */ - function getRelationOptions($relation) + public function getRelationOptions($relation) { $options = []; foreach(['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) { @@ -2293,26 +2303,55 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate } if ($this->relations[$relation] === null) { $options = $this->getRelationOptions($relation); + $to_call = [$options['class_name'], $options['assoc_func']]; if (!is_callable($to_call)) { throw new RuntimeException('assoc_func: ' . join('::', $to_call) . ' is not callable.' ); } + $params = $options['assoc_func_params_func']; if ($options['type'] === 'has_many') { - $records = function($record) use ($to_call, $params, $options) { - $p = (array)$params($record); - return call_user_func_array($to_call, array_merge(count($p) ? $p : [null], [$options['order_by'] ?? null])); + $records = function ($record) use ($to_call, $params, $options) { + $p = (array) $params($record); + return call_user_func_array( + $to_call, + array_merge( + count($p) ? $p : [null], + [empty($options['order_by_php']) ? $options['order_by'] ?? null : null] + ) + ); }; $this->relations[$relation] = new SimpleORMapCollection($records, $options, $this); } elseif ($options['type'] === 'has_and_belongs_to_many') { - $records = function($record) use ($to_call, $params, $options) {$p = (array)$params($record); return call_user_func_array($to_call, array_merge(count($p) ? $p : [null], [$options]));}; + $records = function ($record) use ($to_call, $params, $options) { + $p = (array) $params($record); + return call_user_func_array( + $to_call, + array_merge( + count($p) ? $p : [null], + [$options] + ) + ); + }; $this->relations[$relation] = new SimpleORMapCollection($records, $options, $this); } else { - $p = (array)$params($this); + $p = (array) $params($this); $records = call_user_func_array($to_call, count($p) ? $p : [null]); $result = is_array($records) ? ($records[0] ?? null) : $records; $this->relations[$relation] = $result; } + + if ( + !empty($options['order_by_php']) + && $this->relations[$relation] instanceof SimpleORMapCollection + ) { + $order_options = (array) $options['order_by_php']; + $this->relations[$relation]->orderBy( + $options['order_by_php'][0], + $options['order_by_php'][1] ?? SORT_LOCALE_STRING, + ); + + } } } |
