Version 16.247

This commit is contained in:
Antonio Cañas Vargas 2017-06-20 14:43:26 +02:00
parent 500bd55ca7
commit f639ebb425
19 changed files with 627 additions and 499 deletions

View File

@ -1002,7 +1002,7 @@ void Acc_CompletelyEliminateAccount (struct UsrData *UsrDat,
Att_RemoveUsrFromAllAttEvents (UsrDat->UsrCod); Att_RemoveUsrFromAllAttEvents (UsrDat->UsrCod);
/***** Remove user from all the groups of all courses *****/ /***** Remove user from all the groups of all courses *****/
Grp_RemUsrFromAllGrps (UsrDat); Grp_RemUsrFromAllGrps (UsrDat->UsrCod);
/***** Remove user's requests for inscription *****/ /***** Remove user's requests for inscription *****/
sprintf (Query,"DELETE FROM crs_usr_requests WHERE UsrCod=%ld", sprintf (Query,"DELETE FROM crs_usr_requests WHERE UsrCod=%ld",

View File

@ -236,13 +236,15 @@
/****************************** Public constants *****************************/ /****************************** Public constants *****************************/
/*****************************************************************************/ /*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 16.246 (2017-06-20)" #define Log_PLATFORM_VERSION "SWAD 16.247 (2017-06-20)"
#define CSS_FILE "swad16.235.1.css" #define CSS_FILE "swad16.235.1.css"
#define JS_FILE "swad16.206.3.js" #define JS_FILE "swad16.206.3.js"
// Number of lines (includes comments but not blank lines) has been got with the following command: // Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1 // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1
/* /*
Version 16.247: Jun 20, 2017 Fixed bug when removing a user from a course.
Code refactoring related with caches. (222063 lines)
Version 16.246: Jun 20, 2017 Fixed bugs and code refactoring in groups. (221975 lines) Version 16.246: Jun 20, 2017 Fixed bugs and code refactoring in groups. (221975 lines)
Version 16.245: Jun 12, 2017 Place editable in centre configuration. (221876 lines) Version 16.245: Jun 12, 2017 Place editable in centre configuration. (221876 lines)
Version 16.244.1: Jun 12, 2017 Fix bug in edition of centres. (221817 lines) Version 16.244.1: Jun 12, 2017 Fix bug in edition of centres. (221817 lines)

View File

@ -287,7 +287,7 @@ void Con_GetAndShowLastClicks (void)
/* Get institution code (row[5]) */ /* Get institution code (row[5]) */
Ins.InsCod = Str_ConvertStrCodToLongCod (row[5]); Ins.InsCod = Str_ConvertStrCodToLongCod (row[5]);
Ins_GetShortNameOfInstitutionByCod (&Ins); Ins_GetShortNameOfInstitution (&Ins);
/* Get centre code (row[6]) */ /* Get centre code (row[6]) */
Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[6]); Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[6]);

View File

@ -1403,53 +1403,56 @@ bool Cty_GetDataOfCountryByCod (struct Country *Cty,Cty_GetExtraData_t GetExtraD
/***************************** Get country name ******************************/ /***************************** Get country name ******************************/
/*****************************************************************************/ /*****************************************************************************/
void Cty_FlushCacheCountryName (void)
{
Gbl.Cache.CountryName.CtyCod = -1L;
Gbl.Cache.CountryName.CtyName[0] = '\0';
}
void Cty_GetCountryName (long CtyCod,char CtyName[Cty_MAX_BYTES_NAME + 1]) void Cty_GetCountryName (long CtyCod,char CtyName[Cty_MAX_BYTES_NAME + 1])
{ {
extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES];
char Query[128]; char Query[128];
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
static struct
{
long CtyCod;
char CtyName[Cty_MAX_BYTES_NAME + 1];
} Cached =
{
-1L,
{'\0'}
};
/***** Check if country code is correct *****/ /***** 1. Fast check: Trivial case *****/
if (CtyCod <= 0) if (CtyCod <= 0)
CtyName[0] = '\0'; // Empty name
else
{ {
if (CtyCod != Cached.CtyCod) // If not cached... CtyName[0] = '\0'; // Empty name
{ return;
Cached.CtyCod = CtyCod; }
/***** Get name of the country from database *****/ /***** 2. Fast check: If cached... *****/
sprintf (Query,"SELECT Name_%s FROM countries WHERE CtyCod='%03ld'", if (CtyCod == Gbl.Cache.CountryName.CtyCod)
Txt_STR_LANG_ID[Gbl.Prefs.Language],CtyCod); {
if (DB_QuerySELECT (Query,&mysql_res,"can not get the name of a country")) // Country found... Str_Copy (CtyName,Gbl.Cache.CountryName.CtyName,
{ Cty_MAX_BYTES_NAME);
/* Get row */ return;
row = mysql_fetch_row (mysql_res); }
/* Get the name of the country */ /***** 3. Slow: get country name from database *****/
Str_Copy (Cached.CtyName,row[0], Gbl.Cache.CountryName.CtyCod = CtyCod;
Cty_MAX_BYTES_NAME);
}
else
Cached.CtyName[0] = '\0';
/***** Free structure that stores the query result *****/ sprintf (Query,"SELECT Name_%s FROM countries WHERE CtyCod='%03ld'",
DB_FreeMySQLResult (&mysql_res); Txt_STR_LANG_ID[Gbl.Prefs.Language],CtyCod);
} if (DB_QuerySELECT (Query,&mysql_res,"can not get the name of a country")) // Country found...
{
/* Get row */
row = mysql_fetch_row (mysql_res);
Str_Copy (CtyName,Cached.CtyName, /* Get the name of the country */
Str_Copy (Gbl.Cache.CountryName.CtyName,row[0],
Cty_MAX_BYTES_NAME); Cty_MAX_BYTES_NAME);
} }
else
Gbl.Cache.CountryName.CtyName[0] = '\0';
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
Str_Copy (CtyName,Gbl.Cache.CountryName.CtyName,
Cty_MAX_BYTES_NAME);
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1703,6 +1706,9 @@ void Cty_RemoveCountry (void)
Cty.CtyCod); Cty.CtyCod);
DB_QueryDELETE (Query,"can not remove a country"); DB_QueryDELETE (Query,"can not remove a country");
/***** Flush cache *****/
Cty_FlushCacheCountryName ();
/***** Write message to show the change made *****/ /***** Write message to show the change made *****/
sprintf (Gbl.Alert.Txt,Txt_Country_X_removed, sprintf (Gbl.Alert.Txt,Txt_Country_X_removed,
Cty.Name[Gbl.Prefs.Language]); Cty.Name[Gbl.Prefs.Language]);
@ -1846,6 +1852,9 @@ static void Cty_UpdateCtyNameDB (long CtyCod,const char *FieldName,const char *N
sprintf (Query,"UPDATE countries SET %s='%s' WHERE CtyCod='%03ld'", sprintf (Query,"UPDATE countries SET %s='%s' WHERE CtyCod='%03ld'",
FieldName,NewCtyName,CtyCod); FieldName,NewCtyName,CtyCod);
DB_QueryUPDATE (Query,"can not update the name of a country"); DB_QueryUPDATE (Query,"can not update the name of a country");
/***** Flush cache *****/
Cty_FlushCacheCountryName ();
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -99,6 +99,7 @@ void Cty_FreeListCountries (void);
void Cty_WriteSelectorOfCountry (void); void Cty_WriteSelectorOfCountry (void);
void Cty_WriteCountryName (long CtyCod,const char *ClassLink); void Cty_WriteCountryName (long CtyCod,const char *ClassLink);
bool Cty_GetDataOfCountryByCod (struct Country *Cty,Cty_GetExtraData_t GetExtraData); bool Cty_GetDataOfCountryByCod (struct Country *Cty,Cty_GetExtraData_t GetExtraData);
void Cty_FlushCacheCountryName (void);
void Cty_GetCountryName (long CtyCod,char CtyName[Cty_MAX_BYTES_NAME + 1]); void Cty_GetCountryName (long CtyCod,char CtyName[Cty_MAX_BYTES_NAME + 1]);
void Cty_PutParamCtyCod (long CtyCod); void Cty_PutParamCtyCod (long CtyCod);
long Cty_GetAndCheckParamOtherCtyCod (long MinCodAllowed); long Cty_GetAndCheckParamOtherCtyCod (long MinCodAllowed);

View File

@ -175,8 +175,8 @@ void Enr_PutButtonInlineToRegisterStds (long CrsCod)
{ {
extern const char *Txt_Register_students; extern const char *Txt_Register_students;
if (Rol_GetRoleInCrs (CrsCod,Gbl.Usrs.Me.UsrDat.UsrCod) == Rol_TCH) // I am a teacher in course if (Rol_GetRoleUsrInCrs (Gbl.Usrs.Me.UsrDat.UsrCod,CrsCod) == Rol_TCH) // I am a teacher in course
if (!Usr_GetNumUsrsInCrs (Rol_STD,CrsCod)) // No students in course if (!Usr_GetNumUsrsInCrs (Rol_STD,CrsCod)) // No students in course
{ {
Act_FormStart (ActReqEnrSevStd); Act_FormStart (ActReqEnrSevStd);
Crs_PutParamCrsCod (CrsCod); Crs_PutParamCrsCod (CrsCod);
@ -231,7 +231,7 @@ void Enr_ModifyRoleInCurrentCrs (struct UsrData *UsrDat,Rol_Role_t NewRole)
Enr_NotifyAfterEnrolment (UsrDat,NewRole); Enr_NotifyAfterEnrolment (UsrDat,NewRole);
UsrDat->Roles.InCurrentCrs.Role = NewRole; UsrDat->Roles.InCurrentCrs.Role = NewRole;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
UsrDat->Roles.InCrss = -1; // Force roles to be got from database UsrDat->Roles.InCrss = -1; // Force roles to be got from database
Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles
} }
@ -280,7 +280,7 @@ void Enr_RegisterUsrInCurrentCrs (struct UsrData *UsrDat,Rol_Role_t NewRole,
'N'); 'N');
DB_QueryINSERT (Query,"can not register user in course"); DB_QueryINSERT (Query,"can not register user in course");
UsrDat->Roles.InCurrentCrs.Role = NewRole; UsrDat->Roles.InCurrentCrs.Role = NewRole;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
UsrDat->Roles.InCrss = -1; // Force roles to be got from database UsrDat->Roles.InCrss = -1; // Force roles to be got from database
Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles
@ -3024,7 +3024,7 @@ void Enr_PutLinkToAdminOneUsr (Act_Action_t NextAction)
extern const char *Txt_Administer_me; extern const char *Txt_Administer_me;
extern const char *Txt_Administer_one_user; extern const char *Txt_Administer_one_user;
const char *TitleText = Enr_ICanAdminOtherUsrs[Gbl.Usrs.Me.Role.Logged] ? Txt_Administer_one_user : const char *TitleText = Enr_ICanAdminOtherUsrs[Gbl.Usrs.Me.Role.Logged] ? Txt_Administer_one_user :
Txt_Administer_me; Txt_Administer_me;
Lay_PutContextualLink (NextAction,NULL,NULL, Lay_PutContextualLink (NextAction,NULL,NULL,
"config64x64.gif", "config64x64.gif",
@ -3922,7 +3922,7 @@ void Enr_ModifyUsr1 (void)
if (ItsMe) if (ItsMe)
{ {
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs.Role; Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs.Role;
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod = Gbl.Usrs.Other.UsrDat.UsrCod; Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod = Gbl.Usrs.Other.UsrDat.UsrCod;
Gbl.Usrs.Me.UsrDat.Roles.InCrss = Gbl.Usrs.Other.UsrDat.Roles.InCrss; Gbl.Usrs.Me.UsrDat.Roles.InCrss = Gbl.Usrs.Other.UsrDat.Roles.InCrss;
Rol_SetMyRoles (); Rol_SetMyRoles ();
} }
@ -4134,7 +4134,7 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,struct Course *
extern const char *Txt_THE_USER_X_has_been_removed_from_the_course_Y; extern const char *Txt_THE_USER_X_has_been_removed_from_the_course_Y;
extern const char *Txt_User_not_found_or_you_do_not_have_permission_; extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
char Query[1024]; char Query[1024];
bool ItsMe; bool ItsMe = (UsrDat->UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod);
if (Usr_CheckIfUsrBelongsToCurrentCrs (UsrDat)) if (Usr_CheckIfUsrBelongsToCurrentCrs (UsrDat))
{ {
@ -4142,7 +4142,7 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,struct Course *
Att_RemoveUsrFromCrsAttEvents (UsrDat->UsrCod,Crs->CrsCod); Att_RemoveUsrFromCrsAttEvents (UsrDat->UsrCod,Crs->CrsCod);
/***** Remove user from all the groups in course *****/ /***** Remove user from all the groups in course *****/
Grp_RemUsrFromAllGrpsInCrs (UsrDat,Crs); Grp_RemUsrFromAllGrpsInCrs (UsrDat->UsrCod,Crs->CrsCod);
/***** Remove user's status about reading of course information *****/ /***** Remove user's status about reading of course information *****/
Inf_RemoveUsrFromCrsInfoRead (UsrDat->UsrCod,Crs->CrsCod); Inf_RemoveUsrFromCrsInfoRead (UsrDat->UsrCod,Crs->CrsCod);
@ -4170,13 +4170,44 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,struct Course *
Crs->CrsCod,UsrDat->UsrCod); Crs->CrsCod,UsrDat->UsrCod);
DB_QueryDELETE (Query,"can not remove a user from a course"); DB_QueryDELETE (Query,"can not remove a user from a course");
/***** Flush caches *****/
Usr_FlushCacheUsrBelongsToIns ();
Usr_FlushCacheUsrBelongsToCtr ();
Usr_FlushCacheUsrBelongsToDeg ();
Usr_FlushCacheUsrBelongsToCrs ();
Usr_FlushCacheUsrBelongsToCurrentCrs ();
Usr_FlushCacheUsrHasAcceptedInCurrentCrs ();
Usr_FlushCacheUsrSharesAnyOfMyCrs ();
Rol_FlushCacheRoleUsrInCrs ();
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ();
/***** If it's me, change my roles *****/ /***** If it's me, change my roles *****/
ItsMe = (UsrDat->UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod);
if (ItsMe) if (ItsMe)
{ {
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; /* Flush caches */
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod = UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; Grp_FlushCacheIBelongToGrp ();
Gbl.Usrs.Me.UsrDat.Roles.InCrss = UsrDat->Roles.InCrss = -1; // not yet filled/calculated
/* Now I don't belong to current course */
Gbl.Usrs.Me.IBelongToCurrentCrs =
Gbl.Usrs.Me.UsrDat.Accepted = false;
/* Fill the list with the courses I belong to */
Gbl.Usrs.Me.MyCrss.Filled = false;
Usr_GetMyCourses ();
/* Set my roles */
Gbl.Usrs.Me.Role.FromSession =
Gbl.Usrs.Me.Role.Logged =
Gbl.Usrs.Me.Role.LoggedBeforeCloseSession =
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role =
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod =
UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
Gbl.Usrs.Me.UsrDat.Roles.InCrss =
UsrDat->Roles.InCrss = -1; // not yet filled/calculated
Rol_SetMyRoles (); Rol_SetMyRoles ();
} }

View File

@ -42,6 +42,7 @@
#include "swad_icon.h" #include "swad_icon.h"
#include "swad_parameter.h" #include "swad_parameter.h"
#include "swad_preference.h" #include "swad_preference.h"
#include "swad_role.h"
#include "swad_theme.h" #include "swad_theme.h"
#include "swad_web_service.h" #include "swad_web_service.h"
@ -440,6 +441,22 @@ void Gbl_InitializeGlobals (void)
Gbl.WebService.Function = Svc_unknown; Gbl.WebService.Function = Svc_unknown;
Gbl.Layout.NestedBox = 0; Gbl.Layout.NestedBox = 0;
/* Flush caches */
Cty_FlushCacheCountryName ();
Ins_FlushCacheShortNameOfInstitution ();
Ins_FlushCacheFullNameAndCtyOfInstitution ();
Usr_FlushCacheUsrIsSuperuser ();
Usr_FlushCacheUsrBelongsToIns ();
Usr_FlushCacheUsrBelongsToCtr ();
Usr_FlushCacheUsrBelongsToDeg ();
Usr_FlushCacheUsrBelongsToCrs ();
Usr_FlushCacheUsrBelongsToCurrentCrs ();
Usr_FlushCacheUsrHasAcceptedInCurrentCrs ();
Usr_FlushCacheUsrSharesAnyOfMyCrs ();
Rol_FlushCacheRoleUsrInCrs ();
Grp_FlushCacheIBelongToGrp ();
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ();
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -747,6 +747,88 @@ struct Globals
{ {
char *Str; char *Str;
} QR; } QR;
/* Cache */
struct
{
struct
{
long CtyCod;
char CtyName[Cty_MAX_BYTES_NAME + 1];
} CountryName;
struct
{
long InsCod;
char ShrtName[Hie_MAX_BYTES_SHRT_NAME + 1];
} InstitutionShrtName;
struct
{
long InsCod;
char FullName[Hie_MAX_BYTES_FULL_NAME + 1];
char CtyName[Hie_MAX_BYTES_FULL_NAME + 1];
} InstitutionFullNameAndCty;
struct
{
long UsrCod;
bool IsSuperuser;
} UsrIsSuperuser;
struct
{
long UsrCod;
long InsCod;
bool Belongs;
} UsrBelongsToIns;
struct
{
long UsrCod;
long CtrCod;
bool Belongs;
} UsrBelongsToCtr;
struct
{
long UsrCod;
long DegCod;
bool Belongs;
} UsrBelongsToDeg;
struct
{
long UsrCod;
long CrsCod;
bool CountOnlyAcceptedCourses;
bool Belongs;
} UsrBelongsToCrs;
struct
{
long UsrCod;
bool Belongs;
} UsrBelongsToCurrentCrs;
struct
{
long UsrCod;
bool Accepted;
} UsrHasAcceptedInCurrentCrs;
struct
{
long UsrCod;
bool SharesAnyOfMyCrs;
} UsrSharesAnyOfMyCrs;
struct
{
long GrpCod;
bool IBelong;
} IBelongToGrp;
struct
{
long UsrCod;
bool Shares;
} UsrSharesAnyOfMyGrpsInCurrentCrs;
struct
{
long UsrCod;
long CrsCod;
Rol_Role_t Role;
} RoleUsrInCrs;
} Cache;
}; };
/*****************************************************************************/ /*****************************************************************************/

View File

@ -1130,7 +1130,9 @@ unsigned Grp_RemoveUsrFromGroups (struct UsrData *UsrDat,struct ListCodGrps *Lst
extern const char *Txt_THE_USER_X_has_been_removed_from_one_group; extern const char *Txt_THE_USER_X_has_been_removed_from_one_group;
extern const char *Txt_THE_USER_X_has_been_removed_from_Y_groups; extern const char *Txt_THE_USER_X_has_been_removed_from_Y_groups;
struct ListCodGrps LstGrpsHeBelongs; struct ListCodGrps LstGrpsHeBelongs;
unsigned NumGrpSel,NumGrpHeBelongs,NumGrpsHeIsRemoved = 0; unsigned NumGrpSel;
unsigned NumGrpHeBelongs;
unsigned NumGrpsHeIsRemoved = 0;
/***** Query in the database the group codes of any group the user belongs to *****/ /***** Query in the database the group codes of any group the user belongs to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.CurrentCrs.Crs.CrsCod,-1L, Grp_GetLstCodGrpsUsrBelongs (Gbl.CurrentCrs.Crs.CrsCod,-1L,
@ -1173,9 +1175,10 @@ unsigned Grp_RemoveUsrFromGroups (struct UsrData *UsrDat,struct ListCodGrps *Lst
/*************** Remove a user of all the groups of a course *****************/ /*************** Remove a user of all the groups of a course *****************/
/*****************************************************************************/ /*****************************************************************************/
void Grp_RemUsrFromAllGrpsInCrs (struct UsrData *UsrDat,struct Course *Crs) void Grp_RemUsrFromAllGrpsInCrs (long UsrCod,long CrsCod)
{ {
char Query[512]; char Query[512];
bool ItsMe = (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Remove user from all the groups of the course *****/ /***** Remove user from all the groups of the course *****/
sprintf (Query,"DELETE FROM crs_grp_usr" sprintf (Query,"DELETE FROM crs_grp_usr"
@ -1183,22 +1186,33 @@ void Grp_RemUsrFromAllGrpsInCrs (struct UsrData *UsrDat,struct Course *Crs)
" (SELECT crs_grp.GrpCod FROM crs_grp_types,crs_grp" " (SELECT crs_grp.GrpCod FROM crs_grp_types,crs_grp"
" WHERE crs_grp_types.CrsCod=%ld" " WHERE crs_grp_types.CrsCod=%ld"
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod)", " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod)",
UsrDat->UsrCod,Crs->CrsCod); UsrCod,CrsCod);
DB_QueryDELETE (Query,"can not remove a user from all groups of a course"); DB_QueryDELETE (Query,"can not remove a user from all groups of a course");
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ();
if (ItsMe)
Grp_FlushCacheIBelongToGrp ();
} }
/*****************************************************************************/ /*****************************************************************************/
/******* Remove a user from all the groups of all the user's courses *********/ /******* Remove a user from all the groups of all the user's courses *********/
/*****************************************************************************/ /*****************************************************************************/
void Grp_RemUsrFromAllGrps (struct UsrData *UsrDat) void Grp_RemUsrFromAllGrps (long UsrCod)
{ {
char Query[128]; char Query[128];
bool ItsMe = (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Remove user from all groups *****/ /***** Remove user from all groups *****/
sprintf (Query,"DELETE FROM crs_grp_usr WHERE UsrCod=%ld", sprintf (Query,"DELETE FROM crs_grp_usr WHERE UsrCod=%ld",
UsrDat->UsrCod); UsrCod);
DB_QueryDELETE (Query,"can not remove a user from the groups he/she belongs to"); DB_QueryDELETE (Query,"can not remove a user from the groups he/she belongs to");
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ();
if (ItsMe)
Grp_FlushCacheIBelongToGrp ();
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1208,12 +1222,18 @@ void Grp_RemUsrFromAllGrps (struct UsrData *UsrDat)
static void Grp_RemoveUsrFromGroup (long UsrCod,long GrpCod) static void Grp_RemoveUsrFromGroup (long UsrCod,long GrpCod)
{ {
char Query[256]; char Query[256];
bool ItsMe = (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Remove user from group *****/ /***** Remove user from group *****/
sprintf (Query,"DELETE FROM crs_grp_usr" sprintf (Query,"DELETE FROM crs_grp_usr"
" WHERE GrpCod=%ld AND UsrCod=%ld", " WHERE GrpCod=%ld AND UsrCod=%ld",
GrpCod,UsrCod); GrpCod,UsrCod);
DB_QueryDELETE (Query,"can not remove a user from a group"); DB_QueryDELETE (Query,"can not remove a user from a group");
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ();
if (ItsMe)
Grp_FlushCacheIBelongToGrp ();
} }
/*****************************************************************************/ /*****************************************************************************/
@ -3230,35 +3250,104 @@ static long Grp_GetFirstCodGrpIBelongTo (long GrpTypCod)
} }
/*****************************************************************************/ /*****************************************************************************/
/********************* Check if a user belongs to a group ********************/ /************************ Check if I belong to a group ***********************/
/*****************************************************************************/ /*****************************************************************************/
// Return true if the user identificado belongs al group with código GrpCod // Return true if I belong to group with code GrpCod
void Grp_FlushCacheIBelongToGrp (void)
{
Gbl.Cache.IBelongToGrp.GrpCod = -1L;
Gbl.Cache.IBelongToGrp.IBelong = false;
}
bool Grp_GetIfIBelongToGrp (long GrpCod) bool Grp_GetIfIBelongToGrp (long GrpCod)
{ {
char Query[256]; char Query[256];
static struct
{
long GrpCod;
bool IBelongToGrp;
} Cached =
{
-1L,
false
}; // A cache. If this function is called consecutive times
// with the same group, only the first time is slow
/***** 1. Fast check: Is already calculated if I belong to group? *****/ /***** 1. Fast check: Trivial case *****/
if (GrpCod == Cached.GrpCod) if (GrpCod <= 0)
return Cached.IBelongToGrp; return false;
/***** 2. Slow check: Get if I belong to a group from database *****/ /***** 2. Fast check: Is already calculated if I belong to group? *****/
if (GrpCod == Gbl.Cache.IBelongToGrp.GrpCod)
return Gbl.Cache.IBelongToGrp.IBelong;
/***** 3. Slow check: Get if I belong to a group from database *****/
sprintf (Query,"SELECT COUNT(*) FROM crs_grp_usr" sprintf (Query,"SELECT COUNT(*) FROM crs_grp_usr"
" WHERE GrpCod=%ld AND UsrCod=%ld", " WHERE GrpCod=%ld AND UsrCod=%ld",
GrpCod,Gbl.Usrs.Me.UsrDat.UsrCod); GrpCod,Gbl.Usrs.Me.UsrDat.UsrCod);
Cached.IBelongToGrp = DB_QueryCOUNT (Query,"can not check if you belong to a group") != 0; Gbl.Cache.IBelongToGrp.IBelong = DB_QueryCOUNT (Query,"can not check if you belong to a group") != 0;
Cached.GrpCod = GrpCod; Gbl.Cache.IBelongToGrp.GrpCod = GrpCod;
return Cached.IBelongToGrp; return Gbl.Cache.IBelongToGrp.IBelong;
}
/*****************************************************************************/
/*************** Check if a user belongs to any of my courses ****************/
/*****************************************************************************/
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (void)
{
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.UsrCod = -1L;
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares = false;
}
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat)
{
char Query[512];
/***** 1. Fast check: Am I logged? *****/
if (!Gbl.Usrs.Me.Logged)
return false;
/***** 2. Fast check: Is it a valid user code? *****/
if (UsrDat->UsrCod <= 0)
return false;
/***** 3. Fast check: Is it a course selected? *****/
if (Gbl.CurrentCrs.Crs.CrsCod <= 0)
return false;
/***** 4. Fast check: Do I belong to the current course? *****/
if (!Gbl.Usrs.Me.IBelongToCurrentCrs)
return false;
/***** 5. Fast check: It's me? *****/
if (Gbl.Usrs.Me.UsrDat.UsrCod == UsrDat->UsrCod)
return true;
/***** 6. Fast check: Is already calculated if user shares
any group in the current course with me? *****/
if (UsrDat->UsrCod == Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.UsrCod)
return Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares;
/***** 7. Fast / slow check: Does he/she belong to the current course? *****/
if (!Usr_CheckIfUsrBelongsToCurrentCrs (UsrDat))
{
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.UsrCod = UsrDat->UsrCod;
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares = false;
return false;
}
/***** 8. Slow check: Get if user shares any group in this course with me from database *****/
/* Check if user shares any group with me */
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.UsrCod = UsrDat->UsrCod;
sprintf (Query,"SELECT COUNT(*) FROM crs_grp_usr"
" WHERE UsrCod=%ld"
" AND GrpCod IN"
" (SELECT crs_grp_usr.GrpCod"
" FROM crs_grp_usr,crs_grp,crs_grp_types"
" WHERE crs_grp_usr.UsrCod=%ld"
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod"
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod"
" AND crs_grp_types.CrsCod=%ld)",
UsrDat->UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.CurrentCrs.Crs.CrsCod);
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares = DB_QueryCOUNT (Query,"can not check"
" if a user shares any group"
" in the current course with you") != 0;
return Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -4791,71 +4880,3 @@ void Grp_GetParamWhichGrps (void)
AlreadyGot = true; AlreadyGot = true;
} }
} }
/*****************************************************************************/
/*************** Check if a user belongs to any of my courses ****************/
/*****************************************************************************/
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat)
{
char Query[512];
static struct
{
long UsrCod;
bool UsrSharesAnyOfMyGrpsInCurrentCrs;
} Cached =
{
-1L,
false
}; // A cache. If this function is called consecutive times
// with the same user, only the first time is slow
/***** 1. Fast check: Am I logged? *****/
if (!Gbl.Usrs.Me.Logged)
return false;
/***** 2. Fast check: Is it a valid user code? *****/
if (UsrDat->UsrCod <= 0)
return false;
/***** 3. Fast check: Is it a course selected? *****/
if (Gbl.CurrentCrs.Crs.CrsCod <= 0)
return false;
/***** 4. Fast check: Do I belong to the current course? *****/
if (!Gbl.Usrs.Me.IBelongToCurrentCrs)
return false;
/***** 5. Fast check: It's me? *****/
if (Gbl.Usrs.Me.UsrDat.UsrCod == UsrDat->UsrCod)
return true;
/***** 6. Fast check: Does he/she belong to the current course? *****/
if (!Usr_CheckIfUsrBelongsToCurrentCrs (UsrDat))
return false;
/***** 7. Fast check: Is already calculated if user shares
any group in the current course with me? *****/
if (UsrDat->UsrCod == Cached.UsrCod)
return Cached.UsrSharesAnyOfMyGrpsInCurrentCrs;
/***** 8. Slow check: Get if user shares any group in this course with me from database *****/
/* Check if user shares any group with me */
Cached.UsrCod = UsrDat->UsrCod;
sprintf (Query,"SELECT COUNT(*) FROM crs_grp_usr"
" WHERE UsrCod=%ld"
" AND GrpCod IN"
" (SELECT crs_grp_usr.GrpCod"
" FROM crs_grp_usr,crs_grp,crs_grp_types"
" WHERE crs_grp_usr.UsrCod=%ld"
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod"
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod"
" AND crs_grp_types.CrsCod=%ld)",
UsrDat->UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.CurrentCrs.Crs.CrsCod);
Cached.UsrSharesAnyOfMyGrpsInCurrentCrs = DB_QueryCOUNT (Query,"can not check"
" if a user shares any group"
" in the current course with you") != 0;
return Cached.UsrSharesAnyOfMyGrpsInCurrentCrs;
}

View File

@ -148,8 +148,8 @@ void Grp_ChangeGrpsOtherUsrAtomically (struct ListCodGrps *LstGrpsUsrWants);
bool Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid (Rol_Role_t Role,struct ListCodGrps *LstGrps); bool Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid (Rol_Role_t Role,struct ListCodGrps *LstGrps);
void Grp_RegisterUsrIntoGroups (struct UsrData *UsrDat,struct ListCodGrps *LstGrps); void Grp_RegisterUsrIntoGroups (struct UsrData *UsrDat,struct ListCodGrps *LstGrps);
unsigned Grp_RemoveUsrFromGroups (struct UsrData *UsrDat,struct ListCodGrps *LstGrps); unsigned Grp_RemoveUsrFromGroups (struct UsrData *UsrDat,struct ListCodGrps *LstGrps);
void Grp_RemUsrFromAllGrpsInCrs (struct UsrData *UsrDat,struct Course *Crs); void Grp_RemUsrFromAllGrpsInCrs (long UsrCod,long CrsCod);
void Grp_RemUsrFromAllGrps (struct UsrData *UsrDat); void Grp_RemUsrFromAllGrps (long UsrCod);
void Grp_ListGrpsToEditAsgAttOrSvy (struct GroupType *GrpTyp,long Cod,Grp_AsgOrSvy_t Grp_AsgOrSvy); void Grp_ListGrpsToEditAsgAttOrSvy (struct GroupType *GrpTyp,long Cod,Grp_AsgOrSvy_t Grp_AsgOrSvy);
void Grp_ReqRegisterInGrps (void); void Grp_ReqRegisterInGrps (void);
@ -166,7 +166,12 @@ void Grp_GetDataOfGroupByCod (struct GroupData *GrpDat);
bool Grp_CheckIfGroupExists (long GrpCod); bool Grp_CheckIfGroupExists (long GrpCod);
bool Grp_CheckIfGroupBelongsToCourse (long GrpCod,long CrsCod); bool Grp_CheckIfGroupBelongsToCourse (long GrpCod,long CrsCod);
unsigned Grp_CountNumUsrsInGrp (Rol_Role_t Role,long GrpCod); unsigned Grp_CountNumUsrsInGrp (Rol_Role_t Role,long GrpCod);
void Grp_FlushCacheIBelongToGrp (void);
bool Grp_GetIfIBelongToGrp (long GrpCod); bool Grp_GetIfIBelongToGrp (long GrpCod);
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (void);
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat);
unsigned Grp_NumGrpTypesMandatIDontBelongAsStd (void); unsigned Grp_NumGrpTypesMandatIDontBelongAsStd (void);
void Grp_GetLstCodGrpsWithFileZonesIBelong (struct ListCodGrps *LstGrps); void Grp_GetLstCodGrpsWithFileZonesIBelong (struct ListCodGrps *LstGrps);
void Grp_GetNamesGrpsStdBelongsTo (long GrpTypCod,long UsrCod,char *GrpNames); void Grp_GetNamesGrpsStdBelongsTo (long GrpTypCod,long UsrCod,char *GrpNames);
@ -199,6 +204,4 @@ void Grp_PutParamWhichGrpsAllGrps (void);
void Grp_ShowFormToSelWhichGrps (Act_Action_t Action,void (*FuncParams) ()); void Grp_ShowFormToSelWhichGrps (Act_Action_t Action,void (*FuncParams) ());
void Grp_GetParamWhichGrps (void); void Grp_GetParamWhichGrps (void);
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat);
#endif #endif

View File

@ -80,8 +80,8 @@ static void Ins_GetParamInsOrder (void);
static void Ins_PutIconToViewInstitutions (void); static void Ins_PutIconToViewInstitutions (void);
static void Ins_GetFullNameAndCtyOfInstitutionByCod (struct Instit *Ins, static void Ins_GetFullNameAndCtyOfInstitution (struct Instit *Ins,
char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]); char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]);
static void Ins_ListInstitutionsForEdition (void); static void Ins_ListInstitutionsForEdition (void);
static bool Ins_CheckIfICanEdit (struct Instit *Ins); static bool Ins_CheckIfICanEdit (struct Instit *Ins);
@ -1098,7 +1098,7 @@ void Ins_WriteInstitutionNameAndCty (long InsCod)
/***** Get institution full name *****/ /***** Get institution full name *****/
Ins.InsCod = InsCod; Ins.InsCod = InsCod;
Ins_GetFullNameAndCtyOfInstitutionByCod (&Ins,CtyName); Ins_GetFullNameAndCtyOfInstitution (&Ins,CtyName);
/***** Write institution full name *****/ /***** Write institution full name *****/
fprintf (Gbl.F.Out,"%s<br />%s",Ins.FullName,CtyName); fprintf (Gbl.F.Out,"%s<br />%s",Ins.FullName,CtyName);
@ -1194,116 +1194,127 @@ bool Ins_GetDataOfInstitutionByCod (struct Instit *Ins,
/*********** Get the short name of an institution from its code **************/ /*********** Get the short name of an institution from its code **************/
/*****************************************************************************/ /*****************************************************************************/
void Ins_GetShortNameOfInstitutionByCod (struct Instit *Ins) void Ins_FlushCacheShortNameOfInstitution (void)
{
Gbl.Cache.InstitutionShrtName.InsCod = -1L;
Gbl.Cache.InstitutionShrtName.ShrtName[0] = '\0';
}
void Ins_GetShortNameOfInstitution (struct Instit *Ins)
{ {
char Query[128]; char Query[128];
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
static struct
{
long InsCod;
char ShrtName[Hie_MAX_BYTES_SHRT_NAME + 1];
} Cached =
{
-1L,
{'\0'}
};
/***** 1. Fast check: Trivial case *****/
if (Ins->InsCod <= 0) if (Ins->InsCod <= 0)
Ins->ShrtName[0] = '\0'; // Empty name
else
{ {
if (Ins->InsCod != Cached.InsCod) // If not cached... Ins->ShrtName[0] = '\0'; // Empty name
{ return;
/***** Get the short name of an institution from database *****/ }
sprintf (Query,"SELECT ShortName FROM institutions WHERE InsCod=%ld",
Ins->InsCod);
if (DB_QuerySELECT (Query,&mysql_res,"can not get the short name of an institution") == 1)
{
/***** Get the short name of this institution *****/
row = mysql_fetch_row (mysql_res);
Str_Copy (Cached.ShrtName,row[0], /***** 2. Fast check: If cached... *****/
Hie_MAX_BYTES_SHRT_NAME); if (Ins->InsCod == Gbl.Cache.InstitutionShrtName.InsCod)
} {
else Str_Copy (Ins->ShrtName,Gbl.Cache.InstitutionShrtName.ShrtName,
Cached.ShrtName[0] = '\0'; Hie_MAX_BYTES_SHRT_NAME);
return;
}
/***** Free structure that stores the query result *****/ /***** 3. Slow: get short name of institution from database *****/
DB_FreeMySQLResult (&mysql_res); Gbl.Cache.InstitutionShrtName.InsCod = Ins->InsCod;
}
Str_Copy (Ins->ShrtName,Cached.ShrtName, sprintf (Query,"SELECT ShortName FROM institutions WHERE InsCod=%ld",
Ins->InsCod);
if (DB_QuerySELECT (Query,&mysql_res,"can not get the short name of an institution") == 1)
{
/* Get the short name of this institution */
row = mysql_fetch_row (mysql_res);
Str_Copy (Gbl.Cache.InstitutionShrtName.ShrtName,row[0],
Hie_MAX_BYTES_SHRT_NAME); Hie_MAX_BYTES_SHRT_NAME);
} }
else
Gbl.Cache.InstitutionShrtName.ShrtName[0] = '\0';
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
Str_Copy (Ins->ShrtName,Gbl.Cache.InstitutionShrtName.ShrtName,
Hie_MAX_BYTES_SHRT_NAME);
} }
/*****************************************************************************/ /*****************************************************************************/
/************ Get the full name of an institution from its code **************/ /************ Get the full name of an institution from its code **************/
/*****************************************************************************/ /*****************************************************************************/
static void Ins_GetFullNameAndCtyOfInstitutionByCod (struct Instit *Ins, void Ins_FlushCacheFullNameAndCtyOfInstitution (void)
char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]) {
Gbl.Cache.InstitutionFullNameAndCty.InsCod = -1L;
Gbl.Cache.InstitutionFullNameAndCty.FullName[0] = '\0';
Gbl.Cache.InstitutionFullNameAndCty.CtyName[0] = '\0';
}
static void Ins_GetFullNameAndCtyOfInstitution (struct Instit *Ins,
char CtyName[Hie_MAX_BYTES_FULL_NAME + 1])
{ {
extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES];
char Query[512]; char Query[512];
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
static struct
{
long InsCod;
char FullName[Hie_MAX_BYTES_FULL_NAME + 1];
char CtyName[Hie_MAX_BYTES_FULL_NAME + 1];
} Cached =
{
-1L,
{'\0'},
{'\0'},
};
/***** 1. Fast check: Trivial case *****/
if (Ins->InsCod <= 0) if (Ins->InsCod <= 0)
{ {
Ins->FullName[0] = '\0'; // Empty name Ins->FullName[0] = '\0'; // Empty name
CtyName[0] = '\0'; // Empty name CtyName[0] = '\0'; // Empty name
return;
}
/***** 2. Fast check: If cached... *****/
if (Ins->InsCod == Gbl.Cache.InstitutionFullNameAndCty.InsCod)
{
Str_Copy (Ins->FullName,Gbl.Cache.InstitutionFullNameAndCty.FullName,
Hie_MAX_BYTES_FULL_NAME);
Str_Copy (CtyName,Gbl.Cache.InstitutionFullNameAndCty.CtyName,
Hie_MAX_BYTES_FULL_NAME);
return;
}
/***** 3. Slow: get full name and country of institution from database *****/
Gbl.Cache.InstitutionFullNameAndCty.InsCod = Ins->InsCod;
sprintf (Query,"SELECT institutions.FullName,countries.Name_%s"
" FROM institutions,countries"
" WHERE institutions.InsCod=%ld"
" AND institutions.CtyCod=countries.CtyCod",
Txt_STR_LANG_ID[Gbl.Prefs.Language],Ins->InsCod);
if (DB_QuerySELECT (Query,&mysql_res,"can not get the full name of an institution") == 1)
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get the full name of this institution (row[0]) */
Str_Copy (Gbl.Cache.InstitutionFullNameAndCty.FullName,row[0],
Hie_MAX_BYTES_FULL_NAME);
/* Get the name of the country (row[1]) */
Str_Copy (Gbl.Cache.InstitutionFullNameAndCty.CtyName,row[1],
Hie_MAX_BYTES_FULL_NAME);
} }
else else
{ {
if (Ins->InsCod != Cached.InsCod) // If not cached... Gbl.Cache.InstitutionFullNameAndCty.FullName[0] = '\0';
{ Gbl.Cache.InstitutionFullNameAndCty.CtyName[0] = '\0';
/***** Get the short name of an institution from database *****/
sprintf (Query,"SELECT institutions.FullName,countries.Name_%s"
" FROM institutions,countries"
" WHERE institutions.InsCod=%ld"
" AND institutions.CtyCod=countries.CtyCod",
Txt_STR_LANG_ID[Gbl.Prefs.Language],Ins->InsCod);
if (DB_QuerySELECT (Query,&mysql_res,"can not get the full name of an institution") == 1)
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get the full name of this institution (row[0]) */
Str_Copy (Cached.FullName,row[0],
Hie_MAX_BYTES_FULL_NAME);
/* Get the name of the country (row[1]) */
Str_Copy (Cached.CtyName,row[1],
Hie_MAX_BYTES_FULL_NAME);
}
else
{
Cached.FullName[0] = '\0';
Cached.CtyName[0] = '\0';
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
Str_Copy (Ins->FullName,Cached.FullName,
Hie_MAX_BYTES_FULL_NAME);
Str_Copy (CtyName,Cached.CtyName,
Hie_MAX_BYTES_FULL_NAME);
} }
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
Str_Copy (Ins->FullName,Gbl.Cache.InstitutionFullNameAndCty.FullName,
Hie_MAX_BYTES_FULL_NAME);
Str_Copy (CtyName,Gbl.Cache.InstitutionFullNameAndCty.CtyName,
Hie_MAX_BYTES_FULL_NAME);
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1711,6 +1722,10 @@ void Ins_RemoveInstitution (void)
Ins.InsCod); Ins.InsCod);
DB_QueryDELETE (Query,"can not remove an institution"); DB_QueryDELETE (Query,"can not remove an institution");
/***** Flush caches *****/
Ins_FlushCacheShortNameOfInstitution ();
Ins_FlushCacheFullNameAndCtyOfInstitution ();
/***** Write message to show the change made *****/ /***** Write message to show the change made *****/
sprintf (Gbl.Alert.Txt,Txt_Institution_X_removed, sprintf (Gbl.Alert.Txt,Txt_Institution_X_removed,
Ins.FullName); Ins.FullName);
@ -1859,6 +1874,10 @@ static void Ins_UpdateInsNameDB (long InsCod,const char *FieldName,const char *N
sprintf (Query,"UPDATE institutions SET %s='%s' WHERE InsCod=%ld", sprintf (Query,"UPDATE institutions SET %s='%s' WHERE InsCod=%ld",
FieldName,NewInsName,InsCod); FieldName,NewInsName,InsCod);
DB_QueryUPDATE (Query,"can not update the name of an institution"); DB_QueryUPDATE (Query,"can not update the name of an institution");
/***** Flush caches *****/
Ins_FlushCacheShortNameOfInstitution ();
Ins_FlushCacheFullNameAndCtyOfInstitution ();
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -106,7 +106,9 @@ void Ins_GetListInstitutions (long CtyCod,Ins_GetExtraData_t GetExtraData);
void Ins_WriteInstitutionNameAndCty (long InsCod); void Ins_WriteInstitutionNameAndCty (long InsCod);
bool Ins_GetDataOfInstitutionByCod (struct Instit *Ins, bool Ins_GetDataOfInstitutionByCod (struct Instit *Ins,
Ins_GetExtraData_t GetExtraData); Ins_GetExtraData_t GetExtraData);
void Ins_GetShortNameOfInstitutionByCod (struct Instit *Ins); void Ins_FlushCacheShortNameOfInstitution (void);
void Ins_GetShortNameOfInstitution (struct Instit *Ins);
void Ins_FlushCacheFullNameAndCtyOfInstitution (void);
void Ins_FreeListInstitutions (void); void Ins_FreeListInstitutions (void);
void Ins_WriteSelectorOfInstitution (void); void Ins_WriteSelectorOfInstitution (void);

View File

@ -285,8 +285,9 @@ bool Prf_ShowUserProfile (struct UsrData *UsrDat)
Gbl.CurrentCrs.Crs.CrsCod > 0) // ...and a course is selected Gbl.CurrentCrs.Crs.CrsCod > 0) // ...and a course is selected
{ {
/* Get user's role in current course */ /* Get user's role in current course */
UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod,UsrDat->UsrCod); UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod,
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; Gbl.CurrentCrs.Crs.CrsCod);
UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
/* Get if user has accepted enrolment in current course */ /* Get if user has accepted enrolment in current course */
UsrDat->Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (UsrDat); UsrDat->Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (UsrDat);

View File

@ -2139,7 +2139,7 @@ void Rec_ShowFormOtherNewSharedRecord (struct UsrData *UsrDat,Rol_Role_t Default
Instead it is initialized with the preferred role. */ Instead it is initialized with the preferred role. */
UsrDat->Roles.InCurrentCrs.Role = (Gbl.CurrentCrs.Crs.CrsCod > 0) ? DefaultRole : // Course selected UsrDat->Roles.InCurrentCrs.Role = (Gbl.CurrentCrs.Crs.CrsCod > 0) ? DefaultRole : // Course selected
Rol_UNK; // No course selected Rol_UNK; // No course selected
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
Rec_ShowSharedUsrRecord (Rec_SHA_OTHER_NEW_USR_FORM,UsrDat,NULL); Rec_ShowSharedUsrRecord (Rec_SHA_OTHER_NEW_USR_FORM,UsrDat,NULL);
} }

View File

@ -68,10 +68,10 @@ void Rol_SetMyRoles (void)
bool ICanBeDegAdm = false; bool ICanBeDegAdm = false;
/***** Get my role in current course if not yet filled *****/ /***** Get my role in current course if not yet filled *****/
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod != Gbl.Usrs.Me.UsrDat.UsrCod) if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod != Gbl.Usrs.Me.UsrDat.UsrCod)
{ {
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetMyRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod); Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetMyRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod);
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
} }
/***** Set the user's role I am logged *****/ /***** Set the user's role I am logged *****/
@ -179,7 +179,7 @@ void Rol_SetMyRoles (void)
if (!(Gbl.Usrs.Me.Role.Available & (1 << Gbl.Usrs.Me.Role.Logged))) // Current type I am logged is not available for me if (!(Gbl.Usrs.Me.Role.Available & (1 << Gbl.Usrs.Me.Role.Logged))) // Current type I am logged is not available for me
/* Set the lowest role available for me */ /* Set the lowest role available for me */
for (Gbl.Usrs.Me.Role.Logged = Rol_UNK; for (Gbl.Usrs.Me.Role.Logged = Rol_UNK;
Gbl.Usrs.Me.Role.Logged < Rol_NUM_ROLES; Gbl.Usrs.Me.Role.Logged <= (Rol_Role_t) (Rol_NUM_ROLES - 1);
Gbl.Usrs.Me.Role.Logged++) Gbl.Usrs.Me.Role.Logged++)
if (Gbl.Usrs.Me.Role.Available & (1 << Gbl.Usrs.Me.Role.Logged)) if (Gbl.Usrs.Me.Role.Available & (1 << Gbl.Usrs.Me.Role.Logged))
break; break;
@ -326,50 +326,45 @@ Rol_Role_t Rol_GetMyRoleInCrs (long CrsCod)
/********************** Get role of a user in a course ***********************/ /********************** Get role of a user in a course ***********************/
/*****************************************************************************/ /*****************************************************************************/
Rol_Role_t Rol_GetRoleInCrs (long CrsCod,long UsrCod) void Rol_FlushCacheRoleUsrInCrs (void)
{
Gbl.Cache.RoleUsrInCrs.UsrCod = -1L;
Gbl.Cache.RoleUsrInCrs.CrsCod = -1L;
Gbl.Cache.RoleUsrInCrs.Role = Rol_UNK;
}
Rol_Role_t Rol_GetRoleUsrInCrs (long UsrCod,long CrsCod)
{ {
char Query[256]; char Query[256];
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
static struct
{
long CrsCod;
long UsrCod;
Rol_Role_t RoleInCrs;
} Cached =
{
-1L,
-1L,
Rol_UNK,
}; // A cache. If this function is called consecutive times
// with the same user, only the first time is slow
/***** 1. Fast check: trivial cases *****/ /***** 1. Fast check: trivial cases *****/
if (CrsCod <= 0 || if (UsrCod <= 0 ||
UsrCod <= 0) CrsCod <= 0)
return Rol_UNK; return Rol_UNK;
/***** 2. Fast check: Is role in course already calculated *****/ /***** 2. Fast check: Is role in course already calculated *****/
if (CrsCod == Cached.CrsCod && if (UsrCod == Gbl.Cache.RoleUsrInCrs.UsrCod &&
UsrCod == Cached.UsrCod) CrsCod == Gbl.Cache.RoleUsrInCrs.CrsCod )
return Cached.RoleInCrs; return Gbl.Cache.RoleUsrInCrs.Role;
/***** 3. Slow check: Get rol of a user in a course from database. /***** 3. Slow check: Get rol of a user in a course from database.
The result of the query will have one row or none *****/ The result of the query will have one row or none *****/
Cached.UsrCod = UsrCod; Gbl.Cache.RoleUsrInCrs.UsrCod = UsrCod;
Cached.CrsCod = CrsCod; Gbl.Cache.RoleUsrInCrs.CrsCod = CrsCod;
Cached.RoleInCrs = Rol_UNK; Gbl.Cache.RoleUsrInCrs.Role = Rol_UNK;
sprintf (Query,"SELECT Role FROM crs_usr" sprintf (Query,"SELECT Role FROM crs_usr"
" WHERE CrsCod=%ld AND UsrCod=%ld", " WHERE CrsCod=%ld AND UsrCod=%ld",
CrsCod,UsrCod); CrsCod,UsrCod);
if (DB_QuerySELECT (Query,&mysql_res,"can not get the role of a user in a course") == 1) // User belongs to the course if (DB_QuerySELECT (Query,&mysql_res,"can not get the role of a user in a course") == 1) // User belongs to the course
{ {
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
Cached.RoleInCrs = Rol_ConvertUnsignedStrToRole (row[0]); Gbl.Cache.RoleUsrInCrs.Role = Rol_ConvertUnsignedStrToRole (row[0]);
} }
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);
return Cached.RoleInCrs; return Gbl.Cache.RoleUsrInCrs.Role;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -45,7 +45,8 @@ Rol_Role_t Rol_GetMyMaxRoleInIns (long InsCod);
Rol_Role_t Rol_GetMyMaxRoleInCtr (long CtrCod); Rol_Role_t Rol_GetMyMaxRoleInCtr (long CtrCod);
Rol_Role_t Rol_GetMyMaxRoleInDeg (long DegCod); Rol_Role_t Rol_GetMyMaxRoleInDeg (long DegCod);
Rol_Role_t Rol_GetMyRoleInCrs (long CrsCod); Rol_Role_t Rol_GetMyRoleInCrs (long CrsCod);
Rol_Role_t Rol_GetRoleInCrs (long CrsCod,long UsrCod); void Rol_FlushCacheRoleUsrInCrs (void);
Rol_Role_t Rol_GetRoleUsrInCrs (long UsrCod,long CrsCod);
void Rol_GetRolesInAllCrssIfNotYetGot (struct UsrData *UsrDat); void Rol_GetRolesInAllCrssIfNotYetGot (struct UsrData *UsrDat);
Rol_Role_t Rol_ConvertUnsignedStrToRole (const char *UnsignedStr); Rol_Role_t Rol_ConvertUnsignedStrToRole (const char *UnsignedStr);

View File

@ -296,7 +296,7 @@ void Usr_ResetUsrDataExceptUsrCodAndIDs (struct UsrData *UsrDat)
UsrDat->Nickname[0] = '\0'; UsrDat->Nickname[0] = '\0';
UsrDat->Password[0] = '\0'; UsrDat->Password[0] = '\0';
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = -1L; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = -1L;
UsrDat->Roles.InCrss = -1; // < 0 ==> not yet got from database UsrDat->Roles.InCrss = -1; // < 0 ==> not yet got from database
UsrDat->Accepted = true; UsrDat->Accepted = true;
@ -520,9 +520,9 @@ void Usr_GetUsrDataFromUsrCod (struct UsrData *UsrDat)
Pwd_BYTES_ENCRYPTED_PASSWORD); Pwd_BYTES_ENCRYPTED_PASSWORD);
/* Get roles */ /* Get roles */
UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod, UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod,
UsrDat->UsrCod); Gbl.CurrentCrs.Crs.CrsCod);
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
UsrDat->Roles.InCrss = -1; // Force roles to be got from database UsrDat->Roles.InCrss = -1; // Force roles to be got from database
Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); Rol_GetRolesInAllCrssIfNotYetGot (UsrDat);
@ -801,37 +801,32 @@ bool Usr_CheckIfUsrIsAdm (long UsrCod,Sco_Scope_t Scope,long Cod)
/********************* Check if a user is a superuser ************************/ /********************* Check if a user is a superuser ************************/
/*****************************************************************************/ /*****************************************************************************/
void Usr_FlushCacheUsrIsSuperuser (void)
{
Gbl.Cache.UsrIsSuperuser.UsrCod = -1L;
Gbl.Cache.UsrIsSuperuser.IsSuperuser = false;
}
bool Usr_CheckIfUsrIsSuperuser (long UsrCod) bool Usr_CheckIfUsrIsSuperuser (long UsrCod)
{ {
extern const char *Sco_ScopeDB[Sco_NUM_SCOPES]; extern const char *Sco_ScopeDB[Sco_NUM_SCOPES];
char Query[256]; char Query[256];
static struct
{
long UsrCod;
bool IsSuperuser;
} Cached =
{
-1L,
false
};
/***** 1. Fast check: Trivial case *****/
if (UsrCod <= 0) if (UsrCod <= 0)
{ return false;
/***** Trivial case *****/
Cached.UsrCod = -1L;
Cached.IsSuperuser = false;
}
else if (UsrCod != Cached.UsrCod) // If not cached...
{
/***** Get if a user is superuser from database *****/
sprintf (Query,"SELECT COUNT(*) FROM admin"
" WHERE UsrCod=%ld AND Scope='%s'",
UsrCod,Sco_ScopeDB[Sco_SCOPE_SYS]);
Cached.UsrCod = UsrCod;
Cached.IsSuperuser = (DB_QueryCOUNT (Query,"can not check if a user is superuser") != 0);
}
return Cached.IsSuperuser; /***** 2. Fast check: If cached... *****/
if (UsrCod == Gbl.Cache.UsrIsSuperuser.UsrCod)
return Gbl.Cache.UsrIsSuperuser.IsSuperuser;
/***** 3. Slow check: If not cached, get if a user is superuser from database *****/
sprintf (Query,"SELECT COUNT(*) FROM admin"
" WHERE UsrCod=%ld AND Scope='%s'",
UsrCod,Sco_ScopeDB[Sco_SCOPE_SYS]);
Gbl.Cache.UsrIsSuperuser.UsrCod = UsrCod;
Gbl.Cache.UsrIsSuperuser.IsSuperuser = (DB_QueryCOUNT (Query,"can not check if a user is superuser") != 0);
return Gbl.Cache.UsrIsSuperuser.IsSuperuser;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1168,19 +1163,15 @@ bool Usr_CheckIfICanViewUsrAgenda (struct UsrData *UsrDat)
/*************** Check if a user belongs to any of my courses ****************/ /*************** Check if a user belongs to any of my courses ****************/
/*****************************************************************************/ /*****************************************************************************/
void Usr_FlushCacheUsrSharesAnyOfMyCrs (void)
{
Gbl.Cache.UsrSharesAnyOfMyCrs.UsrCod = -1L;
Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs = false;
}
bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat) bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat)
{ {
char Query[256]; char Query[256];
static struct
{
long UsrCod;
bool UsrSharesAnyOfMyCrs;
} Cached =
{
-1L,
false
}; // A cache. If this function is called consecutive times
// with the same user, only the first time is slow
/***** 1. Fast check: Am I logged? *****/ /***** 1. Fast check: Am I logged? *****/
if (!Gbl.Usrs.Me.Logged) if (!Gbl.Usrs.Me.Logged)
@ -1195,8 +1186,8 @@ bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat)
return true; return true;
/***** 4. Fast check: Is already calculated if user shares any course with me? *****/ /***** 4. Fast check: Is already calculated if user shares any course with me? *****/
if (UsrDat->UsrCod == Cached.UsrCod) if (UsrDat->UsrCod == Gbl.Cache.UsrSharesAnyOfMyCrs.UsrCod)
return Cached.UsrSharesAnyOfMyCrs; return Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs;
/***** 5. Fast check: Is course selected and we both belong to it? *****/ /***** 5. Fast check: Is course selected and we both belong to it? *****/
if (Gbl.Usrs.Me.IBelongToCurrentCrs) if (Gbl.Usrs.Me.IBelongToCurrentCrs)
@ -1219,9 +1210,9 @@ bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat)
" WHERE UsrCod=%ld" " WHERE UsrCod=%ld"
" AND CrsCod IN (SELECT CrsCod FROM my_courses_tmp)", " AND CrsCod IN (SELECT CrsCod FROM my_courses_tmp)",
UsrDat->UsrCod); UsrDat->UsrCod);
Cached.UsrSharesAnyOfMyCrs = DB_QueryCOUNT (Query,"can not check if a user shares any course with you") != 0; Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs = DB_QueryCOUNT (Query,"can not check if a user shares any course with you") != 0;
Cached.UsrCod = UsrDat->UsrCod; Gbl.Cache.UsrSharesAnyOfMyCrs.UsrCod = UsrDat->UsrCod;
return Cached.UsrSharesAnyOfMyCrs; return Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1622,36 +1613,26 @@ static void Usr_RemoveTemporaryTableMyCourses (void)
/**************** Check if a user belongs to an institution ******************/ /**************** Check if a user belongs to an institution ******************/
/*****************************************************************************/ /*****************************************************************************/
void Usr_FlushCacheUsrBelongsToIns (void)
{
Gbl.Cache.UsrBelongsToIns.UsrCod = -1L;
Gbl.Cache.UsrBelongsToIns.InsCod = -1L;
Gbl.Cache.UsrBelongsToIns.Belongs = false;
}
bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod) bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod)
{ {
char Query[512]; char Query[512];
static struct
{
long UsrCod;
long InsCod;
bool Belongs;
} Cached =
{
-1L,
-1L,
false
};
/***** 1. Fast check: Trivial case *****/ /***** 1. Fast check: Trivial case *****/
if (UsrCod <= 0 || if (UsrCod <= 0 ||
InsCod <= 0) InsCod <= 0)
{ return false;
/***** Trivial case *****/
Cached.UsrCod = -1L;
Cached.InsCod = -1L;
Cached.Belongs = false;
return Cached.Belongs;
}
/***** 2. Fast check: If cached... *****/ /***** 2. Fast check: If cached... *****/
if (UsrCod == Cached.UsrCod && if (UsrCod == Gbl.Cache.UsrBelongsToIns.UsrCod &&
InsCod != Cached.InsCod) InsCod != Gbl.Cache.UsrBelongsToIns.InsCod)
return Cached.Belongs; return Gbl.Cache.UsrBelongsToIns.Belongs;
/***** 3. Slow check: Get is user belongs to institution from database *****/ /***** 3. Slow check: Get is user belongs to institution from database *****/
sprintf (Query,"SELECT COUNT(DISTINCT centres.InsCod)" sprintf (Query,"SELECT COUNT(DISTINCT centres.InsCod)"
@ -1663,45 +1644,36 @@ bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod)
" AND degrees.CtrCod=centres.CtrCod" " AND degrees.CtrCod=centres.CtrCod"
" AND centres.InsCod=%ld", " AND centres.InsCod=%ld",
UsrCod,InsCod); UsrCod,InsCod);
Cached.UsrCod = UsrCod; Gbl.Cache.UsrBelongsToIns.UsrCod = UsrCod;
Cached.InsCod = InsCod; Gbl.Cache.UsrBelongsToIns.InsCod = InsCod;
Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to an institution") != 0); Gbl.Cache.UsrBelongsToIns.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to an institution") != 0);
return Cached.Belongs; return Gbl.Cache.UsrBelongsToIns.Belongs;
} }
/*****************************************************************************/ /*****************************************************************************/
/******************* Check if a user belongs to a centre *********************/ /******************* Check if a user belongs to a centre *********************/
/*****************************************************************************/ /*****************************************************************************/
void Usr_FlushCacheUsrBelongsToCtr (void)
{
Gbl.Cache.UsrBelongsToCtr.UsrCod = -1L;
Gbl.Cache.UsrBelongsToCtr.CtrCod = -1L;
Gbl.Cache.UsrBelongsToCtr.Belongs = false;
}
bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod) bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod)
{ {
char Query[512]; char Query[512];
static struct
{
long UsrCod;
long CtrCod;
bool Belongs;
} Cached =
{
-1L,
-1L,
false
};
/***** 1. Fast check: Trivial case *****/ /***** 1. Fast check: Trivial case *****/
if (UsrCod <= 0 || if (UsrCod <= 0 ||
CtrCod <= 0) CtrCod <= 0)
{ return false;
Cached.UsrCod = -1L;
Cached.CtrCod = -1L;
Cached.Belongs = false;
return Cached.Belongs;
}
/***** 2. Fast check: If cached... *****/ /***** 2. Fast check: If cached... *****/
if (UsrCod == Cached.UsrCod && if (UsrCod == Gbl.Cache.UsrBelongsToCtr.UsrCod &&
CtrCod == Cached.CtrCod) CtrCod == Gbl.Cache.UsrBelongsToCtr.CtrCod)
return Cached.Belongs; return Gbl.Cache.UsrBelongsToCtr.Belongs;
/***** 3. Slow check: Get is user belongs to centre from database *****/ /***** 3. Slow check: Get is user belongs to centre from database *****/
sprintf (Query,"SELECT COUNT(DISTINCT degrees.CtrCod)" sprintf (Query,"SELECT COUNT(DISTINCT degrees.CtrCod)"
@ -1712,45 +1684,36 @@ bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod)
" AND courses.DegCod=degrees.DegCod" " AND courses.DegCod=degrees.DegCod"
" AND degrees.CtrCod=%ld", " AND degrees.CtrCod=%ld",
UsrCod,CtrCod); UsrCod,CtrCod);
Cached.UsrCod = UsrCod; Gbl.Cache.UsrBelongsToCtr.UsrCod = UsrCod;
Cached.CtrCod = CtrCod; Gbl.Cache.UsrBelongsToCtr.CtrCod = CtrCod;
Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a centre") != 0); Gbl.Cache.UsrBelongsToCtr.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a centre") != 0);
return Cached.Belongs; return Gbl.Cache.UsrBelongsToCtr.Belongs;
} }
/*****************************************************************************/ /*****************************************************************************/
/******************* Check if a user belongs to a degree *********************/ /******************* Check if a user belongs to a degree *********************/
/*****************************************************************************/ /*****************************************************************************/
void Usr_FlushCacheUsrBelongsToDeg (void)
{
Gbl.Cache.UsrBelongsToDeg.UsrCod = -1L;
Gbl.Cache.UsrBelongsToDeg.DegCod = -1L;
Gbl.Cache.UsrBelongsToDeg.Belongs = false;
}
bool Usr_CheckIfUsrBelongsToDeg (long UsrCod,long DegCod) bool Usr_CheckIfUsrBelongsToDeg (long UsrCod,long DegCod)
{ {
char Query[512]; char Query[512];
static struct
{
long UsrCod;
long DegCod;
bool Belongs;
} Cached =
{
-1L,
-1L,
false
};
/***** 1. Fast check: Trivial case *****/ /***** 1. Fast check: Trivial case *****/
if (UsrCod <= 0 || if (UsrCod <= 0 ||
DegCod <= 0) DegCod <= 0)
{ return false;
Cached.UsrCod = -1L;
Cached.DegCod = -1L;
Cached.Belongs = false;
return Cached.Belongs;
}
/***** 2. Fast check: If cached... *****/ /***** 2. Fast check: If cached... *****/
if (UsrCod == Cached.UsrCod && if (UsrCod == Gbl.Cache.UsrBelongsToDeg.UsrCod &&
DegCod == Cached.DegCod) DegCod == Gbl.Cache.UsrBelongsToDeg.DegCod)
return Cached.Belongs; return Gbl.Cache.UsrBelongsToDeg.Belongs;
/***** 3. Slow check: Get if user belongs to degree from database *****/ /***** 3. Slow check: Get if user belongs to degree from database *****/
sprintf (Query,"SELECT COUNT(DISTINCT courses.DegCod)" sprintf (Query,"SELECT COUNT(DISTINCT courses.DegCod)"
@ -1760,138 +1723,40 @@ bool Usr_CheckIfUsrBelongsToDeg (long UsrCod,long DegCod)
" AND crs_usr.CrsCod=courses.CrsCod" " AND crs_usr.CrsCod=courses.CrsCod"
" AND courses.DegCod=%ld", " AND courses.DegCod=%ld",
UsrCod,DegCod); UsrCod,DegCod);
Cached.UsrCod = UsrCod; Gbl.Cache.UsrBelongsToDeg.UsrCod = UsrCod;
Cached.DegCod = DegCod; Gbl.Cache.UsrBelongsToDeg.DegCod = DegCod;
Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a degree") != 0); Gbl.Cache.UsrBelongsToDeg.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a degree") != 0);
return Cached.Belongs; return Gbl.Cache.UsrBelongsToDeg.Belongs;
}
/*****************************************************************************/
/***** Check if user belongs (no matter if he/she has accepted or not) *******/
/***** to the current course *******/
/*****************************************************************************/
bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat)
{
static struct
{
long UsrCod;
bool Belongs;
} Cached =
{
-1L,
false
};
/***** 1. Fast check: trivial cases *****/
if (UsrDat->UsrCod <= 0 ||
Gbl.CurrentCrs.Crs.CrsCod <= 0)
{
Cached.UsrCod = -1L;
Cached.Belongs = false;
return Cached.Belongs;
}
/***** 2. Fast check: If cached... *****/
if (UsrDat->UsrCod == Cached.UsrCod)
return Cached.Belongs;
/***** 3. Fast check: If we know role of user in the current course *****/
if (UsrDat->Roles.InCurrentCrs.UsrCod == UsrDat->UsrCod)
{
Cached.UsrCod = UsrDat->UsrCod;
Cached.Belongs = UsrDat->Roles.InCurrentCrs.Role == Rol_STD ||
UsrDat->Roles.InCurrentCrs.Role == Rol_NET ||
UsrDat->Roles.InCurrentCrs.Role == Rol_TCH;
return Cached.Belongs;
}
/***** 4. Fast / slow check: Get if user belongs to current course *****/
Cached.UsrCod = UsrDat->UsrCod;
Cached.Belongs = Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
false);
return Cached.Belongs;
}
/*****************************************************************************/
/***** Check if user belongs (no matter if he/she has accepted or not) *******/
/***** to the current course *******/
/*****************************************************************************/
bool Usr_CheckIfUsrHasAcceptedInCurrentCrs (const struct UsrData *UsrDat)
{
static struct
{
long UsrCod;
bool Accepted;
} Cached =
{
-1L,
false
};
/***** 1. Fast check: trivial cases *****/
if (UsrDat->UsrCod <= 0 ||
Gbl.CurrentCrs.Crs.CrsCod <= 0)
{
Cached.UsrCod = -1L;
Cached.Accepted = false;
return Cached.Accepted;
}
/***** 2. Fast check: If cached... *****/
if (UsrDat->UsrCod == Cached.UsrCod)
return Cached.Accepted;
/***** 3. Fast / slow check: Get if user belongs to current course
and has accepted *****/
Cached.UsrCod = UsrDat->UsrCod;
Cached.Accepted = Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
true);
return Cached.Accepted;
} }
/*****************************************************************************/ /*****************************************************************************/
/******************** Check if a user belongs to a course ********************/ /******************** Check if a user belongs to a course ********************/
/*****************************************************************************/ /*****************************************************************************/
void Usr_FlushCacheUsrBelongsToCrs (void)
{
Gbl.Cache.UsrBelongsToCrs.UsrCod = -1L;
Gbl.Cache.UsrBelongsToCrs.CrsCod = -1L;
Gbl.Cache.UsrBelongsToCrs.CountOnlyAcceptedCourses = false;
Gbl.Cache.UsrBelongsToCrs.Belongs = false;
}
bool Usr_CheckIfUsrBelongsToCrs (long UsrCod,long CrsCod, bool Usr_CheckIfUsrBelongsToCrs (long UsrCod,long CrsCod,
bool CountOnlyAcceptedCourses) bool CountOnlyAcceptedCourses)
{ {
char Query[512]; char Query[512];
const char *SubQuery; const char *SubQuery;
static struct
{
long UsrCod;
long CrsCod;
bool CountOnlyAcceptedCourses;
bool Belongs;
} Cached =
{
-1L,
-1L,
false,
false
};
/***** 1. Fast check: trivial cases *****/ /***** 1. Fast check: Trivial cases *****/
if (UsrCod <= 0 || if (UsrCod <= 0 ||
CrsCod <= 0) CrsCod <= 0)
{ return false;
Cached.UsrCod = -1L;
Cached.CrsCod = -1L;
Cached.CountOnlyAcceptedCourses = CountOnlyAcceptedCourses;
Cached.Belongs = false;
return Cached.Belongs;
}
/***** 2. Fast check: If cached... *****/ /***** 2. Fast check: If cached... *****/
if (UsrCod == Cached.UsrCod && if (UsrCod == Gbl.Cache.UsrBelongsToCrs.UsrCod &&
CrsCod == Cached.CrsCod && CrsCod == Gbl.Cache.UsrBelongsToCrs.CrsCod &&
CountOnlyAcceptedCourses == Cached.CountOnlyAcceptedCourses) CountOnlyAcceptedCourses == Gbl.Cache.UsrBelongsToCrs.CountOnlyAcceptedCourses)
return Cached.Belongs; return Gbl.Cache.UsrBelongsToCrs.Belongs;
/***** 3. Slow check: Get if user belongs to course from database *****/ /***** 3. Slow check: Get if user belongs to course from database *****/
SubQuery = (CountOnlyAcceptedCourses ? " AND crs_usr.Accepted='Y'" : SubQuery = (CountOnlyAcceptedCourses ? " AND crs_usr.Accepted='Y'" :
@ -1899,11 +1764,82 @@ bool Usr_CheckIfUsrBelongsToCrs (long UsrCod,long CrsCod,
sprintf (Query,"SELECT COUNT(*) FROM crs_usr" sprintf (Query,"SELECT COUNT(*) FROM crs_usr"
" WHERE CrsCod=%ld AND UsrCod=%ld%s", " WHERE CrsCod=%ld AND UsrCod=%ld%s",
CrsCod,UsrCod,SubQuery); CrsCod,UsrCod,SubQuery);
Cached.UsrCod = UsrCod; Gbl.Cache.UsrBelongsToCrs.UsrCod = UsrCod;
Cached.CrsCod = CrsCod; Gbl.Cache.UsrBelongsToCrs.CrsCod = CrsCod;
Cached.CountOnlyAcceptedCourses = CountOnlyAcceptedCourses; Gbl.Cache.UsrBelongsToCrs.CountOnlyAcceptedCourses = CountOnlyAcceptedCourses;
Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a course") != 0); Gbl.Cache.UsrBelongsToCrs.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a course") != 0);
return Cached.Belongs; return Gbl.Cache.UsrBelongsToCrs.Belongs;
}
/*****************************************************************************/
/***** Check if user belongs (no matter if he/she has accepted or not) *******/
/***** to the current course *******/
/*****************************************************************************/
void Usr_FlushCacheUsrBelongsToCurrentCrs (void)
{
Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = -1L;
Gbl.Cache.UsrBelongsToCurrentCrs.Belongs = false;
}
bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat)
{
/***** 1. Fast check: Trivial cases *****/
if (UsrDat->UsrCod <= 0 ||
Gbl.CurrentCrs.Crs.CrsCod <= 0)
return false;
/***** 2. Fast check: If cached... *****/
if (UsrDat->UsrCod == Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod)
return Gbl.Cache.UsrBelongsToCurrentCrs.Belongs;
/***** 3. Fast check: If we know role of user in the current course *****/
if (UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod == UsrDat->UsrCod)
{
Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = UsrDat->UsrCod;
Gbl.Cache.UsrBelongsToCurrentCrs.Belongs = UsrDat->Roles.InCurrentCrs.Role == Rol_STD ||
UsrDat->Roles.InCurrentCrs.Role == Rol_NET ||
UsrDat->Roles.InCurrentCrs.Role == Rol_TCH;
return Gbl.Cache.UsrBelongsToCurrentCrs.Belongs;
}
/***** 4. Fast / slow check: Get if user belongs to current course *****/
Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = UsrDat->UsrCod;
Gbl.Cache.UsrBelongsToCurrentCrs.Belongs = Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
false);
return Gbl.Cache.UsrBelongsToCurrentCrs.Belongs;
}
/*****************************************************************************/
/***** Check if user belongs (no matter if he/she has accepted or not) *******/
/***** to the current course *******/
/*****************************************************************************/
void Usr_FlushCacheUsrHasAcceptedInCurrentCrs (void)
{
Gbl.Cache.UsrHasAcceptedInCurrentCrs.UsrCod = -1L;
Gbl.Cache.UsrHasAcceptedInCurrentCrs.Accepted = false;
}
bool Usr_CheckIfUsrHasAcceptedInCurrentCrs (const struct UsrData *UsrDat)
{
/***** 1. Fast check: Trivial cases *****/
if (UsrDat->UsrCod <= 0 ||
Gbl.CurrentCrs.Crs.CrsCod <= 0)
return false;
/***** 2. Fast check: If cached... *****/
if (UsrDat->UsrCod == Gbl.Cache.UsrHasAcceptedInCurrentCrs.UsrCod)
return Gbl.Cache.UsrHasAcceptedInCurrentCrs.Accepted;
/***** 3. Fast / slow check: Get if user belongs to current course
and has accepted *****/
Gbl.Cache.UsrHasAcceptedInCurrentCrs.UsrCod = UsrDat->UsrCod;
Gbl.Cache.UsrHasAcceptedInCurrentCrs.Accepted = Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
true);
return Gbl.Cache.UsrHasAcceptedInCurrentCrs.Accepted;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -3111,9 +3047,9 @@ static void Usr_SetMyPrefsAndRoles (void)
Hie_InitHierarchy (); Hie_InitHierarchy ();
/* Get again my role in this course */ /* Get again my role in this course */
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod); Gbl.CurrentCrs.Crs.CrsCod);
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
} }
} }

View File

@ -133,7 +133,7 @@ struct UsrData
{ {
struct struct
{ {
long UsrCod; // Role was got from database for this user (used to not retrieve role if already retrieved) long GotFromDBForUsrCod; // Role was got from database for this user (used to not retrieve role if already retrieved)
Rol_Role_t Role; Rol_Role_t Role;
} InCurrentCrs; // Role in current course (Rol_UNK is no course selected) } InCurrentCrs; // Role in current course (Rol_UNK is no course selected)
int InCrss; // Roles in all his/her courses int InCrss; // Roles in all his/her courses
@ -244,6 +244,7 @@ void Usr_BuildFullName (struct UsrData *UsrDat);
void Usr_WriteFirstNameBRSurnames (const struct UsrData *UsrDat); void Usr_WriteFirstNameBRSurnames (const struct UsrData *UsrDat);
bool Usr_CheckIfUsrIsAdm (long UsrCod,Sco_Scope_t Scope,long Cod); bool Usr_CheckIfUsrIsAdm (long UsrCod,Sco_Scope_t Scope,long Cod);
void Usr_FlushCacheUsrIsSuperuser (void);
bool Usr_CheckIfUsrIsSuperuser (long UsrCod); bool Usr_CheckIfUsrIsSuperuser (long UsrCod);
bool Usr_ICanChangeOtherUsrData (const struct UsrData *UsrDat); bool Usr_ICanChangeOtherUsrData (const struct UsrData *UsrDat);
@ -257,12 +258,15 @@ unsigned Usr_GetNumCrssOfUsrWithARoleNotAccepted (long UsrCod,Rol_Role_t Role);
unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole,
Rol_Role_t OthersRole); Rol_Role_t OthersRole);
void Usr_FlushCacheUsrBelongsToCurrentCrs (void);
bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat); bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat);
void Usr_FlushCacheUsrHasAcceptedInCurrentCrs (void);
bool Usr_CheckIfUsrHasAcceptedInCurrentCrs (const struct UsrData *UsrDat); bool Usr_CheckIfUsrHasAcceptedInCurrentCrs (const struct UsrData *UsrDat);
bool Usr_CheckIfICanViewRecordStd (const struct UsrData *UsrDat); bool Usr_CheckIfICanViewRecordStd (const struct UsrData *UsrDat);
bool Usr_CheckIfICanViewRecordTch (struct UsrData *UsrDat); bool Usr_CheckIfICanViewRecordTch (struct UsrData *UsrDat);
bool Usr_CheckIfICanViewWrkTstAtt (const struct UsrData *UsrDat); bool Usr_CheckIfICanViewWrkTstAtt (const struct UsrData *UsrDat);
bool Usr_CheckIfICanViewUsrAgenda (struct UsrData *UsrDat); bool Usr_CheckIfICanViewUsrAgenda (struct UsrData *UsrDat);
void Usr_FlushCacheUsrSharesAnyOfMyCrs (void);
bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat); bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat);
bool Usr_CheckIfUsrSharesAnyOfMyCrsWithDifferentRole (long UsrCod); bool Usr_CheckIfUsrSharesAnyOfMyCrsWithDifferentRole (long UsrCod);
@ -278,9 +282,13 @@ void Usr_FreeMyCentres (void);
void Usr_FreeMyDegrees (void); void Usr_FreeMyDegrees (void);
void Usr_FreeMyCourses (void); void Usr_FreeMyCourses (void);
void Usr_FlushCacheUsrBelongsToIns (void);
bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod); bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod);
void Usr_FlushCacheUsrBelongsToCtr (void);
bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod); bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod);
void Usr_FlushCacheUsrBelongsToDeg (void);
bool Usr_CheckIfUsrBelongsToDeg (long UsrCod,long DegCod); bool Usr_CheckIfUsrBelongsToDeg (long UsrCod,long DegCod);
void Usr_FlushCacheUsrBelongsToCrs (void);
bool Usr_CheckIfUsrBelongsToCrs (long UsrCod,long CrsCod, bool Usr_CheckIfUsrBelongsToCrs (long UsrCod,long CrsCod,
bool CountOnlyAcceptedCourses); bool CountOnlyAcceptedCourses);

View File

@ -594,18 +594,18 @@ static bool Svc_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod)
{ {
if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) != 1) if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) != 1)
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
} }
else // Impossible else // Impossible
{ {
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
} }
} }
else // User does not belong to course else // User does not belong to course
{ {
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
} }
} }
else else
@ -621,19 +621,19 @@ static bool Svc_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod)
{ {
if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) != 1) if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) != 1)
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
} }
else else
// MAX(Role) == NULL if user does not belong to any course // MAX(Role) == NULL if user does not belong to any course
{ {
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
} }
} }
else // Impossible else // Impossible
{ {
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod;
} }
} }