// swad_notification.c: notifications about events, sent by email
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2019 Antonio Caņas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include // For NULL
#include // For system
#include
#include // For the macro WEXITSTATUS
#include // For unlink
#include "swad_action.h"
#include "swad_box.h"
#include "swad_config.h"
#include "swad_config.h"
#include "swad_database.h"
#include "swad_enrolment.h"
#include "swad_exam.h"
#include "swad_follow.h"
#include "swad_form.h"
#include "swad_global.h"
#include "swad_HTML.h"
#include "swad_mark.h"
#include "swad_notice.h"
#include "swad_notification.h"
#include "swad_parameter.h"
#include "swad_timeline.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
// strings are limited to Ntf_MAX_BYTES_NOTIFY_EVENT characters
const char *Ntf_WSNotifyEvents[Ntf_NUM_NOTIFY_EVENTS] =
{
"unknown", // Ntf_EVENT_UNKNOWN
/* Course tab */
"documentFile", // Ntf_EVENT_DOCUMENT_FILE
"teachersFile", // Ntf_EVENT_TEACHERS_FILE
"sharedFile", // Ntf_EVENT_SHARED_FILE
/* Assessment tab */
"assignment", // Ntf_EVENT_ASSIGNMENT
"examAnnouncement", // Ntf_EVENT_EXAM_ANNOUNCEMENT
"marksFile", // Ntf_EVENT_MARKS_FILE
/* Users tab */
"enrollmentStudent", // Ntf_EVENT_ENROLMENT_STD // TODO: Change to "enrolmentStudent" carefully in future versions
"enrollmentTeacher", // Ntf_EVENT_ENROLMENT_TCH // TODO: Change to "enrolmentTeacher" carefully in future versions
"enrollmentRequest", // Ntf_EVENT_ENROLMENT_REQUEST // TODO: Change to "enrolmentRequest" carefully in future versions
/* Social tab */
"timelineComment", // Ntf_EVENT_TIMELINE_COMMENT
"timelineFav", // Ntf_EVENT_TIMELINE_FAV
"timelineShare", // Ntf_EVENT_TIMELINE_SHARE
"timelineMention", // Ntf_EVENT_TIMELINE_MENTION
"follower", // Ntf_EVENT_FOLLOWER
"forumPostCourse", // Ntf_EVENT_FORUM_POST_COURSE
"forumReply", // Ntf_EVENT_FORUM_REPLY
/* Messages tab */
"notice", // Ntf_EVENT_NOTICE
"message", // Ntf_EVENT_MESSAGE
/* Statistics tab */
/* Profile tab */
"survey", // Ntf_EVENT_SURVEY // TODO: Move to assessment tab (also necessary in database) !!!!!!!!!
"enrolmentNonEditingTeacher", // Ntf_EVENT_ENROLMENT_NET // TODO: Move to users tab (also necessary in database) !!!!!!!!!
};
static const Act_Action_t Ntf_DefaultActions[Ntf_NUM_NOTIFY_EVENTS] =
{
ActUnk, // Ntf_EVENT_UNKNOWN
/* Course tab */
ActSeeAdmDocCrsGrp, // Ntf_EVENT_DOCUMENT_FILE
ActAdmTchCrsGrp, // Ntf_EVENT_TEACHERS_FILE
ActAdmShaCrsGrp, // Ntf_EVENT_SHARED_FILE
/* Assessment tab */
ActSeeAsg, // Ntf_EVENT_ASSIGNMENT
ActSeeAllExaAnn, // Ntf_EVENT_EXAM_ANNOUNCEMENT
ActSeeAdmMrk, // Ntf_EVENT_MARKS_FILE
/* Users tab */
ActReqAccEnrStd, // Ntf_EVENT_ENROLMENT_STD
ActReqAccEnrTch, // Ntf_EVENT_ENROLMENT_TCH
ActSeeSignUpReq, // Ntf_EVENT_ENROLMENT_REQUEST
/* Social tab */
ActSeeSocTmlGbl, // Ntf_EVENT_TIMELINE_COMMENT // TODO: Change position
ActSeeSocTmlGbl, // Ntf_EVENT_TIMELINE_FAV // TODO: Change position
ActSeeSocTmlGbl, // Ntf_EVENT_TIMELINE_SHARE // TODO: Change position
ActSeeSocTmlGbl, // Ntf_EVENT_TIMELINE_MENTION // TODO: Change position
ActSeeFlr, // Ntf_EVENT_FOLLOWER // TODO: Change position
ActSeeFor, // Ntf_EVENT_FORUM_POST_COURSE // TODO: Change position
ActSeeFor, // Ntf_EVENT_FORUM_REPLY // TODO: Change position
/* Messages tab */
ActSeeOneNot, // Ntf_EVENT_NOTICE
ActExpRcvMsg, // Ntf_EVENT_MESSAGE
/* Statistics tab */
/* Profile tab */
ActSeeAllSvy, // Ntf_EVENT_SURVEY // TODO: Move to assessment tab (also necessary in database) !!!!!!!!!
ActReqAccEnrNET, // Ntf_EVENT_ENROLMENT_NET // TODO: Move to users tab (also necessary in database) !!!!!!!!!
};
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
// Notify me notification events
static const char *Ntf_ParamNotifMeAboutNotifyEvents[Ntf_NUM_NOTIFY_EVENTS] =
{
"NotifyNtfEventUnknown", // Ntf_EVENT_UNKNOWN
/* Course tab */
"NotifyNtfEventDocumentFile", // Ntf_EVENT_DOCUMENT_FILE
"NotifyNtfEventTeachersFile", // Ntf_EVENT_TEACHERS_FILE
"NotifyNtfEventSharedFile", // Ntf_EVENT_SHARED_FILE
/* Assessment tab */
"NotifyNtfEventAssignment", // Ntf_EVENT_ASSIGNMENT
"NotifyNtfEventExamAnnouncement", // Ntf_EVENT_EXAM_ANNOUNCEMENT
"NotifyNtfEventMarksFile", // Ntf_EVENT_MARKS_FILE
/* Users tab */
"NotifyNtfEventEnrolmentStudent", // Ntf_EVENT_ENROLMENT_STD
"NotifyNtfEventEnrolmentTeacher", // Ntf_EVENT_ENROLMENT_TCH
"NotifyNtfEventEnrolmentRequest", // Ntf_EVENT_ENROLMENT_REQUEST
/* Social tab */
"NotifyNtfEventTimelineComment", // Ntf_EVENT_TIMELINE_COMMENT
"NotifyNtfEventTimelineFav", // Ntf_EVENT_TIMELINE_FAV
"NotifyNtfEventTimelineShare", // Ntf_EVENT_TIMELINE_SHARE
"NotifyNtfEventTimelineMention", // Ntf_EVENT_TIMELINE_MENTION
"NotifyNtfEventFollower", // Ntf_EVENT_FOLLOWER
"NotifyNtfEventForumPostCourse", // Ntf_EVENT_FORUM_POST_COURSE
"NotifyNtfEventForumReply", // Ntf_EVENT_FORUM_REPLY
/* Messages tab */
"NotifyNtfEventNotice", // Ntf_EVENT_NOTICE
"NotifyNtfEventMessage", // Ntf_EVENT_MESSAGE
/* Statistics tab */
/* Profile tab */
"NotifyNtfEventSurvey", // Ntf_EVENT_SURVEY // TODO: Move to assessment tab (also necessary in database) !!!!!!!!!
"NotifyNtfEventEnrolmentNonEditingTeacher", // Ntf_EVENT_ENROLMENT_NET // TODO: Move to users tab (also necessary in database) !!!!!!!!!
};
// Email me about notification events
static const char *Ntf_ParamEmailMeAboutNotifyEvents[Ntf_NUM_NOTIFY_EVENTS] =
{
"EmailNtfEventUnknown", // Ntf_EVENT_UNKNOWN
/* Course tab */
"EmailNtfEventDocumentFile", // Ntf_EVENT_DOCUMENT_FILE
"EmailNtfEventTeachersFile", // Ntf_EVENT_TEACHERS_FILE
"EmailNtfEventSharedFile", // Ntf_EVENT_SHARED_FILE
/* Assessment tab */
"EmailNtfEventAssignment", // Ntf_EVENT_ASSIGNMENT
"EmailNtfEventExamAnnouncement", // Ntf_EVENT_EXAM_ANNOUNCEMENT
"EmailNtfEventMarksFile", // Ntf_EVENT_MARKS_FILE
/* Users tab */
"EmailNtfEventEnrolmentStudent", // Ntf_EVENT_ENROLMENT_STD
"EmailNtfEventEnrolmentTeacher", // Ntf_EVENT_ENROLMENT_TCH
"EmailNtfEventEnrolmentRequest", // Ntf_EVENT_ENROLMENT_REQUEST
/* Social tab */
"EmailNtfEventTimelineComment", // Ntf_EVENT_TIMELINE_COMMENT
"EmailNtfEventTimelineFav", // Ntf_EVENT_TIMELINE_FAV
"EmailNtfEventTimelineShare", // Ntf_EVENT_TIMELINE_SHARE
"EmailNtfEventTimelineMention", // Ntf_EVENT_TIMELINE_MENTION
"EmailNtfEventSocialFollower", // Ntf_EVENT_FOLLOWER
"EmailNtfEventForumPostCourse", // Ntf_EVENT_FORUM_POST_COURSE
"EmailNtfEventForumReply", // Ntf_EVENT_FORUM_REPLY
/* Messages tab */
"EmailNtfEventNotice", // Ntf_EVENT_NOTICE
"EmailNtfEventMessage", // Ntf_EVENT_MESSAGE
/* Statistics tab */
/* Profile tab */
"EmailNtfEventSurvey", // Ntf_EVENT_SURVEY // TODO: Move to assessment tab (also necessary in database) !!!!!!!!!
"EmailNtfEventEnrolmentNonEditingTeacher", // Ntf_EVENT_ENROLMENT_NET // TODO: Move to users tab (also necessary in database) !!!!!!!!!
};
// Icons for notification events
static const char *Ntf_Icons[Ntf_NUM_NOTIFY_EVENTS] =
{
"question.svg", // Ntf_EVENT_UNKNOWN
/* Course tab */
"file.svg", // Ntf_EVENT_DOCUMENT_FILE
"file.svg", // Ntf_EVENT_TEACHERS_FILE
"file.svg", // Ntf_EVENT_SHARED_FILE
/* Assessment tab */
"edit.svg", // Ntf_EVENT_ASSIGNMENT
"bullhorn.svg", // Ntf_EVENT_EXAM_ANNOUNCEMENT
"clipboard-list.svg",// Ntf_EVENT_MARKS_FILE
/* Users tab */
"user.svg", // Ntf_EVENT_ENROLMENT_STD
"user-tie.svg", // Ntf_EVENT_ENROLMENT_TCH
"hand-point-up.svg", // Ntf_EVENT_ENROLMENT_REQUEST
/* Social tab */
"comment-dots.svg", // Ntf_EVENT_TIMELINE_COMMENT
"star.svg", // Ntf_EVENT_TIMELINE_FAV
"share-alt.svg", // Ntf_EVENT_TIMELINE_SHARE
"at.svg", // Ntf_EVENT_TIMELINE_MENTION
"user-plus.svg", // Ntf_EVENT_FOLLOWER
"comments.svg", // Ntf_EVENT_FORUM_POST_COURSE
"comments.svg", // Ntf_EVENT_FORUM_REPLY
/* Messages tab */
"sticky-note.svg", // Ntf_EVENT_NOTICE
"envelope.svg", // Ntf_EVENT_MESSAGE
/* Statistics tab */
/* Profile tab */
"poll.svg", // Ntf_EVENT_SURVEY // TODO: Move to assessment tab (also necessary in database) !!!!!!!!!
"user-tie.svg", // Ntf_EVENT_ENROLMENT_NET // TODO: Move to users tab (also necessary in database) !!!!!!!!!
};
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Ntf_PutIconsNotif (void);
static void Ntf_WriteFormAllNotifications (bool AllNotifications);
static bool Ntf_GetAllNotificationsFromForm (void);
static bool Ntf_StartFormGoToAction (Ntf_NotifyEvent_t NotifyEvent,
long CrsCod,struct UsrData *UsrDat,long Cod);
static void Ntf_PutHiddenParamNotifyEvent (Ntf_NotifyEvent_t NotifyEvent);
static void Ntf_UpdateMyLastAccessToNotifications (void);
static void Ntf_SendPendingNotifByEMailToOneUsr (struct UsrData *ToUsrDat,unsigned *NumNotif,unsigned *NumMails);
static void Ntf_GetNumNotifSent (long DegCod,long CrsCod,
Ntf_NotifyEvent_t NotifyEvent,
unsigned *NumEvents,unsigned *NumMails);
static void Ntf_UpdateNumNotifSent (long DegCod,long CrsCod,
Ntf_NotifyEvent_t NotifyEvent,
unsigned NumEvents,unsigned NumMails);
static void Ntf_GetParamsNotifyEvents (void);
static unsigned Ntf_GetNumberOfAllMyUnseenNtfs (void);
static unsigned Ntf_GetNumberOfMyNewUnseenNtfs (void);
/*****************************************************************************/
/*************************** Show my notifications ***************************/
/*****************************************************************************/
void Ntf_ShowMyNotifications (void)
{
extern const char *Hlp_START_Notifications;
extern const char *Txt_Settings;
extern const char *Txt_Domains;
extern const char *Txt_Mark_all_NOTIFICATIONS_as_read;
extern const char *Txt_Notifications;
extern const char *Txt_Date;
extern const char *Txt_Event;
extern const char *Txt_Location;
extern const char *Txt_MSG_From;
extern const char *Txt_Email;
extern const char *Txt_NOTIFY_EVENTS_SINGULAR[Ntf_NUM_NOTIFY_EVENTS];
extern const char *Txt_Forum;
extern const char *Txt_Course;
extern const char *Txt_Degree;
extern const char *Txt_Centre;
extern const char *Txt_Institution;
extern const char *Txt_NOTIFICATION_STATUS[Ntf_NUM_STATUS_TXT];
extern const char *Txt_You_have_no_notifications;
extern const char *Txt_You_have_no_unread_notifications;
char SubQuery[128];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumNotif;
unsigned long NumNotifications;
bool AllNotifications;
Ntf_NotifyEvent_t NotifyEvent = (Ntf_NotifyEvent_t) 0; // Initialized to avoid warning
struct UsrData UsrDat;
struct Instit Ins;
struct Centre Ctr;
struct Degree Deg;
struct Course Crs;
long Cod;
char ForumName[For_MAX_BYTES_FORUM_NAME + 1];
time_t DateTimeUTC; // Date-time of the event
Ntf_Status_t Status;
Ntf_StatusTxt_t StatusTxt;
char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1];
char *ContentStr;
const char *ClassBackground;
const char *ClassAnchor;
const char *ClassAuthorBg;
bool PutLink;
/***** Get my notifications from database *****/
AllNotifications = Ntf_GetAllNotificationsFromForm ();
if (AllNotifications)
SubQuery[0] = '\0';
else
sprintf (SubQuery," AND (Status&%u)=0",
Ntf_STATUS_BIT_READ |
Ntf_STATUS_BIT_REMOVED);
NumNotifications = DB_QuerySELECT (&mysql_res,"can not get your notifications",
"SELECT NotifyEvent,FromUsrCod,InsCod,CtrCod,DegCod,CrsCod,"
"Cod,UNIX_TIMESTAMP(TimeNotif),Status"
" FROM notif"
" WHERE ToUsrCod=%ld%s"
" ORDER BY TimeNotif DESC",
Gbl.Usrs.Me.UsrDat.UsrCod,SubQuery);
/***** Contextual links *****/
fprintf (Gbl.F.Out,"