2015-03-18 01:06:43 +01:00
|
|
|
|
// swad_follow.c: user's followers and followed
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
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.
|
2018-04-24 13:21:53 +02:00
|
|
|
|
Copyright (C) 1999-2018 Antonio Ca<EFBFBD>as Vargas
|
2015-03-18 01:06:43 +01:00
|
|
|
|
|
|
|
|
|
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 *********************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-10-16 02:24:29 +02:00
|
|
|
|
#include <stdbool.h> // For boolean type
|
2015-03-18 01:06:43 +01:00
|
|
|
|
#include <stdio.h> // For sprintf
|
2015-03-24 00:01:40 +01:00
|
|
|
|
#include <string.h> // For string functions
|
2015-03-18 01:06:43 +01:00
|
|
|
|
|
2017-06-10 21:38:10 +02:00
|
|
|
|
#include "swad_box.h"
|
2015-03-18 01:06:43 +01:00
|
|
|
|
#include "swad_database.h"
|
|
|
|
|
#include "swad_follow.h"
|
|
|
|
|
#include "swad_global.h"
|
2015-03-24 00:01:40 +01:00
|
|
|
|
#include "swad_notification.h"
|
2016-12-09 13:59:33 +01:00
|
|
|
|
#include "swad_privacy.h"
|
2015-03-18 02:11:23 +01:00
|
|
|
|
#include "swad_profile.h"
|
2015-03-18 01:06:43 +01:00
|
|
|
|
#include "swad_user.h"
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************************** Public constants *****************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Private constants *****************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-12-12 19:47:10 +01:00
|
|
|
|
#define Fol_NUM_COLUMNS_FOLLOW 3
|
2015-03-19 12:32:45 +01:00
|
|
|
|
|
2017-05-25 13:43:54 +02:00
|
|
|
|
#define Fol_FOLLOW_SECTION_ID "follow_section"
|
|
|
|
|
|
2015-03-18 01:06:43 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************************** Internal types *******************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************** External global variables from others modules ****************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
extern struct Globals Gbl;
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************************* Internal global variables *************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Private prototypes ****************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-16 20:22:13 +01:00
|
|
|
|
static unsigned Fol_GetUsrsWhoToFollow (unsigned MaxUsrsToShow,
|
2017-02-17 02:42:00 +01:00
|
|
|
|
bool OnlyUsrsWithPhotos,
|
2017-02-16 20:22:13 +01:00
|
|
|
|
MYSQL_RES **mysql_res);
|
2017-02-16 17:58:37 +01:00
|
|
|
|
|
2016-11-07 10:45:03 +01:00
|
|
|
|
static void Fol_PutIconsWhoToFollow (void);
|
2016-03-24 13:50:57 +01:00
|
|
|
|
static void Fol_PutIconToUpdateWhoToFollow (void);
|
2016-03-24 13:40:05 +01:00
|
|
|
|
|
2015-03-21 19:55:00 +01:00
|
|
|
|
static void Fol_ShowNumberOfFollowingOrFollowers (const struct UsrData *UsrDat,
|
|
|
|
|
unsigned NumUsrs,
|
|
|
|
|
Act_Action_t Action,
|
|
|
|
|
const char *Title);
|
2016-06-12 19:55:33 +02:00
|
|
|
|
|
|
|
|
|
static void Fol_ListFollowingUsr (struct UsrData *UsrDat);
|
|
|
|
|
static void Fol_ListFollowersUsr (struct UsrData *UsrDat);
|
|
|
|
|
|
2016-12-13 13:32:19 +01:00
|
|
|
|
static void Fol_ShowFollowedOrFollower (struct UsrData *UsrDat);
|
2017-02-16 20:22:13 +01:00
|
|
|
|
static void Fol_WriteRowUsrToFollowOnRightColumn (struct UsrData *UsrDat);
|
|
|
|
|
static void Fol_PutInactiveIconToFollowUnfollow (void);
|
|
|
|
|
static void Fol_PutIconToFollow (struct UsrData *UsrDat);
|
|
|
|
|
static void Fol_PutIconToUnfollow (struct UsrData *UsrDat);
|
2015-03-19 00:28:37 +01:00
|
|
|
|
|
2016-01-27 22:31:36 +01:00
|
|
|
|
/*****************************************************************************/
|
2016-01-27 23:40:16 +01:00
|
|
|
|
/********************** Put link to show users to follow **********************/
|
2016-01-27 22:31:36 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Fol_PutLinkWhoToFollow (void)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Who_to_follow;
|
|
|
|
|
|
2017-04-17 19:03:21 +02:00
|
|
|
|
Lay_PutContextualLink (ActSeeSocPrf,NULL,NULL,
|
2016-01-27 22:31:36 +01:00
|
|
|
|
"follow64x64.png",
|
2016-07-01 16:32:42 +02:00
|
|
|
|
Txt_Who_to_follow,Txt_Who_to_follow,
|
|
|
|
|
NULL);
|
2016-01-27 22:31:36 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2017-02-16 20:22:13 +01:00
|
|
|
|
/****************** Show several users to follow on main zone ****************/
|
2016-01-27 22:31:36 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-16 20:22:13 +01:00
|
|
|
|
#define Fol_MAX_USRS_TO_FOLLOW_MAIN_ZONE (Fol_NUM_COLUMNS_FOLLOW * 3)
|
|
|
|
|
|
|
|
|
|
void Fol_SuggestUsrsToFollowMainZone (void)
|
2016-01-27 22:31:36 +01:00
|
|
|
|
{
|
2017-03-30 15:20:25 +02:00
|
|
|
|
extern const char *Hlp_SOCIAL_Profiles_who_to_follow;
|
2016-01-28 21:31:11 +01:00
|
|
|
|
extern const char *Txt_Who_to_follow;
|
2016-01-27 23:28:53 +01:00
|
|
|
|
extern const char *Txt_No_user_to_whom_you_can_follow_Try_again_later;
|
|
|
|
|
MYSQL_RES *mysql_res;
|
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
unsigned NumUsrs;
|
|
|
|
|
unsigned NumUsr;
|
|
|
|
|
struct UsrData UsrDat;
|
2016-01-27 23:04:27 +01:00
|
|
|
|
|
2017-02-17 01:59:58 +01:00
|
|
|
|
/***** Put links to request my public profile and another user's profile *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"CONTEXT_MENU\">");
|
|
|
|
|
Prf_PutLinkMyPublicProfile ();
|
|
|
|
|
Prf_PutLinkRequestAnotherUserProfile ();
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2016-01-29 00:41:52 +01:00
|
|
|
|
|
2017-02-16 17:58:37 +01:00
|
|
|
|
/***** Get users *****/
|
2017-02-16 20:22:13 +01:00
|
|
|
|
if ((NumUsrs = Fol_GetUsrsWhoToFollow (Fol_MAX_USRS_TO_FOLLOW_MAIN_ZONE,
|
2017-02-17 02:42:00 +01:00
|
|
|
|
false,
|
2017-02-16 20:22:13 +01:00
|
|
|
|
&mysql_res)))
|
2017-02-16 17:58:37 +01:00
|
|
|
|
{
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** Start box and table *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_StartBoxTable ("560px",Txt_Who_to_follow,Fol_PutIconsWhoToFollow,
|
2017-06-12 15:03:29 +02:00
|
|
|
|
Hlp_SOCIAL_Profiles_who_to_follow,Box_NOT_CLOSABLE,2);
|
2017-02-16 17:58:37 +01:00
|
|
|
|
|
|
|
|
|
/***** Initialize structure with user's data *****/
|
|
|
|
|
Usr_UsrDataConstructor (&UsrDat);
|
|
|
|
|
|
|
|
|
|
/***** List users *****/
|
|
|
|
|
for (NumUsr = 0;
|
|
|
|
|
NumUsr < NumUsrs;
|
|
|
|
|
NumUsr++)
|
|
|
|
|
{
|
|
|
|
|
/***** Get user *****/
|
|
|
|
|
row = mysql_fetch_row (mysql_res);
|
|
|
|
|
|
|
|
|
|
/* Get user's code (row[0]) */
|
|
|
|
|
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
|
|
|
|
|
|
|
|
|
|
/***** Show user *****/
|
|
|
|
|
if ((NumUsr % Fol_NUM_COLUMNS_FOLLOW) == 0)
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>");
|
|
|
|
|
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat))
|
|
|
|
|
Fol_ShowFollowedOrFollower (&UsrDat);
|
|
|
|
|
if ((NumUsr % Fol_NUM_COLUMNS_FOLLOW) == (Fol_NUM_COLUMNS_FOLLOW-1) ||
|
|
|
|
|
NumUsr == NumUsrs - 1)
|
|
|
|
|
fprintf (Gbl.F.Out,"</tr>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Free memory used for user's data *****/
|
|
|
|
|
Usr_UsrDataDestructor (&UsrDat);
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End table and box *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_EndBoxTable ();
|
2017-02-16 17:58:37 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_INFO,Txt_No_user_to_whom_you_can_follow_Try_again_later);
|
2017-02-16 17:58:37 +01:00
|
|
|
|
|
|
|
|
|
/***** Free structure that stores the query result *****/
|
|
|
|
|
DB_FreeMySQLResult (&mysql_res);
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-16 20:22:13 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**************** Show several users to follow on right column ***************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#define Fol_MAX_USRS_TO_FOLLOW_RIGHT_COLUMN 3
|
|
|
|
|
|
|
|
|
|
void Fol_SuggestUsrsToFollowMainZoneOnRightColumn (void)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Who_to_follow;
|
|
|
|
|
extern const char *Txt_No_user_to_whom_you_can_follow_Try_again_later;
|
|
|
|
|
MYSQL_RES *mysql_res;
|
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
unsigned NumUsrs;
|
|
|
|
|
unsigned NumUsr;
|
|
|
|
|
struct UsrData UsrDat;
|
|
|
|
|
|
|
|
|
|
/***** Get users *****/
|
|
|
|
|
if ((NumUsrs = Fol_GetUsrsWhoToFollow (Fol_MAX_USRS_TO_FOLLOW_RIGHT_COLUMN,
|
2017-02-17 02:42:00 +01:00
|
|
|
|
true,
|
2017-02-16 20:22:13 +01:00
|
|
|
|
&mysql_res)))
|
|
|
|
|
{
|
|
|
|
|
/***** Start container *****/
|
2017-03-04 20:23:45 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"CONNECTED\">");
|
2017-02-16 20:22:13 +01:00
|
|
|
|
|
|
|
|
|
/***** Title with link to suggest more users to follow *****/
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActSeeSocPrf);
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Act_LinkFormSubmit (Txt_Who_to_follow,"CONNECTED_TXT",NULL);
|
|
|
|
|
fprintf (Gbl.F.Out,"%s</a>",Txt_Who_to_follow);
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2017-02-16 20:22:13 +01:00
|
|
|
|
|
|
|
|
|
/***** Start table *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<table>");
|
|
|
|
|
|
|
|
|
|
/***** Initialize structure with user's data *****/
|
|
|
|
|
Usr_UsrDataConstructor (&UsrDat);
|
|
|
|
|
|
|
|
|
|
/***** List users *****/
|
|
|
|
|
for (NumUsr = 0;
|
|
|
|
|
NumUsr < NumUsrs;
|
|
|
|
|
NumUsr++)
|
|
|
|
|
{
|
|
|
|
|
/***** Get user *****/
|
|
|
|
|
row = mysql_fetch_row (mysql_res);
|
|
|
|
|
|
|
|
|
|
/* Get user's code (row[0]) */
|
|
|
|
|
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
|
|
|
|
|
|
|
|
|
|
/***** Show user *****/
|
|
|
|
|
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat))
|
|
|
|
|
Fol_WriteRowUsrToFollowOnRightColumn (&UsrDat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Free memory used for user's data *****/
|
|
|
|
|
Usr_UsrDataDestructor (&UsrDat);
|
|
|
|
|
|
|
|
|
|
/***** End table *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"</table>");
|
|
|
|
|
|
|
|
|
|
/***** End container *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Free structure that stores the query result *****/
|
|
|
|
|
DB_FreeMySQLResult (&mysql_res);
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-16 17:58:37 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*************************** Get users to follow *****************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-16 20:22:13 +01:00
|
|
|
|
static unsigned Fol_GetUsrsWhoToFollow (unsigned MaxUsrsToShow,
|
2017-02-17 02:42:00 +01:00
|
|
|
|
bool OnlyUsrsWithPhotos,
|
2017-02-16 20:22:13 +01:00
|
|
|
|
MYSQL_RES **mysql_res)
|
2017-02-16 17:58:37 +01:00
|
|
|
|
{
|
|
|
|
|
extern const char *Pri_VisibilityDB[Pri_NUM_OPTIONS_PRIVACY];
|
2017-02-17 02:42:00 +01:00
|
|
|
|
char Query[4096];
|
|
|
|
|
char SubQuery1[256];
|
|
|
|
|
char SubQuery2[256];
|
|
|
|
|
char SubQuery3[256];
|
|
|
|
|
char SubQuery4[256];
|
|
|
|
|
|
|
|
|
|
/***** Build subqueries related to photos *****/
|
|
|
|
|
if (OnlyUsrsWithPhotos)
|
|
|
|
|
{
|
|
|
|
|
// Photo visibility should be >= profile visibility in every subquery
|
|
|
|
|
sprintf (SubQuery1,
|
|
|
|
|
" AND usr_data.PhotoVisibility IN ('%s','%s')"
|
|
|
|
|
" AND usr_data.Photo<>''",
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
|
|
|
|
|
sprintf (SubQuery2,
|
|
|
|
|
" 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,
|
|
|
|
|
" 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,
|
|
|
|
|
" AND usr_data.PhotoVisibility IN ('%s','%s')"
|
|
|
|
|
" AND usr_data.Photo<>''",
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SubQuery1[0] = '\0';
|
|
|
|
|
SubQuery2[0] = '\0';
|
|
|
|
|
SubQuery3[0] = '\0';
|
|
|
|
|
SubQuery4[0] = '\0';
|
|
|
|
|
}
|
2017-02-16 17:58:37 +01:00
|
|
|
|
|
|
|
|
|
/***** Build query to get users to follow *****/
|
2016-06-12 13:20:52 +02:00
|
|
|
|
// Get only users with surname 1 and first name
|
2016-01-28 09:50:39 +01:00
|
|
|
|
sprintf (Query,"SELECT DISTINCT UsrCod FROM"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" ("
|
2016-01-28 09:50:39 +01:00
|
|
|
|
/***** Likely known users *****/
|
2016-01-28 10:39:25 +01:00
|
|
|
|
"(SELECT DISTINCT UsrCod FROM"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" ("
|
|
|
|
|
// Users followed by my followed whose privacy is
|
2016-01-27 23:04:27 +01:00
|
|
|
|
// Pri_VISIBILITY_SYSTEM or Pri_VISIBILITY_WORLD
|
2016-01-28 10:39:25 +01:00
|
|
|
|
"("
|
2016-01-28 09:50:39 +01:00
|
|
|
|
"SELECT DISTINCT usr_follow.FollowedCod AS UsrCod"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" FROM usr_follow,"
|
2016-09-22 01:28:31 +02:00
|
|
|
|
"(SELECT FollowedCod FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld) AS my_followed,"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" usr_data"
|
|
|
|
|
" WHERE usr_follow.FollowerCod=my_followed.FollowedCod"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" AND usr_follow.FollowedCod<>%ld"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" AND usr_follow.FollowedCod=usr_data.UsrCod"
|
|
|
|
|
" AND usr_data.ProfileVisibility IN ('%s','%s')"
|
2016-06-12 13:20:52 +02:00
|
|
|
|
" AND usr_data.Surname1<>''" // Surname 1 not empty
|
|
|
|
|
" AND usr_data.FirstName<>''" // First name not empty
|
2017-02-17 02:42:00 +01:00
|
|
|
|
"%s" // SubQuery1
|
2016-01-28 10:39:25 +01:00
|
|
|
|
")"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" UNION "
|
|
|
|
|
// Users who share any course with me
|
|
|
|
|
// and whose privacy is Pri_VISIBILITY_COURSE,
|
|
|
|
|
// Pri_VISIBILITY_SYSTEM or Pri_VISIBILITY_WORLD
|
2016-01-28 10:39:25 +01:00
|
|
|
|
"("
|
2016-01-28 09:50:39 +01:00
|
|
|
|
"SELECT DISTINCT crs_usr.UsrCod"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" FROM crs_usr,"
|
2016-09-22 01:28:31 +02:00
|
|
|
|
"(SELECT CrsCod FROM crs_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE UsrCod=%ld) AS my_crs,"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" usr_data"
|
|
|
|
|
" WHERE crs_usr.CrsCod=my_crs.CrsCod"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" AND crs_usr.UsrCod<>%ld"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" AND crs_usr.UsrCod=usr_data.UsrCod"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" AND usr_data.ProfileVisibility IN ('%s','%s','%s')"
|
2016-06-12 13:20:52 +02:00
|
|
|
|
" AND usr_data.Surname1<>''" // Surname 1 not empty
|
|
|
|
|
" AND usr_data.FirstName<>''" // First name not empty
|
2017-02-17 02:42:00 +01:00
|
|
|
|
"%s" // SubQuery2
|
2016-01-28 10:39:25 +01:00
|
|
|
|
")"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" UNION "
|
|
|
|
|
// Users who share any course with me with another role
|
|
|
|
|
// and whose privacy is Pri_VISIBILITY_USER
|
2016-01-28 10:39:25 +01:00
|
|
|
|
"("
|
2016-01-28 09:50:39 +01:00
|
|
|
|
"SELECT DISTINCT crs_usr.UsrCod"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" FROM crs_usr,"
|
2016-09-22 01:28:31 +02:00
|
|
|
|
"(SELECT CrsCod,Role FROM crs_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE UsrCod=%ld) AS my_crs_role,"
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" usr_data"
|
|
|
|
|
" WHERE crs_usr.CrsCod=my_crs_role.CrsCod"
|
|
|
|
|
" AND crs_usr.Role<>my_crs_role.Role"
|
|
|
|
|
" AND crs_usr.UsrCod=usr_data.UsrCod"
|
|
|
|
|
" AND usr_data.ProfileVisibility='%s'"
|
2016-06-12 13:20:52 +02:00
|
|
|
|
" AND usr_data.Surname1<>''" // Surname 1 not empty
|
|
|
|
|
" AND usr_data.FirstName<>''" // First name not empty
|
2017-02-17 02:42:00 +01:00
|
|
|
|
"%s" // SubQuery3
|
2016-01-28 10:39:25 +01:00
|
|
|
|
")"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
") AS LikelyKnownUsrsToFollow"
|
|
|
|
|
// Do not select my followed
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" WHERE UsrCod NOT IN"
|
|
|
|
|
" (SELECT FollowedCod FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld)"
|
2017-02-16 20:22:13 +01:00
|
|
|
|
// Get only MaxUsrsToShow * 2 users
|
2016-01-28 10:39:25 +01:00
|
|
|
|
" ORDER BY RAND() LIMIT %u"
|
|
|
|
|
")"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" UNION "
|
2016-01-28 10:39:25 +01:00
|
|
|
|
"("
|
2016-01-28 09:50:39 +01:00
|
|
|
|
/***** Likely unknown users *****/
|
|
|
|
|
// Add some likely unknown random users with privacy
|
|
|
|
|
// Pri_VISIBILITY_SYSTEM or Pri_VISIBILITY_WORLD
|
|
|
|
|
"SELECT UsrCod FROM usr_data"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE UsrCod<>%ld"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" AND ProfileVisibility IN ('%s','%s')"
|
2017-02-17 02:42:00 +01:00
|
|
|
|
" AND Surname1<>''" // Surname 1 not empty
|
|
|
|
|
" AND FirstName<>''" // First name not empty
|
|
|
|
|
"%s" // SubQuery4
|
2016-01-28 09:50:39 +01:00
|
|
|
|
// Do not select my followed
|
|
|
|
|
" AND UsrCod NOT IN"
|
|
|
|
|
" (SELECT FollowedCod FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld)"
|
2017-02-16 20:22:13 +01:00
|
|
|
|
// Get only MaxUsrsToShow users
|
2016-01-28 09:50:39 +01:00
|
|
|
|
" ORDER BY RAND() LIMIT %u"
|
2016-01-28 10:39:25 +01:00
|
|
|
|
")"
|
2016-01-28 09:50:39 +01:00
|
|
|
|
") AS UsrsToFollow"
|
2017-02-16 20:22:13 +01:00
|
|
|
|
// Get only MaxUsrsToShow users
|
2016-01-27 23:04:27 +01:00
|
|
|
|
" ORDER BY RAND() LIMIT %u",
|
2017-02-16 20:22:13 +01:00
|
|
|
|
|
2016-01-27 23:04:27 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
|
2016-01-28 09:50:39 +01:00
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ],
|
2017-02-17 02:42:00 +01:00
|
|
|
|
SubQuery1,
|
2016-01-27 23:04:27 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_COURSE],
|
2016-01-28 09:50:39 +01:00
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ],
|
2017-02-17 02:42:00 +01:00
|
|
|
|
SubQuery2,
|
2016-01-28 09:50:39 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_USER ],
|
2017-02-17 02:42:00 +01:00
|
|
|
|
SubQuery3,
|
2016-01-28 09:50:39 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
2017-02-16 20:22:13 +01:00
|
|
|
|
MaxUsrsToShow * 2, // 2/3 likely known users
|
2016-01-28 09:50:39 +01:00
|
|
|
|
|
2016-01-27 23:04:27 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
2016-01-28 09:50:39 +01:00
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM],
|
|
|
|
|
Pri_VisibilityDB[Pri_VISIBILITY_WORLD ],
|
2017-02-17 02:42:00 +01:00
|
|
|
|
SubQuery4,
|
2016-01-27 23:04:27 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
2017-02-16 20:22:13 +01:00
|
|
|
|
MaxUsrsToShow, // 1/3 likely unknown users
|
2016-01-28 10:39:25 +01:00
|
|
|
|
|
2017-02-16 20:22:13 +01:00
|
|
|
|
MaxUsrsToShow);
|
2016-01-27 23:28:53 +01:00
|
|
|
|
|
2017-02-16 17:58:37 +01:00
|
|
|
|
return DB_QuerySELECT (Query,mysql_res,"can not get users to follow");
|
2016-01-27 22:31:36 +01:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-07 10:45:03 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************** Put contextual icons in "who to follow" ******************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void Fol_PutIconsWhoToFollow (void)
|
|
|
|
|
{
|
|
|
|
|
/***** Put icon to update who to follow *****/
|
|
|
|
|
Fol_PutIconToUpdateWhoToFollow ();
|
|
|
|
|
|
|
|
|
|
/***** Put icon to show a figure *****/
|
|
|
|
|
Gbl.Stat.FigureType = Sta_FOLLOW;
|
|
|
|
|
Sta_PutIconToShowFigure ();
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 13:40:05 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************* Put icon to update who to follow **********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-03-24 13:50:57 +01:00
|
|
|
|
static void Fol_PutIconToUpdateWhoToFollow (void)
|
2016-03-24 13:40:05 +01:00
|
|
|
|
{
|
|
|
|
|
extern const char *The_ClassFormBold[The_NUM_THEMES];
|
|
|
|
|
extern const char *Txt_Update;
|
|
|
|
|
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActSeeSocPrf);
|
2016-07-01 17:13:41 +02:00
|
|
|
|
Act_LinkFormSubmitAnimated (Txt_Update,The_ClassFormBold[Gbl.Prefs.Theme],
|
|
|
|
|
NULL);
|
2017-06-11 19:13:28 +02:00
|
|
|
|
Ico_PutCalculateIcon (Txt_Update);
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2016-03-24 13:40:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-18 01:06:43 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*************** Check if a user is a follower of another user ***************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
bool Fol_CheckUsrIsFollowerOf (long FollowerCod,long FollowedCod)
|
|
|
|
|
{
|
|
|
|
|
char Query[256];
|
|
|
|
|
|
|
|
|
|
if (FollowerCod == FollowedCod)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/***** Check if a user is a follower of another user *****/
|
|
|
|
|
sprintf (Query,"SELECT COUNT(*) FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld AND FollowedCod=%ld",
|
2015-03-18 01:06:43 +01:00
|
|
|
|
FollowerCod,FollowedCod);
|
|
|
|
|
return (DB_QueryCOUNT (Query,"can not get if a user is a follower of another one") != 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-29 14:24:37 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*************************** Get number of followed **************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
unsigned Fol_GetNumFollowing (long UsrCod)
|
|
|
|
|
{
|
|
|
|
|
char Query[128];
|
|
|
|
|
|
|
|
|
|
/***** Check if a user is a follower of another user *****/
|
2017-03-24 01:09:27 +01:00
|
|
|
|
sprintf (Query,"SELECT COUNT(*) FROM usr_follow WHERE FollowerCod=%ld",
|
2015-12-29 14:24:37 +01:00
|
|
|
|
UsrCod);
|
|
|
|
|
return DB_QueryCOUNT (Query,"can not get number of followed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************************** Get number of followers **************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
unsigned Fol_GetNumFollowers (long UsrCod)
|
|
|
|
|
{
|
|
|
|
|
char Query[128];
|
|
|
|
|
|
|
|
|
|
/***** Check if a user is a follower of another user *****/
|
2017-03-24 01:09:27 +01:00
|
|
|
|
sprintf (Query,"SELECT COUNT(*) FROM usr_follow WHERE FollowedCod=%ld",
|
2015-12-29 14:24:37 +01:00
|
|
|
|
UsrCod);
|
|
|
|
|
return DB_QueryCOUNT (Query,"can not get number of followers");
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-19 00:28:37 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**************** Show following and followers of a user *********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-12-29 14:24:37 +01:00
|
|
|
|
void Fol_ShowFollowingAndFollowers (const struct UsrData *UsrDat,
|
2015-12-29 19:40:38 +01:00
|
|
|
|
unsigned NumFollowing,unsigned NumFollowers,
|
|
|
|
|
bool UsrFollowsMe,bool IFollowUsr)
|
2015-03-19 00:28:37 +01:00
|
|
|
|
{
|
2015-12-29 20:39:06 +01:00
|
|
|
|
extern const char *Txt_FOLLOWS_YOU;
|
2015-03-19 00:28:37 +01:00
|
|
|
|
extern const char *Txt_Following;
|
|
|
|
|
extern const char *Txt_Followers;
|
2015-12-29 19:40:38 +01:00
|
|
|
|
extern const char *Txt_Following_unfollow;
|
|
|
|
|
extern const char *Txt_Unfollow;
|
|
|
|
|
extern const char *Txt_Follow;
|
2018-10-10 23:56:42 +02:00
|
|
|
|
bool ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
2015-03-19 00:28:37 +01:00
|
|
|
|
|
2015-12-12 19:47:10 +01:00
|
|
|
|
/***** Start section *****/
|
2017-05-25 13:43:54 +02:00
|
|
|
|
Lay_StartSection (Fol_FOLLOW_SECTION_ID);
|
2015-03-19 00:28:37 +01:00
|
|
|
|
|
2015-03-19 12:32:45 +01:00
|
|
|
|
/***** Followed users *****/
|
2015-12-29 19:40:38 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div id=\"following_side\">"
|
|
|
|
|
"<div class=\"FOLLOW_SIDE\">");
|
|
|
|
|
|
|
|
|
|
/* User follows me? */
|
|
|
|
|
fprintf (Gbl.F.Out,"<div id=\"follows_me\" class=\"DAT_LIGHT\">");
|
|
|
|
|
if (UsrFollowsMe)
|
2015-12-29 20:39:06 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"%s",Txt_FOLLOWS_YOU);
|
2015-12-29 19:40:38 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
|
|
|
|
|
|
|
|
|
/* Number of followed */
|
2015-03-21 19:55:00 +01:00
|
|
|
|
Fol_ShowNumberOfFollowingOrFollowers (UsrDat,
|
2015-12-29 14:24:37 +01:00
|
|
|
|
NumFollowing,
|
2015-03-21 19:55:00 +01:00
|
|
|
|
ActSeeFlg,Txt_Following);
|
2015-12-29 19:40:38 +01:00
|
|
|
|
|
|
|
|
|
/* End following side */
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>"
|
|
|
|
|
"</div>");
|
2015-03-21 19:55:00 +01:00
|
|
|
|
|
|
|
|
|
/***** Followers *****/
|
2015-12-29 19:40:38 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div id=\"followers_side\">"
|
|
|
|
|
"<div class=\"FOLLOW_SIDE\">");
|
|
|
|
|
|
|
|
|
|
/* Number of followers */
|
2015-03-21 19:55:00 +01:00
|
|
|
|
Fol_ShowNumberOfFollowingOrFollowers (UsrDat,
|
2015-12-29 14:24:37 +01:00
|
|
|
|
NumFollowers,
|
2015-03-21 19:55:00 +01:00
|
|
|
|
ActSeeFlr,Txt_Followers);
|
2015-12-29 19:40:38 +01:00
|
|
|
|
|
|
|
|
|
/* I follow user? */
|
|
|
|
|
fprintf (Gbl.F.Out,"<div id=\"follow_usr\">");
|
2018-10-10 23:56:42 +02:00
|
|
|
|
if (!ItsMe) // Not me
|
2015-12-29 19:40:38 +01:00
|
|
|
|
{
|
2015-12-30 09:56:06 +01:00
|
|
|
|
if (IFollowUsr) // I follow this user
|
2015-12-29 19:40:38 +01:00
|
|
|
|
{
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActUnfUsr);
|
2015-12-29 19:40:38 +01:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
2016-07-01 17:13:41 +02:00
|
|
|
|
Act_LinkFormSubmit (Txt_Following_unfollow,"REC_DAT_BOLD",NULL);
|
2016-11-14 10:05:41 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"ICO_HIGHLIGHT\""
|
2015-12-29 19:40:38 +01:00
|
|
|
|
" style=\"display:inline;\" >"
|
|
|
|
|
"<img src=\"%s/following64x64.png\""
|
|
|
|
|
" alt=\"%s\" title=\"%s\""
|
2016-11-14 10:05:41 +01:00
|
|
|
|
" class=\"ICO40x40\" />"
|
2015-12-29 19:40:38 +01:00
|
|
|
|
"</div>"
|
|
|
|
|
"</a>",
|
|
|
|
|
Gbl.Prefs.IconsURL,
|
|
|
|
|
Txt_Unfollow,Txt_Following_unfollow);
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2015-12-29 19:40:38 +01:00
|
|
|
|
}
|
2015-12-30 09:56:06 +01:00
|
|
|
|
else // I do not follow this user
|
2015-12-29 19:40:38 +01:00
|
|
|
|
{
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActFolUsr);
|
2015-12-29 19:40:38 +01:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
2016-07-01 17:13:41 +02:00
|
|
|
|
Act_LinkFormSubmit (Txt_Follow,"REC_DAT_BOLD",NULL);
|
2016-11-14 10:05:41 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"ICO_HIGHLIGHT\""
|
2015-12-29 19:40:38 +01:00
|
|
|
|
" style=\"display:inline;\" >"
|
|
|
|
|
"<img src=\"%s/follow64x64.png\""
|
|
|
|
|
" alt=\"%s\" title=\"%s\""
|
2016-11-14 10:05:41 +01:00
|
|
|
|
" class=\"ICO40x40\" />"
|
2015-12-29 19:40:38 +01:00
|
|
|
|
"</div>"
|
|
|
|
|
"</a>",
|
|
|
|
|
Gbl.Prefs.IconsURL,
|
|
|
|
|
Txt_Follow,Txt_Follow);
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2015-12-29 19:40:38 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-12-12 19:47:10 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2015-03-21 19:55:00 +01:00
|
|
|
|
|
2015-12-29 19:40:38 +01:00
|
|
|
|
/* End followers side */
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>"
|
|
|
|
|
"</div>");
|
|
|
|
|
|
2015-12-12 19:47:10 +01:00
|
|
|
|
/***** End section *****/
|
2017-05-25 13:43:54 +02:00
|
|
|
|
Lay_EndSection ();
|
2015-03-21 19:55:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**************** Show following and followers of a user *********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void Fol_ShowNumberOfFollowingOrFollowers (const struct UsrData *UsrDat,
|
|
|
|
|
unsigned NumUsrs,
|
|
|
|
|
Act_Action_t Action,
|
|
|
|
|
const char *Title)
|
|
|
|
|
{
|
2015-07-27 21:25:45 +02:00
|
|
|
|
extern const char *The_ClassForm[The_NUM_THEMES];
|
|
|
|
|
extern const char *The_ClassFormBold[The_NUM_THEMES];
|
2015-03-21 19:55:00 +01:00
|
|
|
|
|
2015-12-12 19:47:10 +01:00
|
|
|
|
/***** Start container *****/
|
2015-12-29 19:40:38 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"FOLLOW_BOX\">");
|
2015-03-21 19:55:00 +01:00
|
|
|
|
|
2015-12-12 19:47:10 +01:00
|
|
|
|
/***** Number *****/
|
2015-03-21 19:55:00 +01:00
|
|
|
|
if (NumUsrs)
|
2015-03-19 12:32:45 +01:00
|
|
|
|
{
|
2015-12-12 02:01:20 +01:00
|
|
|
|
/* Form to list users */
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartFormAnchor (Action,Fol_FOLLOW_SECTION_ID);
|
2015-04-02 18:39:49 +02:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
2015-03-21 19:55:00 +01:00
|
|
|
|
Act_LinkFormSubmit (Title,
|
2016-01-17 15:10:54 +01:00
|
|
|
|
(Gbl.Action.Act == Action) ? "FOLLOW_NUM_B" :
|
2016-07-01 17:13:41 +02:00
|
|
|
|
"FOLLOW_NUM",NULL);
|
2015-03-19 12:32:45 +01:00
|
|
|
|
}
|
2015-12-14 01:25:20 +01:00
|
|
|
|
else
|
|
|
|
|
fprintf (Gbl.F.Out,"<span class=\"%s\">",
|
2016-01-17 15:10:54 +01:00
|
|
|
|
(Gbl.Action.Act == Action) ? "FOLLOW_NUM_B" :
|
2015-12-14 01:25:20 +01:00
|
|
|
|
"FOLLOW_NUM");
|
2015-03-21 19:55:00 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"%u",NumUsrs);
|
|
|
|
|
if (NumUsrs)
|
2015-03-19 12:32:45 +01:00
|
|
|
|
{
|
|
|
|
|
fprintf (Gbl.F.Out,"</a>");
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2015-03-19 12:32:45 +01:00
|
|
|
|
}
|
2015-12-14 01:25:20 +01:00
|
|
|
|
else
|
|
|
|
|
fprintf (Gbl.F.Out,"</span>");
|
2015-03-19 00:28:37 +01:00
|
|
|
|
|
2015-12-12 19:47:10 +01:00
|
|
|
|
/***** Text *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"%s\">",
|
2016-01-17 15:10:54 +01:00
|
|
|
|
(Gbl.Action.Act == Action) ? The_ClassFormBold[Gbl.Prefs.Theme] :
|
2015-07-27 21:25:45 +02:00
|
|
|
|
The_ClassForm[Gbl.Prefs.Theme]);
|
2015-03-21 19:55:00 +01:00
|
|
|
|
if (NumUsrs)
|
2015-03-19 12:32:45 +01:00
|
|
|
|
{
|
2015-12-12 02:01:20 +01:00
|
|
|
|
/* Form to list users */
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartFormAnchor (Action,Fol_FOLLOW_SECTION_ID);
|
2015-04-02 18:39:49 +02:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
2015-03-21 19:55:00 +01:00
|
|
|
|
Act_LinkFormSubmit (Title,
|
2016-01-17 15:10:54 +01:00
|
|
|
|
(Gbl.Action.Act == Action) ? The_ClassFormBold[Gbl.Prefs.Theme] :
|
2016-07-01 17:13:41 +02:00
|
|
|
|
The_ClassForm[Gbl.Prefs.Theme],NULL);
|
2015-03-19 12:32:45 +01:00
|
|
|
|
}
|
2015-03-21 19:55:00 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"%s",Title);
|
|
|
|
|
if (NumUsrs)
|
2015-03-19 12:32:45 +01:00
|
|
|
|
{
|
|
|
|
|
fprintf (Gbl.F.Out,"</a>");
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2015-03-19 12:32:45 +01:00
|
|
|
|
}
|
2015-12-12 19:47:10 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
|
|
|
|
|
|
|
|
|
/***** End container *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2015-03-19 00:28:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-19 01:59:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** List followed users ***************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Fol_ListFollowing (void)
|
2016-06-12 19:55:33 +02:00
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
|
|
|
|
|
|
|
|
|
/***** Get user to view user he/she follows *****/
|
|
|
|
|
Usr_GetParamOtherUsrCodEncryptedAndGetListIDs ();
|
|
|
|
|
|
|
|
|
|
if (Gbl.Usrs.Other.UsrDat.UsrCod > 0)
|
|
|
|
|
{
|
|
|
|
|
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat))
|
|
|
|
|
Fol_ListFollowingUsr (&Gbl.Usrs.Other.UsrDat);
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
|
2016-06-12 19:55:33 +02:00
|
|
|
|
}
|
|
|
|
|
else // If user not specified, view my profile
|
|
|
|
|
Fol_ListFollowingUsr (&Gbl.Usrs.Me.UsrDat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void Fol_ListFollowingUsr (struct UsrData *UsrDat)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-01-28 21:38:24 +01:00
|
|
|
|
extern const char *Txt_Following;
|
2015-03-19 01:59:08 +01:00
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
|
|
|
|
char Query[256];
|
|
|
|
|
MYSQL_RES *mysql_res;
|
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
unsigned NumUsrs;
|
|
|
|
|
unsigned NumUsr;
|
2016-06-12 19:55:33 +02:00
|
|
|
|
struct UsrData FollowingUsrDat;
|
2015-03-19 01:59:08 +01:00
|
|
|
|
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Show user's profile *****/
|
|
|
|
|
if (Prf_ShowUserProfile (UsrDat))
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Check if a user is a follower of another user *****/
|
|
|
|
|
sprintf (Query,"SELECT FollowedCod FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld ORDER BY FollowTime DESC",
|
2016-06-12 19:55:33 +02:00
|
|
|
|
UsrDat->UsrCod);
|
|
|
|
|
NumUsrs = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get followed users");
|
|
|
|
|
if (NumUsrs)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Initialize structure with user's data *****/
|
|
|
|
|
Usr_UsrDataConstructor (&FollowingUsrDat);
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** Start box and table *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_StartBoxTable ("560px",Txt_Following,NULL,
|
2017-06-12 15:03:29 +02:00
|
|
|
|
NULL,Box_NOT_CLOSABLE,2);
|
2016-06-12 19:55:33 +02:00
|
|
|
|
|
|
|
|
|
for (NumUsr = 0;
|
|
|
|
|
NumUsr < NumUsrs;
|
|
|
|
|
NumUsr++)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Get user *****/
|
|
|
|
|
row = mysql_fetch_row (mysql_res);
|
|
|
|
|
|
|
|
|
|
/* Get user's code (row[0]) */
|
|
|
|
|
FollowingUsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
|
|
|
|
|
|
|
|
|
|
/***** Show user *****/
|
|
|
|
|
if ((NumUsr % Fol_NUM_COLUMNS_FOLLOW) == 0)
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>");
|
|
|
|
|
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&FollowingUsrDat))
|
|
|
|
|
Fol_ShowFollowedOrFollower (&FollowingUsrDat);
|
|
|
|
|
if ((NumUsr % Fol_NUM_COLUMNS_FOLLOW) == (Fol_NUM_COLUMNS_FOLLOW-1) ||
|
|
|
|
|
NumUsr == NumUsrs - 1)
|
|
|
|
|
fprintf (Gbl.F.Out,"</tr>");
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End table and box *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_EndBoxTable ();
|
2016-06-12 19:55:33 +02:00
|
|
|
|
|
|
|
|
|
/***** Free memory used for user's data *****/
|
|
|
|
|
Usr_UsrDataDestructor (&FollowingUsrDat);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
2016-06-12 19:55:33 +02:00
|
|
|
|
|
|
|
|
|
/***** Free structure that stores the query result *****/
|
|
|
|
|
DB_FreeMySQLResult (&mysql_res);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************************* List followers ******************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Fol_ListFollowers (void)
|
2016-06-12 19:55:33 +02:00
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
|
|
|
|
|
|
|
|
|
/***** Get user to view user he/she follows *****/
|
|
|
|
|
Usr_GetParamOtherUsrCodEncryptedAndGetListIDs ();
|
|
|
|
|
|
|
|
|
|
if (Gbl.Usrs.Other.UsrDat.UsrCod > 0)
|
|
|
|
|
{
|
|
|
|
|
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat))
|
|
|
|
|
Fol_ListFollowersUsr (&Gbl.Usrs.Other.UsrDat);
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
|
2016-06-12 19:55:33 +02:00
|
|
|
|
}
|
|
|
|
|
else // If user not specified, view my profile
|
|
|
|
|
Fol_ListFollowersUsr (&Gbl.Usrs.Me.UsrDat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void Fol_ListFollowersUsr (struct UsrData *UsrDat)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-01-28 21:38:24 +01:00
|
|
|
|
extern const char *Txt_Followers;
|
2015-03-19 01:59:08 +01:00
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
|
|
|
|
char Query[256];
|
|
|
|
|
MYSQL_RES *mysql_res;
|
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
unsigned NumUsrs;
|
|
|
|
|
unsigned NumUsr;
|
2016-06-12 19:55:33 +02:00
|
|
|
|
struct UsrData FollowerUsrDat;
|
2018-10-10 23:56:42 +02:00
|
|
|
|
bool ItsMe;
|
2015-03-19 01:59:08 +01:00
|
|
|
|
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Show user's profile *****/
|
|
|
|
|
if (Prf_ShowUserProfile (UsrDat))
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Check if a user is a follower of another user *****/
|
|
|
|
|
sprintf (Query,"SELECT FollowerCod FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowedCod=%ld ORDER BY FollowTime DESC",
|
2016-06-12 19:55:33 +02:00
|
|
|
|
UsrDat->UsrCod);
|
|
|
|
|
NumUsrs = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get followers");
|
|
|
|
|
if (NumUsrs)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Initialize structure with user's data *****/
|
|
|
|
|
Usr_UsrDataConstructor (&FollowerUsrDat);
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** Start box and table *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_StartBoxTable ("560px",Txt_Followers,NULL,
|
2017-06-12 15:03:29 +02:00
|
|
|
|
NULL,Box_NOT_CLOSABLE,2);
|
2016-06-12 19:55:33 +02:00
|
|
|
|
|
|
|
|
|
for (NumUsr = 0;
|
|
|
|
|
NumUsr < NumUsrs;
|
|
|
|
|
NumUsr++)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Get user and number of clicks *****/
|
|
|
|
|
row = mysql_fetch_row (mysql_res);
|
|
|
|
|
|
|
|
|
|
/* Get user's code (row[0]) */
|
|
|
|
|
FollowerUsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
|
|
|
|
|
|
|
|
|
|
/***** Show user *****/
|
|
|
|
|
if ((NumUsr % Fol_NUM_COLUMNS_FOLLOW) == 0)
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>");
|
|
|
|
|
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&FollowerUsrDat))
|
|
|
|
|
Fol_ShowFollowedOrFollower (&FollowerUsrDat);
|
|
|
|
|
if ((NumUsr % Fol_NUM_COLUMNS_FOLLOW) == (Fol_NUM_COLUMNS_FOLLOW-1) ||
|
|
|
|
|
NumUsr == NumUsrs - 1)
|
|
|
|
|
fprintf (Gbl.F.Out,"</tr>");
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End table and box *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_EndBoxTable ();
|
2015-03-24 00:01:40 +01:00
|
|
|
|
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Free memory used for user's data *****/
|
|
|
|
|
Usr_UsrDataDestructor (&FollowerUsrDat);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
2016-06-12 19:55:33 +02:00
|
|
|
|
|
|
|
|
|
/***** Free structure that stores the query result *****/
|
|
|
|
|
DB_FreeMySQLResult (&mysql_res);
|
|
|
|
|
|
|
|
|
|
/***** If it's me, mark possible notification as seen *****/
|
2018-10-10 23:56:42 +02:00
|
|
|
|
ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
|
|
|
|
if (ItsMe)
|
2016-06-12 19:55:33 +02:00
|
|
|
|
Ntf_MarkNotifAsSeen (Ntf_EVENT_FOLLOWER,
|
|
|
|
|
-1L,-1L,
|
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2015-12-12 02:01:20 +01:00
|
|
|
|
/************************* Show followed or follower *************************/
|
2015-03-19 01:59:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-12-13 13:32:19 +01:00
|
|
|
|
static void Fol_ShowFollowedOrFollower (struct UsrData *UsrDat)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2017-02-17 01:59:58 +01:00
|
|
|
|
extern const char *Txt_Another_user_s_profile;
|
2015-03-19 01:59:08 +01:00
|
|
|
|
bool ShowPhoto;
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char PhotoURL[PATH_MAX + 1];
|
|
|
|
|
bool Visible = Pri_ShowingIsAllowed (UsrDat->ProfileVisibility,UsrDat);
|
2018-10-10 23:56:42 +02:00
|
|
|
|
bool ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Show user's photo *****/
|
2017-03-05 14:46:56 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"FOLLOW_PHOTO\">");
|
2015-03-19 01:59:08 +01:00
|
|
|
|
if (Visible)
|
|
|
|
|
{
|
2017-01-28 15:58:46 +01:00
|
|
|
|
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (UsrDat,PhotoURL);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
Pho_ShowUsrPhoto (UsrDat,ShowPhoto ? PhotoURL :
|
|
|
|
|
NULL,
|
2016-01-28 10:39:25 +01:00
|
|
|
|
"PHOTO60x80",Pho_ZOOM,false);
|
2015-03-19 01:59:08 +01:00
|
|
|
|
}
|
2016-06-12 19:55:33 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"</td>");
|
2015-03-19 01:59:08 +01:00
|
|
|
|
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/***** Show user's name and icon to follow/unfollow *****/
|
2017-03-05 14:46:56 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"FOLLOW_USR\">");
|
2016-01-29 10:58:16 +01:00
|
|
|
|
if (Visible)
|
2015-03-19 01:59:08 +01:00
|
|
|
|
{
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/* Put form to go to public profile */
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActSeeOthPubPrf);
|
2015-04-02 18:39:49 +02:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
2017-03-05 15:12:48 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"FOLLOW_USR_NAME\">"); // Limited width
|
2017-02-17 01:59:58 +01:00
|
|
|
|
Act_LinkFormSubmit (Txt_Another_user_s_profile,"DAT",NULL);
|
2017-03-05 15:12:48 +01:00
|
|
|
|
Usr_WriteFirstNameBRSurnames (UsrDat);
|
2017-03-05 14:46:56 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</a>"
|
|
|
|
|
"</div>");
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2016-06-12 19:55:33 +02:00
|
|
|
|
}
|
2016-01-29 00:41:52 +01:00
|
|
|
|
|
2018-10-10 23:56:42 +02:00
|
|
|
|
ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
2018-10-10 14:03:06 +02:00
|
|
|
|
if (!Gbl.Usrs.Me.Logged || // Not logged
|
|
|
|
|
ItsMe) // It's me
|
2016-06-12 19:55:33 +02:00
|
|
|
|
/* Inactive icon to follow/unfollow */
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Fol_PutInactiveIconToFollowUnfollow ();
|
2018-10-10 14:03:06 +02:00
|
|
|
|
else // It's not me
|
2016-06-12 19:55:33 +02:00
|
|
|
|
{
|
|
|
|
|
/* Put form to follow / unfollow */
|
|
|
|
|
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,UsrDat->UsrCod)) // I follow user
|
|
|
|
|
/* Form to unfollow */
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Fol_PutIconToUnfollow (UsrDat);
|
2016-06-12 19:55:33 +02:00
|
|
|
|
else if (Visible) // I do not follow this user and I can follow
|
|
|
|
|
/* Form to follow */
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Fol_PutIconToFollow (UsrDat);
|
2016-01-29 00:41:52 +01:00
|
|
|
|
}
|
2015-03-19 01:59:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</td>");
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-16 20:22:13 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************* Write the name of a connected user ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void Fol_WriteRowUsrToFollowOnRightColumn (struct UsrData *UsrDat)
|
|
|
|
|
{
|
2017-02-17 01:59:58 +01:00
|
|
|
|
extern const char *Txt_Another_user_s_profile;
|
2017-02-16 20:22:13 +01:00
|
|
|
|
bool ShowPhoto;
|
|
|
|
|
char PhotoURL[PATH_MAX + 1];
|
|
|
|
|
bool Visible = Pri_ShowingIsAllowed (UsrDat->ProfileVisibility,UsrDat);
|
2018-10-10 23:56:42 +02:00
|
|
|
|
bool ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
2017-02-16 20:22:13 +01:00
|
|
|
|
|
|
|
|
|
/***** Show user's photo *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>"
|
|
|
|
|
"<td class=\"LEFT_MIDDLE COLOR%u\""
|
|
|
|
|
" style=\"width:22px;\">",
|
|
|
|
|
Gbl.RowEvenOdd);
|
|
|
|
|
if (Visible)
|
|
|
|
|
{
|
|
|
|
|
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (UsrDat,PhotoURL);
|
|
|
|
|
Pho_ShowUsrPhoto (UsrDat,ShowPhoto ? PhotoURL :
|
|
|
|
|
NULL,
|
|
|
|
|
"PHOTO21x28",Pho_ZOOM,false);
|
|
|
|
|
}
|
|
|
|
|
fprintf (Gbl.F.Out,"</td>");
|
|
|
|
|
|
|
|
|
|
/***** User's name *****/
|
2017-03-09 21:11:06 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"CON_USR_NARROW CON_CRS COLOR%u\">",
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Gbl.RowEvenOdd);
|
|
|
|
|
if (Visible)
|
|
|
|
|
{
|
|
|
|
|
/* Put form to go to public profile */
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActSeeOthPubPrf);
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
2017-03-09 21:11:06 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"CON_NAME_NARROW\">"); // Limited width
|
2017-02-17 01:59:58 +01:00
|
|
|
|
Act_LinkFormSubmit (Txt_Another_user_s_profile,"CON_CRS",NULL);
|
2017-03-05 15:12:48 +01:00
|
|
|
|
Usr_WriteFirstNameBRSurnames (UsrDat);
|
2017-03-05 14:46:56 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</a>"
|
|
|
|
|
"</div>");
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2017-02-16 20:22:13 +01:00
|
|
|
|
}
|
|
|
|
|
fprintf (Gbl.F.Out,"</td>");
|
|
|
|
|
|
|
|
|
|
/***** Icon to follow *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"RIGHT_MIDDLE COLOR%u\""
|
|
|
|
|
" style=\"width:48px;\">",
|
|
|
|
|
Gbl.RowEvenOdd);
|
2018-10-10 14:03:06 +02:00
|
|
|
|
if (!Gbl.Usrs.Me.Logged || // Not logged
|
|
|
|
|
ItsMe) // It's me
|
2017-02-16 20:22:13 +01:00
|
|
|
|
/* Inactive icon to follow/unfollow */
|
|
|
|
|
Fol_PutInactiveIconToFollowUnfollow ();
|
2018-10-10 14:03:06 +02:00
|
|
|
|
else // It's not me
|
2017-02-16 20:22:13 +01:00
|
|
|
|
{
|
|
|
|
|
/* Put form to follow / unfollow */
|
|
|
|
|
if (Fol_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
|
|
|
|
|
/* Form to follow */
|
|
|
|
|
Fol_PutIconToFollow (UsrDat);
|
|
|
|
|
}
|
|
|
|
|
fprintf (Gbl.F.Out,"</td>"
|
|
|
|
|
"</tr>");
|
|
|
|
|
|
|
|
|
|
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********************** Put icon to unfollow another user *********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void Fol_PutInactiveIconToFollowUnfollow (void)
|
|
|
|
|
{
|
|
|
|
|
/***** Inactive icon to follow/unfollow *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"FOLLOW_USR_ICO ICO_HIDDEN\">"
|
2017-09-17 23:37:03 +02:00
|
|
|
|
"<img src=\"%s/usr64x64.png\""
|
2017-02-16 20:22:13 +01:00
|
|
|
|
" alt=\"\""
|
|
|
|
|
" class=\"ICO20x20\" />"
|
|
|
|
|
"</div>",
|
|
|
|
|
Gbl.Prefs.IconsURL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********************** Put icon to unfollow another user *********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void Fol_PutIconToFollow (struct UsrData *UsrDat)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Follow;
|
|
|
|
|
|
|
|
|
|
/***** Form to unfollow *****/
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActFolUsr);
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
|
|
|
|
Act_LinkFormSubmit (Txt_Follow,NULL,NULL);
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"FOLLOW_USR_ICO ICO_HIGHLIGHT\">"
|
|
|
|
|
"<img src=\"%s/follow64x64.png\""
|
|
|
|
|
" alt=\"%s\" title=\"%s\""
|
|
|
|
|
" class=\"ICO20x20\" />"
|
|
|
|
|
"</div>"
|
|
|
|
|
"</a>",
|
|
|
|
|
Gbl.Prefs.IconsURL,
|
|
|
|
|
Txt_Follow,Txt_Follow);
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2017-02-16 20:22:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************** Put icon to unfollow another user ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void Fol_PutIconToUnfollow (struct UsrData *UsrDat)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Unfollow;
|
|
|
|
|
|
|
|
|
|
/* Form to follow */
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActUnfUsr);
|
2017-02-16 20:22:13 +01:00
|
|
|
|
Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod);
|
|
|
|
|
Act_LinkFormSubmit (Txt_Unfollow,NULL,NULL);
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"FOLLOW_USR_ICO ICO_HIGHLIGHT\">"
|
2017-02-17 02:42:00 +01:00
|
|
|
|
"<img src=\"%s/following64x64.png\""
|
2017-02-16 20:22:13 +01:00
|
|
|
|
" alt=\"%s\" title=\"%s\""
|
|
|
|
|
" class=\"ICO20x20\" />"
|
|
|
|
|
"</div>"
|
|
|
|
|
"</a>",
|
|
|
|
|
Gbl.Prefs.IconsURL,
|
|
|
|
|
Txt_Unfollow,Txt_Unfollow);
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2017-02-16 20:22:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-18 01:06:43 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Follow another user ***************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-17 02:42:00 +01:00
|
|
|
|
void Fol_FollowUsr1 (void)
|
2015-03-18 01:06:43 +01:00
|
|
|
|
{
|
2017-05-09 20:56:02 +02:00
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
2015-03-18 01:06:43 +01:00
|
|
|
|
char Query[256];
|
2015-03-24 00:01:40 +01:00
|
|
|
|
bool CreateNotif;
|
|
|
|
|
bool NotifyByEmail;
|
2015-03-18 01:06:43 +01:00
|
|
|
|
|
2015-03-19 01:59:08 +01:00
|
|
|
|
/***** Get user to be followed *****/
|
2015-03-18 01:06:43 +01:00
|
|
|
|
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
|
|
|
|
|
{
|
2015-03-19 12:47:05 +01:00
|
|
|
|
// Follow only if I can view his/her public profile
|
2017-01-28 15:58:46 +01:00
|
|
|
|
if (Pri_ShowingIsAllowed (Gbl.Usrs.Other.UsrDat.ProfileVisibility,&Gbl.Usrs.Other.UsrDat))
|
2015-03-19 12:47:05 +01:00
|
|
|
|
// Follow only if I do not follow him/her
|
|
|
|
|
if (!Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Gbl.Usrs.Other.UsrDat.UsrCod))
|
|
|
|
|
{
|
|
|
|
|
/***** Follow user in database *****/
|
|
|
|
|
sprintf (Query,"REPLACE INTO usr_follow"
|
|
|
|
|
" (FollowerCod,FollowedCod,FollowTime)"
|
2017-03-13 13:17:53 +01:00
|
|
|
|
" VALUES"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" (%ld,%ld,NOW())",
|
2015-03-19 12:47:05 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Gbl.Usrs.Other.UsrDat.UsrCod);
|
|
|
|
|
DB_QueryREPLACE (Query,"can not follow user");
|
2015-03-24 00:01:40 +01:00
|
|
|
|
|
2016-11-16 23:19:52 +01:00
|
|
|
|
/***** This follow must be notified by email? *****/
|
2016-01-23 19:11:07 +01:00
|
|
|
|
CreateNotif = (Gbl.Usrs.Other.UsrDat.Prefs.NotifNtfEvents & (1 << Ntf_EVENT_FOLLOWER));
|
2015-03-24 00:01:40 +01:00
|
|
|
|
NotifyByEmail = CreateNotif &&
|
2016-01-23 19:11:07 +01:00
|
|
|
|
(Gbl.Usrs.Other.UsrDat.Prefs.EmailNtfEvents & (1 << Ntf_EVENT_FOLLOWER));
|
2015-03-24 00:01:40 +01:00
|
|
|
|
|
|
|
|
|
/***** Create notification for this followed.
|
2016-11-16 23:19:52 +01:00
|
|
|
|
If this followed wants to receive notifications by email, activate the sending of a notification *****/
|
2015-03-24 00:01:40 +01:00
|
|
|
|
if (CreateNotif)
|
2016-01-23 19:11:07 +01:00
|
|
|
|
Ntf_StoreNotifyEventToOneUser (Ntf_EVENT_FOLLOWER,&Gbl.Usrs.Other.UsrDat,Gbl.Usrs.Me.UsrDat.UsrCod,
|
2015-03-24 00:01:40 +01:00
|
|
|
|
(Ntf_Status_t) (NotifyByEmail ? Ntf_STATUS_BIT_EMAIL :
|
|
|
|
|
0));
|
2015-03-19 12:47:05 +01:00
|
|
|
|
}
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Gbl.Alert.Type = Ale_SUCCESS;
|
2015-03-18 01:06:43 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-09 20:56:02 +02:00
|
|
|
|
{
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Gbl.Alert.Type = Ale_WARNING;
|
2018-10-16 15:16:32 +02:00
|
|
|
|
Str_Copy (Gbl.Alert.Txt,Txt_User_not_found_or_you_do_not_have_permission_,
|
|
|
|
|
Ale_MAX_BYTES_ALERT);
|
2017-05-09 20:56:02 +02:00
|
|
|
|
}
|
2017-02-17 02:42:00 +01:00
|
|
|
|
}
|
2015-03-18 02:11:23 +01:00
|
|
|
|
|
2017-02-17 02:42:00 +01:00
|
|
|
|
void Fol_FollowUsr2 (void)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
|
|
|
|
|
2017-05-11 23:45:46 +02:00
|
|
|
|
if (Gbl.Alert.Type == Ale_SUCCESS)
|
2017-02-17 02:42:00 +01:00
|
|
|
|
/***** Show user's profile again *****/
|
2017-05-09 20:56:02 +02:00
|
|
|
|
if (!Prf_ShowUserProfile (&Gbl.Usrs.Other.UsrDat))
|
|
|
|
|
{
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Gbl.Alert.Type = Ale_WARNING;
|
2018-10-16 15:16:32 +02:00
|
|
|
|
Str_Copy (Gbl.Alert.Txt,Txt_User_not_found_or_you_do_not_have_permission_,
|
|
|
|
|
Ale_MAX_BYTES_ALERT);
|
2017-05-09 20:56:02 +02:00
|
|
|
|
}
|
2017-02-17 02:42:00 +01:00
|
|
|
|
|
2017-05-11 23:45:46 +02:00
|
|
|
|
if (Gbl.Alert.Type != Ale_SUCCESS)
|
|
|
|
|
Ale_ShowPendingAlert ();
|
2015-03-18 01:06:43 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Unfollow another user *************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-17 02:42:00 +01:00
|
|
|
|
void Fol_UnfollowUsr1 (void)
|
2015-03-18 01:06:43 +01:00
|
|
|
|
{
|
2017-05-09 20:56:02 +02:00
|
|
|
|
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
|
2015-03-18 01:06:43 +01:00
|
|
|
|
char Query[256];
|
|
|
|
|
|
2015-03-19 01:59:08 +01:00
|
|
|
|
/***** Get user to be unfollowed *****/
|
2015-03-18 01:06:43 +01:00
|
|
|
|
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
|
|
|
|
|
{
|
2015-03-19 12:47:05 +01:00
|
|
|
|
// Unfollow only if I follow him/her
|
2015-03-18 01:06:43 +01:00
|
|
|
|
if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Gbl.Usrs.Other.UsrDat.UsrCod))
|
|
|
|
|
{
|
2017-04-03 10:20:09 +02:00
|
|
|
|
/***** Unfollow user in database *****/
|
2015-03-18 01:06:43 +01:00
|
|
|
|
sprintf (Query,"DELETE FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld AND FollowedCod=%ld",
|
2015-03-18 01:06:43 +01:00
|
|
|
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
|
|
|
|
Gbl.Usrs.Other.UsrDat.UsrCod);
|
|
|
|
|
DB_QueryREPLACE (Query,"can not unfollow user");
|
|
|
|
|
}
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Gbl.Alert.Type = Ale_SUCCESS;
|
2017-02-17 02:42:00 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-09 20:56:02 +02:00
|
|
|
|
{
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Gbl.Alert.Type = Ale_WARNING;
|
2018-10-16 15:16:32 +02:00
|
|
|
|
Str_Copy (Gbl.Alert.Txt,Txt_User_not_found_or_you_do_not_have_permission_,
|
|
|
|
|
Ale_MAX_BYTES_ALERT);
|
2017-05-09 20:56:02 +02:00
|
|
|
|
}
|
2017-02-17 02:42:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Fol_UnfollowUsr2 (void)
|
|
|
|
|
{
|
|
|
|
|
/***** Get user to be unfollowed *****/
|
2017-05-11 23:45:46 +02:00
|
|
|
|
if (Gbl.Alert.Type == Ale_SUCCESS)
|
2017-02-17 02:42:00 +01:00
|
|
|
|
{
|
2015-03-18 02:11:23 +01:00
|
|
|
|
/***** Show user's profile again *****/
|
2016-06-12 19:55:33 +02:00
|
|
|
|
if (!Prf_ShowUserProfile (&Gbl.Usrs.Other.UsrDat)) // I can not view user's profile
|
|
|
|
|
/* 1) I followed a user when I had permission
|
|
|
|
|
2) User restricted permission, so now I can not view his/her profile
|
|
|
|
|
3) Now I can not view his/her profile ==> show users I follow */
|
2016-09-28 13:12:11 +02:00
|
|
|
|
Fol_ListFollowingUsr (&Gbl.Usrs.Me.UsrDat); // List users I follow
|
2015-03-18 01:06:43 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowPendingAlert ();
|
2015-03-18 01:06:43 +01:00
|
|
|
|
}
|
2015-03-23 10:35:15 +01:00
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****** Get and show ranking of users attending to number of followers *******/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Fol_GetAndShowRankingFollowers (void)
|
|
|
|
|
{
|
|
|
|
|
char Query[512];
|
|
|
|
|
|
|
|
|
|
/***** Get ranking from database *****/
|
|
|
|
|
switch (Gbl.Scope.Current)
|
|
|
|
|
{
|
|
|
|
|
case Sco_SCOPE_SYS:
|
|
|
|
|
sprintf (Query,"SELECT FollowedCod,COUNT(FollowerCod) AS N"
|
|
|
|
|
" FROM usr_follow"
|
|
|
|
|
" GROUP BY FollowedCod"
|
|
|
|
|
" ORDER BY N DESC,FollowedCod LIMIT 100");
|
|
|
|
|
break;
|
|
|
|
|
case Sco_SCOPE_CTY:
|
2016-01-27 17:41:43 +01:00
|
|
|
|
sprintf (Query,"SELECT usr_follow.FollowedCod,COUNT(DISTINCT usr_follow.FollowerCod) AS N"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" FROM institutions,centres,degrees,courses,crs_usr,usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE institutions.CtyCod=%ld"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" AND institutions.InsCod=centres.InsCod"
|
|
|
|
|
" AND centres.CtrCod=degrees.CtrCod"
|
|
|
|
|
" AND degrees.DegCod=courses.DegCod"
|
|
|
|
|
" AND courses.CrsCod=crs_usr.CrsCod"
|
|
|
|
|
" AND crs_usr.UsrCod=usr_follow.FollowedCod"
|
|
|
|
|
" GROUP BY usr_follow.FollowedCod"
|
|
|
|
|
" ORDER BY N DESC,usr_follow.FollowedCod LIMIT 100",
|
|
|
|
|
Gbl.CurrentCty.Cty.CtyCod);
|
|
|
|
|
break;
|
|
|
|
|
case Sco_SCOPE_INS:
|
2016-01-27 17:41:43 +01:00
|
|
|
|
sprintf (Query,"SELECT usr_follow.FollowedCod,COUNT(DISTINCT usr_follow.FollowerCod) AS N"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" FROM centres,degrees,courses,crs_usr,usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE centres.InsCod=%ld"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" AND centres.CtrCod=degrees.CtrCod"
|
|
|
|
|
" AND degrees.DegCod=courses.DegCod"
|
|
|
|
|
" AND courses.CrsCod=crs_usr.CrsCod"
|
|
|
|
|
" AND crs_usr.UsrCod=usr_follow.FollowedCod"
|
|
|
|
|
" GROUP BY usr_follow.FollowedCod"
|
|
|
|
|
" ORDER BY N DESC,usr_follow.FollowedCod LIMIT 100",
|
|
|
|
|
Gbl.CurrentIns.Ins.InsCod);
|
|
|
|
|
break;
|
|
|
|
|
case Sco_SCOPE_CTR:
|
2016-01-27 17:41:43 +01:00
|
|
|
|
sprintf (Query,"SELECT usr_follow.FollowedCod,COUNT(DISTINCT usr_follow.FollowerCod) AS N"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" FROM degrees,courses,crs_usr,usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE degrees.CtrCod=%ld"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" AND degrees.DegCod=courses.DegCod"
|
|
|
|
|
" AND courses.CrsCod=crs_usr.CrsCod"
|
|
|
|
|
" AND crs_usr.UsrCod=usr_follow.FollowedCod"
|
|
|
|
|
" GROUP BY usr_follow.FollowedCod"
|
|
|
|
|
" ORDER BY N DESC,usr_follow.FollowedCod LIMIT 100",
|
|
|
|
|
Gbl.CurrentCtr.Ctr.CtrCod);
|
|
|
|
|
break;
|
|
|
|
|
case Sco_SCOPE_DEG:
|
2016-01-27 17:41:43 +01:00
|
|
|
|
sprintf (Query,"SELECT usr_follow.FollowedCod,COUNT(DISTINCT usr_follow.FollowerCod) AS N"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" FROM courses,crs_usr,usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE courses.DegCod=%ld"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" AND courses.CrsCod=crs_usr.CrsCod"
|
|
|
|
|
" AND crs_usr.UsrCod=usr_follow.FollowedCod"
|
|
|
|
|
" GROUP BY usr_follow.FollowedCod"
|
|
|
|
|
" ORDER BY N DESC,usr_follow.FollowedCod LIMIT 100",
|
|
|
|
|
Gbl.CurrentDeg.Deg.DegCod);
|
|
|
|
|
break;
|
|
|
|
|
case Sco_SCOPE_CRS:
|
2016-01-27 17:41:43 +01:00
|
|
|
|
sprintf (Query,"SELECT usr_follow.FollowedCod,COUNT(DISTINCT usr_follow.FollowerCod) AS N"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" FROM crs_usr,usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE crs_usr.CrsCod=%ld"
|
2015-03-23 10:35:15 +01:00
|
|
|
|
" AND crs_usr.UsrCod=usr_follow.FollowedCod"
|
|
|
|
|
" GROUP BY usr_follow.FollowedCod"
|
|
|
|
|
" ORDER BY N DESC,usr_follow.FollowedCod LIMIT 100",
|
|
|
|
|
Gbl.CurrentCrs.Crs.CrsCod);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong scope.");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
Prf_ShowRankingFigure (Query);
|
|
|
|
|
}
|
2015-03-24 00:01:40 +01:00
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************* Get notification of a new follower ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
// This function may be called inside a web service, so don't report error
|
|
|
|
|
|
2017-03-08 14:12:33 +01:00
|
|
|
|
void Fol_GetNotifFollower (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
|
2017-01-15 22:58:26 +01:00
|
|
|
|
char **ContentStr)
|
2015-03-24 00:01:40 +01:00
|
|
|
|
{
|
2017-03-06 13:01:16 +01:00
|
|
|
|
SummaryStr[0] = '\0'; // Return nothing on error
|
2015-03-24 00:01:40 +01:00
|
|
|
|
|
|
|
|
|
if ((*ContentStr = (char *) malloc (1)))
|
2017-01-13 10:49:56 +01:00
|
|
|
|
*ContentStr[0] = '\0';
|
2015-03-24 00:01:40 +01:00
|
|
|
|
}
|
2015-12-12 02:01:20 +01:00
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********************** Remove user from user follow ************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Fol_RemoveUsrFromUsrFollow (long UsrCod)
|
|
|
|
|
{
|
|
|
|
|
char Query[128];
|
|
|
|
|
|
|
|
|
|
sprintf (Query,"DELETE FROM usr_follow"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE FollowerCod=%ld OR FollowedCod=%ld",
|
2015-12-12 02:01:20 +01:00
|
|
|
|
UsrCod,UsrCod);
|
|
|
|
|
DB_QueryDELETE (Query,"can not remove user from followers and followed");
|
|
|
|
|
}
|