Add agenda_reminders configuration setting - refs BT#19392

Enable reminders for agenda events. Requires database changes:

```sql
CREATE TABLE agenda_reminder (id BIGINT AUTO_INCREMENT NOT NULL, type VARCHAR(255) NOT NULL, event_id INT NOT NULL, date_interval VARCHAR(255) NOT NULL COMMENT '(DC2Type:dateinterval)', sent TINYINT(1) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
```
pull/4109/head
Angel Fernando Quiroz Campos 4 years ago
parent c52e1f1760
commit ad71f6d787
  1. 46
      main/calendar/agenda.php
  2. 5
      main/calendar/agenda_js.php
  3. 172
      main/cron/agenda_reminders.php
  4. 7
      main/inc/ajax/agenda.ajax.php
  5. 49
      main/inc/lib/agenda.lib.php
  6. 6
      main/install/configuration.dist.php
  7. 33
      main/template/default/agenda/month.tpl
  8. 113
      src/Chamilo/CoreBundle/Entity/AgendaReminder.php

@ -92,6 +92,45 @@ function add_image_form() {
}
</script>';
$agendaRemindersEnabled = api_get_configuration_value('agenda_reminders');
if ($agendaRemindersEnabled) {
$htmlHeadXtra[] = '<script>
$(function () {
var template = \'<div class="form-group">\' +
\'<div class="col-sm-offset-2 col-sm-3">\' +
\'<input min="0" step="1" id="notification_count[]" type="number" class=" form-control" name="notification_count[]">\' +
\'</div>\' +
\'<div class="col-sm-3">\' +
\'<select class="form-control" name="notification_period[]" id="form_notification_period[]">\' +
\'<option value="i">'.get_lang('Minutes').'</option>\' +
\'<option value="h">'.get_lang('Hours').'</option>\' +
\'<option value="d">'.get_lang('Days').'</option>\' +
\'<option value="w">'.get_lang('Weeks').'</option>\' +
\'</select>\' +
\'</div>\' +
\'<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>\' +
\'<div class="text-right col-sm-2">\' +
\'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>\' +
\'</div>\' +
\'</div>\';
$("#add_event_add_notification").on("click", function (e) {
e.preventDefault();
$(template).appendTo("#notification_list");
$("#notification_list select").selectpicker("refresh");
});
$("#notification_list").on("click", ".delete-notification", function (e) {
e.preventDefault();
$(this).parents(".form-group").remove();
});
});
</script>';
}
// setting the name of the tool
$nameTools = get_lang('Agenda');
@ -161,6 +200,10 @@ if ($allowToEdit) {
$usersToSend = $values['users_to_send'] ?? '';
$startDate = $values['date_range_start'];
$endDate = $values['date_range_end'];
$notificationCount = $_REQUEST['notification_count'] ?? [];
$notificationPeriod = $_REQUEST['notification_period'] ?? [];
$reminders = $notificationCount ? array_map(null, $notificationCount, $notificationPeriod) : [];
$eventId = $agenda->addEvent(
$startDate,
@ -176,7 +219,8 @@ if ($allowToEdit) {
$comment,
'',
$values['invitees'] ?? [],
$values['collective'] ?? false
$values['collective'] ?? false,
$reminders
);
if (!empty($values['repeat']) && !empty($eventId)) {

@ -294,6 +294,11 @@ if (api_get_configuration_value('agenda_collective_invitations') && 'personal' =
$form->addCheckBox('collective', '', get_lang('IsItEditableByTheInvitees'));
}
if (api_get_configuration_value('agenda_reminders')) {
$form->addHtml('<hr><div id="notification_list"></div>');
$form->addButton('add_notification', get_lang('AddNotification'), 'bell-o')->setType('button');
}
$form->addHtml('<div id="attachment_block" style="display: none">');
$form->addLabel(get_lang('Attachment'), '<div id="attachment_text" style="display: none"></div>');
$form->addHtml('</div>');

@ -0,0 +1,172 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This script send notification messages to users that have reminders from an event in their agenda.
*/
require_once __DIR__.'/../../main/inc/global.inc.php';
exit;
if (false === api_get_configuration_value('agenda_reminders')) {
exit;
}
$batchCounter = 0;
$batchSize = 100;
$agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
$now = new DateTime('now', new DateTimeZone('UTC'));
$em = Database::getManager();
$remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
$reminders = $remindersRepo->findBySent(false);
foreach ($reminders as $reminder) {
if ('personal' === $reminder->getType()) {
$event = $em->find('ChamiloCoreBundle:PersonalAgenda', $reminder->getEventId());
$notificationDate = clone $event->getDate();
$notificationDate->sub($reminder->getDateInterval());
if ($notificationDate > $now) {
continue;
}
$eventDetails = [];
$eventDetails[] = '<strong>'.$event->getTitle().'</strong>';
if ($event->getAllDay()) {
$eventDetails[] = get_lang('AllDay');
} else {
$eventDetails[] = sprintf(
get_lang('FromDateX'),
api_get_local_time($event->getDate(), null, null, false, true, true)
);
if (!empty($event->getEnddate())) {
$eventDetails[] = sprintf(
get_lang('UntilDateX'),
api_get_local_time($event->getEnddate(), null, null, false, true, true)
);
}
}
if (!empty($event->getText())) {
$eventDetails[] = $event->getText();
}
$messageSubject = sprintf(get_lang('ReminderXEvent'), $event->getTitle());
$messageContent = implode('<br />', $eventDetails);
MessageManager::send_message_simple(
$event->getUser(),
$messageSubject,
$messageContent,
$event->getUser()
);
if ($agendaCollectiveInvitations) {
$invitees = Agenda::getInviteesForPersonalEvent($reminder->getEventId());
$inviteesIdList = array_column($invitees, 'id');
foreach ($inviteesIdList as $userId) {
MessageManager::send_message_simple(
$userId,
$messageSubject,
$messageContent,
$event->getUser()
);
}
}
}
if ('course' === $reminder->getType()) {
$event = $em->find('ChamiloCourseBundle:CCalendarEvent', $reminder->getEventId());
$agenda = new Agenda('course');
$notificationDate = clone $event->getStartDate();
$notificationDate->sub($reminder->getDateInterval());
if ($notificationDate > $now) {
continue;
}
$eventDetails = [];
$eventDetails[] = '<strong>'.$event->getTitle().'</strong>';
if ($event->getAllDay()) {
$eventDetails[] = get_lang('AllDay');
} else {
$eventDetails[] = sprintf(
get_lang('FromDateX'),
api_get_local_time($event->getStartDate(), null, null, false, true, true)
);
if (!empty($event->getEndDate())) {
$eventDetails[] = sprintf(
get_lang('UntilDateX'),
api_get_local_time($event->getEndDate(), null, null, false, true, true)
);
}
}
if (!empty($event->getContent())) {
$eventDetails[] = $event->getContent();
}
$messageSubject = sprintf(get_lang('ReminderXEvent'), $event->getTitle());
$messageContent = implode('<br />', $eventDetails);
$courseInfo = api_get_course_info_by_id($event->getCId());
$sendTo = $agenda->getUsersAndGroupSubscribedToEvent(
$event->getIid(),
$event->getCId(),
$event->getSessionId()
);
if ($sendTo['everyone']) {
$users = CourseManager::get_user_list_from_course_code($courseInfo['code'], $event->getSessionId());
$userIdList = array_keys($users);
if ($event->getSessionId()) {
$coaches = SessionManager::getCoachesByCourseSession($event->getSessionId(), $event->getCId());
$userIdList += $coaches;
}
foreach ($userIdList as $userId) {
MessageManager::send_message_simple($userId, $messageSubject, $messageContent);
}
} else {
foreach ($sendTo['groups'] as $groupId) {
$groupUserList = GroupManager::get_users($groupId, false, null, null, false, $event->getSessionId());
foreach ($groupUserList as $groupUserId) {
MessageManager::send_message_simple($groupUserId, $messageSubject, $messageContent);
}
}
foreach ($sendTo['users'] as $userId) {
MessageManager::send_message_simple($userId, $messageSubject, $messageContent);
}
}
}
$reminder->setSent(true);
$em->persist($reminder);
++$batchCounter;
if (($batchCounter % $batchSize) === 0) {
$em->flush();
}
}
$em->flush();
$em->clear();

@ -47,6 +47,10 @@ switch ($action) {
$userToSend = isset($_REQUEST['users_to_send']) ? $_REQUEST['users_to_send'] : [];
$inviteesList = $_REQUEST['invitees'] ?? [];
$isCollective = isset($_REQUEST['collective']);
$notificationCount = $_REQUEST['notification_count'] ?? [];
$notificationPeriod = $_REQUEST['notification_period'] ?? [];
$reminders = $notificationCount ? array_map(null, $notificationCount, $notificationPeriod) : [];
$eventId = $agenda->addEvent(
$_REQUEST['start'],
@ -62,7 +66,8 @@ switch ($action) {
$comment,
'',
$inviteesList,
$isCollective
$isCollective,
$reminders
);
echo $eventId;

@ -4,6 +4,7 @@
use Chamilo\CoreBundle\Entity\AgendaEventInvitation;
use Chamilo\CoreBundle\Entity\AgendaEventInvitee;
use Chamilo\CoreBundle\Entity\AgendaReminder;
use Chamilo\UserBundle\Entity\User;
/**
@ -250,7 +251,8 @@ class Agenda
$eventComment = null,
$color = '',
array $inviteesList = [],
bool $isCollective = false
bool $isCollective = false,
array $reminders = []
) {
$start = api_get_utc_datetime($start);
$end = api_get_utc_datetime($end);
@ -452,9 +454,49 @@ class Agenda
break;
}
if (api_get_configuration_value('agenda_reminders')) {
foreach ($reminders as $reminder) {
$this->addReminder($id, $reminder[0], $reminder[1]);
}
}
return $id;
}
/**
* @throws Exception
*/
public function addReminder($eventId, $count, $period)
{
switch ($period) {
case 'i':
$dateInterval = DateInterval::createFromDateString("$count minutes");
break;
case 'h':
$dateInterval = DateInterval::createFromDateString("$count hours");
break;
case 'd':
$dateInterval = DateInterval::createFromDateString("$count days");
break;
case 'w':
$dateInterval = DateInterval::createFromDateString("$count weeks");
break;
default:
return null;
}
$agendaReminder = new AgendaReminder();
$agendaReminder
->setType($this->type)
->setEventId($eventId)
->setDateInterval($dateInterval)
;
$em = Database::getManager();
$em->persist($agendaReminder);
$em->flush();
}
/**
* @param int $eventId
* @param int $courseId
@ -2699,6 +2741,11 @@ class Agenda
$params['collective'] = $isCollective;
}
if (api_get_configuration_value('agenda_reminders') && 'add' === $params['action']) {
$form->addHtml('<hr><div id="notification_list"></div>');
$form->addButton('add_notification', get_lang('AddNotification'), 'bell-o')->setType('button');
}
if ($id) {
$form->addButtonUpdate(get_lang('ModifyEvent'));
} else {

@ -452,6 +452,12 @@ CREATE UNIQUE INDEX UNIQ_D8612460AF68C6B ON personal_agenda (agenda_event_invita
// Then add the "@" symbol to AgendaEventInvitation and AgendaEventInvitee classes in the ORM\Entity() line.
// Then uncomment the "use EventCollectiveTrait;" line in the PersonalAgenda class.
//$_configuration['agenda_collective_invitations'] = false;
// Enable reminders for agenda events. Requires database changes:
/*
CREATE TABLE agenda_reminder (id BIGINT AUTO_INCREMENT NOT NULL, type VARCHAR(255) NOT NULL, event_id INT NOT NULL, date_interval VARCHAR(255) NOT NULL COMMENT '(DC2Type:dateinterval)', sent TINYINT(1) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
*/
// Then add the "@" symbol to AgendaReminder class in the ORM\Entity() line.
//$_configuration['agenda_reminders'] = false;
// ------
//
// Save some tool titles with HTML editor. Require DB changes:

@ -870,6 +870,39 @@ $(function() {
else $('#loading').hide();
}
});
{% if 'agenda_reminders'|api_get_configuration_value %}
var template = '<div class="form-group">' +
'<div class="col-sm-offset-2 col-sm-3">' +
'<input min="0" step="1" id="notification_count[]" type="number" class=" form-control" name="notification_count[]">' +
'</div>' +
'<div class="col-sm-3">' +
'<select class="form-control" name="notification_period[]" id="form_notification_period[]">' +
'<option value="i">{{ 'Minutes'|get_lang }}</option>' +
'<option value="h">{{ 'Hours'|get_lang }}</option>' +
'<option value="d">{{ 'Days'|get_lang }}</option>' +
'<option value="w">{{ 'Weeks'|get_lang }}</option>' +
'</select>' +
'</div>' +
'<div class="col-sm-2"><p class="form-control-static">{{ 'Before'|get_lang }}</p></div>' +
'<div class="text-right col-sm-2">' +
'<button class="btn btn-default delete-notification" type="button" aria-label="{{ 'Delete'|get_lang }}"><em class="fa fa-times"></em></button>' +
'</div>' +
'</div>';
$('#form_add_notification').on('click', function (e) {
e.preventDefault();
$(template).appendTo('#notification_list');
$('#notification_list select').selectpicker('refresh');
});
$('#notification_list').on('click', '.delete-notification', function (e) {
e.preventDefault();
$(this).parents('.form-group').remove();
});
{% endif %}
});
</script>
{{ actions_div }}

@ -0,0 +1,113 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Entity;
use Chamilo\CoreBundle\Traits\TimestampableTypedEntity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="agenda_reminder")
* Add @ to the next line when activatiing the agenda_reminders configuration setting
* ORM\Entity()
*/
class AgendaReminder
{
use TimestampableTypedEntity;
/**
* @var int
*
* @ORM\Id()
* @ORM\Column(type="bigint")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
*
* @ORM\Column(name="type", type="string")
*/
protected $type;
/**
* @var int
*
* @ORM\Column(name="event_id", type="integer")
*/
protected $eventId;
/**
* @var \DateInterval
*
* @ORM\Column(name="date_interval", type="dateinterval")
*/
protected $dateInterval;
/**
* @var bool
*
* @ORM\Column(name="sent", type="boolean")
*/
protected $sent;
public function __construct()
{
$this->sent = false;
}
public function getId(): int
{
return $this->id;
}
public function getType(): string
{
return $this->type;
}
public function setType(string $type): AgendaReminder
{
$this->type = $type;
return $this;
}
public function getEventId(): int
{
return $this->eventId;
}
public function setEventId(int $eventId): AgendaReminder
{
$this->eventId = $eventId;
return $this;
}
public function getDateInterval(): \DateInterval
{
return $this->dateInterval;
}
public function setDateInterval(\DateInterval $dateInterval): AgendaReminder
{
$this->dateInterval = $dateInterval;
return $this;
}
public function isSent(): bool
{
return $this->sent;
}
public function setSent(bool $sent): AgendaReminder
{
$this->sent = $sent;
return $this;
}
}
Loading…
Cancel
Save