From f639ebb425d528aea743457fb73587663dd150f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Tue, 20 Jun 2017 14:43:26 +0200 Subject: [PATCH] Version 16.247 --- swad_account.c | 2 +- swad_changelog.h | 4 +- swad_connected.c | 2 +- swad_country.c | 73 ++++---- swad_country.h | 1 + swad_enrolment.c | 55 ++++-- swad_global.c | 17 ++ swad_global.h | 82 +++++++++ swad_group.c | 205 +++++++++++++---------- swad_group.h | 11 +- swad_institution.c | 181 +++++++++++--------- swad_institution.h | 4 +- swad_profile.c | 5 +- swad_record.c | 2 +- swad_role.c | 49 +++--- swad_role.h | 3 +- swad_user.c | 408 +++++++++++++++++++-------------------------- swad_user.h | 10 +- swad_web_service.c | 12 +- 19 files changed, 627 insertions(+), 499 deletions(-) diff --git a/swad_account.c b/swad_account.c index 2ad0b329..93b4e1b3 100644 --- a/swad_account.c +++ b/swad_account.c @@ -1002,7 +1002,7 @@ void Acc_CompletelyEliminateAccount (struct UsrData *UsrDat, Att_RemoveUsrFromAllAttEvents (UsrDat->UsrCod); /***** Remove user from all the groups of all courses *****/ - Grp_RemUsrFromAllGrps (UsrDat); + Grp_RemUsrFromAllGrps (UsrDat->UsrCod); /***** Remove user's requests for inscription *****/ sprintf (Query,"DELETE FROM crs_usr_requests WHERE UsrCod=%ld", diff --git a/swad_changelog.h b/swad_changelog.h index aaa7cb96..ebf7e8c4 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -236,13 +236,15 @@ /****************************** 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 JS_FILE "swad16.206.3.js" // 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 /* + 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.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) diff --git a/swad_connected.c b/swad_connected.c index d46c683e..9b0164af 100644 --- a/swad_connected.c +++ b/swad_connected.c @@ -287,7 +287,7 @@ void Con_GetAndShowLastClicks (void) /* Get institution code (row[5]) */ Ins.InsCod = Str_ConvertStrCodToLongCod (row[5]); - Ins_GetShortNameOfInstitutionByCod (&Ins); + Ins_GetShortNameOfInstitution (&Ins); /* Get centre code (row[6]) */ Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[6]); diff --git a/swad_country.c b/swad_country.c index dca1cacd..91abd90b 100644 --- a/swad_country.c +++ b/swad_country.c @@ -1403,53 +1403,56 @@ bool Cty_GetDataOfCountryByCod (struct Country *Cty,Cty_GetExtraData_t GetExtraD /***************************** 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]) { extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; char Query[128]; MYSQL_RES *mysql_res; 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) - CtyName[0] = '\0'; // Empty name - else { - if (CtyCod != Cached.CtyCod) // If not cached... - { - Cached.CtyCod = CtyCod; + CtyName[0] = '\0'; // Empty name + return; + } - /***** Get name of the country from database *****/ - sprintf (Query,"SELECT Name_%s FROM countries WHERE CtyCod='%03ld'", - 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); + /***** 2. Fast check: If cached... *****/ + if (CtyCod == Gbl.Cache.CountryName.CtyCod) + { + Str_Copy (CtyName,Gbl.Cache.CountryName.CtyName, + Cty_MAX_BYTES_NAME); + return; + } - /* Get the name of the country */ - Str_Copy (Cached.CtyName,row[0], - Cty_MAX_BYTES_NAME); - } - else - Cached.CtyName[0] = '\0'; + /***** 3. Slow: get country name from database *****/ + Gbl.Cache.CountryName.CtyCod = CtyCod; - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - } + sprintf (Query,"SELECT Name_%s FROM countries WHERE CtyCod='%03ld'", + 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); } + 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); DB_QueryDELETE (Query,"can not remove a country"); + /***** Flush cache *****/ + Cty_FlushCacheCountryName (); + /***** Write message to show the change made *****/ sprintf (Gbl.Alert.Txt,Txt_Country_X_removed, 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'", FieldName,NewCtyName,CtyCod); DB_QueryUPDATE (Query,"can not update the name of a country"); + + /***** Flush cache *****/ + Cty_FlushCacheCountryName (); } /*****************************************************************************/ diff --git a/swad_country.h b/swad_country.h index 01c89c6b..bddfd8f2 100644 --- a/swad_country.h +++ b/swad_country.h @@ -99,6 +99,7 @@ void Cty_FreeListCountries (void); void Cty_WriteSelectorOfCountry (void); void Cty_WriteCountryName (long CtyCod,const char *ClassLink); 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_PutParamCtyCod (long CtyCod); long Cty_GetAndCheckParamOtherCtyCod (long MinCodAllowed); diff --git a/swad_enrolment.c b/swad_enrolment.c index eb015807..0e4972b5 100644 --- a/swad_enrolment.c +++ b/swad_enrolment.c @@ -175,8 +175,8 @@ void Enr_PutButtonInlineToRegisterStds (long CrsCod) { extern const char *Txt_Register_students; - if (Rol_GetRoleInCrs (CrsCod,Gbl.Usrs.Me.UsrDat.UsrCod) == Rol_TCH) // I am a teacher in course - if (!Usr_GetNumUsrsInCrs (Rol_STD,CrsCod)) // No students 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 { Act_FormStart (ActReqEnrSevStd); Crs_PutParamCrsCod (CrsCod); @@ -231,7 +231,7 @@ void Enr_ModifyRoleInCurrentCrs (struct UsrData *UsrDat,Rol_Role_t NewRole) Enr_NotifyAfterEnrolment (UsrDat,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 Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles } @@ -280,7 +280,7 @@ void Enr_RegisterUsrInCurrentCrs (struct UsrData *UsrDat,Rol_Role_t NewRole, 'N'); DB_QueryINSERT (Query,"can not register user in course"); 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 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_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, "config64x64.gif", @@ -3922,7 +3922,7 @@ void Enr_ModifyUsr1 (void) if (ItsMe) { 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; 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_User_not_found_or_you_do_not_have_permission_; char Query[1024]; - bool ItsMe; + bool ItsMe = (UsrDat->UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); if (Usr_CheckIfUsrBelongsToCurrentCrs (UsrDat)) { @@ -4142,7 +4142,7 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,struct Course * Att_RemoveUsrFromCrsAttEvents (UsrDat->UsrCod,Crs->CrsCod); /***** 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 *****/ Inf_RemoveUsrFromCrsInfoRead (UsrDat->UsrCod,Crs->CrsCod); @@ -4170,13 +4170,44 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,struct Course * Crs->CrsCod,UsrDat->UsrCod); 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 *****/ - ItsMe = (UsrDat->UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); if (ItsMe) { - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod = UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; - Gbl.Usrs.Me.UsrDat.Roles.InCrss = UsrDat->Roles.InCrss = -1; // not yet filled/calculated + /* Flush caches */ + Grp_FlushCacheIBelongToGrp (); + + /* 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 (); } diff --git a/swad_global.c b/swad_global.c index 4b1217ac..91904052 100644 --- a/swad_global.c +++ b/swad_global.c @@ -42,6 +42,7 @@ #include "swad_icon.h" #include "swad_parameter.h" #include "swad_preference.h" +#include "swad_role.h" #include "swad_theme.h" #include "swad_web_service.h" @@ -440,6 +441,22 @@ void Gbl_InitializeGlobals (void) Gbl.WebService.Function = Svc_unknown; 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 (); } /*****************************************************************************/ diff --git a/swad_global.h b/swad_global.h index 473e110b..e73a5b9c 100644 --- a/swad_global.h +++ b/swad_global.h @@ -747,6 +747,88 @@ struct Globals { char *Str; } 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; }; /*****************************************************************************/ diff --git a/swad_group.c b/swad_group.c index 9e790be8..ef9692e5 100644 --- a/swad_group.c +++ b/swad_group.c @@ -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_Y_groups; 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 *****/ 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 *****************/ /*****************************************************************************/ -void Grp_RemUsrFromAllGrpsInCrs (struct UsrData *UsrDat,struct Course *Crs) +void Grp_RemUsrFromAllGrpsInCrs (long UsrCod,long CrsCod) { char Query[512]; + bool ItsMe = (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); /***** Remove user from all the groups of the course *****/ 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" " WHERE crs_grp_types.CrsCod=%ld" " 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"); + + /***** Flush caches *****/ + Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (); + if (ItsMe) + Grp_FlushCacheIBelongToGrp (); } /*****************************************************************************/ /******* 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]; + bool ItsMe = (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); /***** Remove user from all groups *****/ 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"); + + /***** 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) { char Query[256]; + bool ItsMe = (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); /***** Remove user from group *****/ sprintf (Query,"DELETE FROM crs_grp_usr" " WHERE GrpCod=%ld AND UsrCod=%ld", GrpCod,UsrCod); 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) { 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? *****/ - if (GrpCod == Cached.GrpCod) - return Cached.IBelongToGrp; + /***** 1. Fast check: Trivial case *****/ + if (GrpCod <= 0) + 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" " WHERE GrpCod=%ld AND UsrCod=%ld", GrpCod,Gbl.Usrs.Me.UsrDat.UsrCod); - Cached.IBelongToGrp = DB_QueryCOUNT (Query,"can not check if you belong to a group") != 0; - Cached.GrpCod = GrpCod; - return Cached.IBelongToGrp; + Gbl.Cache.IBelongToGrp.IBelong = DB_QueryCOUNT (Query,"can not check if you belong to a group") != 0; + Gbl.Cache.IBelongToGrp.GrpCod = GrpCod; + 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; } } - -/*****************************************************************************/ -/*************** 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; - } diff --git a/swad_group.h b/swad_group.h index 5d400d8e..12bc3ab8 100644 --- a/swad_group.h +++ b/swad_group.h @@ -148,8 +148,8 @@ void Grp_ChangeGrpsOtherUsrAtomically (struct ListCodGrps *LstGrpsUsrWants); bool Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid (Rol_Role_t Role,struct ListCodGrps *LstGrps); void Grp_RegisterUsrIntoGroups (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_RemUsrFromAllGrps (struct UsrData *UsrDat); +void Grp_RemUsrFromAllGrpsInCrs (long UsrCod,long CrsCod); +void Grp_RemUsrFromAllGrps (long UsrCod); void Grp_ListGrpsToEditAsgAttOrSvy (struct GroupType *GrpTyp,long Cod,Grp_AsgOrSvy_t Grp_AsgOrSvy); void Grp_ReqRegisterInGrps (void); @@ -166,7 +166,12 @@ void Grp_GetDataOfGroupByCod (struct GroupData *GrpDat); bool Grp_CheckIfGroupExists (long GrpCod); bool Grp_CheckIfGroupBelongsToCourse (long GrpCod,long CrsCod); unsigned Grp_CountNumUsrsInGrp (Rol_Role_t Role,long GrpCod); + +void Grp_FlushCacheIBelongToGrp (void); bool Grp_GetIfIBelongToGrp (long GrpCod); +void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (void); +bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat); + unsigned Grp_NumGrpTypesMandatIDontBelongAsStd (void); void Grp_GetLstCodGrpsWithFileZonesIBelong (struct ListCodGrps *LstGrps); 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_GetParamWhichGrps (void); -bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat); - #endif diff --git a/swad_institution.c b/swad_institution.c index 5c2b508a..67091cd4 100644 --- a/swad_institution.c +++ b/swad_institution.c @@ -80,8 +80,8 @@ static void Ins_GetParamInsOrder (void); static void Ins_PutIconToViewInstitutions (void); -static void Ins_GetFullNameAndCtyOfInstitutionByCod (struct Instit *Ins, - char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]); +static void Ins_GetFullNameAndCtyOfInstitution (struct Instit *Ins, + char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]); static void Ins_ListInstitutionsForEdition (void); static bool Ins_CheckIfICanEdit (struct Instit *Ins); @@ -1098,7 +1098,7 @@ void Ins_WriteInstitutionNameAndCty (long InsCod) /***** Get institution full name *****/ Ins.InsCod = InsCod; - Ins_GetFullNameAndCtyOfInstitutionByCod (&Ins,CtyName); + Ins_GetFullNameAndCtyOfInstitution (&Ins,CtyName); /***** Write institution full name *****/ fprintf (Gbl.F.Out,"%s
%s",Ins.FullName,CtyName); @@ -1194,116 +1194,127 @@ bool Ins_GetDataOfInstitutionByCod (struct Instit *Ins, /*********** 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]; MYSQL_RES *mysql_res; 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) - Ins->ShrtName[0] = '\0'; // Empty name - else { - if (Ins->InsCod != Cached.InsCod) // If not cached... - { - /***** 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); + Ins->ShrtName[0] = '\0'; // Empty name + return; + } - Str_Copy (Cached.ShrtName,row[0], - Hie_MAX_BYTES_SHRT_NAME); - } - else - Cached.ShrtName[0] = '\0'; + /***** 2. Fast check: If cached... *****/ + if (Ins->InsCod == Gbl.Cache.InstitutionShrtName.InsCod) + { + Str_Copy (Ins->ShrtName,Gbl.Cache.InstitutionShrtName.ShrtName, + Hie_MAX_BYTES_SHRT_NAME); + return; + } - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - } + /***** 3. Slow: get short name of institution from database *****/ + 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); } + 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 **************/ /*****************************************************************************/ -static void Ins_GetFullNameAndCtyOfInstitutionByCod (struct Instit *Ins, - char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]) +void Ins_FlushCacheFullNameAndCtyOfInstitution (void) + { + 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]; char Query[512]; MYSQL_RES *mysql_res; 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) { Ins->FullName[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 { - if (Ins->InsCod != Cached.InsCod) // If not cached... - { - /***** 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); + Gbl.Cache.InstitutionFullNameAndCty.FullName[0] = '\0'; + Gbl.Cache.InstitutionFullNameAndCty.CtyName[0] = '\0'; } + + /* 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); DB_QueryDELETE (Query,"can not remove an institution"); + /***** Flush caches *****/ + Ins_FlushCacheShortNameOfInstitution (); + Ins_FlushCacheFullNameAndCtyOfInstitution (); + /***** Write message to show the change made *****/ sprintf (Gbl.Alert.Txt,Txt_Institution_X_removed, 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", FieldName,NewInsName,InsCod); DB_QueryUPDATE (Query,"can not update the name of an institution"); + + /***** Flush caches *****/ + Ins_FlushCacheShortNameOfInstitution (); + Ins_FlushCacheFullNameAndCtyOfInstitution (); } /*****************************************************************************/ diff --git a/swad_institution.h b/swad_institution.h index 70a3c719..b60e99ce 100644 --- a/swad_institution.h +++ b/swad_institution.h @@ -106,7 +106,9 @@ void Ins_GetListInstitutions (long CtyCod,Ins_GetExtraData_t GetExtraData); void Ins_WriteInstitutionNameAndCty (long InsCod); bool Ins_GetDataOfInstitutionByCod (struct Instit *Ins, 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_WriteSelectorOfInstitution (void); diff --git a/swad_profile.c b/swad_profile.c index e2174178..5f748aab 100644 --- a/swad_profile.c +++ b/swad_profile.c @@ -285,8 +285,9 @@ bool Prf_ShowUserProfile (struct UsrData *UsrDat) Gbl.CurrentCrs.Crs.CrsCod > 0) // ...and a course is selected { /* Get user's role in current course */ - UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod,UsrDat->UsrCod); - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, + Gbl.CurrentCrs.Crs.CrsCod); + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; /* Get if user has accepted enrolment in current course */ UsrDat->Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (UsrDat); diff --git a/swad_record.c b/swad_record.c index b6a9730c..8c3e0ae6 100644 --- a/swad_record.c +++ b/swad_record.c @@ -2139,7 +2139,7 @@ void Rec_ShowFormOtherNewSharedRecord (struct UsrData *UsrDat,Rol_Role_t Default Instead it is initialized with the preferred role. */ UsrDat->Roles.InCurrentCrs.Role = (Gbl.CurrentCrs.Crs.CrsCod > 0) ? DefaultRole : // 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); } diff --git a/swad_role.c b/swad_role.c index e440b391..dbe0415a 100644 --- a/swad_role.c +++ b/swad_role.c @@ -68,10 +68,10 @@ void Rol_SetMyRoles (void) bool ICanBeDegAdm = false; /***** 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.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetMyRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod); + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; } /***** 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 /* Set the lowest role available for me */ 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++) if (Gbl.Usrs.Me.Role.Available & (1 << Gbl.Usrs.Me.Role.Logged)) break; @@ -326,50 +326,45 @@ Rol_Role_t Rol_GetMyRoleInCrs (long CrsCod) /********************** 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]; MYSQL_RES *mysql_res; 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 *****/ - if (CrsCod <= 0 || - UsrCod <= 0) + if (UsrCod <= 0 || + CrsCod <= 0) return Rol_UNK; /***** 2. Fast check: Is role in course already calculated *****/ - if (CrsCod == Cached.CrsCod && - UsrCod == Cached.UsrCod) - return Cached.RoleInCrs; + if (UsrCod == Gbl.Cache.RoleUsrInCrs.UsrCod && + CrsCod == Gbl.Cache.RoleUsrInCrs.CrsCod ) + return Gbl.Cache.RoleUsrInCrs.Role; /***** 3. Slow check: Get rol of a user in a course from database. The result of the query will have one row or none *****/ - Cached.UsrCod = UsrCod; - Cached.CrsCod = CrsCod; - Cached.RoleInCrs = Rol_UNK; + Gbl.Cache.RoleUsrInCrs.UsrCod = UsrCod; + Gbl.Cache.RoleUsrInCrs.CrsCod = CrsCod; + Gbl.Cache.RoleUsrInCrs.Role = Rol_UNK; sprintf (Query,"SELECT Role FROM crs_usr" " WHERE CrsCod=%ld AND UsrCod=%ld", 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 { row = mysql_fetch_row (mysql_res); - Cached.RoleInCrs = Rol_ConvertUnsignedStrToRole (row[0]); + Gbl.Cache.RoleUsrInCrs.Role = Rol_ConvertUnsignedStrToRole (row[0]); } DB_FreeMySQLResult (&mysql_res); - return Cached.RoleInCrs; + return Gbl.Cache.RoleUsrInCrs.Role; } /*****************************************************************************/ diff --git a/swad_role.h b/swad_role.h index 964af070..90f395a8 100644 --- a/swad_role.h +++ b/swad_role.h @@ -45,7 +45,8 @@ Rol_Role_t Rol_GetMyMaxRoleInIns (long InsCod); Rol_Role_t Rol_GetMyMaxRoleInCtr (long CtrCod); Rol_Role_t Rol_GetMyMaxRoleInDeg (long DegCod); 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); Rol_Role_t Rol_ConvertUnsignedStrToRole (const char *UnsignedStr); diff --git a/swad_user.c b/swad_user.c index 2c606d86..a2d9bc08 100644 --- a/swad_user.c +++ b/swad_user.c @@ -296,7 +296,7 @@ void Usr_ResetUsrDataExceptUsrCodAndIDs (struct UsrData *UsrDat) UsrDat->Nickname[0] = '\0'; UsrDat->Password[0] = '\0'; 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->Accepted = true; @@ -520,9 +520,9 @@ void Usr_GetUsrDataFromUsrCod (struct UsrData *UsrDat) Pwd_BYTES_ENCRYPTED_PASSWORD); /* Get roles */ - UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod, - UsrDat->UsrCod); - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, + Gbl.CurrentCrs.Crs.CrsCod); + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; UsrDat->Roles.InCrss = -1; // Force roles to be got from database 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 ************************/ /*****************************************************************************/ +void Usr_FlushCacheUsrIsSuperuser (void) + { + Gbl.Cache.UsrIsSuperuser.UsrCod = -1L; + Gbl.Cache.UsrIsSuperuser.IsSuperuser = false; + } + bool Usr_CheckIfUsrIsSuperuser (long UsrCod) { extern const char *Sco_ScopeDB[Sco_NUM_SCOPES]; char Query[256]; - static struct - { - long UsrCod; - bool IsSuperuser; - } Cached = - { - -1L, - false - }; + /***** 1. Fast check: Trivial case *****/ if (UsrCod <= 0) - { - /***** 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 false; - 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 ****************/ /*****************************************************************************/ +void Usr_FlushCacheUsrSharesAnyOfMyCrs (void) + { + Gbl.Cache.UsrSharesAnyOfMyCrs.UsrCod = -1L; + Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs = false; + } + bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat) { 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? *****/ if (!Gbl.Usrs.Me.Logged) @@ -1195,8 +1186,8 @@ bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat) return true; /***** 4. Fast check: Is already calculated if user shares any course with me? *****/ - if (UsrDat->UsrCod == Cached.UsrCod) - return Cached.UsrSharesAnyOfMyCrs; + if (UsrDat->UsrCod == Gbl.Cache.UsrSharesAnyOfMyCrs.UsrCod) + return Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs; /***** 5. Fast check: Is course selected and we both belong to it? *****/ if (Gbl.Usrs.Me.IBelongToCurrentCrs) @@ -1219,9 +1210,9 @@ bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat) " WHERE UsrCod=%ld" " AND CrsCod IN (SELECT CrsCod FROM my_courses_tmp)", UsrDat->UsrCod); - Cached.UsrSharesAnyOfMyCrs = DB_QueryCOUNT (Query,"can not check if a user shares any course with you") != 0; - Cached.UsrCod = UsrDat->UsrCod; - return Cached.UsrSharesAnyOfMyCrs; + Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs = DB_QueryCOUNT (Query,"can not check if a user shares any course with you") != 0; + Gbl.Cache.UsrSharesAnyOfMyCrs.UsrCod = UsrDat->UsrCod; + return Gbl.Cache.UsrSharesAnyOfMyCrs.SharesAnyOfMyCrs; } /*****************************************************************************/ @@ -1622,36 +1613,26 @@ static void Usr_RemoveTemporaryTableMyCourses (void) /**************** 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) { char Query[512]; - static struct - { - long UsrCod; - long InsCod; - bool Belongs; - } Cached = - { - -1L, - -1L, - false - }; /***** 1. Fast check: Trivial case *****/ if (UsrCod <= 0 || InsCod <= 0) - { - /***** Trivial case *****/ - Cached.UsrCod = -1L; - Cached.InsCod = -1L; - Cached.Belongs = false; - return Cached.Belongs; - } + return false; /***** 2. Fast check: If cached... *****/ - if (UsrCod == Cached.UsrCod && - InsCod != Cached.InsCod) - return Cached.Belongs; + if (UsrCod == Gbl.Cache.UsrBelongsToIns.UsrCod && + InsCod != Gbl.Cache.UsrBelongsToIns.InsCod) + return Gbl.Cache.UsrBelongsToIns.Belongs; /***** 3. Slow check: Get is user belongs to institution from database *****/ sprintf (Query,"SELECT COUNT(DISTINCT centres.InsCod)" @@ -1663,45 +1644,36 @@ bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod) " AND degrees.CtrCod=centres.CtrCod" " AND centres.InsCod=%ld", UsrCod,InsCod); - Cached.UsrCod = UsrCod; - Cached.InsCod = InsCod; - Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to an institution") != 0); - return Cached.Belongs; + Gbl.Cache.UsrBelongsToIns.UsrCod = UsrCod; + Gbl.Cache.UsrBelongsToIns.InsCod = InsCod; + Gbl.Cache.UsrBelongsToIns.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to an institution") != 0); + return Gbl.Cache.UsrBelongsToIns.Belongs; } /*****************************************************************************/ /******************* 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) { char Query[512]; - static struct - { - long UsrCod; - long CtrCod; - bool Belongs; - } Cached = - { - -1L, - -1L, - false - }; /***** 1. Fast check: Trivial case *****/ if (UsrCod <= 0 || CtrCod <= 0) - { - Cached.UsrCod = -1L; - Cached.CtrCod = -1L; - Cached.Belongs = false; - return Cached.Belongs; - } + return false; /***** 2. Fast check: If cached... *****/ - if (UsrCod == Cached.UsrCod && - CtrCod == Cached.CtrCod) - return Cached.Belongs; + if (UsrCod == Gbl.Cache.UsrBelongsToCtr.UsrCod && + CtrCod == Gbl.Cache.UsrBelongsToCtr.CtrCod) + return Gbl.Cache.UsrBelongsToCtr.Belongs; /***** 3. Slow check: Get is user belongs to centre from database *****/ sprintf (Query,"SELECT COUNT(DISTINCT degrees.CtrCod)" @@ -1712,45 +1684,36 @@ bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod) " AND courses.DegCod=degrees.DegCod" " AND degrees.CtrCod=%ld", UsrCod,CtrCod); - Cached.UsrCod = UsrCod; - Cached.CtrCod = CtrCod; - Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a centre") != 0); - return Cached.Belongs; + Gbl.Cache.UsrBelongsToCtr.UsrCod = UsrCod; + Gbl.Cache.UsrBelongsToCtr.CtrCod = CtrCod; + Gbl.Cache.UsrBelongsToCtr.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a centre") != 0); + return Gbl.Cache.UsrBelongsToCtr.Belongs; } /*****************************************************************************/ /******************* 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) { char Query[512]; - static struct - { - long UsrCod; - long DegCod; - bool Belongs; - } Cached = - { - -1L, - -1L, - false - }; /***** 1. Fast check: Trivial case *****/ if (UsrCod <= 0 || DegCod <= 0) - { - Cached.UsrCod = -1L; - Cached.DegCod = -1L; - Cached.Belongs = false; - return Cached.Belongs; - } + return false; /***** 2. Fast check: If cached... *****/ - if (UsrCod == Cached.UsrCod && - DegCod == Cached.DegCod) - return Cached.Belongs; + if (UsrCod == Gbl.Cache.UsrBelongsToDeg.UsrCod && + DegCod == Gbl.Cache.UsrBelongsToDeg.DegCod) + return Gbl.Cache.UsrBelongsToDeg.Belongs; /***** 3. Slow check: Get if user belongs to degree from database *****/ 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 courses.DegCod=%ld", UsrCod,DegCod); - Cached.UsrCod = UsrCod; - Cached.DegCod = DegCod; - Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a degree") != 0); - return Cached.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; + Gbl.Cache.UsrBelongsToDeg.UsrCod = UsrCod; + Gbl.Cache.UsrBelongsToDeg.DegCod = DegCod; + Gbl.Cache.UsrBelongsToDeg.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a degree") != 0); + return Gbl.Cache.UsrBelongsToDeg.Belongs; } /*****************************************************************************/ /******************** 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 CountOnlyAcceptedCourses) { char Query[512]; 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 || CrsCod <= 0) - { - Cached.UsrCod = -1L; - Cached.CrsCod = -1L; - Cached.CountOnlyAcceptedCourses = CountOnlyAcceptedCourses; - Cached.Belongs = false; - return Cached.Belongs; - } + return false; /***** 2. Fast check: If cached... *****/ - if (UsrCod == Cached.UsrCod && - CrsCod == Cached.CrsCod && - CountOnlyAcceptedCourses == Cached.CountOnlyAcceptedCourses) - return Cached.Belongs; + if (UsrCod == Gbl.Cache.UsrBelongsToCrs.UsrCod && + CrsCod == Gbl.Cache.UsrBelongsToCrs.CrsCod && + CountOnlyAcceptedCourses == Gbl.Cache.UsrBelongsToCrs.CountOnlyAcceptedCourses) + return Gbl.Cache.UsrBelongsToCrs.Belongs; /***** 3. Slow check: Get if user belongs to course from database *****/ 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" " WHERE CrsCod=%ld AND UsrCod=%ld%s", CrsCod,UsrCod,SubQuery); - Cached.UsrCod = UsrCod; - Cached.CrsCod = CrsCod; - Cached.CountOnlyAcceptedCourses = CountOnlyAcceptedCourses; - Cached.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a course") != 0); - return Cached.Belongs; + Gbl.Cache.UsrBelongsToCrs.UsrCod = UsrCod; + Gbl.Cache.UsrBelongsToCrs.CrsCod = CrsCod; + Gbl.Cache.UsrBelongsToCrs.CountOnlyAcceptedCourses = CountOnlyAcceptedCourses; + Gbl.Cache.UsrBelongsToCrs.Belongs = (DB_QueryCOUNT (Query,"can not check if a user belongs to a course") != 0); + 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 (); /* Get again my role in this course */ - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetRoleInCrs (Gbl.CurrentCrs.Crs.CrsCod, - Gbl.Usrs.Me.UsrDat.UsrCod); - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (Gbl.Usrs.Me.UsrDat.UsrCod, + Gbl.CurrentCrs.Crs.CrsCod); + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.GotFromDBForUsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; } } diff --git a/swad_user.h b/swad_user.h index 573a3e9e..8970e169 100644 --- a/swad_user.h +++ b/swad_user.h @@ -133,7 +133,7 @@ struct UsrData { 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; } InCurrentCrs; // Role in current course (Rol_UNK is no course selected) 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); bool Usr_CheckIfUsrIsAdm (long UsrCod,Sco_Scope_t Scope,long Cod); +void Usr_FlushCacheUsrIsSuperuser (void); bool Usr_CheckIfUsrIsSuperuser (long UsrCod); 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, Rol_Role_t OthersRole); +void Usr_FlushCacheUsrBelongsToCurrentCrs (void); bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat); +void Usr_FlushCacheUsrHasAcceptedInCurrentCrs (void); bool Usr_CheckIfUsrHasAcceptedInCurrentCrs (const struct UsrData *UsrDat); bool Usr_CheckIfICanViewRecordStd (const struct UsrData *UsrDat); bool Usr_CheckIfICanViewRecordTch (struct UsrData *UsrDat); bool Usr_CheckIfICanViewWrkTstAtt (const struct UsrData *UsrDat); bool Usr_CheckIfICanViewUsrAgenda (struct UsrData *UsrDat); +void Usr_FlushCacheUsrSharesAnyOfMyCrs (void); bool Usr_CheckIfUsrSharesAnyOfMyCrs (struct UsrData *UsrDat); bool Usr_CheckIfUsrSharesAnyOfMyCrsWithDifferentRole (long UsrCod); @@ -278,9 +282,13 @@ void Usr_FreeMyCentres (void); void Usr_FreeMyDegrees (void); void Usr_FreeMyCourses (void); +void Usr_FlushCacheUsrBelongsToIns (void); bool Usr_CheckIfUsrBelongsToIns (long UsrCod,long InsCod); +void Usr_FlushCacheUsrBelongsToCtr (void); bool Usr_CheckIfUsrBelongsToCtr (long UsrCod,long CtrCod); +void Usr_FlushCacheUsrBelongsToDeg (void); bool Usr_CheckIfUsrBelongsToDeg (long UsrCod,long DegCod); +void Usr_FlushCacheUsrBelongsToCrs (void); bool Usr_CheckIfUsrBelongsToCrs (long UsrCod,long CrsCod, bool CountOnlyAcceptedCourses); diff --git a/swad_web_service.c b/swad_web_service.c index 174a628c..17c35fda 100644 --- a/swad_web_service.c +++ b/swad_web_service.c @@ -594,18 +594,18 @@ static bool Svc_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod) { if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) != 1) UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; } else // Impossible { 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 { UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; } } else @@ -621,19 +621,19 @@ static bool Svc_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod) { if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) != 1) UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; } else // MAX(Role) == NULL if user does not belong to any course { UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; } } else // Impossible { UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.UsrCod = UsrDat->UsrCod; + UsrDat->Roles.InCurrentCrs.GotFromDBForUsrCod = UsrDat->UsrCod; } }