From b01ae186a6bd3534b6cd04af404f2a98cf356b9f Mon Sep 17 00:00:00 2001 From: blackcoder87 Date: Thu, 16 Jan 2025 09:26:01 +0100 Subject: [PATCH] Training: Improve getNextTrainings Fix deleting of multiple trainings. --- .../modules/training/boxes/Nexttraining.php | 10 +-- .../training/controllers/admin/Index.php | 6 +- .../modules/training/mappers/Training.php | 70 +++++++++++-------- .../modules/training/models/Training.php | 2 +- .../training/views/admin/index/index.php | 10 +-- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/application/modules/training/boxes/Nexttraining.php b/application/modules/training/boxes/Nexttraining.php index b47947bcb..484231063 100644 --- a/application/modules/training/boxes/Nexttraining.php +++ b/application/modules/training/boxes/Nexttraining.php @@ -9,7 +9,6 @@ use Modules\Training\Mappers\Training as TrainingMapper; use Modules\Training\Mappers\Entrants as EntrantsMapper; -use Modules\Training\Models\Training as TrainingModel; use Modules\User\Mappers\User as UserMapper; class Nexttraining extends \Ilch\Box @@ -31,15 +30,8 @@ public function render() } } - // Get trainings, calculate next date if it's a recurrent event and sort them by date. - $trainings = $trainingMapper->getNextTrainings($config->get('training_boxNexttrainingLimit') ?? 5, $groupIds); - foreach ($trainings as $training) { - $trainingMapper->calculateNextTrainingDate($training); - } - usort($trainings, fn(TrainingModel $a, TrainingModel $b) => strcmp($a->getDate(), $b->getDate())); - $this->getView()->set('trainingMapper', $trainingMapper) ->set('entrantsMapper', $entrantsMapper) - ->set('trainings', $trainings); + ->set('trainings', $trainingMapper->getNextTrainings($config->get('training_boxNexttrainingLimit') ?? 5, $groupIds)); } } diff --git a/application/modules/training/controllers/admin/Index.php b/application/modules/training/controllers/admin/Index.php index c13123813..9ce86e8f8 100644 --- a/application/modules/training/controllers/admin/Index.php +++ b/application/modules/training/controllers/admin/Index.php @@ -52,8 +52,8 @@ public function indexAction() $trainingMapper = new TrainingMapper(); $this->getLayout()->getAdminHmenu() ->add($this->getTranslator()->trans('menuTraining'), ['action' => 'index']); - if ($this->getRequest()->getPost('check_training') && $this->getRequest()->getPost('action') === 'delete') { - foreach ($this->getRequest()->getPost('check_training') as $trainingId) { + if ($this->getRequest()->getPost('check_trainings') && $this->getRequest()->getPost('action') === 'delete') { + foreach ($this->getRequest()->getPost('check_trainings') as $trainingId) { $trainingMapper->delete($trainingId); } $this->redirect() @@ -61,7 +61,7 @@ public function indexAction() ->to(['action' => 'index']); } - $this->getView()->set('training', $trainingMapper->getEntriesBy()); + $this->getView()->set('trainings', $trainingMapper->getEntriesBy()); } public function treatAction() diff --git a/application/modules/training/mappers/Training.php b/application/modules/training/mappers/Training.php index 41f970b77..5e4ecd505 100644 --- a/application/modules/training/mappers/Training.php +++ b/application/modules/training/mappers/Training.php @@ -176,37 +176,52 @@ public function getTrainingsListWithLimt(?int $limit = null, $groupIds = '3', st * * @param int|null $limit * @param string|array|null $groupIds A string like '1,2,3' or an array like [1,2,3] - * @param string $order ASC|DESC * @return TrainingModel[]|null * @since Version 1.10.0 */ - public function getNextTrainings(?int $limit = null, $groupIds = '3', string $order = 'ASC'): ?array + public function getNextTrainings(?int $limit = null, $groupIds = '3'): ?array { + $pagination = new Pagination(); + if ($limit) { - $pagination = new Pagination(); $pagination->setRowsPerPage($limit); } $currentDate = new \Ilch\Date(); $currentDate->format("Y-m-d H:i:s"); - $select = $this->db()->select(); + + // Get all recurrent trainings with a repeat until date not in the past. + $where = [ + 't.period_type !=' => '', + 't.repeat_until >' => $currentDate, + 'ra.read_access' => $groupIds + ]; + $recurrentTrainings = $this->getEntriesBy($where) ?? []; + + // Calculate next training dates for the recurrent trainings. + foreach ($recurrentTrainings as $training) { + $this->calculateNextTrainingDate($training); + } + + // Get the next trainings. Taking the limit into account. $where = [ - $select->orX([ - $select->andX([ - 't.period_type !=' => '', - 't.repeat_until >' => $currentDate, - ] - ), - $select->andX([ - 't.period_type =' => '', - 't.date >=' => $currentDate, - ] - ), - ]), + 't.period_type =' => '', + 't.date >=' => $currentDate, 'ra.read_access' => $groupIds ]; - return $this->getEntriesBy($where, ['t.date' => $order], $pagination ?? null); + $trainings = array_merge($recurrentTrainings, $this->getEntriesBy($where, ['t.date' => 'ASC'], $pagination ?? null) ?? []); + + // Sort all trainings by date. + usort($trainings, fn(TrainingModel $a, TrainingModel $b) => strcmp($a->getDate(), $b->getDate())); + + // If there is a limit then only return the number of trainings according to the limit as there + // might be more results than needed. + if ($limit) { + return array_slice($trainings, 0, $limit); + } + + return $trainings; } /** @@ -248,31 +263,26 @@ public function countdown(\Ilch\Date $countdown_date, int $countdown_time = 60) } /** - * Calculate the next training date. + * Calculate the next training date. Updates the passed parameter. * * @param TrainingModel $training - * @return TrainingModel + * @return void * @throws \DateMalformedPeriodStringException * @since Version 1.10.0 */ - public function calculateNextTrainingDate(TrainingModel $training): TrainingModel + public function calculateNextTrainingDate(TrainingModel $training) { // Early return if this is not a recurrent training. if ($training->getPeriodType() === '') { - return $training; + return; } $givenDate = new \Ilch\Date(); $begin = new \Ilch\Date($training->getDate()); - // Early return if the date is still in the future. - if ($begin > $givenDate) { - return $training; - } - - // Early return if the repeat until date is in the past. - if ($givenDate > new \Ilch\Date($training->getRepeatUntil())) { - return $training; + // Early return if the date is still in the future or if the repeat until date is in the past. + if ($begin > $givenDate || ($givenDate > new \Ilch\Date($training->getRepeatUntil()))) { + return; } $interval = null; @@ -337,8 +347,6 @@ public function calculateNextTrainingDate(TrainingModel $training): TrainingMode $training->setEnd($date->format('Y-m-d H:i:s')); break; } - - return $training; } /** diff --git a/application/modules/training/models/Training.php b/application/modules/training/models/Training.php index 1ba9b3167..01552a055 100644 --- a/application/modules/training/models/Training.php +++ b/application/modules/training/models/Training.php @@ -45,7 +45,7 @@ class Training extends \Ilch\Model protected int $periodDay = 0; /** - * period day of the training. + * period type of the training. * * @var string */ diff --git a/application/modules/training/views/admin/index/index.php b/application/modules/training/views/admin/index/index.php index e56543717..030ac4030 100644 --- a/application/modules/training/views/admin/index/index.php +++ b/application/modules/training/views/admin/index/index.php @@ -2,8 +2,8 @@ /** @var \Ilch\View $this */ -/** @var \Modules\Training\Models\Training[]|null $training */ -$training = $this->get('training'); +/** @var \Modules\Training\Models\Training[]|null $trainings */ +$trainings = $this->get('trainings'); $periodDays = [ '1' => $this->getTranslator()->trans('Monday'), @@ -24,7 +24,7 @@ ]; ?>

getTrans('manage') ?>

- +
getTokenField() ?>
@@ -41,7 +41,7 @@ - getCheckAllCheckbox('check_training') ?> + getCheckAllCheckbox('check_trainings') ?> getTrans('start') ?> @@ -52,7 +52,7 @@ - getDate()) { $date = new \Ilch\Date($model->getDate());