diff --git a/Makefile b/Makefile
index 8f1e7756..3bc7a30c 100644
--- a/Makefile
+++ b/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 \
diff --git a/swad_changelog.h b/swad_changelog.h
index 97803ab9..aff1e795 100644
--- a/swad_changelog.h
+++ b/swad_changelog.h
@@ -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)
diff --git a/swad_notification.c b/swad_notification.c
index fb616564..626bbb39 100644
--- a/swad_notification.c
+++ b/swad_notification.c
@@ -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);
diff --git a/swad_profile.c b/swad_profile.c
index 877813f5..c727ff59 100644
--- a/swad_profile.c
+++ b/swad_profile.c
@@ -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))
diff --git a/swad_session.c b/swad_session.c
index 59870691..20013210 100644
--- a/swad_session.c
+++ b/swad_session.c
@@ -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 ();
}
/*****************************************************************************/
diff --git a/swad_timeline.c b/swad_timeline.c
index fd4e8498..28083990 100644
--- a/swad_timeline.c
+++ b/swad_timeline.c
@@ -47,6 +47,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"
/*****************************************************************************/
@@ -57,15 +58,8 @@
/************************* Private constants and types ***********************/
/*****************************************************************************/
-// Number of recent publishings got and shown the first time, before refreshing
-#define TL_MAX_REC_PUBS_TO_GET_AND_SHOW 10 // Recent publishings to show (first time)
-#define TL_MAX_NEW_PUBS_TO_GET_AND_SHOW 10000 // New publishings retrieved (big number)
-#define TL_MAX_OLD_PUBS_TO_GET_AND_SHOW 20 // Old publishings are retrieved in packs of this size
-
#define TL_MAX_CHARS_IN_POST 1000 // Maximum number of characters in a post
-#define TL_MAX_BYTES_SUBQUERY (128 - 1)
-
/*
mysql> SHOW TABLES LIKE 'tl_%';
+-----------------------+
@@ -164,21 +158,6 @@ mysql> SHOW TABLES LIKE 'tl_%';
*/
-struct TL_SubQueries
- {
- char *TablePublishers;
- char Publishers[TL_MAX_BYTES_SUBQUERY + 1];
- char RangeBottom[TL_MAX_BYTES_SUBQUERY + 1];
- char RangeTop[TL_MAX_BYTES_SUBQUERY + 1];
- char AlreadyExists[TL_MAX_BYTES_SUBQUERY + 1];
- };
-
-struct TL_RangePubsToGet
- {
- long Top;
- long Bottom;
- };
-
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
@@ -199,24 +178,6 @@ Usr_Who_t TL_GlobalWho;
static void TL_GetAndShowOldTimeline (struct TL_Timeline *Timeline);
-static void TL_GetListPubsToShowInTimeline (struct TL_Timeline *Timeline);
-static unsigned TL_GetMaxPubsToGet (const struct TL_Timeline *Timeline);
-static long TL_GetPubCodFromSession (const char *FieldName);
-static void TL_UpdateFirstLastPubCodesIntoSession (const struct TL_Timeline *Timeline);
-static void TL_CreateTmpTableCurrentTimeline (const struct TL_Timeline *Timeline);
-static void TL_CreateTmpTablePublishers (void);
-static void TL_DropTmpTablesUsedToQueryTimeline (void);
-static void TL_CreateSubQueryPublishers (const struct TL_Timeline *Timeline,
- struct TL_SubQueries *SubQueries);
-static void TL_CreateSubQueryAlreadyExists (const struct TL_Timeline *Timeline,
- struct TL_SubQueries *SubQueries);
-static void TL_CreateSubQueryRangeBottom (const struct TL_RangePubsToGet *RangePubsToGet,
- struct TL_SubQueries *SubQueries);
-static void TL_CreateSubQueryRangeTop (const struct TL_RangePubsToGet *RangePubsToGet,
- struct TL_SubQueries *SubQueries);
-static void TL_FreeListPubs (struct TL_Timeline *Timeline);
-static struct TL_Publication *TL_SelectTheMostRecentPub (const struct TL_SubQueries *SubQueries);
-
static void TL_ShowTimeline (struct TL_Timeline *Timeline,
const char *Title,long NotCodToHighlight);
static void TL_PutIconsTimeline (__attribute__((unused)) void *Args);
@@ -229,26 +190,10 @@ static void TL_SaveWhoInDB (struct TL_Timeline *Timeline);
static void TL_ShowWarningYouDontFollowAnyUser (void);
-static void TL_InsertNewPubsInTimeline (struct TL_Timeline *Timeline);
-static void TL_ShowOldPubsInTimeline (struct TL_Timeline *Timeline);
-
-static void TL_PutLinkToViewNewPublications (void);
-static void TL_PutLinkToViewOldPublications (void);
-
static void TL_PutFormToWriteNewPost (struct TL_Timeline *Timeline);
static long TL_ReceivePost (void);
-static long TL_Pub_GetNotCodFromPubCod (long PubCod);
-
-static void TL_GetDataOfPublicationFromNextRow (MYSQL_RES *mysql_res,
- struct TL_Publication *Pub);
-static TL_PubType_t TL_GetPubTypeFromStr (const char *Str);
-
-// static void TL_Pub_ResetPublication (struct TL_Publication *Pub);
-
-static void TL_ClearTimelineThisSession (void);
-
/*****************************************************************************/
/************************ Initialize global timeline *************************/
/*****************************************************************************/
@@ -313,7 +258,7 @@ void TL_ShowNoteAndTimelineGbl (struct TL_Timeline *Timeline)
/***** Get parameter with the code of a publication *****/
// This parameter is optional. It can be provided by a notification.
// If > 0 ==> the note is shown highlighted above the timeline
- PubCod = TL_GetParamPubCod ();
+ PubCod = TL_Pub_GetParamPubCod ();
/***** If a note should be highlighted ==> get code of note from database *****/
if (PubCod > 0)
@@ -340,13 +285,13 @@ void TL_ShowTimelineGblHighlightingNot (struct TL_Timeline *Timeline,
/***** Get list of pubications to show in timeline *****/
Timeline->UsrOrGbl = TL_TIMELINE_GBL;
Timeline->WhatToGet = TL_GET_RECENT_TIMELINE;
- TL_GetListPubsToShowInTimeline (Timeline);
+ TL_Pub_GetListPubsToShowInTimeline (Timeline);
/***** Show timeline *****/
TL_ShowTimeline (Timeline,Txt_Timeline,NotCod);
/***** Free chained list of publications *****/
- TL_FreeListPubs (Timeline);
+ TL_Pub_FreeListPubs (Timeline);
}
/*****************************************************************************/
@@ -370,7 +315,7 @@ void TL_ShowTimelineUsrHighlightingNot (struct TL_Timeline *Timeline,
/***** Get list of pubications to show in timeline *****/
Timeline->UsrOrGbl = TL_TIMELINE_USR;
Timeline->WhatToGet = TL_GET_RECENT_TIMELINE;
- TL_GetListPubsToShowInTimeline (Timeline);
+ TL_Pub_GetListPubsToShowInTimeline (Timeline);
/***** Show timeline *****/
TL_ShowTimeline (Timeline,
@@ -380,7 +325,7 @@ void TL_ShowTimelineUsrHighlightingNot (struct TL_Timeline *Timeline,
Str_FreeString ();
/***** Free chained list of publications *****/
- TL_FreeListPubs (Timeline);
+ TL_Pub_FreeListPubs (Timeline);
}
/*****************************************************************************/
@@ -402,13 +347,13 @@ void TL_RefreshNewTimelineGbl (void)
/***** Get list of pubications to show in timeline *****/
Timeline.UsrOrGbl = TL_TIMELINE_GBL;
Timeline.WhatToGet = TL_GET_ONLY_NEW_PUBS;
- TL_GetListPubsToShowInTimeline (&Timeline);
+ TL_Pub_GetListPubsToShowInTimeline (&Timeline);
/***** Show new timeline *****/
- TL_InsertNewPubsInTimeline (&Timeline);
+ TL_Pub_InsertNewPubsInTimeline (&Timeline);
/***** Free chained list of publications *****/
- TL_FreeListPubs (&Timeline);
+ TL_Pub_FreeListPubs (&Timeline);
}
}
@@ -456,13 +401,13 @@ void TL_RefreshOldTimelineUsr (void)
static void TL_GetAndShowOldTimeline (struct TL_Timeline *Timeline)
{
/***** Get list of pubications to show in timeline *****/
- TL_GetListPubsToShowInTimeline (Timeline);
+ TL_Pub_GetListPubsToShowInTimeline (Timeline);
/***** Show old timeline *****/
- TL_ShowOldPubsInTimeline (Timeline);
+ TL_Pub_ShowOldPubsInTimeline (Timeline);
/***** Free chained list of publications *****/
- TL_FreeListPubs (Timeline);
+ TL_Pub_FreeListPubs (Timeline);
}
/*****************************************************************************/
@@ -478,467 +423,6 @@ void TL_MarkMyNotifAsSeen (void)
Ntf_MarkNotifAsSeen (Ntf_EVENT_TIMELINE_MENTION,-1L,-1L,Gbl.Usrs.Me.UsrDat.UsrCod);
}
-/*****************************************************************************/
-/*************** Get list of pubications to show in timeline *****************/
-/*****************************************************************************/
-
-static void TL_GetListPubsToShowInTimeline (struct TL_Timeline *Timeline)
- {
- struct TL_SubQueries SubQueries;
- struct TL_RangePubsToGet RangePubsToGet;
- unsigned MaxPubsToGet = TL_GetMaxPubsToGet (Timeline);
- unsigned NumPub;
- struct TL_Publication *Pub;
-
- /***** Clear timeline for this session in database *****/
- if (Timeline->WhatToGet == TL_GET_RECENT_TIMELINE)
- TL_ClearTimelineThisSession ();
-
- /***** Create temporary table with notes in current timeline *****/
- TL_CreateTmpTableCurrentTimeline (Timeline);
-
- /***** Create temporary table and subquery with potential publishers *****/
- TL_CreateSubQueryPublishers (Timeline,&SubQueries);
-
- /***** Create subquery to get only notes not present in timeline *****/
- TL_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_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_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_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_CreateSubQueryRangeTop (&RangePubsToGet,&SubQueries);
-
- /* Select the most recent publication from tl_pubs */
- Pub = TL_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_UpdateFirstLastPubCodesIntoSession (Timeline);
-
- /***** Add notes just retrieved to current timeline for this session *****/
- TL_Not_AddNotesJustRetrievedToTimelineThisSession ();
-
- /***** Drop temporary tables *****/
- TL_DropTmpTablesUsedToQueryTimeline ();
- }
-
-/*****************************************************************************/
-/********* Get maximum number of publications to get from database ***********/
-/*****************************************************************************/
-
-static unsigned TL_GetMaxPubsToGet (const struct TL_Timeline *Timeline)
- {
- static const unsigned MaxPubsToGet[TL_NUM_WHAT_TO_GET] =
- {
- [TL_GET_RECENT_TIMELINE] = TL_MAX_REC_PUBS_TO_GET_AND_SHOW,
- [TL_GET_ONLY_NEW_PUBS ] = TL_MAX_NEW_PUBS_TO_GET_AND_SHOW,
- [TL_GET_ONLY_OLD_PUBS ] = TL_MAX_OLD_PUBS_TO_GET_AND_SHOW,
- };
-
- return MaxPubsToGet[Timeline->WhatToGet];
- }
-
-/*****************************************************************************/
-/************* Get last/first publication code stored in session *************/
-/*****************************************************************************/
-// FieldName can be:
-// "LastPubCod"
-// "FirstPubCod"
-
-static long TL_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_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;
- }
- }
-
-/*****************************************************************************/
-/************* Create temporary tables used to query timeline ****************/
-/*****************************************************************************/
-
-static void TL_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_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_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_CreateSubQueryPublishers (const struct TL_Timeline *Timeline,
- struct TL_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_CreateTmpTablePublishers ();
- SubQueries->TablePublishers = ",tl_tmp_publishers";
- Str_Copy (SubQueries->Publishers,
- "tl_pubs.PublisherCod=tl_tmp_publishers.UsrCod AND ",
- TL_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_CreateSubQueryAlreadyExists (const struct TL_Timeline *Timeline,
- struct TL_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_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_MAX_BYTES_SUBQUERY);
- break;
- }
- }
-
-/*****************************************************************************/
-/***** Create subqueries with range of publications to get from tl_pubs ******/
-/*****************************************************************************/
-
-static void TL_CreateSubQueryRangeBottom (const struct TL_RangePubsToGet *RangePubsToGet,
- struct TL_SubQueries *SubQueries)
- {
- if (RangePubsToGet->Bottom > 0)
- sprintf (SubQueries->RangeBottom,"tl_pubs.PubCod>%ld AND ",
- RangePubsToGet->Bottom);
- else
- SubQueries->RangeBottom[0] = '\0';
- }
-
-static void TL_CreateSubQueryRangeTop (const struct TL_RangePubsToGet *RangePubsToGet,
- struct TL_SubQueries *SubQueries)
- {
- if (RangePubsToGet->Top > 0)
- sprintf (SubQueries->RangeTop,"tl_pubs.PubCod<%ld AND ",
- RangePubsToGet->Top);
- else
- SubQueries->RangeTop[0] = '\0';
- }
-
-/*****************************************************************************/
-/************** Free chained list of publications in timeline ****************/
-/*****************************************************************************/
-
-static void TL_FreeListPubs (struct TL_Timeline *Timeline)
- {
- struct TL_Publication *Pub;
- struct TL_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_Publication *TL_SelectTheMostRecentPub (const struct TL_SubQueries *SubQueries)
- {
- MYSQL_RES *mysql_res;
- unsigned NumPubs = 0; // Initialized to avoid warning
- struct TL_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_Publication *) malloc (sizeof (struct TL_Publication))) == NULL)
- Lay_ShowErrorAndExit ("Error allocating memory publication.");
-
- /* Get data of publication */
- TL_GetDataOfPublicationFromNextRow (mysql_res,Pub);
- Pub->Next = NULL;
- }
- else
- Pub = NULL;
- /* Reset data of publication */
- // TL_Pub_ResetPublication (Pub);
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
-
- return Pub;
- }
-
/*****************************************************************************/
/******************************* Show timeline *******************************/
/*****************************************************************************/
@@ -975,7 +459,7 @@ static void TL_ShowTimeline (struct TL_Timeline *Timeline,
const char *Title,long NotCodToHighlight)
{
extern const char *Hlp_START_Timeline;
- struct TL_Publication *Pub;
+ struct TL_Pub_Publication *Pub;
struct TL_Not_Note Not;
unsigned NumPubs;
bool GlobalTimeline = (Gbl.Usrs.Other.UsrDat.UsrCod <= 0);
@@ -998,7 +482,7 @@ static void TL_ShowTimeline (struct TL_Timeline *Timeline,
if (GlobalTimeline)
{
/* Link to view new publications via AJAX */
- TL_PutLinkToViewNewPublications ();
+ TL_Pub_PutLinkToViewNewPublications ();
/* Hidden list where insert just received (not visible) publications via AJAX */
HTM_UL_Begin ("id=\"just_now_timeline_list\" class=\"TL_LIST\"");
@@ -1031,10 +515,10 @@ static void TL_ShowTimeline (struct TL_Timeline *Timeline,
/***** If the number of publications shown is the maximum,
probably there will be more, so show link to get more *****/
- if (NumPubs == TL_MAX_REC_PUBS_TO_GET_AND_SHOW)
+ if (NumPubs == TL_Pub_MAX_REC_PUBS_TO_GET_AND_SHOW)
{
/* Link to view old publications via AJAX */
- TL_PutLinkToViewOldPublications ();
+ TL_Pub_PutLinkToViewOldPublications ();
/* Hidden list where insert old publications via AJAX */
HTM_UL_Begin ("id=\"old_timeline_list\" class=\"TL_LIST\"");
@@ -1224,117 +708,6 @@ static void TL_ShowWarningYouDontFollowAnyUser (void)
}
}
-/*****************************************************************************/
-/******************* Show new publications in timeline ***********************/
-/*****************************************************************************/
-// The publications are inserted as list elements of a hidden list
-
-static void TL_InsertNewPubsInTimeline (struct TL_Timeline *Timeline)
- {
- struct TL_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
-
-static void TL_ShowOldPubsInTimeline (struct TL_Timeline *Timeline)
- {
- struct TL_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 *************/
-/*****************************************************************************/
-
-static void TL_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 *************/
-/*****************************************************************************/
-
-static void TL_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 ();
- }
-
/*****************************************************************************/
/*************** Write sharer/commenter if distinct to author ****************/
/*****************************************************************************/
@@ -1461,28 +834,6 @@ void TL_GetAndWritePost (long PstCod)
Med_MediaDestructor (&Content.Media);
}
-/*****************************************************************************/
-/********************* Publish note/comment in timeline **********************/
-/*****************************************************************************/
-// Pub->PubCod is set by the function
-
-void TL_PublishPubInTimeline (struct TL_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);
- }
-
/*****************************************************************************/
/********************** Form to write a new publication **********************/
/*****************************************************************************/
@@ -1614,7 +965,7 @@ static long TL_ReceivePost (void)
{
struct TL_PostContent Content;
long PstCod;
- struct TL_Publication Pub;
+ struct TL_Pub_Publication Pub;
/***** Get the content of the new post *****/
Par_GetParAndChangeFormat ("Txt",Content.Txt,Cns_MAX_BYTES_LONG_TEXT,
@@ -1662,91 +1013,6 @@ static long TL_ReceivePost (void)
return Pub.NotCod;
}
-/*****************************************************************************/
-/*************** Put parameter with the code of a publication ****************/
-/*****************************************************************************/
-
-void TL_PutHiddenParamPubCod (long PubCod)
- {
- Par_PutHiddenParamLong (NULL,"PubCod",PubCod);
- }
-
-/*****************************************************************************/
-/**************** Get parameter with the code of a publication ***************/
-/*****************************************************************************/
-
-long TL_GetParamPubCod (void)
- {
- /***** Get comment code *****/
- return Par_GetParToLong ("PubCod");
- }
-
-/*****************************************************************************/
-/*********** Create a notification for the author of a post/comment **********/
-/*****************************************************************************/
-
-void TL_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 *******************/
-/*****************************************************************************/
-
-static 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 code of publication of the original note ****************/
/*****************************************************************************/
@@ -1794,7 +1060,7 @@ void TL_RemoveUsrContent (long UsrCod)
" WHERE tl_pubs.PublisherCod=%ld" // Author of the comment
" AND tl_pubs.PubType=%u"
" AND tl_pubs.PubCod=tl_comments_fav.PubCod",
- UsrCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
+ UsrCod,(unsigned) TL_Pub_COMMENT_TO_NOTE);
/* Remove all favs for all comments in all the notes of the user */
DB_QueryDELETE ("can not remove comments",
@@ -1804,7 +1070,7 @@ void TL_RemoveUsrContent (long UsrCod)
" AND tl_notes.NotCod=tl_pubs.NotCod"
" AND tl_pubs.PubType=%u"
" AND tl_pubs.PubCod=tl_comments_fav.PubCod",
- UsrCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
+ UsrCod,(unsigned) TL_Pub_COMMENT_TO_NOTE);
/***** Remove favs for notes *****/
/* Remove all favs made by this user in any note */
@@ -1830,7 +1096,7 @@ void TL_RemoveUsrContent (long UsrCod)
" AND tl_notes.NotCod=tl_pubs.NotCod"
" AND tl_pubs.PubType=%u"
" AND tl_pubs.PubCod=tl_comments.PubCod",
- UsrCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
+ UsrCod,(unsigned) TL_Pub_COMMENT_TO_NOTE);
/* Remove all the comments from any user in any note of the user */
DB_QueryDELETE ("can not remove comments",
@@ -1839,7 +1105,7 @@ void TL_RemoveUsrContent (long UsrCod)
" WHERE tl_notes.UsrCod=%ld"
" AND tl_notes.NotCod=tl_pubs.NotCod"
" AND tl_pubs.PubType=%u",
- UsrCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
+ UsrCod,(unsigned) TL_Pub_COMMENT_TO_NOTE);
/* Remove content of all the comments of the user in any note */
DB_QueryDELETE ("can not remove comments",
@@ -1848,7 +1114,7 @@ void TL_RemoveUsrContent (long UsrCod)
" WHERE tl_pubs.PublisherCod=%ld"
" AND tl_pubs.PubType=%u"
" AND tl_pubs.PubCod=tl_comments.PubCod",
- UsrCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
+ UsrCod,(unsigned) TL_Pub_COMMENT_TO_NOTE);
/***** Remove all the posts of the user *****/
DB_QueryDELETE ("can not remove posts",
@@ -2023,239 +1289,3 @@ void TL_FormFavSha (Act_Action_t ActionGbl,Act_Action_t ActionUsr,
/* Free allocated memory */
free (OnSubmit);
}
-
-/*****************************************************************************/
-/***************** Get data of publication using its code ********************/
-/*****************************************************************************/
-
-static void TL_GetDataOfPublicationFromNextRow (MYSQL_RES *mysql_res,
- struct TL_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_GetPubTypeFromStr ((const char *) row[3]);
- Pub->TopMessage = TopMessages[Pub->PubType];
- }
-
-/*****************************************************************************/
-/******* Get publication type from string number coming from database ********/
-/*****************************************************************************/
-
-static TL_PubType_t TL_GetPubTypeFromStr (const char *Str)
- {
- unsigned UnsignedNum;
-
- if (sscanf (Str,"%u",&UnsignedNum) == 1)
- if (UnsignedNum < TL_NUM_PUB_TYPES)
- return (TL_PubType_t) UnsignedNum;
-
- return TL_PUB_UNKNOWN;
- }
-
-/*****************************************************************************/
-/************************ Reset fields of publication ************************/
-/*****************************************************************************/
-/*
-static void TL_Pub_ResetPublication (struct TL_Publication *Pub)
- {
- Pub->PubCod = -1L;
- Pub->NotCod = -1L;
- Pub->PublisherCod = -1L;
- Pub->PubType = TL_PUB_UNKNOWN;
- Pub->TopMessage = TL_TOP_MESSAGE_NONE;
- }
-*/
-/*****************************************************************************/
-/******************* Clear unused old timelines in database ******************/
-/*****************************************************************************/
-
-void TL_ClearOldTimelinesDB (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 ****************/
-/*****************************************************************************/
-
-static void TL_ClearTimelineThisSession (void)
- {
- /***** Remove timeline for this session *****/
- DB_QueryDELETE ("can not remove timeline",
- "DELETE FROM tl_timelines"
- " WHERE SessionId='%s'",
- Gbl.Session.Id);
- }
-
-/*****************************************************************************/
-/***************** Get notification of a new publication *********************/
-/*****************************************************************************/
-
-void TL_GetNotifPublication (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
- char **ContentStr,
- long PubCod,bool GetContent)
- {
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
- struct TL_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_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';
- }
-
-/*****************************************************************************/
-/****************** Get number of publications from a user *******************/
-/*****************************************************************************/
-
-unsigned long TL_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);
- }
diff --git a/swad_timeline.h b/swad_timeline.h
index a54daa32..f8ecf7b3 100644
--- a/swad_timeline.h
+++ b/swad_timeline.h
@@ -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
diff --git a/swad_timeline_comment.c b/swad_timeline_comment.c
index ad7a7aaf..d52c51c7 100644
--- a/swad_timeline_comment.c
+++ b/swad_timeline_comment.c
@@ -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);
diff --git a/swad_timeline_favourite.c b/swad_timeline_favourite.c
index eb534934..545f9332 100644
--- a/swad_timeline_favourite.c
+++ b/swad_timeline_favourite.c
@@ -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)
diff --git a/swad_timeline_note.c b/swad_timeline_note.c
index f913bf2c..fd65de40 100644
--- a/swad_timeline_note.c
+++ b/swad_timeline_note.c
@@ -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);
+ }
diff --git a/swad_timeline_note.h b/swad_timeline_note.h
index ddf5bcd0..96934c82 100644
--- a/swad_timeline_note.h
+++ b/swad_timeline_note.h
@@ -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
diff --git a/swad_timeline_publication.c b/swad_timeline_publication.c
new file mode 100644
index 00000000..fb9b3638
--- /dev/null
+++ b/swad_timeline_publication.c
@@ -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 .
+*/
+/*****************************************************************************/
+/*********************************** Headers *********************************/
+/*****************************************************************************/
+
+#define _GNU_SOURCE // For asprintf
+#include // For PATH_MAX
+#include // For asprintf
+#include // For malloc and free
+#include // For string functions
+#include // 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);
+ }
diff --git a/swad_timeline_publication.h b/swad_timeline_publication.h
new file mode 100644
index 00000000..ad859e79
--- /dev/null
+++ b/swad_timeline_publication.h
@@ -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 .
+*/
+/*****************************************************************************/
+/********************************** 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
diff --git a/swad_timeline_share.c b/swad_timeline_share.c
index dda26cf8..a8b4dcb2 100644
--- a/swad_timeline_share.c
+++ b/swad_timeline_share.c
@@ -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);
}
}
}