Version 20.70: May 07, 2021 New module swad_follow_database for database queries related to followin/followers.

This commit is contained in:
acanas 2021-05-07 19:11:57 +02:00
parent 4818af539d
commit 300662e301
10 changed files with 635 additions and 421 deletions

View File

@ -40,7 +40,7 @@ OBJS = swad_account.o swad_action.o swad_agenda.o swad_alert.o \
swad_exam_set.o \
swad_figure.o swad_figure_cache.o swad_file.o swad_file_browser.o \
swad_file_extension.o swad_file_MIME.o swad_firewall.o swad_follow.o \
swad_form.o swad_forum.o \
swad_follow_database.o swad_form.o swad_forum.o \
swad_game.o swad_global.o swad_group.o \
swad_help.o swad_hierarchy.o swad_hierarchy_config.o swad_holiday.o \
swad_HTML.o \

View File

@ -600,13 +600,14 @@ TODO: Salvador Romero Cort
TODO: FIX BUG, URGENT! En las fechas como parámetro Dat_WriteParamsIniEndDates(), por ejemplo al cambiar el color de la gráfica de accesos por día y hora, no se respeta la zona horaria.
*/
#define Log_PLATFORM_VERSION "SWAD 20.69.2 (2021-05-04)"
#define Log_PLATFORM_VERSION "SWAD 20.70 (2021-05-07)"
#define CSS_FILE "swad20.45.css"
#define JS_FILE "swad20.69.1.js"
/*
TODO: Rename CENTRE to CENTER in help wiki.
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
Version 20.70: May 07, 2021 New module swad_follow_database for database queries related to followin/followers. (309943 lines)
Version 20.69.2: May 04, 2021 Fixed bug in removal of timeline favs. (309778 lines)
Version 20.69.1: Apr 30, 2021 Code refactoring in JavaScript (firstChild instead of childNodes[0]). (309775 lines)
Version 20.69: Apr 30, 2021 Changes in timeline to not repeat notes in new activity. (309773 lines)

View File

@ -33,6 +33,7 @@
#include "swad_error.h"
#include "swad_figure.h"
#include "swad_follow.h"
#include "swad_follow_database.h"
#include "swad_form.h"
#include "swad_global.h"
#include "swad_HTML.h"
@ -58,12 +59,6 @@
/******************************* Private types *******************************/
/*****************************************************************************/
typedef enum
{
Fol_SUGGEST_ONLY_USERS_WITH_PHOTO,
Fol_SUGGEST_ANY_USER,
} Fol_WhichUsersSuggestToFollowThem_t;
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
@ -78,10 +73,6 @@ extern struct Globals Gbl;
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static unsigned Fol_GetUsrsToFollow (unsigned MaxUsrsToShow,
Fol_WhichUsersSuggestToFollowThem_t WhichUsersSuggestToFollowThem,
MYSQL_RES **mysql_res);
static void Fol_PutIconsWhoToFollow (__attribute__((unused)) void *Args);
static void Fol_PutIconToUpdateWhoToFollow (void);
@ -146,9 +137,9 @@ void Fol_SuggestUsrsToFollowMainZone (void)
Mnu_ContextMenuEnd ();
/***** Get users *****/
if ((NumUsrs = Fol_GetUsrsToFollow (Fol_MAX_USRS_TO_FOLLOW_MAIN_ZONE,
Fol_SUGGEST_ANY_USER,
&mysql_res)))
if ((NumUsrs = Fol_DB_GetUsrsToFollow (Fol_MAX_USRS_TO_FOLLOW_MAIN_ZONE,
Fol_SUGGEST_ANY_USER,
&mysql_res)))
{
/***** Begin box and table *****/
Box_BoxTableBegin ("560px",Txt_Who_to_follow,
@ -211,9 +202,9 @@ void Fol_SuggestUsrsToFollowMainZoneOnRightColumn (void)
struct UsrData UsrDat;
/***** Get users *****/
if ((NumUsrs = Fol_GetUsrsToFollow (Fol_MAX_USRS_TO_FOLLOW_RIGHT_COLUMN,
Fol_SUGGEST_ONLY_USERS_WITH_PHOTO,
&mysql_res)))
if ((NumUsrs = Fol_DB_GetUsrsToFollow (Fol_MAX_USRS_TO_FOLLOW_RIGHT_COLUMN,
Fol_SUGGEST_ONLY_USERS_WITH_PHOTO,
&mysql_res)))
{
/***** Begin container *****/
HTM_DIV_Begin ("class=\"CONNECTED\"");
@ -263,171 +254,6 @@ void Fol_SuggestUsrsToFollowMainZoneOnRightColumn (void)
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/*************************** Get users to follow *****************************/
/*****************************************************************************/
static unsigned Fol_GetUsrsToFollow (unsigned MaxUsrsToShow,
Fol_WhichUsersSuggestToFollowThem_t WhichUsersSuggestToFollowThem,
MYSQL_RES **mysql_res)
{
extern const char *Pri_VisibilityDB[Pri_NUM_OPTIONS_PRIVACY];
char SubQuery1[256];
char SubQuery2[256];
char SubQuery3[256];
char SubQuery4[256];
/***** Build subqueries related to photos *****/
switch (WhichUsersSuggestToFollowThem)
{
case Fol_SUGGEST_ONLY_USERS_WITH_PHOTO:
// Photo visibility should be >= profile visibility in every subquery
sprintf (SubQuery1, // 1. Users followed by my followed
" AND usr_data.PhotoVisibility IN ('%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
sprintf (SubQuery2, // 2. Users who share any course with me
" AND usr_data.PhotoVisibility IN ('%s','%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_COURSE],
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
sprintf (SubQuery3, // 3. Users who share any course with me with another role
" AND usr_data.PhotoVisibility IN ('%s','%s','%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_USER ],
Pri_VisibilityDB[Pri_VISIBILITY_COURSE],
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
sprintf (SubQuery4, // 4. Add some likely unknown random users
" AND usr_data.PhotoVisibility IN ('%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
break;
case Fol_SUGGEST_ANY_USER:
SubQuery1[0] = '\0';
SubQuery2[0] = '\0';
SubQuery3[0] = '\0';
SubQuery4[0] = '\0';
break;
}
/***** Build query to get users to follow *****/
// Get only users with surname 1 and first name
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get users to follow",
"SELECT DISTINCT UsrCod FROM"
" ("
/***** Likely known users *****/
"(SELECT DISTINCT UsrCod FROM"
" ("
// 1. Users followed by my followed
"("
"SELECT DISTINCT usr_follow.FollowedCod AS UsrCod"
" FROM usr_follow,"
"(SELECT FollowedCod"
" FROM usr_follow"
" WHERE FollowerCod=%ld) AS my_followed,"
" usr_data"
" WHERE usr_follow.FollowerCod=my_followed.FollowedCod"
" AND usr_follow.FollowedCod<>%ld"
" AND usr_follow.FollowedCod=usr_data.UsrCod"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery1
")"
" UNION "
// 2. Users who share any course with me
"("
"SELECT DISTINCT crs_users.UsrCod"
" FROM crs_users,"
"(SELECT CrsCod"
" FROM crs_users"
" WHERE UsrCod=%ld) AS my_crs,"
" usr_data"
" WHERE crs_users.CrsCod=my_crs.CrsCod"
" AND crs_users.UsrCod<>%ld"
" AND crs_users.UsrCod=usr_data.UsrCod"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery2
")"
" UNION "
// 3. Users who share any course with me with another role
"("
"SELECT DISTINCT crs_users.UsrCod"
" FROM crs_users,"
"(SELECT CrsCod,Role"
" FROM crs_users"
" WHERE UsrCod=%ld) AS my_crs_role,"
" usr_data"
" WHERE crs_users.CrsCod=my_crs_role.CrsCod"
" AND crs_users.Role<>my_crs_role.Role"
" AND crs_users.UsrCod=usr_data.UsrCod"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery3
")"
") AS LikelyKnownUsrsToFollow"
// Do not select my followed
" WHERE UsrCod NOT IN"
" (SELECT FollowedCod FROM usr_follow"
" WHERE FollowerCod=%ld)"
// Get only MaxUsrsToShow * 3 users
" ORDER BY RAND() LIMIT %u"
")"
" UNION "
"("
/***** Likely unknown userd *****/
// 4. Add some likely unknown random user
// Be careful with the method to get some random users
// from the big table of users.
// It's much faster getting a random code and then get the first users
// with codes >= that random code
// that getting all users and then ordering by rand.
"SELECT usr_data.UsrCod"
" FROM usr_data,"
"(SELECT ROUND(RAND()*(SELECT MAX(UsrCod)"
" FROM usr_data)) AS RandomUsrCod) AS random_usr" // a random user code
" WHERE usr_data.UsrCod<>%ld"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery4
// Do not select my followed
" AND usr_data.UsrCod NOT IN"
" (SELECT FollowedCod"
" FROM usr_follow"
" WHERE FollowerCod=%ld)"
" AND usr_data.UsrCod>=random_usr.RandomUsrCod" // random user code could not exists in table of users
// Get only MaxUsrsToShow users
" LIMIT %u"
")"
") AS UsrsToFollow"
// Get only MaxUsrsToShow users
" ORDER BY RAND()"
" LIMIT %u",
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery1,
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery2,
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery3,
Gbl.Usrs.Me.UsrDat.UsrCod,
MaxUsrsToShow * 2, // 2/3 likely known users
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery4,
Gbl.Usrs.Me.UsrDat.UsrCod,
MaxUsrsToShow, // 1/3 likely unknown users
MaxUsrsToShow);
}
/*****************************************************************************/
/****************** Put contextual icons in "who to follow" ******************/
/*****************************************************************************/
@ -456,24 +282,6 @@ static void Fol_PutIconToUpdateWhoToFollow (void)
Frm_EndForm ();
}
/*****************************************************************************/
/*************** Check if a user is a follower of another user ***************/
/*****************************************************************************/
bool Fol_CheckUsrIsFollowerOf (long FollowerCod,long FollowedCod)
{
if (FollowerCod == FollowedCod)
return false;
/***** Check if a user is a follower of another user *****/
return (DB_QueryCOUNT ("can not get if a user is a follower of another one",
"SELECT COUNT(*)"
" FROM usr_follow"
" WHERE FollowerCod=%ld"
" AND FollowedCod=%ld",
FollowerCod,FollowedCod) != 0);
}
/*****************************************************************************/
/*************************** Get number of followed **************************/
/*****************************************************************************/
@ -505,18 +313,8 @@ void Fol_GetNumFollow (long UsrCod,
/***** 3. Slow check: Get number of following/followers from database *****/
Gbl.Cache.Follow.UsrCod = UsrCod;
*NumFollowing = Gbl.Cache.Follow.NumFollowing = (unsigned)
DB_QueryCOUNT ("can not get number of followed",
"SELECT COUNT(*)"
" FROM usr_follow"
" WHERE FollowerCod=%ld",
UsrCod);
*NumFollowers = Gbl.Cache.Follow.NumFollowers = (unsigned)
DB_QueryCOUNT ("can not get number of followers",
"SELECT COUNT(*)"
" FROM usr_follow"
" WHERE FollowedCod=%ld",
UsrCod);
*NumFollowing = Gbl.Cache.Follow.NumFollowing = Fol_DB_GetNumFollowing (UsrCod);
*NumFollowers = Gbl.Cache.Follow.NumFollowers = Fol_DB_GetNumFollowers (UsrCod);
}
/*****************************************************************************/
@ -690,14 +488,8 @@ static void Fol_ListFollowingUsr (struct UsrData *UsrDat)
/***** Show user's profile *****/
if (Prf_ShowUserProfile (UsrDat))
{
/***** Check if a user is a follower of another user *****/
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get followed users",
"SELECT FollowedCod" // row[0]
" FROM usr_follow"
" WHERE FollowerCod=%ld"
" ORDER BY FollowTime DESC",
UsrDat->UsrCod);
/***** Get list of following *****/
NumUsrs = Fol_DB_GetListFollowing (UsrDat->UsrCod,&mysql_res);
if (NumUsrs)
{
@ -776,14 +568,8 @@ static void Fol_ListFollowersUsr (struct UsrData *UsrDat)
/***** Show user's profile *****/
if (Prf_ShowUserProfile (UsrDat))
{
/***** Check if a user is a follower of another user *****/
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get followers",
"SELECT FollowerCod"
" FROM usr_follow"
" WHERE FollowedCod=%ld"
" ORDER BY FollowTime DESC",
UsrDat->UsrCod);
/***** Get list of followers *****/
NumUsrs = Fol_DB_GetListFollowers (UsrDat->UsrCod,&mysql_res);
if (NumUsrs)
{
@ -875,7 +661,8 @@ static void Fol_ShowFollowedOrFollower (struct UsrData *UsrDat)
else // It's not me
{
/* Put form to follow / unfollow */
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,UsrDat->UsrCod)) // I follow user
if (Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat->UsrCod)) // I follow user
/* Form to unfollow */
Fol_PutIconToUnfollow (UsrDat);
else if (Visible) // I do not follow this user and I can follow
@ -930,7 +717,8 @@ static void Fol_WriteRowUsrToFollowOnRightColumn (struct UsrData *UsrDat)
else // It's not me
{
/* Put form to follow / unfollow */
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,UsrDat->UsrCod)) // I follow user
if (Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat->UsrCod)) // I follow user
/* Form to unfollow */
Fol_PutIconToUnfollow (UsrDat);
else if (Visible) // I do not follow this user and I can follow
@ -998,8 +786,8 @@ void Fol_FollowUsr1 (void)
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
{
// Follow only if I do not follow him/her
if (!Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Other.UsrDat.UsrCod))
if (!Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Other.UsrDat.UsrCod))
Fol_FollowUsr (&Gbl.Usrs.Other.UsrDat);
Ale_CreateAlert (Ale_SUCCESS,NULL,""); // Txt not used
@ -1033,8 +821,8 @@ void Fol_UnfollowUsr1 (void)
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
{
// Unfollow only if I follow him/her
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Other.UsrDat.UsrCod))
if (Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Other.UsrDat.UsrCod))
Fol_UnfollowUsr (&Gbl.Usrs.Other.UsrDat);
Ale_CreateAlert (Ale_SUCCESS,NULL,""); // Txt not used
@ -1167,7 +955,6 @@ static void Fol_GetFollowedFromSelectedUsrs (unsigned *NumFollowed,
extern const char *Txt_Selected_users_X_Followed_Y_Not_followed_Z;
struct UsrData UsrDat;
const char *Ptr;
bool IFollowUsr;
unsigned NumUsrs = 0;
/***** Initialize structure with user's data *****/
@ -1187,12 +974,9 @@ static void Fol_GetFollowedFromSelectedUsrs (unsigned *NumFollowed,
Usr_DONT_GET_ROLE_IN_CURRENT_CRS)) // Get from the database the data of the student
if (Usr_CheckIfUsrBelongsToCurrentCrs (&UsrDat))
{
/* Check if I follow this user */
IFollowUsr = Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat.UsrCod);
/* Update number of users */
if (IFollowUsr)
/* Check if I follow this user, and update number of users */
if (Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat.UsrCod)) // I follow user
(*NumFollowed)++;
NumUsrs++;
}
@ -1238,8 +1022,8 @@ void Fol_FollowUsrs ()
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
if (Usr_CheckIfUsrBelongsToCurrentCrs (&UsrDat))
/* If I don't follow this user ==> follow him/her */
if (!Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat.UsrCod))
if (!Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat.UsrCod))
{
Fol_FollowUsr (&UsrDat);
NumFollowed++;
@ -1287,8 +1071,8 @@ void Fol_UnfollowUsrs (void)
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
if (Usr_CheckIfUsrBelongsToCurrentCrs (&UsrDat))
/* If I follow this user ==> unfollow him/her */
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat.UsrCod))
if (Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat.UsrCod))
{
Fol_UnfollowUsr (&UsrDat);
NumUnfollowed++;
@ -1325,13 +1109,7 @@ static void Fol_FollowUsr (struct UsrData *UsrDat)
return;
/***** Follow user in database *****/
DB_QueryREPLACE ("can not follow user",
"REPLACE INTO usr_follow"
" (FollowerCod,FollowedCod,FollowTime)"
" VALUES"
" (%ld,%ld,NOW())",
Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat->UsrCod);
Fol_DB_FollowUsr (UsrDat->UsrCod);
/***** Flush cache *****/
Fol_FlushCacheFollow ();
@ -1367,12 +1145,7 @@ static void Fol_UnfollowUsr (struct UsrData *UsrDat)
return;
/***** Unfollow user in database *****/
DB_QueryDELETE ("can not unfollow user",
"DELETE FROM usr_follow"
" WHERE FollowerCod=%ld"
" AND FollowedCod=%ld",
Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat->UsrCod);
Fol_DB_UnfollowUsr (UsrDat->UsrCod);
/***** Flush cache *****/
Fol_FlushCacheFollow ();
@ -1385,122 +1158,12 @@ static void Fol_UnfollowUsr (struct UsrData *UsrDat)
void Fol_GetAndShowRankingFollowers (void)
{
MYSQL_RES *mysql_res;
unsigned NumUsrs = 0; // Initialized to avoid warning
unsigned NumUsrs;
/***** Get ranking from database *****/
switch (Gbl.Scope.Current)
{
case Hie_Lvl_SYS:
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get ranking",
"SELECT FollowedCod," // row[0]
"COUNT(FollowerCod) AS N" // row[1]
" FROM usr_follow"
" GROUP BY FollowedCod"
" ORDER BY N DESC,"
"FollowedCod"
" LIMIT 100");
break;
case Hie_Lvl_CTY:
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM ins_instits,"
"ctr_centers,"
"deg_degrees,"
"crs_courses,"
"crs_users,"
"usr_follow"
" WHERE ins_instits.CtyCod=%ld"
" AND ins_instits.InsCod=ctr_centers.InsCod"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Cty.CtyCod);
break;
case Hie_Lvl_INS:
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM ctr_centers,"
"deg_degrees,"
"crs_courses,"
"crs_users,"
"usr_follow"
" WHERE ctr_centers.InsCod=%ld"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Ins.InsCod);
break;
case Hie_Lvl_CTR:
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM deg_degrees,"
"crs_courses,"
"crs_users,"
"usr_follow"
" WHERE deg_degrees.CtrCod=%ld"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Ctr.CtrCod);
break;
case Hie_Lvl_DEG:
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM crs_courses,"
"crs_users,"
"usr_follow"
" WHERE crs_courses.DegCod=%ld"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Deg.DegCod);
break;
case Hie_Lvl_CRS:
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM crs_users,"
"usr_follow"
" WHERE crs_users.CrsCod=%ld"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Crs.CrsCod);
break;
default:
Err_WrongScopeExit ();
break;
}
NumUsrs = Fol_DB_GetRankingFollowers (&mysql_res);
/***** Show ranking *****/
Prf_ShowRankingFigure (&mysql_res,NumUsrs);
}
@ -1523,40 +1186,9 @@ void Fol_GetNotifFollower (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
void Fol_RemoveUsrFromUsrFollow (long UsrCod)
{
DB_QueryDELETE ("can not remove user from followers and followed",
"DELETE FROM usr_follow"
" WHERE FollowerCod=%ld"
" OR FollowedCod=%ld",
UsrCod,UsrCod);
/***** Remove user from followers and followed *****/
Fol_DB_RemoveUsrFromUsrFollow (UsrCod);
/***** Flush cache *****/
Fol_FlushCacheFollow ();
}
/*****************************************************************************/
/******* Create/drop temporary tables with me and the users I follow *********/
/*****************************************************************************/
void Fol_CreateTmpTableMeAndUsrsIFollow (void)
{
/***** Create temporary table with me and the users I follow *****/
DB_Query ("can not create temporary table",
"CREATE TEMPORARY TABLE fol_tmp_me_and_followed "
"(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);
}
void Fol_DropTmpTableMeAndUsrsIFollow (void)
{
/***** Drop temporary table with me and the users I follow *****/
DB_Query ("can not remove temporary table",
"DROP TEMPORARY TABLE IF EXISTS fol_tmp_me_and_followed");
}

View File

@ -27,10 +27,7 @@
/********************************** Headers **********************************/
/*****************************************************************************/
#include <stdlib.h> // For malloc
#include "swad_notification.h"
#include "swad_user.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
@ -40,6 +37,12 @@
/******************************** Public types *******************************/
/*****************************************************************************/
typedef enum
{
Fol_SUGGEST_ONLY_USERS_WITH_PHOTO,
Fol_SUGGEST_ANY_USER,
} Fol_WhichUsersSuggestToFollowThem_t;
/*****************************************************************************/
/****************************** Public prototypes ****************************/
/*****************************************************************************/
@ -48,7 +51,6 @@ void Fol_PutLinkWhoToFollow (void);
void Fol_SuggestUsrsToFollowMainZone (void);
void Fol_SuggestUsrsToFollowMainZoneOnRightColumn (void);
bool Fol_CheckUsrIsFollowerOf (long FollowerCod,long FollowedCod);
void Fol_FlushCacheFollow (void);
void Fol_GetNumFollow (long UsrCod,
unsigned *NumFollowing,unsigned *NumFollowers);
@ -78,7 +80,7 @@ void Fol_GetNotifFollower (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
void Fol_RemoveUsrFromUsrFollow (long UsrCod);
void Fol_CreateTmpTableMeAndUsrsIFollow (void);
void Fol_DropTmpTableMeAndUsrsIFollow (void);
void Fol_DB_CreateTmpTableMeAndUsrsIFollow (void);
void Fol_DB_DropTmpTableMeAndUsrsIFollow (void);
#endif

513
swad_follow_database.c Normal file
View File

@ -0,0 +1,513 @@
// swad_follow_database.c: user's followers and followed operations with database
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2021 Antonio Cañas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General 3 License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/*********************************** Headers *********************************/
/*****************************************************************************/
#include "swad_database.h"
#include "swad_error.h"
#include "swad_follow.h"
#include "swad_follow_database.h"
#include "swad_global.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Private global variables **************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
/*****************************************************************************/
/*************************** Get users to follow *****************************/
/*****************************************************************************/
unsigned Fol_DB_GetUsrsToFollow (unsigned MaxUsrsToShow,
Fol_WhichUsersSuggestToFollowThem_t WhichUsersSuggestToFollowThem,
MYSQL_RES **mysql_res)
{
extern const char *Pri_VisibilityDB[Pri_NUM_OPTIONS_PRIVACY];
char SubQuery1[256];
char SubQuery2[256];
char SubQuery3[256];
char SubQuery4[256];
/***** Build subqueries related to photos *****/
switch (WhichUsersSuggestToFollowThem)
{
case Fol_SUGGEST_ONLY_USERS_WITH_PHOTO:
// Photo visibility should be >= profile visibility in every subquery
sprintf (SubQuery1, // 1. Users followed by my followed
" AND usr_data.PhotoVisibility IN ('%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
sprintf (SubQuery2, // 2. Users who share any course with me
" AND usr_data.PhotoVisibility IN ('%s','%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_COURSE],
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
sprintf (SubQuery3, // 3. Users who share any course with me with another role
" AND usr_data.PhotoVisibility IN ('%s','%s','%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_USER ],
Pri_VisibilityDB[Pri_VISIBILITY_COURSE],
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
sprintf (SubQuery4, // 4. Add some likely unknown random users
" AND usr_data.PhotoVisibility IN ('%s','%s')"
" AND usr_data.Photo<>''",
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
break;
case Fol_SUGGEST_ANY_USER:
SubQuery1[0] = '\0';
SubQuery2[0] = '\0';
SubQuery3[0] = '\0';
SubQuery4[0] = '\0';
break;
}
/***** Build query to get users to follow *****/
// Get only users with surname 1 and first name
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get users to follow",
"SELECT DISTINCT UsrCod FROM"
" ("
/***** Likely known users *****/
"(SELECT DISTINCT UsrCod FROM"
" ("
// 1. Users followed by my followed
"("
"SELECT DISTINCT usr_follow.FollowedCod AS UsrCod"
" FROM usr_follow,"
"(SELECT FollowedCod"
" FROM usr_follow"
" WHERE FollowerCod=%ld) AS my_followed,"
" usr_data"
" WHERE usr_follow.FollowerCod=my_followed.FollowedCod"
" AND usr_follow.FollowedCod<>%ld"
" AND usr_follow.FollowedCod=usr_data.UsrCod"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery1
")"
" UNION "
// 2. Users who share any course with me
"("
"SELECT DISTINCT crs_users.UsrCod"
" FROM crs_users,"
"(SELECT CrsCod"
" FROM crs_users"
" WHERE UsrCod=%ld) AS my_crs,"
" usr_data"
" WHERE crs_users.CrsCod=my_crs.CrsCod"
" AND crs_users.UsrCod<>%ld"
" AND crs_users.UsrCod=usr_data.UsrCod"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery2
")"
" UNION "
// 3. Users who share any course with me with another role
"("
"SELECT DISTINCT crs_users.UsrCod"
" FROM crs_users,"
"(SELECT CrsCod,Role"
" FROM crs_users"
" WHERE UsrCod=%ld) AS my_crs_role,"
" usr_data"
" WHERE crs_users.CrsCod=my_crs_role.CrsCod"
" AND crs_users.Role<>my_crs_role.Role"
" AND crs_users.UsrCod=usr_data.UsrCod"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery3
")"
") AS LikelyKnownUsrsToFollow"
// Do not select my followed
" WHERE UsrCod NOT IN"
" (SELECT FollowedCod FROM usr_follow"
" WHERE FollowerCod=%ld)"
// Get only MaxUsrsToShow * 3 users
" ORDER BY RAND() LIMIT %u"
")"
" UNION "
"("
/***** Likely unknown userd *****/
// 4. Add some likely unknown random user
// Be careful with the method to get some random users
// from the big table of users.
// It's much faster getting a random code and then get the first users
// with codes >= that random code
// that getting all users and then ordering by rand.
"SELECT usr_data.UsrCod"
" FROM usr_data,"
"(SELECT ROUND(RAND()*(SELECT MAX(UsrCod)"
" FROM usr_data)) AS RandomUsrCod) AS random_usr" // a random user code
" WHERE usr_data.UsrCod<>%ld"
" AND usr_data.Surname1<>''" // Surname 1 not empty
" AND usr_data.FirstName<>''" // First name not empty
"%s" // SubQuery4
// Do not select my followed
" AND usr_data.UsrCod NOT IN"
" (SELECT FollowedCod"
" FROM usr_follow"
" WHERE FollowerCod=%ld)"
" AND usr_data.UsrCod>=random_usr.RandomUsrCod" // random user code could not exists in table of users
// Get only MaxUsrsToShow users
" LIMIT %u"
")"
") AS UsrsToFollow"
// Get only MaxUsrsToShow users
" ORDER BY RAND()"
" LIMIT %u",
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery1,
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery2,
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery3,
Gbl.Usrs.Me.UsrDat.UsrCod,
MaxUsrsToShow * 2, // 2/3 likely known users
Gbl.Usrs.Me.UsrDat.UsrCod,
SubQuery4,
Gbl.Usrs.Me.UsrDat.UsrCod,
MaxUsrsToShow, // 1/3 likely unknown users
MaxUsrsToShow);
}
/*****************************************************************************/
/*************** Check if a user is a follower of another user ***************/
/*****************************************************************************/
bool Fol_DB_CheckUsrIsFollowerOf (long FollowerCod,long FollowedCod)
{
if (FollowerCod == FollowedCod)
return false;
/***** Check if a user is a follower of another user *****/
return (DB_QueryCOUNT ("can not get if a user is a follower of another one",
"SELECT COUNT(*)"
" FROM usr_follow"
" WHERE FollowerCod=%ld"
" AND FollowedCod=%ld",
FollowerCod,FollowedCod) != 0);
}
/*****************************************************************************/
/*************************** Get number of followed **************************/
/*****************************************************************************/
unsigned Fol_DB_GetNumFollowing (long UsrCod)
{
/***** Get number of following from database *****/
return (unsigned)
DB_QueryCOUNT ("can not get number of followed",
"SELECT COUNT(*)"
" FROM usr_follow"
" WHERE FollowerCod=%ld",
UsrCod);
}
/*****************************************************************************/
/*************************** Get number of followers *************************/
/*****************************************************************************/
unsigned Fol_DB_GetNumFollowers (long UsrCod)
{
/***** Get number of followers from database *****/
return (unsigned)
DB_QueryCOUNT ("can not get number of followers",
"SELECT COUNT(*)"
" FROM usr_follow"
" WHERE FollowedCod=%ld",
UsrCod);
}
/*****************************************************************************/
/************************** Get list of following ****************************/
/*****************************************************************************/
unsigned Fol_DB_GetListFollowing (long UsrCod,MYSQL_RES **mysql_res)
{
/***** Trivial check: user code should be > 0 *****/
if (UsrCod <= 0)
return 0;
/***** Get followed users from database *****/
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get following",
"SELECT FollowedCod" // row[0]
" FROM usr_follow"
" WHERE FollowerCod=%ld"
" ORDER BY FollowTime DESC",
UsrCod);
}
/*****************************************************************************/
/************************** Get list of followers ****************************/
/*****************************************************************************/
unsigned Fol_DB_GetListFollowers (long UsrCod,MYSQL_RES **mysql_res)
{
/***** Trivial check: user code should be > 0 *****/
if (UsrCod <= 0)
return 0;
/***** Get followed users from database *****/
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get followers",
"SELECT FollowerCod"
" FROM usr_follow"
" WHERE FollowedCod=%ld"
" ORDER BY FollowTime DESC",
UsrCod);
}
/*****************************************************************************/
/******************************** Follow user ********************************/
/*****************************************************************************/
void Fol_DB_FollowUsr (long UsrCod)
{
/***** Trivial check: user code should be > 0 *****/
if (UsrCod <= 0)
return;
/***** Follow user in database *****/
DB_QueryREPLACE ("can not follow user",
"REPLACE INTO usr_follow"
" (FollowerCod,FollowedCod,FollowTime)"
" VALUES"
" (%ld,%ld,NOW())",
Gbl.Usrs.Me.UsrDat.UsrCod,
UsrCod);
}
/*****************************************************************************/
/******************************* Unfollow user *******************************/
/*****************************************************************************/
void Fol_DB_UnfollowUsr (long UsrCod)
{
/***** Trivial check: user code should be > 0 *****/
if (UsrCod <= 0)
return;
/***** Unfollow user in database *****/
DB_QueryDELETE ("can not unfollow user",
"DELETE FROM usr_follow"
" WHERE FollowerCod=%ld"
" AND FollowedCod=%ld",
Gbl.Usrs.Me.UsrDat.UsrCod,
UsrCod);
}
/*****************************************************************************/
/*********** Get ranking of users attending to number of followers ***********/
/*****************************************************************************/
unsigned Fol_DB_GetRankingFollowers (MYSQL_RES **mysql_res)
{
/***** Get ranking from database *****/
switch (Gbl.Scope.Current)
{
case Hie_Lvl_SYS:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get ranking",
"SELECT FollowedCod," // row[0]
"COUNT(FollowerCod) AS N" // row[1]
" FROM usr_follow"
" GROUP BY FollowedCod"
" ORDER BY N DESC,"
"FollowedCod"
" LIMIT 100");
case Hie_Lvl_CTY:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM ins_instits,"
"ctr_centers,"
"deg_degrees,"
"crs_courses,"
"crs_users,"
"usr_follow"
" WHERE ins_instits.CtyCod=%ld"
" AND ins_instits.InsCod=ctr_centers.InsCod"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Cty.CtyCod);
case Hie_Lvl_INS:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM ctr_centers,"
"deg_degrees,"
"crs_courses,"
"crs_users,"
"usr_follow"
" WHERE ctr_centers.InsCod=%ld"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Ins.InsCod);
case Hie_Lvl_CTR:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM deg_degrees,"
"crs_courses,"
"crs_users,"
"usr_follow"
" WHERE deg_degrees.CtrCod=%ld"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Ctr.CtrCod);
case Hie_Lvl_DEG:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM crs_courses,"
"crs_users,"
"usr_follow"
" WHERE crs_courses.DegCod=%ld"
" AND crs_courses.CrsCod=crs_users.CrsCod"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Deg.DegCod);
case Hie_Lvl_CRS:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get ranking",
"SELECT usr_follow.FollowedCod," // row[0]
"COUNT(DISTINCT usr_follow.FollowerCod) AS N" // row[1]
" FROM crs_users,"
"usr_follow"
" WHERE crs_users.CrsCod=%ld"
" AND crs_users.UsrCod=usr_follow.FollowedCod"
" GROUP BY usr_follow.FollowedCod"
" ORDER BY N DESC,"
"usr_follow.FollowedCod"
" LIMIT 100",
Gbl.Hierarchy.Crs.CrsCod);
break;
default:
Err_WrongScopeExit ();
return 0; // Not reached
}
}
/*****************************************************************************/
/*********************** Remove user from user follow ************************/
/*****************************************************************************/
void Fol_DB_RemoveUsrFromUsrFollow (long UsrCod)
{
/***** Trivial check: user code should be > 0 *****/
if (UsrCod <= 0)
return;
/***** Remove user from followers and followed *****/
DB_QueryDELETE ("can not remove user from followers and followed",
"DELETE FROM usr_follow"
" WHERE FollowerCod=%ld"
" OR FollowedCod=%ld",
UsrCod,
UsrCod);
}
/*****************************************************************************/
/******* Create/drop temporary tables with me and the users I follow *********/
/*****************************************************************************/
void Fol_DB_CreateTmpTableMeAndUsrsIFollow (void)
{
/***** Create temporary table with me and the users I follow *****/
DB_Query ("can not create temporary table",
"CREATE TEMPORARY TABLE fol_tmp_me_and_followed "
"(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);
}
void Fol_DB_DropTmpTableMeAndUsrsIFollow (void)
{
/***** Drop temporary table with me and the users I follow *****/
DB_Query ("can not remove temporary table",
"DROP TEMPORARY TABLE IF EXISTS fol_tmp_me_and_followed");
}

66
swad_follow_database.h Normal file
View File

@ -0,0 +1,66 @@
// swad_follow_database.h: user's followers and followed operations with database
#ifndef _SWAD_FOL_DB
#define _SWAD_FOL_DB
/*
SWAD (Shared Workspace At a Distance in Spanish),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2021 Antonio Cañas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************** Headers **********************************/
/*****************************************************************************/
#include "swad_follow.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************************** Public types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/****************************** Public prototypes ****************************/
/*****************************************************************************/
unsigned Fol_DB_GetUsrsToFollow (unsigned MaxUsrsToShow,
Fol_WhichUsersSuggestToFollowThem_t WhichUsersSuggestToFollowThem,
MYSQL_RES **mysql_res);
bool Fol_DB_CheckUsrIsFollowerOf (long FollowerCod,long FollowedCod);
unsigned Fol_DB_GetNumFollowing (long UsrCod);
unsigned Fol_DB_GetNumFollowers (long UsrCod);
unsigned Fol_DB_GetListFollowing (long UsrCod,MYSQL_RES **mysql_res);
unsigned Fol_DB_GetListFollowers (long UsrCod,MYSQL_RES **mysql_res);
void Fol_DB_FollowUsr (long UsrCod);
void Fol_DB_UnfollowUsr (long UsrCod);
unsigned Fol_DB_GetRankingFollowers (MYSQL_RES **mysql_res);
void Fol_DB_RemoveUsrFromUsrFollow (long UsrCod);
void Fol_DB_CreateTmpTableMeAndUsrsIFollow (void);
void Fol_DB_DropTmpTableMeAndUsrsIFollow (void);
#endif

View File

@ -35,7 +35,7 @@
#include "swad_database.h"
#include "swad_error.h"
#include "swad_figure.h"
#include "swad_follow.h"
#include "swad_follow_database.h"
#include "swad_form.h"
#include "swad_forum.h"
#include "swad_global.h"
@ -335,12 +335,12 @@ bool Prf_ShowUserProfile (struct UsrData *UsrDat)
Fol_GetNumFollow (UsrDat->UsrCod,&NumFollowing,&NumFollowers);
UsrFollowsMe = false;
if (NumFollowing)
UsrFollowsMe = Fol_CheckUsrIsFollowerOf (UsrDat->UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
UsrFollowsMe = Fol_DB_CheckUsrIsFollowerOf (UsrDat->UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
IFollowUsr = false;
if (NumFollowers)
IFollowUsr = Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat->UsrCod);
IFollowUsr = Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
UsrDat->UsrCod);
/***** Show following and followers *****/
Fol_ShowFollowingAndFollowers (UsrDat,

View File

@ -40,7 +40,7 @@
#include "swad_department.h"
#include "swad_enrolment.h"
#include "swad_error.h"
#include "swad_follow.h"
#include "swad_follow_database.h"
#include "swad_form.h"
#include "swad_global.h"
#include "swad_HTML.h"
@ -2630,8 +2630,8 @@ static void Rec_PutIconsCommands (__attribute__((unused)) void *Args)
/***** Button to follow / unfollow *****/
if (!ItsMe) // Not me
{
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Record.UsrDat->UsrCod))
if (Fol_DB_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Record.UsrDat->UsrCod))
// I follow user
Lay_PutContextualLinkOnlyIcon (ActUnfUsr,NULL,
Rec_PutParamUsrCodEncrypted,NULL,

View File

@ -733,7 +733,7 @@ void Tml_DB_CreateSubQueryPublishers (const struct Tml_Timeline *Timeline,
Gbl.Usrs.Me.UsrDat.UsrCod);
break;
case Usr_WHO_FOLLOWED: // Show the timeline of the users I follow
Fol_CreateTmpTableMeAndUsrsIFollow ();
Fol_DB_CreateTmpTableMeAndUsrsIFollow ();
SubQueries->TablePublishers = ",fol_tmp_me_and_followed";
Str_Copy (SubQueries->Publishers,
"tml_pubs.PublisherCod=fol_tmp_me_and_followed.UsrCod AND ",

View File

@ -193,7 +193,7 @@ void Tml_Pub_GetListPubsToShowInTimeline (struct Tml_Timeline *Timeline)
/* Drop temporary table with me and users I follow */
if (Timeline->UsrOrGbl == Tml_Usr_TIMELINE_GBL && // Show the global timeline
Timeline->Who == Usr_WHO_FOLLOWED) // Show the timeline of the users I follow
Fol_DropTmpTableMeAndUsrsIFollow ();
Fol_DB_DropTmpTableMeAndUsrsIFollow ();
}
/*****************************************************************************/