Skip to content
Snippets Groups Projects
Commit 545fe939 authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms
Browse files

allow sorm relations to be explicitely ordered in php on the collection and...

allow sorm relations to be explicitely ordered in php on the collection and use that for CourseDate::statusgruppen relation, fixes #4776
parent 595fe442
No related branches found
No related tags found
No related merge requests found
Pipeline #28246 passed
...@@ -682,8 +682,12 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate ...@@ -682,8 +682,12 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$db_table = static::db_table(); $db_table = static::db_table();
$sql = "SELECT `$db_table`.* FROM `$thru_table` $sql = "SELECT `$db_table`.* FROM `$thru_table`
INNER JOIN `$db_table` ON `$thru_table`.`$thru_assoc_key` = `$db_table`.`$assoc_foreign_key` JOIN `$db_table` ON `$thru_table`.`$thru_assoc_key` = `$db_table`.`$assoc_foreign_key`
WHERE `$thru_table`.`$thru_key` = ? " . ($options['order_by'] ?? ''); 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 = DBManager::get()->prepare($sql);
$st->execute([$foreign_key_value]); $st->execute([$foreign_key_value]);
...@@ -1180,11 +1184,15 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate ...@@ -1180,11 +1184,15 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
* or callback to invoke before record gets deleted * or callback to invoke before record gets deleted
* 'on_store': contains simply 'store' to indicate that related records should be stored * 'on_store': contains simply 'store' to indicate that related records should be stored
* or callback to invoke after record gets 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
*
* Note: Defining order_by_php will disable any set order_by option.
* *
* @param string $relation name of relation * @param string $relation name of relation
* @return array assoc array containing options * @return array assoc array containing options
*/ */
function getRelationOptions($relation) public function getRelationOptions($relation)
{ {
$options = []; $options = [];
foreach(['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) { foreach(['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) {
...@@ -2272,19 +2280,36 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate ...@@ -2272,19 +2280,36 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
} }
if ($this->relations[$relation] === null) { if ($this->relations[$relation] === null) {
$options = $this->getRelationOptions($relation); $options = $this->getRelationOptions($relation);
$to_call = [$options['class_name'], $options['assoc_func']]; $to_call = [$options['class_name'], $options['assoc_func']];
if (!is_callable($to_call)) { if (!is_callable($to_call)) {
throw new RuntimeException('assoc_func: ' . join('::', $to_call) . ' is not callable.' ); throw new RuntimeException('assoc_func: ' . join('::', $to_call) . ' is not callable.' );
} }
$params = $options['assoc_func_params_func']; $params = $options['assoc_func_params_func'];
if ($options['type'] === 'has_many') { if ($options['type'] === 'has_many') {
$records = function ($record) use ($to_call, $params, $options) { $records = function ($record) use ($to_call, $params, $options) {
$p = (array) $params($record); $p = (array) $params($record);
return call_user_func_array($to_call, array_merge(count($p) ? $p : [null], [$options['order_by'] ?? null])); 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); $this->relations[$relation] = new SimpleORMapCollection($records, $options, $this);
} elseif ($options['type'] === 'has_and_belongs_to_many') { } 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); $this->relations[$relation] = new SimpleORMapCollection($records, $options, $this);
} else { } else {
$p = (array) $params($this); $p = (array) $params($this);
...@@ -2292,6 +2317,14 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate ...@@ -2292,6 +2317,14 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$result = is_array($records) ? ($records[0] ?? null) : $records; $result = is_array($records) ? ($records[0] ?? null) : $records;
$this->relations[$relation] = $result; $this->relations[$relation] = $result;
} }
if (
!empty($options['order_by_php'])
&& $this->relations[$relation] instanceof SimpleORMapCollection
) {
$this->relations[$relation]->orderBy($options['order_by_php']);
}
} }
} }
......
...@@ -59,7 +59,7 @@ class CourseDate extends SimpleORMap implements PrivacyObject, Event ...@@ -59,7 +59,7 @@ class CourseDate extends SimpleORMap implements PrivacyObject, Event
$config['has_and_belongs_to_many']['statusgruppen'] = [ $config['has_and_belongs_to_many']['statusgruppen'] = [
'class_name' => Statusgruppen::class, 'class_name' => Statusgruppen::class,
'thru_table' => 'termin_related_groups', 'thru_table' => 'termin_related_groups',
'order_by' => 'ORDER BY position', 'order_by_php' => 'position',
'on_delete' => 'delete', 'on_delete' => 'delete',
'on_store' => 'store' 'on_store' => 'store'
]; ];
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment