Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Training module: Add support for recurrent events #1140

Merged
merged 6 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/modules/training/boxes/views/nexttraining.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

<?php if ($training) : ?>
<?php foreach ($training as $model) :
$countdown = $trainingMapper->countdown(new \Ilch\Date($model->getDate()), $model->getTime());
$countdown = $trainingMapper->countdown(new \Ilch\Date($model->getDate()));
if ($countdown === false) {
continue;
}
Expand Down
32 changes: 27 additions & 5 deletions application/modules/training/config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Config extends \Ilch\Config\Install
{
public array $config = [
'key' => 'training',
'version' => '1.9.2',
'version' => '1.10.0',
'icon_small' => 'fa-solid fa-graduation-cap',
'author' => 'Veldscholten, Kevin',
'link' => 'https://ilch.de',
Expand Down Expand Up @@ -74,7 +74,10 @@ public function getInstallSql(): string
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL,
`date` DATETIME NOT NULL,
`time` INT(11) NOT NULL,
`end` DATETIME DEFAULT NULL,
`period_type` VARCHAR(100) NOT NULL,
`period_day` INT(11) NOT NULL,
`repeat_until` DATETIME DEFAULT NULL,
`place` VARCHAR(100) NOT NULL,
`contact` INT(11) UNSIGNED NOT NULL,
`voice_server` INT(11) NOT NULL,
Expand Down Expand Up @@ -132,7 +135,7 @@ public function getUpdate(string $installedVersion): string
// Convert tables to new character set and collate
$this->db()->query('ALTER TABLE `[prefix]_training` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->db()->query('ALTER TABLE `[prefix]_training_entrants` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
// no break
// no break
case "1.3.0":
case "1.4.0":
case "1.5.0":
Expand Down Expand Up @@ -265,14 +268,33 @@ public function getUpdate(string $installedVersion): string
$this->db()->query('ALTER TABLE `[prefix]_training_entrants` ADD CONSTRAINT `FK_[prefix]_training_entrants_[prefix]_users` FOREIGN KEY (`user_id`) REFERENCES `[prefix]_users` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE;');
// no break
case "1.8.0":
// no break
case "1.8.1":
// no break
case "1.9.0":
if ($this->db()->ifTableExists('calendar_events') && $this->db()->select('COUNT(*)', 'calendar_events', ['url' => 'training/trainings/index/'])->execute()->fetchCell() == 0) {
$this->db()->insert('calendar_events', ['url' => 'training/trainings/index/'])->execute();
}
// no break
case "1.9.1":
case "1.9.2":
// Add new columns for recurrent trainings feature.
$this->db()->queryMulti('ALTER TABLE `[prefix]_training` ADD `end` DATETIME DEFAULT NULL AFTER `date`;
ALTER TABLE `[prefix]_training` ADD `period_type` VARCHAR(100) NOT NULL AFTER `time`;
ALTER TABLE `[prefix]_training` ADD `period_day` INT(11) NOT NULL AFTER `period_type`;
ALTER TABLE `[prefix]_training` ADD `repeat_until` DATETIME DEFAULT NULL AFTER `period_day`;');

// Calculate the value for the end column with the columns date and time. Update the end column in the table.
$trainings = $this->db()->select(['id', 'date', 'time'])
->from(['training'])
->execute()
->fetchRows();

foreach ($trainings ?? [] as $training) {
$end = date("Y-m-d H:i:s", strtotime('+' . $training['time'] . ' minutes', strtotime($training['date'])));
$this->db()->update('training', ['end' => $end], ['id' => $training['id']]);
}

// Drop time column
$this->db()->query('ALTER TABLE `[prefix]_training` DROP COLUMN `time`;');
}

return '"' . $this->config['key'] . '" Update-function executed.';
Expand Down
4 changes: 4 additions & 0 deletions application/modules/training/controllers/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Modules\Training\Mappers\Entrants as EntrantsMapper;
use Modules\Training\Models\Entrants as EntrantsModel;
use Modules\User\Mappers\User as UserMapper;
use Modules\Calendar\Mappers\Calendar as CalendarMapper;

class Index extends \Ilch\Controller\Frontend
{
Expand Down Expand Up @@ -41,6 +42,7 @@ public function showAction()
$entrantsMapper = new EntrantsMapper();
$entrantsModel = new EntrantsModel();
$userMapper = new UserMapper();
$calendarMapper = new CalendarMapper();

$groupIds = [3];
if ($this->getUser()) {
Expand Down Expand Up @@ -85,6 +87,8 @@ public function showAction()

$trainEntrantsUser = $entrantsMapper->getEntrantsById($training->getId());
$this->getView()->set('training', $training)
->set('calendarMapper', $calendarMapper)
->set('iteration', $this->getRequest()->getParam('iteration'))
->set('trainEntrantsUser', $trainEntrantsUser);
}
}
5 changes: 4 additions & 1 deletion application/modules/training/controllers/Trainings.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@

use Modules\Training\Mappers\Training as TrainingMapper;
use Modules\User\Mappers\User as UserMapper;
use Modules\Calendar\Mappers\Calendar as CalendarMapper;

class Trainings extends \Ilch\Controller\Frontend
{
public function indexAction()
{
$trainingMapper = new TrainingMapper();
$userMapper = new UserMapper();
$calendarMapper = new CalendarMapper();
$this->getLayout()->setFile('modules/calendar/layouts/events');
$groupIds = [3];
if ($this->getUser()) {
Expand All @@ -27,6 +29,7 @@ public function indexAction()
}
}

$this->getView()->set('trainingList', $trainingMapper->getTrainingsForJson($this->getRequest()->getQuery('start'), $this->getRequest()->getQuery('end'), $groupIds));
$this->getView()->set('trainingList', $trainingMapper->getTrainingsForJson($this->getRequest()->getQuery('start'), $this->getRequest()->getQuery('end'), $groupIds))
->set('calendarMapper', $calendarMapper);
}
}
27 changes: 24 additions & 3 deletions application/modules/training/controllers/admin/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,35 @@ public function treatAction()
$this->getView()->set('training', $model);

if ($this->getRequest()->isPost()) {
Validation::setCustomFieldAliases([
'periodDay' => 'periodEntry',
'periodDays' => 'periodEntry',
'periodType' => 'periodEntry',
'date' => 'start',
]);

$rules = [
'title' => 'required',
'date' => 'required|date:d.m.Y H\:i',
'end' => 'required|date:d.m.Y H\:i',
'contact' => 'required|integer|min:1|exists:users,id,id,' . $this->getRequest()->getPost('contact'),
'voiceServer' => 'required|integer|min:0|max:1',
'gameServer' => 'required|integer|min:0|max:1',
'groups' => 'required',
'time' => 'required|integer',
'calendarShow' => 'required|integer|min:0|max:1',
];

if ($this->getRequest()->getPost('periodType') == 'days') {
$_POST['periodDay'] = $this->getRequest()->getPost('periodDays');
$rules['periodDay'] = 'required|numeric|min:1|max:7';
} elseif ($this->getRequest()->getPost('periodType') != '') {
$rules['periodDay'] = 'required|numeric|min:1';
}

if ($this->getRequest()->getPost('periodType') != '') {
$rules['repeatUntil'] = 'required|date:d.m.Y H\:i';
}

// Require atleast the address of the voice or gameserver if enabled.
if ($this->getRequest()->getPost('voiceServer')) {
$rules['voiceServerIP'] = 'required';
Expand All @@ -107,7 +126,10 @@ public function treatAction()
if ($validation->isValid()) {
$model->setTitle($this->getRequest()->getPost('title'))
->setDate(new \Ilch\Date($this->getRequest()->getPost('date')))
->setTime($this->getRequest()->getPost('time'))
->setEnd(new \Ilch\Date($this->getRequest()->getPost('end')))
->setPeriodDay($this->getRequest()->getPost('periodDay'))
->setPeriodType($this->getRequest()->getPost('periodType'))
->setRepeatUntil($this->getRequest()->getPost('repeatUntil') ? new \Ilch\Date($this->getRequest()->getPost('repeatUntil')) : '1000-01-01 00:00:00')
->setPlace($this->getRequest()->getPost('place'))
->setContact($this->getRequest()->getPost('contact'))
->setVoiceServer($this->getRequest()->getPost('voiceServer') ?? false)
Expand All @@ -119,7 +141,6 @@ public function treatAction()
->setText($this->getRequest()->getPost('text'))
->setShow($this->getRequest()->getPost('calendarShow'))
->setReadAccess(implode(',', $this->getRequest()->getPost('groups')));

$trainingMapper->save($model);

$this->redirect(['action' => 'index'])
Expand Down
36 changes: 31 additions & 5 deletions application/modules/training/mappers/Training.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Modules\Training\Mappers;

use Ilch\Date;
use Ilch\Pagination;
use Modules\Training\Models\Training as TrainingModel;

Expand Down Expand Up @@ -39,7 +40,7 @@ public function getEntriesBy(array $where = [], array $orderBy = ['t.date' => 'A
}

$select = $this->db()->select();
$select->fields(['t.id', 't.title', 't.date', 't.time', 't.place', 't.contact', 't.voice_server', 't.voice_server_ip', 't.voice_server_pw', 't.game_server', 't.game_server_ip', 't.game_server_pw', 't.text', 't.show', 't.access_all'])
$select->fields(['t.id', 't.title', 't.date', 't.end', 't.period_type', 't.period_day', 't.repeat_until', 't.place', 't.contact', 't.voice_server', 't.voice_server_ip', 't.voice_server_pw', 't.game_server', 't.game_server_ip', 't.game_server_pw', 't.text', 't.show', 't.access_all'])
->from(['t' => $this->tablename])
->join(['ra' => $this->tablenameAccess], 't.id = ra.training_id', 'LEFT', ['read_access' => 'GROUP_CONCAT(ra.group_id)'])
->where(array_merge($where, ($access ? [$select->orX(['ra.group_id' => $access, 't.access_all' => '1'])] : [])))
Expand Down Expand Up @@ -114,11 +115,36 @@ public function getTrainingById(int $id, $groupIds = '3'): ?TrainingModel
*/
public function getTrainingsForJson(?string $start, ?string $end, $groupIds = '3'): ?array
{
if ($start && $end) {
$start = new \Ilch\Date($start);
$end = new \Ilch\Date($end);
if (\is_string($groupIds)) {
$groupIds = explode(',', $groupIds);
}

return $this->getTraining(['t.date >=' => $start, 't.date <=' => $end, 't.show' => 1], $groupIds);
if ($start && $end) {
if (!is_a($start, Date::class)) {
$start = new Date($start);
}
if (!is_a($end, Date::class)) {
$end = new Date($end);
}
$select = $this->db()->select();
return $this->getEntriesBy(
[
$select->orX(
[
$select->andX(['t.end <=' => $end->format('Y-m-d') . ' 23:59:59']),
$select->andX(['t.date >=' => $start->format('Y-m-d') . ' 00:00:00', 't.end <=' => $end->format('Y-m-d') . ' 23:59:59']),
$select->andX(
[
't.period_type !=' => '',
't.date <=' => $end->format('Y-m-d') . ' 00:00:00',
$select->orX(['t.end >=' => $start->format('Y-m-d') . ' 23:59:59', 't.end =' => '1000-01-01 00:00:00'])
]
)
]
),
'ra.group_id' => $groupIds
]
);
} else {
return null;
}
Expand Down
Loading