aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Eibrink-Lunzenauer <lunzenauer@elan-ev.de>2022-01-21 10:10:40 +0000
committerMarcus Eibrink-Lunzenauer <lunzenauer@elan-ev.de>2022-01-21 10:10:40 +0000
commitb6389b549adefbdbd5441e39b6514e7ed1f0e566 (patch)
tree6f0cf3df05b357d9522d67a973678cf133c1e7c0
parent27d90b64023cea588932282b1290325d14c3d26d (diff)
Courseware-Fortschrittseite beschleunigen (SORMless edition)
-rwxr-xr-xapp/controllers/course/courseware.php47
-rwxr-xr-xlib/models/Courseware/Instance.php35
2 files changed, 58 insertions, 24 deletions
diff --git a/app/controllers/course/courseware.php b/app/controllers/course/courseware.php
index c4aae64..1d93a0a 100755
--- a/app/controllers/course/courseware.php
+++ b/app/controllers/course/courseware.php
@@ -131,7 +131,7 @@ class Course_CoursewareController extends AuthenticatedController
return array_combine(array_column($elements, 'id'), $elements);
}
- private function computeChildrenOf(iterable $elements): iterable
+ private function computeChildrenOf(iterable &$elements): iterable
{
$childrenOf = [];
foreach ($elements as $elementId => $element) {
@@ -149,19 +149,28 @@ class Course_CoursewareController extends AuthenticatedController
private function computeSelfProgresses(
Instance $instance,
User $user,
- iterable $elements,
+ iterable &$elements,
bool $showProgressForAllParticipants
): iterable {
$progress = [];
/** @var \Course $course */
$course = $instance->getRange();
- $allBlocks = $instance->findAllBlocksGroupedByStructuralElementId();
+ $allBlockIds = $instance->findAllBlocksGroupedByStructuralElementId(function ($row) {
+ return $row['id'];
+ });
$courseMemberIds = $showProgressForAllParticipants
? array_column($course->getMembersWithStatus('autor'), 'user_id')
: [$user->getId()];
- $userProgresses = UserProgress::findBySQL('user_id IN (?)', [$courseMemberIds]);
+
+ $sql =
+ 'SELECT block_id, COUNT(grade) as count, SUM(grade) as grade ' .
+ 'FROM cw_user_progresses ' .
+ 'WHERE block_id IN (?) AND user_id IN (?) ' .
+ 'GROUP BY block_id';
+ $userProgresses = \DBManager::get()->fetchGrouped($sql, [$allBlockIds, $courseMemberIds]);
+
foreach ($elements as $elementId => $element) {
- $selfProgress = $this->getSelfProgresses($allBlocks, $elementId, $userProgresses, $courseMemberIds);
+ $selfProgress = $this->getSelfProgresses($allBlockIds, $elementId, $userProgresses, $courseMemberIds);
$progress[$elementId] = [
'self' => $selfProgress['counter'] ? $selfProgress['progress'] / $selfProgress['counter'] : 1,
];
@@ -171,31 +180,35 @@ class Course_CoursewareController extends AuthenticatedController
}
private function getSelfProgresses(
- array $allBlocks,
+ array &$allBlockIds,
string $elementId,
- array $userProgresses,
- array $courseMemberIds
+ array &$userProgresses,
+ array &$courseMemberIds
): array {
- $blks = $allBlocks[$elementId] ?: [];
+ $blks = $allBlockIds[$elementId] ?: [];
+ if (!count($blks)) {
+ return [
+ 'counter' => 0,
+ 'progress' => 1,
+ ];
+ }
$data = [
'counter' => count($blks),
'progress' => 0,
];
+
$usersCounter = count($courseMemberIds);
foreach ($blks as $blk) {
- $progresses = array_filter($userProgresses, function ($progress) use ($blk, $courseMemberIds) {
- return $progress->block_id === $blk->getId() && in_array($progress->user_id, $courseMemberIds);
- });
- $usersProgress = count($progresses) ? array_sum(array_column($progresses, 'grade')) : 0;
-
+ $progresses = $userProgresses[$blk];
+ $usersProgress = $progresses['count'] ? (float) $progresses['sum'] : 0;
$data['progress'] += $usersProgress / $usersCounter;
}
return $data;
}
- private function computeCumulativeProgresses(Instance $instance, iterable $elements, iterable $progress): iterable
+ private function computeCumulativeProgresses(Instance $instance, iterable &$elements, iterable &$progress): iterable
{
$childrenOf = $this->computeChildrenOf($elements);
@@ -225,7 +238,7 @@ class Course_CoursewareController extends AuthenticatedController
return $progress;
}
- private function prepareProgressData(iterable $elements, iterable $progress): iterable
+ private function prepareProgressData(iterable &$elements, iterable &$progress): iterable
{
$data = [];
foreach ($elements as $elementId => $element) {
@@ -246,7 +259,7 @@ class Course_CoursewareController extends AuthenticatedController
return $data;
}
- private function getChapterCounter(array $chapters): array
+ private function getChapterCounter(array &$chapters): array
{
$finished = 0;
$started = 0;
diff --git a/lib/models/Courseware/Instance.php b/lib/models/Courseware/Instance.php
index cc9189c..c823a4e 100755
--- a/lib/models/Courseware/Instance.php
+++ b/lib/models/Courseware/Instance.php
@@ -37,12 +37,19 @@ class Instance
$range->getConfiguration()->delete('COURSEWARE_SEQUENTIAL_PROGRESSION');
$range->getConfiguration()->delete('COURSEWARE_EDITING_PERMISSION');
- $last_element_configs = \ConfigValue::findBySQL('field = ? AND value LIKE ?', ['COURSEWARE_LAST_ELEMENT', '%'.$range->getRangeId().'%']);
+ $last_element_configs = \ConfigValue::findBySQL('field = ? AND value LIKE ?', [
+ 'COURSEWARE_LAST_ELEMENT',
+ '%' . $range->getRangeId() . '%',
+ ]);
foreach ($last_element_configs as $config) {
$arr = json_decode($config->value, true);
- $arr = array_filter($arr, function ($key) use ($range) {
- return $key !== $range->id;
- }, ARRAY_FILTER_USE_KEY);
+ $arr = array_filter(
+ $arr,
+ function ($key) use ($range) {
+ return $key !== $range->id;
+ },
+ ARRAY_FILTER_USE_KEY
+ );
\UserConfig::get($config->range_id)->unsetValue('COURSEWARE_LAST_ELEMENT');
\UserConfig::get($config->range_id)->store('COURSEWARE_LAST_ELEMENT', $arr);
}
@@ -270,8 +277,23 @@ class Instance
return $data;
}
- public function findAllBlocksGroupedByStructuralElementId(): iterable
+ /**
+ * Find all blocks of this instance and group them by their structural element's ID.
+ * You may specify your own `$formatter` instead of the default one which stores the blocks as instances of \Courseware\Block.
+ *
+ * @param ?callable(array $row): mixed $formatter Provide your own callable if you need something else instead of
+ * full-blown instances of \Courseware\Block.
+ * @return iterable all the (optionally formatted) blocks grouped by the IDs of the structural element containing
+ * that block.
+ */
+ public function findAllBlocksGroupedByStructuralElementId(callable $formatter = null): iterable
{
+ if (!$formatter) {
+ $formatter = function ($row) {
+ return \Courseware\Block::build($row, false);
+ };
+ }
+
$sql = 'SELECT se.id AS structural_element_id, b.*
FROM cw_structural_elements se
JOIN cw_containers c ON se.id = c.structural_element_id
@@ -286,11 +308,10 @@ class Instance
$structuralElementId = $row['structural_element_id'];
unset($row['structural_element_id']);
- $block = \Courseware\Block::build($row, false);
if (!isset($data[$structuralElementId])) {
$data[$structuralElementId] = [];
}
- $data[$structuralElementId][] = $block;
+ $data[$structuralElementId][] = $formatter($row);
}
return $data;