mirror of https://github.com/acanas/swad-core.git
Version20.25
This commit is contained in:
parent
d5439d6032
commit
636665abda
3
Makefile
3
Makefile
|
@ -62,7 +62,8 @@ OBJS = swad_account.o swad_action.o swad_agenda.o swad_alert.o \
|
|||
swad_tab.o swad_tag.o swad_test.o swad_test_config.o \
|
||||
swad_test_import.o swad_test_print.o swad_test_visibility.o \
|
||||
swad_theme.o swad_timeline.o swad_timeline_comment.o \
|
||||
swad_timeline_favourite.o swad_timeline_note.o swad_timeline_share.o \
|
||||
swad_timeline_favourite.o swad_timeline_note.o \
|
||||
swad_timeline_publication.o swad_timeline_share.o \
|
||||
swad_timetable.o \
|
||||
swad_user.o \
|
||||
swad_xml.o \
|
||||
|
|
|
@ -553,7 +553,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
|||
En OpenSWAD:
|
||||
ps2pdf source.ps destination.pdf
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 20.24 (2021-02-11)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 20.25 (2021-02-11)"
|
||||
#define CSS_FILE "swad20.8.css"
|
||||
#define JS_FILE "swad20.6.2.js"
|
||||
/*
|
||||
|
@ -601,6 +601,7 @@ TODO: DNI de un estudiante sale err
|
|||
TODO: BUG: Cuando un tipo de grupo sólo tiene un grupo, inscribirse es voluntario, el estudiante sólo puede pertenecer a un grupo, y se inscribe en él, debería poder desapuntarse. Ahora no puede.
|
||||
TODO: Salvador Romero Cortés: @acanas opción para editar posts
|
||||
|
||||
Version 20.25: Feb 11, 2021 New module swad_timeline_publication. (305440 lines)
|
||||
Version 20.24: Feb 11, 2021 Code refactoring in timeline. New linked list to hold publications. (305354 lines)
|
||||
Version 20.23: Feb 11, 2021 New modules swad_timeline_comment and swad_timeline_note. (305319 lines)
|
||||
Version 20.22: Feb 10, 2021 Code refactoring in timeline. (305137 lines)
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "swad_parameter.h"
|
||||
#include "swad_survey.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
|
@ -725,7 +726,7 @@ static bool Ntf_StartFormGoToAction (Ntf_NotifyEvent_t NotifyEvent,
|
|||
case Ntf_EVENT_TIMELINE_MENTION:
|
||||
// Cod is the code of the social publishing
|
||||
Frm_StartForm (ActSeeTmlGbl);
|
||||
TL_PutHiddenParamPubCod (Cod);
|
||||
TL_Pub_PutHiddenParamPubCod (Cod);
|
||||
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
||||
Ntf_PutHiddenParamNotifyEvent (NotifyEvent);
|
||||
break;
|
||||
|
@ -877,7 +878,7 @@ void Ntf_GetNotifSummaryAndContent (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
|
|||
case Ntf_EVENT_TIMELINE_SHARE:
|
||||
case Ntf_EVENT_TIMELINE_MENTION:
|
||||
// Cod is the code of the social publishing
|
||||
TL_GetNotifPublication (SummaryStr,ContentStr,Cod,GetContent);
|
||||
TL_Pub_GetNotifPublication (SummaryStr,ContentStr,Cod,GetContent);
|
||||
break;
|
||||
case Ntf_EVENT_FOLLOWER:
|
||||
Fol_GetNotifFollower (SummaryStr,ContentStr);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "swad_setting.h"
|
||||
#include "swad_theme.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
#include "swad_user.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1129,7 +1130,7 @@ static void Prf_GetNumSocialPubsAndStoreAsUsrFigure (long UsrCod)
|
|||
Prf_ResetUsrFigures (&UsrFigures);
|
||||
|
||||
/***** Get number of forum posts from database *****/
|
||||
UsrFigures.NumSocPub = TL_GetNumPubsUsr (UsrCod);
|
||||
UsrFigures.NumSocPub = TL_Pub_GetNumPubsUsr (UsrCod);
|
||||
|
||||
/***** Update number of forum posts in user's figures *****/
|
||||
if (Prf_CheckIfUsrFiguresExists (UsrCod))
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "swad_database.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_parameter.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_note.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private constants *****************************/
|
||||
|
@ -229,7 +229,7 @@ static void Ses_RemoveSessionFromDB (void)
|
|||
|
||||
/***** Clear old unused social timelines in database *****/
|
||||
// This is necessary to prevent the table growing and growing
|
||||
TL_ClearOldTimelinesDB ();
|
||||
TL_Not_ClearOldTimelinesNotesFromDB ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
1014
swad_timeline.c
1014
swad_timeline.c
File diff suppressed because it is too large
Load Diff
|
@ -94,8 +94,8 @@ struct TL_Timeline
|
|||
TL_WhatToGet_t WhatToGet;
|
||||
struct
|
||||
{
|
||||
struct TL_Publication *Top; // Points to first element in list of publications
|
||||
struct TL_Publication *Bottom; // Points to last element in list of publications
|
||||
struct TL_Pub_Publication *Top; // Points to first element in list of publications
|
||||
struct TL_Pub_Publication *Bottom; // Points to last element in list of publications
|
||||
} Pubs;
|
||||
long NotCod; // Used as parameter about social note to be edited, removed...
|
||||
long PubCod; // Used as parameter about social publishing to be edited, removed...
|
||||
|
@ -107,27 +107,6 @@ typedef enum
|
|||
TL_SHOW_ALL_USRS, // Show all favers/sharers
|
||||
} TL_HowManyUsrs_t;
|
||||
|
||||
#define TL_NUM_PUB_TYPES 4
|
||||
// If the numbers assigned to each event type change,
|
||||
// it is necessary to change old numbers to new ones in database table tl_notes
|
||||
typedef enum
|
||||
{
|
||||
TL_PUB_UNKNOWN = 0,
|
||||
TL_PUB_ORIGINAL_NOTE = 1,
|
||||
TL_PUB_SHARED_NOTE = 2,
|
||||
TL_PUB_COMMENT_TO_NOTE = 3,
|
||||
} TL_PubType_t;
|
||||
|
||||
struct TL_Publication
|
||||
{
|
||||
long PubCod;
|
||||
long NotCod;
|
||||
long PublisherCod; // Sharer or writer of the publication
|
||||
TL_PubType_t PubType;
|
||||
TL_TopMessage_t TopMessage; // Used to show feedback on the action made
|
||||
struct TL_Publication *Next; // Used for chained list
|
||||
};
|
||||
|
||||
struct TL_PostContent
|
||||
{
|
||||
char Txt[Cns_MAX_BYTES_LONG_TEXT + 1];
|
||||
|
@ -183,22 +162,11 @@ void TL_WriteDateTime (time_t TimeUTC);
|
|||
|
||||
void TL_GetAndWritePost (long PstCod);
|
||||
|
||||
void TL_PublishPubInTimeline (struct TL_Publication *Pub);
|
||||
|
||||
void TL_PutTextarea (const char *Placeholder,const char *ClassTextArea);
|
||||
|
||||
void TL_ReceivePostUsr (void);
|
||||
void TL_ReceivePostGbl (void);
|
||||
|
||||
void TL_Com_ShowHiddenCommentsUsr (void);
|
||||
void TL_Com_ShowHiddenCommentsGbl (void);
|
||||
|
||||
void TL_PutHiddenParamPubCod (long PubCod);
|
||||
long TL_GetParamPubCod (void);
|
||||
|
||||
void TL_CreateNotifToAuthor (long AuthorCod,long PubCod,
|
||||
Ntf_NotifyEvent_t NotifyEvent);
|
||||
|
||||
void TL_RemoveUsrContent (long UsrCod);
|
||||
|
||||
void TL_ShowNumSharersOrFavers (unsigned NumUsrs);
|
||||
|
@ -211,12 +179,4 @@ void TL_FormFavSha (Act_Action_t ActionGbl,Act_Action_t ActionUsr,
|
|||
const char *ParamFormat,long ParamCod,
|
||||
const char *Icon,const char *Title);
|
||||
|
||||
void TL_ClearOldTimelinesDB (void);
|
||||
|
||||
void TL_GetNotifPublication (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
|
||||
char **ContentStr,
|
||||
long PubCod,bool GetContent);
|
||||
|
||||
unsigned long TL_GetNumPubsUsr (long UsrCod);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_favourite.h"
|
||||
#include "swad_timeline_note.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
#include "swad_timeline_share.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -185,7 +186,7 @@ unsigned long TL_Com_GetNumCommentsInNote (long NotCod)
|
|||
return DB_QueryCOUNT ("can not get number of comments in a note",
|
||||
"SELECT COUNT(*) FROM tl_pubs"
|
||||
" WHERE NotCod=%ld AND PubType=%u",
|
||||
NotCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
|
||||
NotCod,(unsigned) TL_Pub_COMMENT_TO_NOTE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -237,7 +238,7 @@ void TL_Com_WriteCommentsInNote (struct TL_Timeline *Timeline,
|
|||
" ORDER BY tl_pubs.PubCod DESC LIMIT %u"
|
||||
") AS comments"
|
||||
" ORDER BY PubCod",
|
||||
Not->NotCod,(unsigned) TL_PUB_COMMENT_TO_NOTE,
|
||||
Not->NotCod,(unsigned) TL_Pub_COMMENT_TO_NOTE,
|
||||
NumFinalCommentsToGet);
|
||||
|
||||
/*
|
||||
|
@ -454,7 +455,7 @@ static unsigned TL_Com_WriteHiddenComments (struct TL_Timeline *Timeline,
|
|||
" AND tl_pubs.PubCod=tl_comments.PubCod"
|
||||
" ORDER BY tl_pubs.PubCod"
|
||||
" LIMIT %lu",
|
||||
NotCod,(unsigned) TL_PUB_COMMENT_TO_NOTE,
|
||||
NotCod,(unsigned) TL_Pub_COMMENT_TO_NOTE,
|
||||
NumInitialCommentsToGet);
|
||||
|
||||
/***** List with comments *****/
|
||||
|
@ -699,7 +700,7 @@ static void TL_Com_PutFormToRemoveComment (const struct TL_Timeline *Timeline,
|
|||
|
||||
/***** Form to remove publication *****/
|
||||
TL_FormStart (Timeline,ActReqRemTL_ComGbl,ActReqRemTL_ComUsr);
|
||||
TL_PutHiddenParamPubCod (PubCod);
|
||||
TL_Pub_PutHiddenParamPubCod (PubCod);
|
||||
Ico_PutIconLink ("trash.svg",Txt_Remove);
|
||||
Frm_EndForm ();
|
||||
}
|
||||
|
@ -754,7 +755,7 @@ static long TL_Com_ReceiveComment (void)
|
|||
extern const char *Txt_The_original_post_no_longer_exists;
|
||||
struct TL_PostContent Content;
|
||||
struct TL_Not_Note Not;
|
||||
struct TL_Publication Pub;
|
||||
struct TL_Pub_Publication Pub;
|
||||
|
||||
/***** Get data of note *****/
|
||||
Not.NotCod = TL_Not_GetParamNotCod ();
|
||||
|
@ -786,8 +787,8 @@ static long TL_Com_ReceiveComment (void)
|
|||
/* Insert into publications */
|
||||
Pub.NotCod = Not.NotCod;
|
||||
Pub.PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod;
|
||||
Pub.PubType = TL_PUB_COMMENT_TO_NOTE;
|
||||
TL_PublishPubInTimeline (&Pub); // Set Pub.PubCod
|
||||
Pub.PubType = TL_Pub_COMMENT_TO_NOTE;
|
||||
TL_Pub_PublishPubInTimeline (&Pub); // Set Pub.PubCod
|
||||
|
||||
/* Insert comment content in the database */
|
||||
DB_QueryINSERT ("can not store comment content",
|
||||
|
@ -872,7 +873,7 @@ static void TL_Com_RequestRemovalComment (struct TL_Timeline *Timeline)
|
|||
Med_MediaConstructor (&Com.Content.Media);
|
||||
|
||||
/***** Get data of comment *****/
|
||||
Com.PubCod = TL_GetParamPubCod ();
|
||||
Com.PubCod = TL_Pub_GetParamPubCod ();
|
||||
TL_Com_GetDataOfCommByCod (&Com);
|
||||
|
||||
if (Com.PubCod > 0)
|
||||
|
@ -920,7 +921,7 @@ static void TL_Com_PutParamsRemoveComment (void *Timeline)
|
|||
Usr_PutParamOtherUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EncryptedUsrCod);
|
||||
else
|
||||
Usr_PutHiddenParamWho (((struct TL_Timeline *) Timeline)->Who);
|
||||
TL_PutHiddenParamPubCod (((struct TL_Timeline *) Timeline)->PubCod);
|
||||
TL_Pub_PutHiddenParamPubCod (((struct TL_Timeline *) Timeline)->PubCod);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,7 +980,7 @@ static void TL_Com_RemoveComment (void)
|
|||
Med_MediaConstructor (&Com.Content.Media);
|
||||
|
||||
/***** Get data of comment *****/
|
||||
Com.PubCod = TL_GetParamPubCod ();
|
||||
Com.PubCod = TL_Pub_GetParamPubCod ();
|
||||
TL_Com_GetDataOfCommByCod (&Com);
|
||||
|
||||
if (Com.PubCod > 0)
|
||||
|
@ -1058,7 +1059,7 @@ void TL_Com_RemoveCommentMediaAndDBEntries (long PubCod)
|
|||
" AND PubType=%u", // Extra check: it's a comment
|
||||
PubCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
(unsigned) TL_PUB_COMMENT_TO_NOTE);
|
||||
(unsigned) TL_Pub_COMMENT_TO_NOTE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1084,7 +1085,7 @@ void TL_Com_GetDataOfCommByCod (struct TL_Com_Comment *Com)
|
|||
" WHERE tl_pubs.PubCod=%ld"
|
||||
" AND tl_pubs.PubType=%u"
|
||||
" AND tl_pubs.PubCod=tl_comments.PubCod",
|
||||
Com->PubCod,(unsigned) TL_PUB_COMMENT_TO_NOTE))
|
||||
Com->PubCod,(unsigned) TL_Pub_COMMENT_TO_NOTE))
|
||||
{
|
||||
/***** Get data of comment *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "swad_global.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_favourite.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Public constants *****************************/
|
||||
|
@ -273,7 +274,7 @@ static void TL_Fav_FavNote (struct TL_Not_Note *Not)
|
|||
for the author of the post *****/
|
||||
OriginalPubCod = TL_Not_GetPubCodOfOriginalNote (Not->NotCod);
|
||||
if (OriginalPubCod > 0)
|
||||
TL_CreateNotifToAuthor (Not->UsrCod,OriginalPubCod,Ntf_EVENT_TIMELINE_FAV);
|
||||
TL_Pub_CreateNotifToAuthor (Not->UsrCod,OriginalPubCod,Ntf_EVENT_TIMELINE_FAV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +333,7 @@ void TL_Fav_ShowAllFaversComGbl (void)
|
|||
|
||||
/***** Get data of comment *****/
|
||||
Med_MediaConstructor (&Com.Content.Media);
|
||||
Com.PubCod = TL_GetParamPubCod ();
|
||||
Com.PubCod = TL_Pub_GetParamPubCod ();
|
||||
TL_Com_GetDataOfCommByCod (&Com);
|
||||
Med_MediaDestructor (&Com.Content.Media);
|
||||
|
||||
|
@ -418,7 +419,7 @@ static void TL_Fav_FavComment (struct TL_Com_Comment *Com)
|
|||
Med_MediaConstructor (&Com->Content.Media);
|
||||
|
||||
/***** Get data of comment *****/
|
||||
Com->PubCod = TL_GetParamPubCod ();
|
||||
Com->PubCod = TL_Pub_GetParamPubCod ();
|
||||
TL_Com_GetDataOfCommByCod (Com);
|
||||
|
||||
if (Com->PubCod > 0)
|
||||
|
@ -442,7 +443,7 @@ static void TL_Fav_FavComment (struct TL_Com_Comment *Com)
|
|||
|
||||
/**** Create notification about favourite post
|
||||
for the author of the post ***/
|
||||
TL_CreateNotifToAuthor (Com->UsrCod,Com->PubCod,Ntf_EVENT_TIMELINE_FAV);
|
||||
TL_Pub_CreateNotifToAuthor (Com->UsrCod,Com->PubCod,Ntf_EVENT_TIMELINE_FAV);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,7 +459,7 @@ static void TL_Fav_UnfComment (struct TL_Com_Comment *Com)
|
|||
Med_MediaConstructor (&Com->Content.Media);
|
||||
|
||||
/***** Get data of comment *****/
|
||||
Com->PubCod = TL_GetParamPubCod ();
|
||||
Com->PubCod = TL_Pub_GetParamPubCod ();
|
||||
TL_Com_GetDataOfCommByCod (Com);
|
||||
|
||||
if (Com->PubCod > 0)
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "swad_profile.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_favourite.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
#include "swad_timeline_share.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -660,12 +661,12 @@ void TL_Not_GetNoteSummary (const struct TL_Not_Note *Not,
|
|||
|
||||
void TL_Not_StoreAndPublishNote (TL_Not_NoteType_t NoteType,long Cod)
|
||||
{
|
||||
struct TL_Publication Pub;
|
||||
struct TL_Pub_Publication Pub;
|
||||
|
||||
TL_Not_StoreAndPublishNoteInternal (NoteType,Cod,&Pub);
|
||||
}
|
||||
|
||||
void TL_Not_StoreAndPublishNoteInternal (TL_Not_NoteType_t NoteType,long Cod,struct TL_Publication *Pub)
|
||||
void TL_Not_StoreAndPublishNoteInternal (TL_Not_NoteType_t NoteType,long Cod,struct TL_Pub_Publication *Pub)
|
||||
{
|
||||
long HieCod; // Hierarchy code (institution/centre/degree/course)
|
||||
|
||||
|
@ -707,7 +708,7 @@ void TL_Not_StoreAndPublishNoteInternal (TL_Not_NoteType_t NoteType,long Cod,str
|
|||
/***** Publish note in timeline *****/
|
||||
Pub->PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod;
|
||||
Pub->PubType = TL_PUB_ORIGINAL_NOTE;
|
||||
TL_PublishPubInTimeline (Pub);
|
||||
TL_Pub_PublishPubInTimeline (Pub);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1084,7 +1085,7 @@ static void TL_Not_RemoveNoteMediaAndDBEntries (struct TL_Not_Note *Not)
|
|||
" FROM tl_pubs"
|
||||
" WHERE NotCod=%ld AND PubType=%u",
|
||||
Not->NotCod,
|
||||
(unsigned) TL_PUB_COMMENT_TO_NOTE);
|
||||
(unsigned) TL_Pub_COMMENT_TO_NOTE);
|
||||
|
||||
/* For each comment... */
|
||||
for (NumCom = 0;
|
||||
|
@ -1309,3 +1310,27 @@ void TL_Not_GetDataOfNoteByCod (struct TL_Not_Note *Not)
|
|||
TL_Not_ResetNote (Not);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Clear unused old timelines in database ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Not_ClearOldTimelinesNotesFromDB (void)
|
||||
{
|
||||
/***** Remove timelines for expired sessions *****/
|
||||
DB_QueryDELETE ("can not remove old timelines",
|
||||
"DELETE LOW_PRIORITY FROM tl_timelines"
|
||||
" WHERE SessionId NOT IN (SELECT SessionId FROM sessions)");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************** Clear timeline for this session in database ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Not_ClearTimelineNotesThisSessionFromDB (void)
|
||||
{
|
||||
/***** Remove timeline for this session *****/
|
||||
DB_QueryDELETE ("can not remove timeline",
|
||||
"DELETE FROM tl_timelines"
|
||||
" WHERE SessionId='%s'",
|
||||
Gbl.Session.Id);
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ void TL_Not_GetNoteSummary (const struct TL_Not_Note *Not,
|
|||
char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1]);
|
||||
|
||||
void TL_Not_StoreAndPublishNote (TL_Not_NoteType_t NoteType,long Cod);
|
||||
void TL_Not_StoreAndPublishNoteInternal (TL_Not_NoteType_t NoteType,long Cod,struct TL_Publication *Pub);
|
||||
void TL_Not_StoreAndPublishNoteInternal (TL_Not_NoteType_t NoteType,long Cod,struct TL_Pub_Publication *Pub);
|
||||
void TL_Not_MarkNoteAsUnavailable (TL_Not_NoteType_t NoteType,long Cod);
|
||||
void TL_Not_MarkNoteOneFileAsUnavailable (const char *Path);
|
||||
void TL_Not_MarkNotesChildrenOfFolderAsUnavailable (const char *Path);
|
||||
|
@ -121,4 +121,7 @@ long TL_Not_GetPubCodOfOriginalNote (long NotCod);
|
|||
|
||||
void TL_Not_GetDataOfNoteByCod (struct TL_Not_Note *Not);
|
||||
|
||||
void TL_Not_ClearOldTimelinesNotesFromDB (void);
|
||||
void TL_Not_ClearTimelineNotesThisSessionFromDB (void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,988 @@
|
|||
// swad_timeline_publication.c: social timeline publications
|
||||
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/*********************************** Headers *********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _GNU_SOURCE // For asprintf
|
||||
#include <linux/limits.h> // For PATH_MAX
|
||||
#include <stdio.h> // For asprintf
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include <string.h> // For string functions
|
||||
#include <sys/types.h> // For time_t
|
||||
|
||||
#include "swad_database.h"
|
||||
#include "swad_exam_announcement.h"
|
||||
#include "swad_figure.h"
|
||||
#include "swad_follow.h"
|
||||
#include "swad_form.h"
|
||||
#include "swad_forum.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_message.h"
|
||||
#include "swad_notice.h"
|
||||
#include "swad_photo.h"
|
||||
#include "swad_profile.h"
|
||||
#include "swad_setting.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_favourite.h"
|
||||
#include "swad_timeline_note.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
#include "swad_timeline_share.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Public constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************* Private constants and types ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define TL_Pub_MAX_BYTES_SUBQUERY (128 - 1)
|
||||
struct TL_Pub_SubQueries
|
||||
{
|
||||
char *TablePublishers;
|
||||
char Publishers [TL_Pub_MAX_BYTES_SUBQUERY + 1];
|
||||
char RangeBottom [TL_Pub_MAX_BYTES_SUBQUERY + 1];
|
||||
char RangeTop [TL_Pub_MAX_BYTES_SUBQUERY + 1];
|
||||
char AlreadyExists[TL_Pub_MAX_BYTES_SUBQUERY + 1];
|
||||
};
|
||||
|
||||
struct TL_Pub_RangePubsToGet
|
||||
{
|
||||
long Top;
|
||||
long Bottom;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
extern struct Globals Gbl;
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************* Private global variables **************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static unsigned TL_Pub_GetMaxPubsToGet (const struct TL_Timeline *Timeline);
|
||||
|
||||
static void TL_Pub_CreateTmpTableCurrentTimeline (const struct TL_Timeline *Timeline);
|
||||
static void TL_Pub_CreateTmpTablePublishers (void);
|
||||
static void TL_Pub_DropTmpTablesUsedToQueryTimeline (void);
|
||||
|
||||
static void TL_Pub_CreateSubQueryPublishers (const struct TL_Timeline *Timeline,
|
||||
struct TL_Pub_SubQueries *SubQueries);
|
||||
static void TL_Pub_CreateSubQueryAlreadyExists (const struct TL_Timeline *Timeline,
|
||||
struct TL_Pub_SubQueries *SubQueries);
|
||||
static void TL_Pub_CreateSubQueryRangeBottom (const struct TL_Pub_RangePubsToGet *RangePubsToGet,
|
||||
struct TL_Pub_SubQueries *SubQueries);
|
||||
static void TL_Pub_CreateSubQueryRangeTop (const struct TL_Pub_RangePubsToGet *RangePubsToGet,
|
||||
struct TL_Pub_SubQueries *SubQueries);
|
||||
|
||||
static long TL_Pub_GetPubCodFromSession (const char *FieldName);
|
||||
static void TL_Pub_UpdateFirstLastPubCodesIntoSession (const struct TL_Timeline *Timeline);
|
||||
|
||||
static struct TL_Pub_Publication *TL_Pub_SelectTheMostRecentPub (const struct TL_Pub_SubQueries *SubQueries);
|
||||
|
||||
static void TL_Pub_GetDataOfPublicationFromNextRow (MYSQL_RES *mysql_res,
|
||||
struct TL_Pub_Publication *Pub);
|
||||
static TL_Pub_PubType_t TL_Pub_GetPubTypeFromStr (const char *Str);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*************** Get list of pubications to show in timeline *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_GetListPubsToShowInTimeline (struct TL_Timeline *Timeline)
|
||||
{
|
||||
struct TL_Pub_SubQueries SubQueries;
|
||||
struct TL_Pub_RangePubsToGet RangePubsToGet;
|
||||
unsigned MaxPubsToGet = TL_Pub_GetMaxPubsToGet (Timeline);
|
||||
unsigned NumPub;
|
||||
struct TL_Pub_Publication *Pub;
|
||||
|
||||
/***** Clear timeline for this session in database *****/
|
||||
if (Timeline->WhatToGet == TL_GET_RECENT_TIMELINE)
|
||||
TL_Not_ClearTimelineNotesThisSessionFromDB ();
|
||||
|
||||
/***** Create temporary table with notes in current timeline *****/
|
||||
TL_Pub_CreateTmpTableCurrentTimeline (Timeline);
|
||||
|
||||
/***** Create temporary table and subquery with potential publishers *****/
|
||||
TL_Pub_CreateSubQueryPublishers (Timeline,&SubQueries);
|
||||
|
||||
/***** Create subquery to get only notes not present in timeline *****/
|
||||
TL_Pub_CreateSubQueryAlreadyExists (Timeline,&SubQueries);
|
||||
|
||||
/***** Get the publications in timeline *****/
|
||||
/* Initialize range of pubs:
|
||||
|
||||
tl_pubs
|
||||
_____
|
||||
|_____|11
|
||||
|_____|10
|
||||
_|_____| 9 <-- RangePubsToGet.Top
|
||||
Get / |_____| 8
|
||||
pubs | |_____| 7
|
||||
from < |_____| 6
|
||||
this | |_____| 5
|
||||
range \_|_____| 4
|
||||
|_____| 3 <-- RangePubsToGet.Bottom
|
||||
|_____| 2
|
||||
|_____| 1
|
||||
0
|
||||
*/
|
||||
switch (Timeline->WhatToGet)
|
||||
{
|
||||
case TL_GET_ONLY_NEW_PUBS: // Get the publications (without limit) newer than LastPubCod
|
||||
/* This query is made via AJAX automatically from time to time */
|
||||
RangePubsToGet.Top = 0; // +Infinite
|
||||
RangePubsToGet.Bottom = TL_Pub_GetPubCodFromSession ("LastPubCod");
|
||||
break;
|
||||
case TL_GET_ONLY_OLD_PUBS: // Get some limited publications older than FirstPubCod
|
||||
/* This query is made via AJAX
|
||||
when I click in link to get old publications */
|
||||
RangePubsToGet.Top = TL_Pub_GetPubCodFromSession ("FirstPubCod");
|
||||
RangePubsToGet.Bottom = 0; // -Infinite
|
||||
break;
|
||||
case TL_GET_RECENT_TIMELINE: // Get some limited recent publications
|
||||
default:
|
||||
/* This is the first query to get initial timeline shown
|
||||
==> no notes yet in current timeline table */
|
||||
RangePubsToGet.Top = 0; // +Infinite
|
||||
RangePubsToGet.Bottom = 0; // -Infinite
|
||||
break;
|
||||
}
|
||||
/* Create subquery with bottom range of publications to get from tl_pubs.
|
||||
Bottom publication code remains unchanged in all iterations of the next loop. */
|
||||
TL_Pub_CreateSubQueryRangeBottom (&RangePubsToGet,&SubQueries);
|
||||
|
||||
/*
|
||||
With the current approach, we select one by one
|
||||
the publications and notes in a loop. In each iteration,
|
||||
we get the more recent publication (original, shared or commment)
|
||||
of every set of publications corresponding to the same note,
|
||||
checking that the note is not already retrieved.
|
||||
After getting a publication, its note code is stored
|
||||
in order to not get it again.
|
||||
|
||||
As an alternative, we tried to get the maximum PubCod,
|
||||
i.e more recent publication (original, shared or commment),
|
||||
of every set of publications corresponding to the same note:
|
||||
"SELECT MAX(PubCod) AS NewestPubCod FROM tl_pubs ...
|
||||
" GROUP BY NotCod ORDER BY NewestPubCod DESC LIMIT ..."
|
||||
but this query is slow (several seconds) with a big table.
|
||||
*/
|
||||
|
||||
/*
|
||||
Chained list of publications:
|
||||
|
||||
Timeline->Pubs.Top Pub #0
|
||||
______ ______ Pub #1
|
||||
|______|------>|______| ______ Pub #2
|
||||
|______| -> |______| ______ Pub #3
|
||||
|______| / |______| ->|______| ______
|
||||
|______| / |______| / |______| ->|______|
|
||||
|_Next_|-- |______| / |______| // |______|
|
||||
|_Next_|-- |______| // |______|
|
||||
______ |_Next_|--/ |______|
|
||||
|______|---------------------------------------------- |_NULL_|
|
||||
|
||||
Timeline->Pubs.Bottom
|
||||
|
||||
*/
|
||||
Timeline->Pubs.Top =
|
||||
Timeline->Pubs.Bottom = NULL;
|
||||
|
||||
for (NumPub = 0;
|
||||
NumPub < MaxPubsToGet;
|
||||
NumPub++)
|
||||
{
|
||||
/* Create subquery with top range of publications to get from tl_pubs
|
||||
In each iteration of this loop, top publication code is changed to a lower value */
|
||||
TL_Pub_CreateSubQueryRangeTop (&RangePubsToGet,&SubQueries);
|
||||
|
||||
/* Select the most recent publication from tl_pubs */
|
||||
Pub = TL_Pub_SelectTheMostRecentPub (&SubQueries);
|
||||
|
||||
/* Chain the previous publication with the current one */
|
||||
if (NumPub == 0)
|
||||
Timeline->Pubs.Top = Pub; // Pointer to top publication
|
||||
else
|
||||
Timeline->Pubs.Bottom->Next = Pub; // Chain the previous publication with the current one
|
||||
Timeline->Pubs.Bottom = Pub; // Update pointer to bottom publication
|
||||
|
||||
if (Pub == NULL) // Nothing got ==> abort loop
|
||||
break; // Last publication
|
||||
|
||||
/* Insert note in temporary tables with just retrieved notes.
|
||||
These tables will be used to not get notes already shown */
|
||||
TL_Not_InsertNoteInJustRetrievedNotes (Pub->NotCod);
|
||||
if (Timeline->WhatToGet == TL_GET_ONLY_OLD_PUBS)
|
||||
TL_Not_InsertNoteInVisibleTimeline (Pub->NotCod);
|
||||
|
||||
/* Narrow the range for the next iteration */
|
||||
RangePubsToGet.Top = Pub->PubCod;
|
||||
}
|
||||
|
||||
/***** Update first (oldest) and last (more recent) publication codes
|
||||
into session for next refresh *****/
|
||||
TL_Pub_UpdateFirstLastPubCodesIntoSession (Timeline);
|
||||
|
||||
/***** Add notes just retrieved to current timeline for this session *****/
|
||||
TL_Not_AddNotesJustRetrievedToTimelineThisSession ();
|
||||
|
||||
/***** Drop temporary tables *****/
|
||||
TL_Pub_DropTmpTablesUsedToQueryTimeline ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********* Get maximum number of publications to get from database ***********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static unsigned TL_Pub_GetMaxPubsToGet (const struct TL_Timeline *Timeline)
|
||||
{
|
||||
static const unsigned MaxPubsToGet[TL_NUM_WHAT_TO_GET] =
|
||||
{
|
||||
[TL_GET_RECENT_TIMELINE] = TL_Pub_MAX_REC_PUBS_TO_GET_AND_SHOW,
|
||||
[TL_GET_ONLY_NEW_PUBS ] = TL_Pub_MAX_NEW_PUBS_TO_GET_AND_SHOW,
|
||||
[TL_GET_ONLY_OLD_PUBS ] = TL_Pub_MAX_OLD_PUBS_TO_GET_AND_SHOW,
|
||||
};
|
||||
|
||||
return MaxPubsToGet[Timeline->WhatToGet];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************* Create temporary tables used to query timeline ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_CreateTmpTableCurrentTimeline (const struct TL_Timeline *Timeline)
|
||||
{
|
||||
/***** Create temporary table with notes just retrieved *****/
|
||||
DB_Query ("can not create temporary table",
|
||||
"CREATE TEMPORARY TABLE tl_tmp_just_retrieved_notes "
|
||||
"(NotCod BIGINT NOT NULL,UNIQUE INDEX(NotCod))"
|
||||
" ENGINE=MEMORY");
|
||||
|
||||
if (Timeline->WhatToGet == TL_GET_ONLY_OLD_PUBS)
|
||||
/***** Create temporary table with all notes visible in timeline *****/
|
||||
DB_Query ("can not create temporary table",
|
||||
"CREATE TEMPORARY TABLE tl_tmp_visible_timeline "
|
||||
"(NotCod BIGINT NOT NULL,UNIQUE INDEX(NotCod))"
|
||||
" ENGINE=MEMORY"
|
||||
" SELECT NotCod FROM tl_timelines WHERE SessionId='%s'",
|
||||
Gbl.Session.Id);
|
||||
}
|
||||
|
||||
static void TL_Pub_CreateTmpTablePublishers (void)
|
||||
{
|
||||
/***** Create temporary table with me and the users I follow *****/
|
||||
DB_Query ("can not create temporary table",
|
||||
"CREATE TEMPORARY TABLE tl_tmp_publishers "
|
||||
"(UsrCod INT NOT NULL,"
|
||||
"UNIQUE INDEX(UsrCod))"
|
||||
" ENGINE=MEMORY"
|
||||
" SELECT %ld AS UsrCod" // Me
|
||||
" UNION"
|
||||
" SELECT FollowedCod AS UsrCod" // Users I follow
|
||||
" FROM usr_follow"
|
||||
" WHERE FollowerCod=%ld",
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*************** Drop temporary tables used to query timeline ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_DropTmpTablesUsedToQueryTimeline (void)
|
||||
{
|
||||
DB_Query ("can not remove temporary tables",
|
||||
"DROP TEMPORARY TABLE IF EXISTS "
|
||||
"tl_tmp_just_retrieved_notes,"
|
||||
"tl_tmp_visible_timeline,"
|
||||
"tl_tmp_publishers");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******* Create temporary table and subquery with potential publishers *******/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_CreateSubQueryPublishers (const struct TL_Timeline *Timeline,
|
||||
struct TL_Pub_SubQueries *SubQueries)
|
||||
{
|
||||
/***** Create temporary table and subquery with potential publishers *****/
|
||||
switch (Timeline->UsrOrGbl)
|
||||
{
|
||||
case TL_TIMELINE_USR: // Show the timeline of a user
|
||||
SubQueries->TablePublishers = "";
|
||||
sprintf (SubQueries->Publishers,"tl_pubs.PublisherCod=%ld AND ",
|
||||
Gbl.Usrs.Other.UsrDat.UsrCod);
|
||||
break;
|
||||
case TL_TIMELINE_GBL: // Show the global timeline
|
||||
switch (Timeline->Who)
|
||||
{
|
||||
case Usr_WHO_ME: // Show my timeline
|
||||
SubQueries->TablePublishers = "";
|
||||
snprintf (SubQueries->Publishers,sizeof (SubQueries->Publishers),
|
||||
"tl_pubs.PublisherCod=%ld AND ",
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
break;
|
||||
case Usr_WHO_FOLLOWED: // Show the timeline of the users I follow
|
||||
TL_Pub_CreateTmpTablePublishers ();
|
||||
SubQueries->TablePublishers = ",tl_tmp_publishers";
|
||||
Str_Copy (SubQueries->Publishers,
|
||||
"tl_pubs.PublisherCod=tl_tmp_publishers.UsrCod AND ",
|
||||
TL_Pub_MAX_BYTES_SUBQUERY);
|
||||
break;
|
||||
case Usr_WHO_ALL: // Show the timeline of all users
|
||||
SubQueries->TablePublishers = "";
|
||||
SubQueries->Publishers[0] = '\0';
|
||||
break;
|
||||
default:
|
||||
Lay_WrongWhoExit ();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********* Create subquery to get only notes not present in timeline *********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_CreateSubQueryAlreadyExists (const struct TL_Timeline *Timeline,
|
||||
struct TL_Pub_SubQueries *SubQueries)
|
||||
{
|
||||
switch (Timeline->WhatToGet)
|
||||
{
|
||||
case TL_GET_RECENT_TIMELINE:
|
||||
case TL_GET_ONLY_NEW_PUBS:
|
||||
Str_Copy (SubQueries->AlreadyExists,
|
||||
" tl_pubs.NotCod NOT IN"
|
||||
" (SELECT NotCod FROM tl_tmp_just_retrieved_notes)", // Avoid notes just retrieved
|
||||
TL_Pub_MAX_BYTES_SUBQUERY);
|
||||
break;
|
||||
case TL_GET_ONLY_OLD_PUBS:
|
||||
Str_Copy (SubQueries->AlreadyExists,
|
||||
" tl_pubs.NotCod NOT IN"
|
||||
" (SELECT NotCod FROM tl_tmp_visible_timeline)", // Avoid notes already shown
|
||||
TL_Pub_MAX_BYTES_SUBQUERY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***** Create subqueries with range of publications to get from tl_pubs ******/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_CreateSubQueryRangeBottom (const struct TL_Pub_RangePubsToGet *RangePubsToGet,
|
||||
struct TL_Pub_SubQueries *SubQueries)
|
||||
{
|
||||
if (RangePubsToGet->Bottom > 0)
|
||||
sprintf (SubQueries->RangeBottom,"tl_pubs.PubCod>%ld AND ",
|
||||
RangePubsToGet->Bottom);
|
||||
else
|
||||
SubQueries->RangeBottom[0] = '\0';
|
||||
}
|
||||
|
||||
static void TL_Pub_CreateSubQueryRangeTop (const struct TL_Pub_RangePubsToGet *RangePubsToGet,
|
||||
struct TL_Pub_SubQueries *SubQueries)
|
||||
{
|
||||
if (RangePubsToGet->Top > 0)
|
||||
sprintf (SubQueries->RangeTop,"tl_pubs.PubCod<%ld AND ",
|
||||
RangePubsToGet->Top);
|
||||
else
|
||||
SubQueries->RangeTop[0] = '\0';
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************* Get last/first publication code stored in session *************/
|
||||
/*****************************************************************************/
|
||||
// FieldName can be:
|
||||
// "LastPubCod"
|
||||
// "FirstPubCod"
|
||||
|
||||
static long TL_Pub_GetPubCodFromSession (const char *FieldName)
|
||||
{
|
||||
extern const char *Txt_The_session_has_expired;
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
long PubCod;
|
||||
|
||||
/***** Get last publication code from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get publication code from session",
|
||||
"SELECT %s FROM sessions"
|
||||
" WHERE SessionId='%s'",
|
||||
FieldName,Gbl.Session.Id) != 1)
|
||||
Lay_ShowErrorAndExit (Txt_The_session_has_expired);
|
||||
|
||||
/***** Get last publication code *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
if (sscanf (row[0],"%ld",&PubCod) != 1)
|
||||
PubCod = 0;
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
return PubCod;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************* Update first (oldest) and last (more recent) ***************/
|
||||
/************* publication codes into session for next refresh ***************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_UpdateFirstLastPubCodesIntoSession (const struct TL_Timeline *Timeline)
|
||||
{
|
||||
long FirstPubCod;
|
||||
|
||||
switch (Timeline->WhatToGet)
|
||||
{
|
||||
case TL_GET_ONLY_NEW_PUBS:
|
||||
DB_QueryUPDATE ("can not update first/last publication codes into session",
|
||||
"UPDATE sessions"
|
||||
" SET LastPubCod="
|
||||
"(SELECT IFNULL(MAX(PubCod),0)"
|
||||
" FROM tl_pubs)" // The most recent publication
|
||||
" WHERE SessionId='%s'",
|
||||
Gbl.Session.Id);
|
||||
break;
|
||||
case TL_GET_ONLY_OLD_PUBS:
|
||||
// The oldest publication code retrieved and shown
|
||||
FirstPubCod = Timeline->Pubs.Bottom ? Timeline->Pubs.Bottom->PubCod :
|
||||
0;
|
||||
|
||||
DB_QueryUPDATE ("can not update first/last publication codes into session",
|
||||
"UPDATE sessions"
|
||||
" SET FirstPubCod=%ld"
|
||||
" WHERE SessionId='%s'",
|
||||
FirstPubCod,
|
||||
Gbl.Session.Id);
|
||||
break;
|
||||
case TL_GET_RECENT_TIMELINE:
|
||||
// The oldest publication code retrieved and shown
|
||||
FirstPubCod = Timeline->Pubs.Bottom ? Timeline->Pubs.Bottom->PubCod :
|
||||
0;
|
||||
|
||||
DB_QueryUPDATE ("can not update first/last publication codes into session",
|
||||
"UPDATE sessions"
|
||||
" SET FirstPubCod=%ld,"
|
||||
"LastPubCod="
|
||||
"(SELECT IFNULL(MAX(PubCod),0)"
|
||||
" FROM tl_pubs)" // The most recent publication
|
||||
" WHERE SessionId='%s'",
|
||||
FirstPubCod,
|
||||
Gbl.Session.Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Free chained list of publications in timeline ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_FreeListPubs (struct TL_Timeline *Timeline)
|
||||
{
|
||||
struct TL_Pub_Publication *Pub;
|
||||
struct TL_Pub_Publication *Next;
|
||||
|
||||
/***** Go over the list freeing memory *****/
|
||||
for (Pub = Timeline->Pubs.Top;
|
||||
Pub;
|
||||
Pub = Next)
|
||||
{
|
||||
/* Save a copy of pointer to next element before freeing it */
|
||||
Next = Pub->Next;
|
||||
|
||||
/* Free memory used for this publication */
|
||||
free (Pub);
|
||||
}
|
||||
|
||||
/***** Reset pointers to top and bottom elements *****/
|
||||
Timeline->Pubs.Top =
|
||||
Timeline->Pubs.Bottom = NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Select the most recent publication from tl_pubs **************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static struct TL_Pub_Publication *TL_Pub_SelectTheMostRecentPub (const struct TL_Pub_SubQueries *SubQueries)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
unsigned NumPubs = 0; // Initialized to avoid warning
|
||||
struct TL_Pub_Publication *Pub;
|
||||
|
||||
NumPubs =
|
||||
(unsigned) DB_QuerySELECT (&mysql_res,"can not get publication",
|
||||
"SELECT tl_pubs.PubCod," // row[0]
|
||||
"tl_pubs.NotCod," // row[1]
|
||||
"tl_pubs.PublisherCod," // row[2]
|
||||
"tl_pubs.PubType" // row[3]
|
||||
" FROM tl_pubs%s"
|
||||
" WHERE %s%s%s%s"
|
||||
" ORDER BY tl_pubs.PubCod DESC LIMIT 1",
|
||||
SubQueries->TablePublishers,
|
||||
SubQueries->RangeBottom,
|
||||
SubQueries->RangeTop,
|
||||
SubQueries->Publishers,
|
||||
SubQueries->AlreadyExists);
|
||||
|
||||
if (NumPubs == 1)
|
||||
{
|
||||
/* Allocate space for publication */
|
||||
if ((Pub = (struct TL_Pub_Publication *) malloc (sizeof (struct TL_Pub_Publication))) == NULL)
|
||||
Lay_ShowErrorAndExit ("Error allocating memory publication.");
|
||||
|
||||
/* Get data of publication */
|
||||
TL_Pub_GetDataOfPublicationFromNextRow (mysql_res,Pub);
|
||||
Pub->Next = NULL;
|
||||
}
|
||||
else
|
||||
Pub = NULL;
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
return Pub;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Show new publications in timeline ***********************/
|
||||
/*****************************************************************************/
|
||||
// The publications are inserted as list elements of a hidden list
|
||||
|
||||
void TL_Pub_InsertNewPubsInTimeline (struct TL_Timeline *Timeline)
|
||||
{
|
||||
struct TL_Pub_Publication *Pub;
|
||||
struct TL_Not_Note Not;
|
||||
|
||||
/***** List new publications timeline *****/
|
||||
for (Pub = Timeline->Pubs.Top;
|
||||
Pub;
|
||||
Pub = Pub->Next)
|
||||
{
|
||||
/* Get data of note */
|
||||
Not.NotCod = Pub->NotCod;
|
||||
TL_Not_GetDataOfNoteByCod (&Not);
|
||||
|
||||
/* Write note */
|
||||
TL_Not_WriteNote (Timeline,&Not,
|
||||
Pub->TopMessage,
|
||||
Pub->PublisherCod,
|
||||
TL_DONT_HIGHLIGHT,
|
||||
TL_DONT_SHOW_ALONE);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Show old publications in timeline *********************/
|
||||
/*****************************************************************************/
|
||||
// The publications are inserted as list elements of a hidden list
|
||||
|
||||
void TL_Pub_ShowOldPubsInTimeline (struct TL_Timeline *Timeline)
|
||||
{
|
||||
struct TL_Pub_Publication *Pub;
|
||||
struct TL_Not_Note Not;
|
||||
|
||||
/***** List old publications in timeline *****/
|
||||
for (Pub = Timeline->Pubs.Top;
|
||||
Pub;
|
||||
Pub = Pub->Next)
|
||||
{
|
||||
/* Get data of note */
|
||||
Not.NotCod = Pub->NotCod;
|
||||
TL_Not_GetDataOfNoteByCod (&Not);
|
||||
|
||||
/* Write note */
|
||||
TL_Not_WriteNote (Timeline,&Not,
|
||||
Pub->TopMessage,
|
||||
Pub->PublisherCod,
|
||||
TL_DONT_HIGHLIGHT,
|
||||
TL_DONT_SHOW_ALONE);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Put link to view new publications in timeline *************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_PutLinkToViewNewPublications (void)
|
||||
{
|
||||
extern const char *The_ClassFormInBoxBold[The_NUM_THEMES];
|
||||
extern const char *Txt_See_new_activity;
|
||||
|
||||
/***** Link to view (show hidden) new publications *****/
|
||||
// div is hidden. When new posts arrive to the client via AJAX, div is shown
|
||||
HTM_DIV_Begin ("id=\"view_new_posts_container\""
|
||||
" class=\"TL_WIDTH TL_SEP VERY_LIGHT_BLUE\""
|
||||
" style=\"display:none;\"");
|
||||
HTM_A_Begin ("href=\"\" class=\"%s\""
|
||||
" onclick=\"moveNewTimelineToTimeline();return false;\"",
|
||||
The_ClassFormInBoxBold[Gbl.Prefs.Theme]);
|
||||
HTM_TxtF ("%s (",Txt_See_new_activity);
|
||||
HTM_SPAN_Begin ("id=\"view_new_posts_count\"");
|
||||
HTM_Unsigned (0);
|
||||
HTM_SPAN_End ();
|
||||
HTM_Txt (")");
|
||||
HTM_A_End ();
|
||||
HTM_DIV_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Put link to view old publications in timeline *************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_PutLinkToViewOldPublications (void)
|
||||
{
|
||||
extern const char *The_ClassFormInBoxBold[The_NUM_THEMES];
|
||||
extern const char *Txt_See_more;
|
||||
|
||||
/***** Animated link to view old publications *****/
|
||||
HTM_DIV_Begin ("id=\"view_old_posts_container\""
|
||||
" class=\"TL_WIDTH TL_SEP VERY_LIGHT_BLUE\"");
|
||||
HTM_A_Begin ("href=\"\" class=\"%s\" onclick=\""
|
||||
"document.getElementById('get_old_timeline').style.display='none';" // Icon to be hidden on click
|
||||
"document.getElementById('getting_old_timeline').style.display='';" // Icon to be shown on click
|
||||
"refreshOldTimeline();"
|
||||
"return false;\"",
|
||||
The_ClassFormInBoxBold[Gbl.Prefs.Theme]);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"recycle16x16.gif","Txt_See_more",
|
||||
"class=\"ICO20x20\" id=\"get_old_timeline\"");
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"working16x16.gif",Txt_See_more,
|
||||
"class=\"ICO20x20\" style=\"display:none;\" id=\"getting_old_timeline\""); // Animated icon hidden
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"recycle16x16.gif","Txt_See_more",
|
||||
"class=\"ICO20x20\" style=\"display:none;\" id=\"get_old_timeline\"");
|
||||
HTM_TxtF (" %s",Txt_See_more);
|
||||
HTM_A_End ();
|
||||
HTM_DIV_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*************** Put parameter with the code of a publication ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_PutHiddenParamPubCod (long PubCod)
|
||||
{
|
||||
Par_PutHiddenParamLong (NULL,"PubCod",PubCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************** Get parameter with the code of a publication ***************/
|
||||
/*****************************************************************************/
|
||||
|
||||
long TL_Pub_GetParamPubCod (void)
|
||||
{
|
||||
/***** Get comment code *****/
|
||||
return Par_GetParToLong ("PubCod");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Create a notification for the author of a post/comment **********/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_CreateNotifToAuthor (long AuthorCod,long PubCod,
|
||||
Ntf_NotifyEvent_t NotifyEvent)
|
||||
{
|
||||
struct UsrData UsrDat;
|
||||
bool CreateNotif;
|
||||
bool NotifyByEmail;
|
||||
|
||||
/***** Initialize structure with user's data *****/
|
||||
Usr_UsrDataConstructor (&UsrDat);
|
||||
|
||||
UsrDat.UsrCod = AuthorCod;
|
||||
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS))
|
||||
{
|
||||
/***** This fav must be notified by email? *****/
|
||||
CreateNotif = (UsrDat.NtfEvents.CreateNotif & (1 << NotifyEvent));
|
||||
NotifyByEmail = CreateNotif &&
|
||||
(UsrDat.NtfEvents.SendEmail & (1 << NotifyEvent));
|
||||
|
||||
/***** Create notification for the author of the post.
|
||||
If this author wants to receive notifications by email,
|
||||
activate the sending of a notification *****/
|
||||
if (CreateNotif)
|
||||
Ntf_StoreNotifyEventToOneUser (NotifyEvent,&UsrDat,PubCod,
|
||||
(Ntf_Status_t) (NotifyByEmail ? Ntf_STATUS_BIT_EMAIL :
|
||||
0),
|
||||
Gbl.Hierarchy.Ins.InsCod,
|
||||
Gbl.Hierarchy.Ctr.CtrCod,
|
||||
Gbl.Hierarchy.Deg.DegCod,
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
}
|
||||
|
||||
/***** Free memory used for user's data *****/
|
||||
Usr_UsrDataDestructor (&UsrDat);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Get code of note of a publication *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
long TL_Pub_GetNotCodFromPubCod (long PubCod)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
long NotCod = -1L;
|
||||
|
||||
/***** Get code of note from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get code of note",
|
||||
"SELECT NotCod FROM tl_pubs"
|
||||
" WHERE PubCod=%ld",
|
||||
PubCod) == 1) // Result should have a unique row
|
||||
{
|
||||
/* Get code of note */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
NotCod = Str_ConvertStrCodToLongCod (row[0]);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
return NotCod;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Get data of publication using its code ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TL_Pub_GetDataOfPublicationFromNextRow (MYSQL_RES *mysql_res,
|
||||
struct TL_Pub_Publication *Pub)
|
||||
{
|
||||
static const TL_TopMessage_t TopMessages[TL_NUM_PUB_TYPES] =
|
||||
{
|
||||
[TL_PUB_UNKNOWN ] = TL_TOP_MESSAGE_NONE,
|
||||
[TL_PUB_ORIGINAL_NOTE ] = TL_TOP_MESSAGE_NONE,
|
||||
[TL_PUB_SHARED_NOTE ] = TL_TOP_MESSAGE_SHARED,
|
||||
[TL_Pub_COMMENT_TO_NOTE] = TL_TOP_MESSAGE_COMMENTED,
|
||||
};
|
||||
MYSQL_ROW row;
|
||||
|
||||
/***** Get next row from result *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
/*
|
||||
row[0]: PubCod
|
||||
row[1]: NotCod
|
||||
row[2]: PublisherCod
|
||||
row[3]: PubType
|
||||
*/
|
||||
|
||||
/***** Get code of publication (row[0]) *****/
|
||||
Pub->PubCod = Str_ConvertStrCodToLongCod (row[0]);
|
||||
|
||||
/***** Get note code (row[1]) *****/
|
||||
Pub->NotCod = Str_ConvertStrCodToLongCod (row[1]);
|
||||
|
||||
/***** Get publisher's code (row[2]) *****/
|
||||
Pub->PublisherCod = Str_ConvertStrCodToLongCod (row[2]);
|
||||
|
||||
/***** Get type of publication (row[3]) *****/
|
||||
Pub->PubType = TL_Pub_GetPubTypeFromStr ((const char *) row[3]);
|
||||
Pub->TopMessage = TopMessages[Pub->PubType];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******* Get publication type from string number coming from database ********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static TL_Pub_PubType_t TL_Pub_GetPubTypeFromStr (const char *Str)
|
||||
{
|
||||
unsigned UnsignedNum;
|
||||
|
||||
if (sscanf (Str,"%u",&UnsignedNum) == 1)
|
||||
if (UnsignedNum < TL_NUM_PUB_TYPES)
|
||||
return (TL_Pub_PubType_t) UnsignedNum;
|
||||
|
||||
return TL_PUB_UNKNOWN;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Get notification of a new publication *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_GetNotifPublication (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
|
||||
char **ContentStr,
|
||||
long PubCod,bool GetContent)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
struct TL_Pub_Publication Pub;
|
||||
struct TL_Not_Note Not;
|
||||
struct TL_PostContent Content;
|
||||
size_t Length;
|
||||
bool ContentCopied = false;
|
||||
|
||||
/***** Return nothing on error *****/
|
||||
Pub.PubType = TL_PUB_UNKNOWN;
|
||||
SummaryStr[0] = '\0'; // Return nothing on error
|
||||
Content.Txt[0] = '\0';
|
||||
|
||||
/***** Get summary and content from post from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get data of publication",
|
||||
"SELECT PubCod," // row[0]
|
||||
"NotCod," // row[1]
|
||||
"PublisherCod," // row[2]
|
||||
"PubType" // row[3]
|
||||
" FROM tl_pubs WHERE PubCod=%ld",
|
||||
PubCod) == 1) // Result should have a unique row
|
||||
/* Get data of publication from row */
|
||||
TL_Pub_GetDataOfPublicationFromNextRow (mysql_res,&Pub);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Get summary and content *****/
|
||||
switch (Pub.PubType)
|
||||
{
|
||||
case TL_PUB_UNKNOWN:
|
||||
break;
|
||||
case TL_PUB_ORIGINAL_NOTE:
|
||||
case TL_PUB_SHARED_NOTE:
|
||||
/* Get data of note */
|
||||
Not.NotCod = Pub.NotCod;
|
||||
TL_Not_GetDataOfNoteByCod (&Not);
|
||||
|
||||
if (Not.NoteType == TL_NOTE_POST)
|
||||
{
|
||||
/***** Get content of post from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get the content of a post",
|
||||
"SELECT Txt" // row[0]
|
||||
" FROM tl_posts"
|
||||
" WHERE PstCod=%ld",
|
||||
Not.Cod) == 1) // Result should have a unique row
|
||||
{
|
||||
/***** Get row *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/****** Get content (row[0]) *****/
|
||||
Str_Copy (Content.Txt,row[0],
|
||||
Cns_MAX_BYTES_LONG_TEXT);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Copy content string *****/
|
||||
if (GetContent)
|
||||
{
|
||||
Length = strlen (Content.Txt);
|
||||
if ((*ContentStr = (char *) malloc (Length + 1)) != NULL)
|
||||
{
|
||||
Str_Copy (*ContentStr,Content.Txt,
|
||||
Length);
|
||||
ContentCopied = true;
|
||||
}
|
||||
}
|
||||
|
||||
/***** Copy summary string *****/
|
||||
Str_LimitLengthHTMLStr (Content.Txt,Ntf_MAX_CHARS_SUMMARY);
|
||||
Str_Copy (SummaryStr,Content.Txt,
|
||||
Ntf_MAX_BYTES_SUMMARY);
|
||||
}
|
||||
else
|
||||
TL_Not_GetNoteSummary (&Not,SummaryStr);
|
||||
break;
|
||||
case TL_Pub_COMMENT_TO_NOTE:
|
||||
/***** Get content of post from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get the content"
|
||||
" of a comment to a note",
|
||||
"SELECT Txt" // row[0]
|
||||
" FROM tl_comments"
|
||||
" WHERE PubCod=%ld",
|
||||
Pub.PubCod) == 1) // Result should have a unique row
|
||||
{
|
||||
/***** Get row *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/****** Get content (row[0]) *****/
|
||||
Str_Copy (Content.Txt,row[0],
|
||||
Cns_MAX_BYTES_LONG_TEXT);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Copy content string *****/
|
||||
if (GetContent)
|
||||
{
|
||||
Length = strlen (Content.Txt);
|
||||
if ((*ContentStr = (char *) malloc (Length + 1)) != NULL)
|
||||
{
|
||||
Str_Copy (*ContentStr,Content.Txt,
|
||||
Length);
|
||||
ContentCopied = true;
|
||||
}
|
||||
}
|
||||
|
||||
/***** Copy summary string *****/
|
||||
Str_LimitLengthHTMLStr (Content.Txt,Ntf_MAX_CHARS_SUMMARY);
|
||||
Str_Copy (SummaryStr,Content.Txt,
|
||||
Ntf_MAX_BYTES_SUMMARY);
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Create empty content string if nothing copied *****/
|
||||
if (GetContent && !ContentCopied)
|
||||
if ((*ContentStr = (char *) malloc (1)) != NULL)
|
||||
(*ContentStr)[0] = '\0';
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Publish note/comment in timeline **********************/
|
||||
/*****************************************************************************/
|
||||
// Pub->PubCod is set by the function
|
||||
|
||||
void TL_Pub_PublishPubInTimeline (struct TL_Pub_Publication *Pub)
|
||||
{
|
||||
/***** Publish note in timeline *****/
|
||||
Pub->PubCod =
|
||||
DB_QueryINSERTandReturnCode ("can not publish note/comment",
|
||||
"INSERT INTO tl_pubs"
|
||||
" (NotCod,PublisherCod,PubType,TimePublish)"
|
||||
" VALUES"
|
||||
" (%ld,%ld,%u,NOW())",
|
||||
Pub->NotCod,
|
||||
Pub->PublisherCod,
|
||||
(unsigned) Pub->PubType);
|
||||
|
||||
/***** Increment number of publications in user's figures *****/
|
||||
Prf_IncrementNumPubsUsr (Pub->PublisherCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************** Get number of publications from a user *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned long TL_Pub_GetNumPubsUsr (long UsrCod)
|
||||
{
|
||||
/***** Get number of posts from a user from database *****/
|
||||
return DB_QueryCOUNT ("can not get number of publications from a user",
|
||||
"SELECT COUNT(*) FROM tl_pubs"
|
||||
" WHERE PublisherCod=%ld",
|
||||
UsrCod);
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
// swad_timeline_publication.h: social timeline publications
|
||||
|
||||
#ifndef _SWAD_TL_PUB
|
||||
#define _SWAD_TL_PUB
|
||||
/*
|
||||
SWAD (Shared Workspace At a Distance in Spanish),
|
||||
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 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/********************************** Headers **********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "swad_form.h"
|
||||
#include "swad_media.h"
|
||||
#include "swad_notification.h"
|
||||
#include "swad_user.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Public constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
// Number of recent publishings got and shown the first time, before refreshing
|
||||
#define TL_Pub_MAX_REC_PUBS_TO_GET_AND_SHOW 10 // Recent publishings to show (first time)
|
||||
#define TL_Pub_MAX_NEW_PUBS_TO_GET_AND_SHOW 10000 // New publishings retrieved (big number)
|
||||
#define TL_Pub_MAX_OLD_PUBS_TO_GET_AND_SHOW 20 // Old publishings are retrieved in packs of this size
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************** Public types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define TL_NUM_PUB_TYPES 4
|
||||
// If the numbers assigned to each event type change,
|
||||
// it is necessary to change old numbers to new ones in database table tl_notes
|
||||
typedef enum
|
||||
{
|
||||
TL_PUB_UNKNOWN = 0,
|
||||
TL_PUB_ORIGINAL_NOTE = 1,
|
||||
TL_PUB_SHARED_NOTE = 2,
|
||||
TL_Pub_COMMENT_TO_NOTE = 3,
|
||||
} TL_Pub_PubType_t;
|
||||
|
||||
struct TL_Pub_Publication
|
||||
{
|
||||
long PubCod;
|
||||
long NotCod;
|
||||
long PublisherCod; // Sharer or writer of the publication
|
||||
TL_Pub_PubType_t PubType;
|
||||
TL_TopMessage_t TopMessage; // Used to show feedback on the action made
|
||||
struct TL_Pub_Publication *Next; // Used for chained list
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Public prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TL_Pub_GetListPubsToShowInTimeline (struct TL_Timeline *Timeline);
|
||||
void TL_Pub_FreeListPubs (struct TL_Timeline *Timeline);
|
||||
|
||||
void TL_Pub_InsertNewPubsInTimeline (struct TL_Timeline *Timeline);
|
||||
void TL_Pub_ShowOldPubsInTimeline (struct TL_Timeline *Timeline);
|
||||
|
||||
void TL_Pub_PutLinkToViewNewPublications (void);
|
||||
void TL_Pub_PutLinkToViewOldPublications (void);
|
||||
|
||||
void TL_Pub_PutHiddenParamPubCod (long PubCod);
|
||||
long TL_Pub_GetParamPubCod (void);
|
||||
|
||||
void TL_Pub_CreateNotifToAuthor (long AuthorCod,long PubCod,
|
||||
Ntf_NotifyEvent_t NotifyEvent);
|
||||
|
||||
long TL_Pub_GetNotCodFromPubCod (long PubCod);
|
||||
|
||||
void TL_Pub_GetNotifPublication (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
|
||||
char **ContentStr,
|
||||
long PubCod,bool GetContent);
|
||||
|
||||
void TL_Pub_PublishPubInTimeline (struct TL_Pub_Publication *Pub);
|
||||
|
||||
unsigned long TL_Pub_GetNumPubsUsr (long UsrCod);
|
||||
|
||||
#endif
|
|
@ -28,6 +28,7 @@
|
|||
#include "swad_database.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_timeline.h"
|
||||
#include "swad_timeline_publication.h"
|
||||
#include "swad_timeline_share.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -161,8 +162,7 @@ void TL_Sha_ShaNoteGbl (void)
|
|||
|
||||
static void TL_Sha_ShaNote (struct TL_Not_Note *Not)
|
||||
{
|
||||
// extern const char *Txt_The_original_post_no_longer_exists;
|
||||
struct TL_Publication Pub;
|
||||
struct TL_Pub_Publication Pub;
|
||||
bool ItsMe;
|
||||
long OriginalPubCod;
|
||||
|
||||
|
@ -181,7 +181,7 @@ static void TL_Sha_ShaNote (struct TL_Not_Note *Not)
|
|||
Pub.NotCod = Not->NotCod;
|
||||
Pub.PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod;
|
||||
Pub.PubType = TL_PUB_SHARED_NOTE;
|
||||
TL_PublishPubInTimeline (&Pub); // Set Pub.PubCod
|
||||
TL_Pub_PublishPubInTimeline (&Pub); // Set Pub.PubCod
|
||||
|
||||
/* Update number of times this note is shared */
|
||||
TL_Sha_UpdateNumTimesANoteHasBeenShared (Not);
|
||||
|
@ -190,7 +190,7 @@ static void TL_Sha_ShaNote (struct TL_Not_Note *Not)
|
|||
for the author of the post ***/
|
||||
OriginalPubCod = TL_Not_GetPubCodOfOriginalNote (Not->NotCod);
|
||||
if (OriginalPubCod > 0)
|
||||
TL_CreateNotifToAuthor (Not->UsrCod,OriginalPubCod,Ntf_EVENT_TIMELINE_SHARE);
|
||||
TL_Pub_CreateNotifToAuthor (Not->UsrCod,OriginalPubCod,Ntf_EVENT_TIMELINE_SHARE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue