@ -4,7 +4,10 @@
use Chamilo\CoreBundle\Entity\AgendaEventInvitation;
use Chamilo\CoreBundle\Entity\AgendaEventInvitee;
use Chamilo\CoreBundle\Entity\AgendaEventSubscriber;
use Chamilo\CoreBundle\Entity\AgendaEventSubscription;
use Chamilo\CoreBundle\Entity\AgendaReminder;
use Chamilo\CoreBundle\Entity\PersonalAgenda;
use Chamilo\UserBundle\Entity\User;
/**
@ -254,13 +257,18 @@ class Agenda
bool $isCollective = false,
array $reminders = [],
int $careerId = 0,
int $promotionId = 0
int $promotionId = 0,
int $subscriptionVisibility = 0,
?int $subscriptionItemId = null,
int $maxSubscriptions = 0
) {
$start = api_get_utc_datetime($start);
$end = api_get_utc_datetime($end);
$allDay = isset($allDay) & & ($allDay === 'true' || $allDay == 1) ? 1 : 0;
$id = null;
$em = Database::getManager();
switch ($this->type) {
case 'personal':
$attributes = [
@ -281,6 +289,26 @@ class Agenda
if (api_get_configuration_value('agenda_collective_invitations')) {
Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
}
if (api_get_configuration_value('agenda_event_subscriptions') & & api_is_platform_admin()) {
$personalEvent = $em->find(PersonalAgenda::class, $id);
$personalEvent
->setSubscriptionVisibility($subscriptionVisibility)
->setSubscriptionItemId($subscriptionItemId ?: null)
;
$subscription = (new AgendaEventSubscription())
->setCreator(api_get_user_entity(api_get_user_id()))
->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0)
;
$personalEvent
->setCollective(false)
->setInvitation($subscription)
;
$em->flush();
}
break;
case 'course':
$attributes = [
@ -865,7 +893,11 @@ class Agenda
bool $isCollective = false,
array $remindersList = [],
int $careerId = 0,
int $promotionId = 0
int $promotionId = 0,
int $subscriptionVisibility = 0,
?int $subscriptionItemId = null,
int $maxSubscriptions = 0,
array $subscribers = []
) {
$id = (int) $id;
$start = api_get_utc_datetime($start);
@ -874,6 +906,8 @@ class Agenda
$currentUserId = api_get_user_id();
$authorId = empty($authorId) ? $currentUserId : (int) $authorId;
$em = Database::getManager();
switch ($this->type) {
case 'personal':
$eventInfo = $this->get_event($id);
@ -909,6 +943,24 @@ class Agenda
if (api_get_configuration_value('agenda_collective_invitations')) {
Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
}
if (api_get_configuration_value('agenda_event_subscriptions') & & api_is_platform_admin()) {
$personalEvent = $em->find(PersonalAgenda::class, $id);
$personalEvent->setSubscriptionVisibility($subscriptionVisibility);
/** @var AgendaEventSubscription $subscription */
$subscription = $personalEvent->getInvitation();
$subscription->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0);
if ($personalEvent->getSubscriptionItemId() != $subscriptionItemId) {
$personalEvent->setSubscriptionItemId($subscriptionItemId ?: null);
$subscription->removeInvitees();
} else {
$subscription->removeInviteesNotInIdList($subscribers);
}
$em->flush();
}
break;
case 'course':
$eventInfo = $this->get_event($id);
@ -1306,6 +1358,80 @@ class Agenda
}
}
public function subscribeCurrentUserToEvent(int $id)
{
if (false === api_get_configuration_value('agenda_event_subscriptions')) {
return;
}
if ('personal' !== $this->type) {
return;
}
$em = Database::getManager();
$currentUser = api_get_user_entity(api_get_user_id());
$personalEvent = $em->find(PersonalAgenda::class, $id);
/** @var AgendaEventSubscription $subscription */
$subscription = $personalEvent ? $personalEvent->getInvitation() : null;
if (!$subscription) {
return;
}
if ($subscription->getInvitees()->count() >= $subscription->getMaxAttendees()
& & $subscription->getMaxAttendees() > 0
) {
return;
}
if (AgendaEventSubscription::SUBSCRIPTION_CLASS === $personalEvent->getSubscriptionVisibility()) {
$objGroup = new UserGroup();
$groupList = $objGroup->getUserGroupListByUser($currentUser->getId(), UserGroup::NORMAL_CLASS);
$groupIdList = array_column($groupList, 'id');
if (!in_array($personalEvent->getSubscriptionItemId(), $groupIdList)) {
return;
}
}
$subscriber = (new AgendaEventSubscriber())
->setUser($currentUser)
;
$subscription->addInvitee($subscriber);
$em->flush();
}
public function unsubscribeCurrentUserToEvent(int $id)
{
if (false === api_get_configuration_value('agenda_event_subscriptions')) {
return;
}
if ('personal' !== $this->type) {
return;
}
$em = Database::getManager();
$currentUser = api_get_user_entity(api_get_user_id());
$personalEvent = $em->find(PersonalAgenda::class, $id);
/** @var AgendaEventSubscription $subscription */
$subscription = $personalEvent ? $personalEvent->getInvitation() : null;
if (!$subscription) {
return;
}
$subscription->removeInviteeUser($currentUser);
$em->flush();
}
/**
* Get agenda events.
*
@ -1759,57 +1885,114 @@ class Agenda
$endCondition = '';
$agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
$agendaEventSubscriptions = api_get_configuration_value('agenda_event_subscriptions');
$userIsAdmin = api_is_platform_admin();
$queryParams = [];
if ($start !== 0) {
$startDate = api_get_utc_datetime($start, true, true);
$startCondition = "AND date >= '".$startDate->format('Y-m-d H:i:s')."'";
$queryParams['start_date'] = api_get_utc_datetime($start, true, true);
$startCondition = "AND pa.date >= :start_date ";
}
if ($end !== 0) {
$endDate = api_get_utc_datetime($end, false, true);
$endCondition = "AND (enddate < = '".$endDate->format('Y-m-d H:i:s')."' OR enddate IS NULL)";
$queryParams['end_date'] = api_get_utc_datetime($end, false, true);
$endCondition = "AND (pa.enddate < = :end_date OR pa. enddate IS NULL)";
}
$user_id = api_get_user_id();
$sql = "SELECT * FROM ".$this->tbl_personal_agenda."
WHERE user = $user_id $startCondition $endCondition";
$queryParams['user_id'] = $user_id;
$userCondition = "pa.user = :user_id";
$objGroup = new UserGroup();
if ($agendaEventSubscriptions) {
$groupList = $objGroup->getUserGroupListByUser($user_id, UserGroup::NORMAL_CLASS);
$userCondition = "(
$userCondition
OR (
pa.subscriptionVisibility = ".AgendaEventSubscription::SUBSCRIPTION_ALL;
if ($groupList) {
$userCondition .= "
OR (
pa.subscriptionVisibility = ".AgendaEventSubscription::SUBSCRIPTION_CLASS."
AND pa.subscriptionItemId IN (".implode(', ', array_column($groupList, 'id')).")
)
";
}
$userCondition .= "
)
)
";
}
$sql = "SELECT pa FROM ChamiloCoreBundle:PersonalAgenda AS pa WHERE $userCondition $startCondition $endCondition";
$result = Database::getManager()
->createQuery($sql)
->setParameters($queryParams)
->getResult();
$result = Database::query($sql);
$my_events = [];
if (Database::num_rows($result)) {
while ($row = Database::fetch_array($result, 'ASSOC')) {
/** @var PersonalAgenda $row */
foreach ($result as $row) {
$event = [];
$event['id'] = 'personal_'.$row['id'];
$event['title'] = $row['title'];
$event['id'] = 'personal_'.$row->getId() ;
$event['title'] = $row->getTitle() ;
$event['className'] = 'personal';
$event['borderColor'] = $event['backgroundColor'] = $this->event_personal_color;
$event['editable'] = true;
$event['editable'] = $user_id === (int) $row->getUser() ;
$event['sent_to'] = get_lang('Me');
$event['type'] = 'personal';
if (!empty($row['date'])) {
$event['start'] = $this->formatEventDate($row['date']);
$event['start_date_localtime'] = api_get_local_time($row['date']);
if (!empty($row->getDate() )) {
$event['start'] = $this->formatEventDate($row->getDate() );
$event['start_date_localtime'] = api_get_local_time($row->getDate() );
}
if (!empty($row['enddate'])) {
$event['end'] = $this->formatEventDate($row['enddate']);
$event['end_date_localtime'] = api_get_local_time($row['enddate']);
if (!empty($row->getEnddate() )) {
$event['end'] = $this->formatEventDate($row->getEnddate() );
$event['end_date_localtime'] = api_get_local_time($row->getEnddate() );
}
$event['description'] = $row['text'];
$event['allDay'] = isset($row['all_day']) & & $row['all_day'] == 1 ? $row['all_day'] : 0;
$event['description'] = $row->getText() ;
$event['allDay'] = $row->getAllDay() ;
$event['parent_event_id'] = 0;
$event['has_children'] = 0;
if ($agendaCollectiveInvitations) {
$event['collective'] = (bool) $row['collective'];
$event['invitees'] = self::getInviteesForPersonalEvent($row['id']);
if ($agendaCollectiveInvitations || $agendaEventSubscriptions) {
$subscription = $row->getInvitation();
if ($subscription instanceof AgendaEventSubscription) {
$subscribers = $subscription->getInvitees();
$event['subscription_visibility'] = $row->getSubscriptionVisibility();
$event['max_subscriptions'] = $subscription->getMaxAttendees();
$event['can_subscribe'] = $subscribers->count() < $subscription->getMaxAttendees()
|| $subscription->getMaxAttendees() === 0;
$event['user_is_subscribed'] = $subscription->hasUserAsInvitee(api_get_user_entity($user_id));
$event['count_subscribers'] = $subscribers->count();
if ($userIsAdmin) {
$event['subscribers'] = self::getInviteesForPersonalEvent($row->getId(), AgendaEventSubscriber::class);
}
if (AgendaEventSubscription::SUBSCRIPTION_CLASS === $row->getSubscriptionVisibility()) {
$groupInfo = $objGroup->get($row->getSubscriptionItemId());
$event['usergroup'] = $groupInfo['name'];
}
} else {
$event['collective'] = $row->isCollective();
$event['invitees'] = self::getInviteesForPersonalEvent($row->getId());
}
}
$my_events[] = $event;
$this->events[] = $event;
}
}
if ($agendaCollectiveInvitations) {
$this->loadEventsAsInvitee(
@ -1837,13 +2020,21 @@ class Agenda
return $my_events;
}
public static function getInviteesForPersonalEvent($eventId): array
public static function getInviteesForPersonalEvent($eventId, $type = AgendaEventInvitee::class ): array
{
$em = Database::getManager();
$event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
$inviteeRepo = $em->getRepository('ChamiloCoreBundle:AgendaEventInvitee');
$invitees = $inviteeRepo->findByInvitation($event->getInvitation());
$invitation = $event->getInvitation();
if ($invitation instanceof AgendaEventSubscription
& & AgendaEventInvitee::class === $type
) {
return [];
}
$inviteeRepo = $em->getRepository($type);
$invitees = $inviteeRepo->findByInvitation($invitation);
$inviteeList = [];
@ -2680,6 +2871,9 @@ class Agenda
$action = isset($params['action']) ? Security::remove_XSS($params['action']) : null;
$id = isset($params['id']) ? (int) $params['id'] : 0;
$em = Database::getManager();
$personalEvent = 'personal' === $this->type & & $id ? $em->find('ChamiloCoreBundle:PersonalAgenda', $id) : null;
$url = api_get_self().'?action='.$action.'&id='.$id.'&type='.$this->type;
if ($this->type == 'course') {
$url = api_get_self().'?'.api_get_cidreq().'&action='.$action.'&id='.$id.'&type='.$this->type;
@ -2894,16 +3088,15 @@ class Agenda
$agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
if ($agendaCollectiveInvitations & & 'personal' === $this->type) {
$em = Database::getManager();
$invitees = [];
$isCollective = false;
$allowInvitees = true;
if ($id ) {
$event = $em->find('ChamiloCoreBundle:PersonalAgenda', $id );
$eventInvitation = $event->getInvitation() ;
if ($personalEvent ) {
$eventInvitation = $personalEvent->getInvitation( );
$allowInvitees = !$eventInvitation instanceof AgendaEventSubscription ;
if ($eventInvitation) {
if ($eventInvitation & & $allowInvitees ) {
foreach ($eventInvitation->getInvitees() as $invitee) {
$inviteeUser = $invitee->getUser();
@ -2911,9 +3104,10 @@ class Agenda
}
}
$isCollective = $event->isCollective();
$isCollective = $p ersonalE vent->isCollective();
}
if ($allowInvitees) {
$form->addSelectAjax(
'invitees',
get_lang('Invitees'),
@ -2924,13 +3118,15 @@ class Agenda
]
);
$form->addCheckBox('collective', '', get_lang('IsItEditableByTheInvitees'));
$form->addHtml('< hr > ');
$params['invitees'] = array_keys($invitees);
$params['collective'] = $isCollective;
}
}
if (api_get_configuration_value('agenda_reminders')) {
$form->addHtml('< hr > < div id = "notification_list" > ');
$form->addHtml('< div id = "notification_list" > ');
if ($id) {
$this->addFieldsForRemindersToForm($id, $form);
@ -2941,6 +3137,83 @@ class Agenda
$form->addHtml('< hr > ');
}
if (api_is_platform_admin()
& & true === api_get_configuration_value('agenda_event_subscriptions')
) {
$form->addHtml('< hr > ');
$form->addSelect(
'subscription_visibility',
get_lang('AllowSubscriptions'),
[
AgendaEventSubscription::SUBSCRIPTION_NO => get_lang('No'),
AgendaEventSubscription::SUBSCRIPTION_ALL => get_lang('AllUsersOfThePlatform'),
AgendaEventSubscription::SUBSCRIPTION_CLASS => get_lang('UsersInsideClass'),
]
);
$slctItem = $form->addSelectAjax(
'subscription_item',
get_lang('SocialGroup').' / '.get_lang('Class'),
[],
[
'url' => api_get_path(WEB_AJAX_PATH).'usergroup.ajax.php?a=get_class_by_keyword',
'disabled' => 'disabled',
]
);
$form->addNumeric(
'max_subscriptions',
['', get_lang('MaxSubscriptionsLeaveEmptyToNotLimit')],
[
'disabled' => 'disabled',
'step' => 1,
'min' => 0,
'value' => 0,
]
);
$form->addHtml("< script >
$(function () {
$('#add_event_subscription_visibility')
.on('change', function () {
$('#max_subscriptions').prop('disabled', this.value == 0);
$('#add_event_subscription_item').prop('disabled', this.value != 2);
})
.trigger('change');
})
< / script >
");
if ($personalEvent) {
$subscribers = self::getInviteesForPersonalEvent($personalEvent->getId(), AgendaEventSubscriber::class);
$subscribers = array_combine(
array_column($subscribers, 'id'),
array_column($subscribers, 'name')
);
$params['subscribers'] = array_keys($subscribers);
$form->addSelect(
'subscribers',
get_lang('Subscribers'),
$subscribers,
['multiple' => 'multiple']
);
/** @var AgendaEventSubscription $subscription */
$subscription = $personalEvent->getInvitation();
$params['max_subscriptions'] = $subscription->getMaxAttendees();
$groupId = $personalEvent->getSubscriptionItemId();
if ($groupId) {
$objUserGroup = new UserGroup();
$groupInfo = $objUserGroup->get($groupId);
$slctItem->addOption($groupInfo['name'], $groupId);
}
}
}
if (api_get_configuration_value('allow_careers_in_global_agenda') & & 'admin' === $this->type) {
Career::addCareerFieldsToForm($form);
$form->addHtml('< hr > ');
@ -4589,10 +4862,15 @@ class Agenda
*/
public function formatEventDate($utcTime)
{
if ($utcTime instanceof DateTime) {
$eventDate = $utcTime;
} else {
$utcTimeZone = new DateTimeZone('UTC');
$eventDate = new DateTime($utcTime, $utcTimeZone);
}
$platformTimeZone = new DateTimeZone(api_get_timezone());
$eventDate = new DateTime($utcTime, $utcTimeZone);
$eventDate->setTimezone($platformTimeZone);
return $eventDate->format(DateTime::ISO8601);
@ -4609,25 +4887,34 @@ class Agenda
$event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
$invitation = $event->getInvitation();
if ($invitation instanceof AgendaEventSubscription) {
return;
}
if (!$invitation) {
$invitation = new AgendaEventInvitation();
$invitation->setCreator(api_get_user_entity(api_get_user_id()));
$event
->setCollective($isCollective)
->setInvitation($invitation)
;
$event->setInvitation($invitation);
}
$em->persist($event );
$event->setCollective($isCollective);
foreach ($inviteeUserList as $inviteeId) {
$userInvitee = api_get_user_entity($inviteeId);
if (!$invitation->hasUserAsInvitee($userInvitee)) {
$invitee = new AgendaEventInvitee();
$invitee
->setUser(api_get_user_entity($inviteeId))
->setUser($userInvitee )
->setInvitation($invitation)
;
$em->persist($invitee);
}
}
$em->flush();
}