aboutsummaryrefslogtreecommitdiff
path: root/lib/models/SimpleORMap.class.php
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+studip@gmail.com>2024-10-29 13:47:36 +0000
committerJan-Hendrik Willms <tleilax+github@gmail.com>2024-10-29 14:49:35 +0100
commit39720acf9a5242bf208bc9f3f7777016c7cb64be (patch)
tree903f8ced9ac65549b3932234201e8ea16dfc872b /lib/models/SimpleORMap.class.php
parentc6a3494a08f0f45edede344d11651549c2848988 (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.php55
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,
+ );
+
+ }
}
}