// swad_timeline_comment.c: social timeline comments
/*
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-2021 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 3 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 *********************************/
/*****************************************************************************/
#define _GNU_SOURCE // For asprintf
#include // For PATH_MAX
#include // For asprintf
#include "swad_forum.h"
#include "swad_global.h"
#include "swad_message.h"
#include "swad_photo.h"
#include "swad_profile.h"
#include "swad_timeline.h"
#include "swad_timeline_database.h"
#include "swad_timeline_favourite.h"
#include "swad_timeline_form.h"
#include "swad_timeline_note.h"
#include "swad_timeline_publication.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/************************* Private constants and types ***********************/
/*****************************************************************************/
#define TL_Com_NUM_VISIBLE_COMMENTS 3 // Maximum number of comments visible before expanding them
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Private global variables **************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static unsigned TL_Com_WriteHiddenComms (struct TL_Timeline *Timeline,
long NotCod,
char IdComms[Frm_MAX_BYTES_ID + 1],
unsigned NumInitialCommsToGet);
static void TL_Com_WriteOneCommInList (const struct TL_Timeline *Timeline,
MYSQL_RES *mysql_res);
static void TL_Com_LinkToShowOnlyLatestComms (const char IdComms[Frm_MAX_BYTES_ID + 1]);
static void TL_Com_LinkToShowPreviousComms (const char IdComms[Frm_MAX_BYTES_ID + 1],
unsigned NumInitialComms);
static void TL_Com_PutIconToToggleComms (const char *UniqueId,
const char *Icon,const char *Text);
static void TL_Com_CheckAndWriteComm (const struct TL_Timeline *Timeline,
struct TL_Com_Comment *Com);
static void TL_Com_WriteComm (const struct TL_Timeline *Timeline,
struct TL_Com_Comment *Com);
static void TL_Com_ShowAuthorPhoto (struct UsrData *UsrDat);
static void TL_Com_WriteAuthorTimeAndContent (struct TL_Com_Comment *Com,
const struct UsrData *UsrDat);
static void TL_Com_WriteAuthorName (const struct UsrData *UsrDat);
static void TL_Com_WriteContent (struct TL_Com_Comment *Com);
static void TL_Com_WriteButtons (const struct TL_Timeline *Timeline,
const struct TL_Com_Comment *Com,
const struct UsrData *UsrDat);
static void TL_Com_PutFormToRemoveComm (const struct TL_Timeline *Timeline,
long PubCod);
static long TL_Com_ReceiveComm (void);
static void TL_Com_RequestRemovalComm (struct TL_Timeline *Timeline);
static void TL_Com_PutParamsRemoveComm (void *Timeline);
static void TL_Com_RemoveComm (void);
static void TL_Com_GetDataOfCommFromRow (MYSQL_ROW row,
struct TL_Com_Comment *Com);
static void TL_Com_ResetComm (struct TL_Com_Comment *Com);
/*****************************************************************************/
/********* Put an icon to toggle on/off the form to comment a note ***********/
/*****************************************************************************/
void TL_Com_PutIconToToggleComm (const char UniqueId[Frm_MAX_BYTES_ID + 1])
{
extern const char *Txt_Comment;
/***** Link to toggle on/off the form to comment a note *****/
/* Begin container */
HTM_DIV_Begin ("id=\"%s_ico\" class=\"TL_ICO_COM_OFF\"",UniqueId);
/* Begin anchor */
HTM_A_Begin ("href=\"\" onclick=\"toggleNewComment ('%s');"
"return false;\"",
UniqueId);
/* Icon to toggle comment */
Ico_PutIcon ("comment-regular.svg",Txt_Comment,"CONTEXT_ICO_16x16");
/* End anchor */
HTM_A_End ();
/* End container */
HTM_DIV_End ();
}
/*****************************************************************************/
/********** Put an icon to toggle on/off the form to comment a note **********/
/*****************************************************************************/
void TL_Com_PutIconCommDisabled (void)
{
extern const char *Txt_Comment;
/***** Disabled icon to comment a note *****/
/* Begin container */
HTM_DIV_Begin ("class=\"TL_ICO_COM_OFF TL_ICO_DISABLED\"");
/* Disabled icon */
Ico_PutIcon ("edit.svg",Txt_Comment,"ICO16x16");
/* End container */
HTM_DIV_End ();
}
/*****************************************************************************/
/************************* Form to comment a note ****************************/
/*****************************************************************************/
void TL_Com_PutHiddenFormToWriteNewComm (const struct TL_Timeline *Timeline,
long NotCod,
const char IdNewComm[Frm_MAX_BYTES_ID + 1])
{
extern const char *Txt_New_TIMELINE_comment;
bool ShowPhoto = false;
char PhotoURL[PATH_MAX + 1];
/***** Begin container *****/
HTM_DIV_Begin ("id=\"%s\" class=\"TL_FORM_NEW_COM TL_RIGHT_WIDTH\""
" style=\"display:none;\"",
IdNewComm);
/***** Left: write author's photo (my photo) *****/
HTM_DIV_Begin ("class=\"TL_COM_PHOTO\"");
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (&Gbl.Usrs.Me.UsrDat,PhotoURL);
Pho_ShowUsrPhoto (&Gbl.Usrs.Me.UsrDat,ShowPhoto ? PhotoURL :
NULL,
"PHOTO30x40",Pho_ZOOM,true); // Use unique id
HTM_DIV_End ();
/***** Right: form to write the comment *****/
/* Begin right container */
HTM_DIV_Begin ("class=\"TL_COM_CONT TL_COMM_WIDTH\"");
/* Begin form to write the post */
TL_Frm_BeginForm (Timeline,TL_Frm_RECEIVE_COMM);
TL_Not_PutHiddenParamNotCod (NotCod);
/* Textarea and button */
TL_Pst_PutTextarea (Txt_New_TIMELINE_comment,
"TL_COM_TEXTAREA TL_COMM_WIDTH");
/* End form */
TL_Frm_EndForm ();
/* End right container */
HTM_DIV_End ();
/***** End container *****/
HTM_DIV_End ();
}
/*****************************************************************************/
/*********************** Write comments in a note ****************************/
/*****************************************************************************/
void TL_Com_WriteCommsInNote (const struct TL_Timeline *Timeline,
const struct TL_Not_Note *Not)
{
MYSQL_RES *mysql_res;
unsigned NumComms;
unsigned NumInitialComms;
unsigned NumFinalCommsToGet;
unsigned NumFinalCommsGot;
unsigned NumCom;
char IdComms[Frm_MAX_BYTES_ID + 1];
/***** Get number of comments in note *****/
NumComms = TL_DB_GetNumCommsInNote (Not->NotCod);
/***** Trivial check: if no comments ==> nothing to do *****/
if (!NumComms)
return;
/***** Compute how many initial comments will be hidden
and how many final comments will be visible *****/
// Never hide only one comment
// So, the number of comments initially hidden must be 0 or >= 2
if (NumComms <= TL_Com_NUM_VISIBLE_COMMENTS + 1)
{
NumInitialComms = 0;
NumFinalCommsToGet = NumComms;
}
else
{
NumInitialComms = NumComms - TL_Com_NUM_VISIBLE_COMMENTS;
NumFinalCommsToGet = TL_Com_NUM_VISIBLE_COMMENTS;
}
/***** Get final comments of this note from database *****/
NumFinalCommsGot = TL_DB_GetFinalComms (Not->NotCod,
NumFinalCommsToGet,
&mysql_res);
/*
Before clicking "See prev..." --> After clicking "See prev..."
_________________________________ _________________________________
| div con_ | | div con_ |
| (hidden) | | (visible) |
| _____________________________ | | _____________________________ |
| | v See only the latest | | | | v See only the latest | |
| |_____________________________| | | |_____________________________| |
|_________________________________| |_________________________________|
_________________________________ _________________________________
| div | | div updated |
| which content | | _____________________________ |
| will be updated via AJAX | | | ul com_ | |
| (parent of parent of form) | | | _________________________ | |
| | | | | li (comment 1) | | |
| | | | |_________________________| | |
| | | | | ... | | |
| | | | |_________________________| | |
| | | | | li (comment n) | | |
| | --> | | |_________________________| | |
| | | |_____________________________| |
| _____________________________ | | _____________________________ |
| | div exp_ | | | | div exp_ | |
| | _________________________ | | | | (hidden) | |
| | | form | | | | | | |
| | | _____________________ | | | | | _____________________ | |
| | | | ^ See prev.comments | | | | | | | ^ See prev.comments | | |
| | | |_____________________| | | | | | |_____________________| | |
| | |_________________________| | | | | | |
| |_____________________________| | | |_____________________________| |
|_________________________________| |_________________________________|
_________________________________ _________________________________
| ul com_ | | ul com_ |
| _________________________ | | _________________________ |
| | li (comment 1) | | | | li (comment 1) | |
| |_________________________| | | |_________________________| |
| | ... | | | | ... | |
| |_________________________| | | |_________________________| |
| | li (comment n) | | | | li (comment n) | |
| |_________________________| | | |_________________________| |
|_________________________________| |_________________________________|
*/
/***** Link to show initial hidden comments *****/
if (NumInitialComms)
{
/***** Create unique id for list of hidden comments *****/
Frm_SetUniqueId (IdComms);
/***** Link (initially hidden) to show only the latest comments *****/
TL_Com_LinkToShowOnlyLatestComms (IdComms);
/***** Div which content will be updated via AJAX *****/
HTM_DIV_Begin ("id=\"%s\" class=\"TL_RIGHT_WIDTH\"",IdComms);
TL_Frm_FormToShowHiddenComms (Not->NotCod,IdComms,NumInitialComms);
HTM_DIV_End ();
}
/***** List final visible comments *****/
if (NumFinalCommsGot)
{
HTM_UL_Begin ("class=\"TL_LIST\"");
for (NumCom = 0;
NumCom < NumFinalCommsGot;
NumCom++)
TL_Com_WriteOneCommInList (Timeline,mysql_res);
HTM_UL_End ();
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********************** Write hidden comments via AJAX ***********************/
/*****************************************************************************/
void TL_Com_ShowHiddenCommsUsr (void)
{
/***** Get user whom profile is displayed *****/
Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ();
/***** Show hidden comments *****/
TL_Com_ShowHiddenCommsGbl ();
}
void TL_Com_ShowHiddenCommsGbl (void)
{
struct TL_Timeline Timeline;
long NotCod;
char IdComms[Frm_MAX_BYTES_ID + 1];
unsigned NumInitialCommsToGet;
unsigned NumInitialCommsGot;
/***** Reset timeline context *****/
TL_ResetTimeline (&Timeline);
/***** Get parameters *****/
/* Get note code */
NotCod = TL_Not_GetParamNotCod ();
/* Get identifier */
Par_GetParToText ("IdComments",IdComms,Frm_MAX_BYTES_ID);
/* Get number of comments to get */
NumInitialCommsToGet = (unsigned) Par_GetParToLong ("NumHidCom");
/***** Write HTML inside DIV with hidden comments *****/
NumInitialCommsGot =
TL_Com_WriteHiddenComms (&Timeline,NotCod,IdComms,NumInitialCommsToGet);
/***** Link to show the first comments *****/
TL_Com_LinkToShowPreviousComms (IdComms,NumInitialCommsGot);
}
/*****************************************************************************/
/**************************** Write hidden comments **************************/
/*****************************************************************************/
// Returns the number of comments got
static unsigned TL_Com_WriteHiddenComms (struct TL_Timeline *Timeline,
long NotCod,
char IdComms[Frm_MAX_BYTES_ID + 1],
unsigned NumInitialCommsToGet)
{
MYSQL_RES *mysql_res;
unsigned long NumInitialCommsGot;
unsigned long NumCom;
/***** Get comments of this note from database *****/
NumInitialCommsGot = TL_DB_GetInitialComms (NotCod,
NumInitialCommsToGet,
&mysql_res);
/***** List comments *****/
HTM_UL_Begin ("id=\"com_%s\" class=\"TL_LIST\"",IdComms);
for (NumCom = 0;
NumCom < NumInitialCommsGot;
NumCom++)
TL_Com_WriteOneCommInList (Timeline,mysql_res);
HTM_UL_End ();
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumInitialCommsGot;
}
/*****************************************************************************/
/************************* Write a comment in list ***************************/
/*****************************************************************************/
static void TL_Com_WriteOneCommInList (const struct TL_Timeline *Timeline,
MYSQL_RES *mysql_res)
{
MYSQL_ROW row;
struct TL_Com_Comment Com;
/***** Initialize image *****/
Med_MediaConstructor (&Com.Content.Media);
/***** Get data of comment *****/
row = mysql_fetch_row (mysql_res);
TL_Com_GetDataOfCommFromRow (row,&Com);
/***** Write comment *****/
HTM_LI_Begin ("class=\"TL_COM\"");
TL_Com_CheckAndWriteComm (Timeline,&Com);
HTM_LI_End ();
/***** Free image *****/
Med_MediaDestructor (&Com.Content.Media);
}
/*****************************************************************************/
/****************** Link to show only the latest comments ********************/
/*****************************************************************************/
static void TL_Com_LinkToShowOnlyLatestComms (const char IdComms[Frm_MAX_BYTES_ID + 1])
{
extern const char *Txt_See_only_the_latest_COMMENTS;
/***** Icon and text to show only the latest comments ****/
HTM_DIV_Begin ("id=\"con_%s\" class=\"TL_EXPAND_COM TL_RIGHT_WIDTH\""
" style=\"display:none;\"", // Hidden
IdComms);
TL_Com_PutIconToToggleComms (IdComms,"angle-down.svg",
Txt_See_only_the_latest_COMMENTS);
HTM_DIV_End ();
}
/*****************************************************************************/
/********************* Link to show the first comments ***********************/
/*****************************************************************************/
static void TL_Com_LinkToShowPreviousComms (const char IdComms[Frm_MAX_BYTES_ID + 1],
unsigned NumInitialComms)
{
extern const char *Txt_See_the_previous_X_COMMENTS;
/***** Icon and text to show only the latest comments ****/
HTM_DIV_Begin ("id=\"exp_%s\" class=\"TL_EXPAND_COM TL_RIGHT_WIDTH\""
" style=\"display:none;\"", // Hidden
IdComms);
TL_Com_PutIconToToggleComms (IdComms,"angle-up.svg",
Str_BuildStringLong (Txt_See_the_previous_X_COMMENTS,
(long) NumInitialComms));
Str_FreeString ();
HTM_DIV_End ();
}
/*****************************************************************************/
/********** Put an icon to toggle on/off comments in a publication ***********/
/*****************************************************************************/
static void TL_Com_PutIconToToggleComms (const char *UniqueId,
const char *Icon,const char *Text)
{
extern const char *The_ClassFormLinkInBox[The_NUM_THEMES];
char *OnClick;
if (asprintf (&OnClick,"toggleComments('%s')",UniqueId) < 0)
Lay_NotEnoughMemoryExit ();
/***** Link to toggle on/off some divs *****/
HTM_BUTTON_BUTTON_Begin (Text,The_ClassFormLinkInBox[Gbl.Prefs.Theme],OnClick);
Ico_PutIconTextLink (Icon,Text);
HTM_BUTTON_End ();
free (OnClick);
}
/*****************************************************************************/
/************************** Check and write comment **************************/
/*****************************************************************************/
static void TL_Com_CheckAndWriteComm (const struct TL_Timeline *Timeline,
struct TL_Com_Comment *Com)
{
/*__________________________________________
| _____ | | | \ \
|| | | Author's name | Date-time | | |
||Auth.| |______________________|___________| | |
||photo| | | | author's |
||_____| | | > name, time |
| | Comment | | and content > comment
| | content | | |
| | | | |
| |__________________________________| / |
| | | | \ |
| | Favs |Remove| > buttons |
|________|___________________________|______| / /
*/
/***** Trivial check: codes *****/
if (Com->PubCod <= 0 ||
Com->NotCod <= 0 ||
Com->UsrCod <= 0)
{
Ale_ShowAlert (Ale_ERROR,"Error in comment.");
return;
}
/***** Write comment *****/
TL_Com_WriteComm (Timeline,Com);
}
/*****************************************************************************/
/******************************** Write comment ******************************/
/*****************************************************************************/
static void TL_Com_WriteComm (const struct TL_Timeline *Timeline,
struct TL_Com_Comment *Com)
{
struct UsrData UsrDat; // Author of the comment
/***** Get author's data *****/
Usr_UsrDataConstructor (&UsrDat);
UsrDat.UsrCod = Com->UsrCod;
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS);
/***** Left: author's photo *****/
TL_Com_ShowAuthorPhoto (&UsrDat);
/***** Right: author's name, time, content, and buttons *****/
/* Begin container */
HTM_DIV_Begin ("class=\"TL_COM_CONT TL_COMM_WIDTH\"");
/* Right top: author's name, time, and content */
TL_Com_WriteAuthorTimeAndContent (Com,&UsrDat);
/* Right bottom: buttons */
TL_Com_WriteButtons (Timeline,Com,&UsrDat);
/* End container */
HTM_DIV_End ();
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
/*****************************************************************************/
/********************* Show photo of author of a comment *********************/
/*****************************************************************************/
static void TL_Com_ShowAuthorPhoto (struct UsrData *UsrDat)
{
bool ShowPhoto = false;
char PhotoURL[PATH_MAX + 1];
/***** Show author's photo *****/
/* Begin container */
HTM_DIV_Begin ("class=\"TL_COM_PHOTO\"");
/* Author's photo */
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (UsrDat,PhotoURL);
Pho_ShowUsrPhoto (UsrDat,ShowPhoto ? PhotoURL :
NULL,
"PHOTO30x40",Pho_ZOOM,true); // Use unique id
/* End container */
HTM_DIV_End ();
}
/*****************************************************************************/
/**** Write top right part of a note: author's name, time and note content ***/
/*****************************************************************************/
static void TL_Com_WriteAuthorTimeAndContent (struct TL_Com_Comment *Com,
const struct UsrData *UsrDat) // Author
{
/***** Write author's full name and nickname *****/
TL_Com_WriteAuthorName (UsrDat);
/***** Write date and time *****/
TL_WriteDateTime (Com->DateTimeUTC);
/***** Write content of the comment *****/
TL_Com_WriteContent (Com);
}
/*****************************************************************************/
/*************** Write name of author of a comment to a note *****************/
/*****************************************************************************/
static void TL_Com_WriteAuthorName (const struct UsrData *UsrDat) // Author
{
extern const char *Txt_My_public_profile;
extern const char *Txt_Another_user_s_profile;
/***** Show user's name inside form to go to user's public profile *****/
/* Begin form */
Frm_BeginFormUnique (ActSeeOthPubPrf);
Usr_PutParamUsrCodEncrypted (UsrDat->EnUsrCod);
/* Author's name */
HTM_BUTTON_SUBMIT_Begin (Usr_ItsMe (UsrDat->UsrCod) ? Txt_My_public_profile :
Txt_Another_user_s_profile,
"BT_LINK TL_COM_AUTHOR TL_COMM_AUTHOR_WIDTH DAT_BOLD",NULL);
HTM_Txt (UsrDat->FullName);
HTM_BUTTON_End ();
/* End form */
Frm_EndForm ();
}
/*****************************************************************************/
/************************* Write content of comment **************************/
/*****************************************************************************/
static void TL_Com_WriteContent (struct TL_Com_Comment *Com)
{
/***** Write content of the comment *****/
if (Com->Content.Txt[0])
{
HTM_DIV_Begin ("class=\"TL_TXT\"");
Msg_WriteMsgContent (Com->Content.Txt,Cns_MAX_BYTES_LONG_TEXT,true,false);
HTM_DIV_End ();
}
/***** Show image *****/
Med_ShowMedia (&Com->Content.Media,"TL_COM_MED_CONT TL_COMM_WIDTH",
"TL_COM_MED TL_COMM_WIDTH");
}
/*****************************************************************************/
/********************* Write bottom part of a comment ************************/
/*****************************************************************************/
static void TL_Com_WriteButtons (const struct TL_Timeline *Timeline,
const struct TL_Com_Comment *Com,
const struct UsrData *UsrDat) // Author
{
static unsigned NumDiv = 0; // Used to create unique div id for fav
NumDiv++;
/***** Begin buttons container *****/
HTM_DIV_Begin ("class=\"TL_FOOT TL_COMM_WIDTH\"");
/***** Foot column 1: fav zone *****/
HTM_DIV_Begin ("id=\"fav_com_%s_%u\" class=\"TL_FAV_COM TL_FAV_WIDTH\"",
Gbl.UniqueNameEncrypted,NumDiv);
TL_Fav_PutIconToFavUnfComm (Com,TL_Usr_SHOW_FEW_USRS);
HTM_DIV_End ();
/***** Foot column 2: icon to remove this comment *****/
HTM_DIV_Begin ("class=\"TL_REM\"");
if (Usr_ItsMe (UsrDat->UsrCod)) // I am the author
TL_Com_PutFormToRemoveComm (Timeline,Com->PubCod);
HTM_DIV_End ();
/***** End buttons container *****/
HTM_DIV_End ();
}
/*****************************************************************************/
/************************* Form to remove comment ****************************/
/*****************************************************************************/
static void TL_Com_PutFormToRemoveComm (const struct TL_Timeline *Timeline,
long PubCod)
{
extern const char *Txt_Remove;
/***** Form to remove publication *****/
/* Begin form */
TL_Frm_BeginForm (Timeline,TL_Frm_REQ_REM_COMM);
TL_Pub_PutHiddenParamPubCod (PubCod);
/* Icon to remove */
Ico_PutIconLink ("trash.svg",Txt_Remove);
/* End form */
TL_Frm_EndForm ();
}
/*****************************************************************************/
/******************************* Comment a note ******************************/
/*****************************************************************************/
void TL_Com_ReceiveCommUsr (void)
{
struct TL_Timeline Timeline;
long NotCod;
/***** Reset timeline context *****/
TL_ResetTimeline (&Timeline);
/***** Get user whom profile is displayed *****/
Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ();
/***** Show user's profile *****/
Prf_ShowUserProfile (&Gbl.Usrs.Other.UsrDat);
/***** Begin section *****/
HTM_SECTION_Begin (TL_TIMELINE_SECTION_ID);
/***** Receive comment in a note
and write updated timeline after commenting (user) *****/
NotCod = TL_Com_ReceiveComm ();
TL_ShowTimelineUsrHighlightingNot (&Timeline,NotCod);
/***** End section *****/
HTM_SECTION_End ();
}
void TL_Com_ReceiveCommGbl (void)
{
struct TL_Timeline Timeline;
long NotCod;
/***** Initialize timeline *****/
TL_InitTimelineGbl (&Timeline);
/***** Receive comment in a note *****/
NotCod = TL_Com_ReceiveComm ();
/***** Write updated timeline after commenting (global) *****/
TL_ShowTimelineGblHighlightingNot (&Timeline,NotCod);
}
static long TL_Com_ReceiveComm (void)
{
extern const char *Txt_The_original_post_no_longer_exists;
struct TL_Pst_PostContent Content;
struct TL_Not_Note Not;
struct TL_Pub_Publication Pub;
/***** Get data of note *****/
Not.NotCod = TL_Not_GetParamNotCod ();
TL_Not_GetDataOfNoteByCod (&Not);
/***** Trivial check: note code *****/
if (Not.NotCod <= 0)
{
Ale_ShowAlert (Ale_WARNING,Txt_The_original_post_no_longer_exists);
return -1L;
}
/***** Get the content of the comment *****/
Par_GetParAndChangeFormat ("Txt",Content.Txt,Cns_MAX_BYTES_LONG_TEXT,
Str_TO_RIGOROUS_HTML,true);
/***** Initialize image *****/
Med_MediaConstructor (&Content.Media);
/***** Get attached image (action, file and title) *****/
Content.Media.Width = TL_IMAGE_SAVED_MAX_WIDTH;
Content.Media.Height = TL_IMAGE_SAVED_MAX_HEIGHT;
Content.Media.Quality = TL_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (-1L,-1L,-1,&Content.Media,NULL,NULL);
Ale_ShowAlerts (NULL);
if (Content.Txt[0] || // Text not empty
Content.Media.Status == Med_PROCESSED) // A media is attached
{
/***** Store media in filesystem and database *****/
Med_RemoveKeepOrStoreMedia (-1L,&Content.Media);
/***** Publish *****/
/* Insert into publications */
Pub.NotCod = Not.NotCod;
Pub.PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Pub.PubType = TL_Pub_COMMENT_TO_NOTE;
TL_Pub_PublishPubInTimeline (&Pub); // Set Pub.PubCod
/* Insert comment content in the database */
TL_DB_InsertCommContent (Pub.PubCod,&Content);
/***** Store notifications about the new comment *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_COMMENT,Pub.PubCod);
/***** Analyze content and store notifications about mentions *****/
Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (Pub.PubCod,Content.Txt);
}
/***** Free image *****/
Med_MediaDestructor (&Content.Media);
return Not.NotCod;
}
/*****************************************************************************/
/**************** Request the removal of a comment in a note *****************/
/*****************************************************************************/
void TL_Com_RequestRemComUsr (void)
{
struct TL_Timeline Timeline;
/***** Reset timeline context *****/
TL_ResetTimeline (&Timeline);
/***** Get user whom profile is displayed *****/
Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ();
/***** Show user's profile *****/
Prf_ShowUserProfile (&Gbl.Usrs.Other.UsrDat);
/***** Begin section *****/
HTM_SECTION_Begin (TL_TIMELINE_SECTION_ID);
/***** Request the removal of comment in note *****/
TL_Com_RequestRemovalComm (&Timeline);
/***** Write timeline again (user) *****/
TL_ShowTimelineUsr (&Timeline);
/***** End section *****/
HTM_SECTION_End ();
}
void TL_Com_RequestRemComGbl (void)
{
struct TL_Timeline Timeline;
/***** Initialize timeline *****/
TL_InitTimelineGbl (&Timeline);
/***** Request the removal of comment in note *****/
TL_Com_RequestRemovalComm (&Timeline);
/***** Write timeline again (global) *****/
TL_ShowNoteAndTimelineGbl (&Timeline);
}
static void TL_Com_RequestRemovalComm (struct TL_Timeline *Timeline)
{
extern const char *Txt_The_comment_no_longer_exists;
extern const char *Txt_Do_you_really_want_to_remove_the_following_comment;
struct TL_Com_Comment Com;
/***** Initialize media *****/
Med_MediaConstructor (&Com.Content.Media);
/***** Get data of comment *****/
Com.PubCod = TL_Pub_GetParamPubCod ();
TL_Com_GetDataOfCommByCod (&Com);
/***** Trivial check 1: publication code *****/
if (Com.PubCod <= 0)
{
Med_MediaDestructor (&Com.Content.Media);
Ale_ShowAlert (Ale_WARNING,Txt_The_comment_no_longer_exists);
return;
}
/***** Trivial check 2: only if I am the author of this comment *****/
if (!Usr_ItsMe (Com.UsrCod))
{
Med_MediaDestructor (&Com.Content.Media);
Ale_ShowAlert (Ale_ERROR,"You are not the author.");
return;
}
/***** Show question and button to remove comment *****/
/* Begin alert */
TL_Frm_BeginAlertRemove (Txt_Do_you_really_want_to_remove_the_following_comment);
/* Show comment */
Box_BoxBegin (NULL,NULL,
NULL,NULL,
NULL,Box_NOT_CLOSABLE);
HTM_DIV_Begin ("class=\"TL_LEFT_PHOTO\"");
HTM_DIV_End ();
HTM_DIV_Begin ("class=\"TL_RIGHT_CONT TL_RIGHT_WIDTH\"");
TL_Com_CheckAndWriteComm (Timeline,&Com);
HTM_DIV_End ();
Box_BoxEnd ();
/* End alert */
Timeline->PubCod = Com.PubCod; // Publication to be removed
TL_Frm_EndAlertRemove (Timeline,TL_Frm_REM_COMM,
TL_Com_PutParamsRemoveComm);
/***** Free media *****/
Med_MediaDestructor (&Com.Content.Media);
}
/*****************************************************************************/
/******************** Put parameters to remove a comment *********************/
/*****************************************************************************/
static void TL_Com_PutParamsRemoveComm (void *Timeline)
{
if (Timeline)
{
if (Gbl.Usrs.Other.UsrDat.UsrCod > 0) // User's timeline
Usr_PutParamOtherUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EnUsrCod);
else // Global timeline
Usr_PutHiddenParamWho (((struct TL_Timeline *) Timeline)->Who);
TL_Pub_PutHiddenParamPubCod (((struct TL_Timeline *) Timeline)->PubCod);
}
}
/*****************************************************************************/
/***************************** Remove a comment ******************************/
/*****************************************************************************/
void TL_Com_RemoveComUsr (void)
{
struct TL_Timeline Timeline;
/***** Reset timeline context *****/
TL_ResetTimeline (&Timeline);
/***** Get user whom profile is displayed *****/
Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ();
/***** Show user's profile *****/
Prf_ShowUserProfile (&Gbl.Usrs.Other.UsrDat);
/***** Begin section *****/
HTM_SECTION_Begin (TL_TIMELINE_SECTION_ID);
/***** Remove a comment *****/
TL_Com_RemoveComm ();
/***** Write updated timeline after removing (user) *****/
TL_ShowTimelineUsr (&Timeline);
/***** End section *****/
HTM_SECTION_End ();
}
void TL_Com_RemoveComGbl (void)
{
struct TL_Timeline Timeline;
/***** Initialize timeline *****/
TL_InitTimelineGbl (&Timeline);
/***** Remove a comment *****/
TL_Com_RemoveComm ();
/***** Write updated timeline after removing (global) *****/
TL_ShowNoteAndTimelineGbl (&Timeline);
}
static void TL_Com_RemoveComm (void)
{
extern const char *Txt_The_comment_no_longer_exists;
extern const char *Txt_Comment_removed;
struct TL_Com_Comment Com;
/***** Initialize media *****/
Med_MediaConstructor (&Com.Content.Media);
/***** Get data of comment *****/
Com.PubCod = TL_Pub_GetParamPubCod ();
TL_Com_GetDataOfCommByCod (&Com);
/***** Trivial check 1: publication code *****/
if (Com.PubCod <= 0)
{
Med_MediaDestructor (&Com.Content.Media);
Ale_ShowAlert (Ale_WARNING,Txt_The_comment_no_longer_exists);
return;
}
/***** Trivial check 2: only if I am the author of this comment *****/
if (!Usr_ItsMe (Com.UsrCod))
{
Med_MediaDestructor (&Com.Content.Media);
Ale_ShowAlert (Ale_ERROR,"You are not the author.");
return;
}
/***** Remove media associated to comment
and delete comment from database *****/
TL_Com_RemoveCommMediaAndDBEntries (Com.PubCod);
/***** Free media *****/
Med_MediaDestructor (&Com.Content.Media);
/***** Reset fields of comment *****/
TL_Com_ResetComm (&Com);
/***** Message of success *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_Comment_removed);
}
/*****************************************************************************/
/*************** Remove comment media and database entries *******************/
/*****************************************************************************/
void TL_Com_RemoveCommMediaAndDBEntries (long PubCod)
{
/***** Remove media associated to comment *****/
Med_RemoveMedia (TL_DB_GetMedCodFromComm (PubCod));
/***** Mark possible notifications on this comment as removed *****/
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_COMMENT,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_FAV ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_MENTION,PubCod);
/***** Remove favs for this comment *****/
TL_DB_RemoveCommFavs (PubCod);
/***** Remove content of this comment *****/
TL_DB_RemoveCommContent (PubCod);
/***** Remove this comment publication *****/
TL_DB_RemoveCommPub (PubCod);
}
/*****************************************************************************/
/******************* Get data of comment using its code **********************/
/*****************************************************************************/
void TL_Com_GetDataOfCommByCod (struct TL_Com_Comment *Com)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Trivial check: publication code should be > 0 *****/
if (Com->PubCod <= 0)
{
/***** Reset fields of comment *****/
TL_Com_ResetComm (Com);
return;
}
/***** Get data of comment from database *****/
if (TL_DB_GetDataOfCommByCod (Com->PubCod,&mysql_res))
{
/* Get data of comment */
row = mysql_fetch_row (mysql_res);
TL_Com_GetDataOfCommFromRow (row,Com);
}
else
/* Reset fields of comment */
TL_Com_ResetComm (Com);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********************** Get data of comment from row *************************/
/*****************************************************************************/
static void TL_Com_GetDataOfCommFromRow (MYSQL_ROW row,
struct TL_Com_Comment *Com)
{
/*
row[0]: PubCod
row[1]: PublisherCod]
row[2]: NotCod
row[3]: TimePublish
row[4]: Txt
row[5]: MedCod
*/
/***** Get code of comment (row[0]), publisher code (row[1])
and note code (row[2) *****/
Com->PubCod = Str_ConvertStrCodToLongCod (row[0]);
Com->UsrCod = Str_ConvertStrCodToLongCod (row[1]);
Com->NotCod = Str_ConvertStrCodToLongCod (row[2]);
/***** Get date-time of the note (row[3]) *****/
Com->DateTimeUTC = Dat_GetUNIXTimeFromStr (row[3]);
/***** Get text content (row[4]) and media content (row[5]) *****/
Str_Copy (Com->Content.Txt,row[4],sizeof (Com->Content.Txt) - 1);
Com->Content.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Com->Content.Media);
/***** Get number of times this comment has been favourited *****/
Com->NumFavs = TL_DB_GetNumTimesHasBeenFav (TL_Fav_COMM,
Com->PubCod,Com->UsrCod);
}
/*****************************************************************************/
/************************** Reset fields of comment **************************/
/*****************************************************************************/
static void TL_Com_ResetComm (struct TL_Com_Comment *Com)
{
Com->PubCod =
Com->UsrCod =
Com->NotCod = -1L;
Com->DateTimeUTC = (time_t) 0;
Com->Content.Txt[0] = '\0';
Com->NumFavs = 0;
}