diff --git a/html/install/index.html b/html/install/index.html index 7e24461c2..3734844ba 100644 --- a/html/install/index.html +++ b/html/install/index.html @@ -523,6 +523,34 @@ + + +

+ SWAD needs convert + (part of ImageMagick) + to convert the size and format of the images uploaded by users. +

+ + @@ -841,6 +869,12 @@

+

+ To allow the META tags in HTML content to override a charset choice, comment out this directive:
+ AddDefaultCharset UTF-8
+ by adding #:
+ #AddDefaultCharset UTF-8 +

Optionally, if we want to redirect from http://... to https://... diff --git a/sql/cambios.sql b/sql/cambios.sql index 5822b139e..348cd9a53 100644 --- a/sql/cambios.sql +++ b/sql/cambios.sql @@ -11597,3 +11597,16 @@ CREATE TABLE IF NOT EXISTS usr_duplicated (UsrCod INT NOT NULL,InformerCod INT N SELECT DISTINCT UsrCod FROM (SELECT DISTINCT UsrCod FROM usr_IDs WHERE UsrID IN (SELECT UsrID FROM usr_IDs WHERE UsrCod='1') UNION SELECT UsrCod FROM usr_data WHERE Surname1='' AND Surname2='' AND FirstName='') AS I; + + + + + + + + + + + + +SELECT * FROM file_view,files WHERE files.FileBrowser='9' AND files.Cod='-1' AND files.FilCod=file_view.FilCod; diff --git a/sql/swad.sql b/sql/swad.sql index ddb0ef58e..77458edb4 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -192,6 +192,7 @@ CREATE TABLE IF NOT EXISTS connected ( LastCrsCod INT NOT NULL DEFAULT -1, LastTime DATETIME NOT NULL, UNIQUE INDEX(UsrCod), + INDEX(RoleInLastCrs), INDEX(LastCrsCod)); -- -- Table countries: stores the countries diff --git a/swad_changelog.h b/swad_changelog.h index ee22db324..af2822596 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -139,13 +139,18 @@ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 15.256.3 (2016-09-19)" +#define Log_PLATFORM_VERSION "SWAD 16.0 (2016-09-22)" #define CSS_FILE "swad15.229.css" #define JS_FILE "swad15.238.1.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.0: Sep 22, 2016 Temporary table with my courses. + Added indexes to database. (204811 lines) + 1 change necessary in database: +ALTER TABLE connected ADD INDEX (RoleInLastCrs); + Version 15.256.3: Sep 19, 2016 Fixed bug in web service function sendAttendanceEvent, reported by Rubén Martín Hidalgo. (204755 lines) Version 15.256.2: Sep 19, 2016 Fixed bug in web service function removeAttendanceEvent, reported by Rubén Martín Hidalgo. (204750 lines) Version 15.256.1: Sep 19, 2016 Fixed bug in web service while sending a message. diff --git a/swad_database.c b/swad_database.c index 2edcd8267..c186a7c07 100644 --- a/swad_database.c +++ b/swad_database.c @@ -476,11 +476,11 @@ mysql> DESCRIBE connected; | Field | Type | Null | Key | Default | Extra | +---------------+------------+------+-----+---------+-------+ | UsrCod | int(11) | NO | PRI | NULL | | -| RoleInLastCrs | tinyint(4) | NO | | 0 | | +| RoleInLastCrs | tinyint(4) | NO | MUL | 0 | | | LastCrsCod | int(11) | NO | MUL | -1 | | | LastTime | datetime | NO | | NULL | | +---------------+------------+------+-----+---------+-------+ -4 rows in set (0.01 sec) +4 rows in set (0,00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS connected (" "UsrCod INT NOT NULL," @@ -488,6 +488,7 @@ mysql> DESCRIBE connected; "LastCrsCod INT NOT NULL DEFAULT -1," "LastTime DATETIME NOT NULL," "UNIQUE INDEX(UsrCod)," + "INDEX(RoleInLastCrs)," "INDEX(LastCrsCod))"); /***** Table countries *****/ diff --git a/swad_follow.c b/swad_follow.c index 1e9e4789f..9286edea4 100644 --- a/swad_follow.c +++ b/swad_follow.c @@ -125,7 +125,7 @@ void Fol_SuggestWhoToFollow (void) "(" "SELECT DISTINCT usr_follow.FollowedCod AS UsrCod" " FROM usr_follow," - " (SELECT FollowedCod FROM usr_follow" + "(SELECT FollowedCod FROM usr_follow" " WHERE FollowerCod='%ld') AS my_followed," " usr_data" " WHERE usr_follow.FollowerCod=my_followed.FollowedCod" @@ -142,7 +142,7 @@ void Fol_SuggestWhoToFollow (void) "(" "SELECT DISTINCT crs_usr.UsrCod" " FROM crs_usr," - " (SELECT CrsCod FROM crs_usr" + "(SELECT CrsCod FROM crs_usr" " WHERE UsrCod='%ld') AS my_crs," " usr_data" " WHERE crs_usr.CrsCod=my_crs.CrsCod" @@ -158,7 +158,7 @@ void Fol_SuggestWhoToFollow (void) "(" "SELECT DISTINCT crs_usr.UsrCod" " FROM crs_usr," - " (SELECT CrsCod,Role FROM crs_usr" + "(SELECT CrsCod,Role FROM crs_usr" " WHERE UsrCod='%ld') AS my_crs_role," " usr_data" " WHERE crs_usr.CrsCod=my_crs_role.CrsCod" diff --git a/swad_global.c b/swad_global.c index 807e508c1..83a1f557f 100644 --- a/swad_global.c +++ b/swad_global.c @@ -443,6 +443,7 @@ void Gbl_Cleanup (void) Act_Actions[Gbl.Action.Act].BrowserWindow == Act_MAIN_WINDOW && !Gbl.HiddenParamsInsertedIntoDB) Ses_RemoveHiddenParFromThisSession (); + Usr_FreeMyCourses (); Usr_UsrDataDestructor (&Gbl.Usrs.Me.UsrDat); Usr_UsrDataDestructor (&Gbl.Usrs.Other.UsrDat); Rec_FreeListFields (); diff --git a/swad_user.c b/swad_user.c index 3488e1df5..8f5af9486 100644 --- a/swad_user.c +++ b/swad_user.c @@ -115,6 +115,8 @@ static Usr_Sex_t Usr_GetSexFromStr (const char *Str); static bool Usr_CheckIfMyBirthdayHasNotBeenCongratulated (void); static void Usr_InsertMyBirthday (void); +static void Usr_RemoveTemporaryTableMyCourses (void); + static void Usr_GetParamOtherUsrIDNickOrEMail (void); static bool Usr_ChkUsrAndGetUsrDataFromDirectLogin (void); @@ -857,12 +859,12 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, // The temporary table achieves speedup from ~2s to few ms /***** Remove temporary table if exists *****/ - sprintf (Query,"DROP TEMPORARY TABLE IF EXISTS my_courses_tmp"); + sprintf (Query,"DROP TEMPORARY TABLE IF EXISTS usr_courses_tmp"); if (mysql_query (&Gbl.mysql,Query)) DB_ExitOnMySQLError ("can not remove temporary tables"); /***** Create temporary table with all my courses for a role *****/ - sprintf (Query,"CREATE TEMPORARY TABLE IF NOT EXISTS my_courses_tmp" + sprintf (Query,"CREATE TEMPORARY TABLE IF NOT EXISTS usr_courses_tmp" " (CrsCod INT NOT NULL,UNIQUE INDEX (CrsCod))" " ENGINE=MEMORY" " SELECT CrsCod FROM crs_usr" @@ -873,14 +875,14 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, /***** Get the number of teachers in a course from database ******/ sprintf (Query,"SELECT COUNT(DISTINCT crs_usr.UsrCod)" - " FROM crs_usr,my_courses_tmp" - " WHERE crs_usr.CrsCod=my_courses_tmp.CrsCod" + " FROM crs_usr,usr_courses_tmp" + " WHERE crs_usr.CrsCod=usr_courses_tmp.CrsCod" " AND crs_usr.Role='%u'", (unsigned) OthersRole); NumUsrs = (unsigned) DB_QueryCOUNT (Query,"can not get the number of users"); /***** Remove temporary table *****/ - sprintf (Query,"DROP TEMPORARY TABLE IF EXISTS my_courses_tmp"); + sprintf (Query,"DROP TEMPORARY TABLE IF EXISTS usr_courses_tmp"); if (mysql_query (&Gbl.mysql,Query)) DB_ExitOnMySQLError ("can not remove temporary tables"); @@ -893,13 +895,13 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, bool Usr_CheckIfUsrSharesAnyOfMyCrs (long UsrCod) { - char Query[512]; + char Query[256]; /***** Get if a user shares any course with me from database *****/ - sprintf (Query,"SELECT COUNT(*) FROM crs_usr WHERE UsrCod='%ld'" - " AND CrsCod IN" - " (SELECT CrsCod FROM crs_usr WHERE UsrCod='%ld')", - UsrCod,Gbl.Usrs.Me.UsrDat.UsrCod); + sprintf (Query,"SELECT COUNT(*) FROM crs_usr" + " WHERE UsrCod='%ld'" + " AND CrsCod IN (SELECT CrsCod FROM my_courses_tmp)", + UsrCod); return (DB_QueryCOUNT (Query,"can not check if a user shares any course with you") != 0); } @@ -912,12 +914,11 @@ bool Usr_CheckIfUsrSharesAnyOfMyCrsWithDifferentRole (long UsrCod) char Query[512]; /***** Get if a user shares any course with me from database *****/ - sprintf (Query,"SELECT COUNT(*) FROM" - "(SELECT CrsCod,Role FROM crs_usr WHERE UsrCod='%ld') AS my_courses," + sprintf (Query,"SELECT COUNT(*) FROM my_courses_tmp," "(SELECT CrsCod,Role FROM crs_usr WHERE UsrCod='%ld') AS usr_courses" - " WHERE my_courses.CrsCod=usr_courses.CrsCod" - " AND my_courses.Role<>usr_courses.Role", - Gbl.Usrs.Me.UsrDat.UsrCod,UsrCod); + " WHERE my_courses_tmp.CrsCod=usr_courses.CrsCod" + " AND my_courses_tmp.Role<>usr_courses.Role", + UsrCod); return (DB_QueryCOUNT (Query,"can not check if a user shares any course with you") != 0); } @@ -1068,6 +1069,7 @@ void Usr_GetMyDegrees (void) void Usr_GetMyCourses (void) { + char Query[512]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCrs; @@ -1079,36 +1081,92 @@ void Usr_GetMyCourses (void) { Gbl.Usrs.Me.MyCourses.Num = 0; - /***** Get my courses from database *****/ - if ((NumCrss = (unsigned) Usr_GetCrssFromUsr (Gbl.Usrs.Me.UsrDat.UsrCod,-1L,&mysql_res)) > 0) // Courses found - for (NumCrs = 0; - NumCrs < NumCrss; - NumCrs++) - { - /* Get next course */ - row = mysql_fetch_row (mysql_res); + if (Gbl.Usrs.Me.Logged) + { + /***** Remove temporary table with my courses *****/ + Usr_RemoveTemporaryTableMyCourses (); - /* Get course code */ - if ((CrsCod = Str_ConvertStrCodToLongCod (row[0])) > 0) - { - if (Gbl.Usrs.Me.MyCourses.Num == Crs_MAX_COURSES_PER_USR) - Lay_ShowErrorAndExit ("Maximum number of courses of a user exceeded."); + /***** Create temporary table with my courses *****/ + sprintf (Query,"CREATE TEMPORARY TABLE IF NOT EXISTS my_courses_tmp " + "(CrsCod INT NOT NULL," + "Role TINYINT NOT NULL," + "DegCod INT NOT NULL," + "UNIQUE INDEX(CrsCod),INDEX(Role)) ENGINE=MEMORY" + " SELECT crs_usr.CrsCod,crs_usr.Role,courses.DegCod" + " FROM crs_usr,courses,degrees" + " WHERE crs_usr.UsrCod='%ld'" + " AND crs_usr.CrsCod=courses.CrsCod" + " AND courses.DegCod=degrees.DegCod" + " ORDER BY degrees.ShortName,courses.ShortName", + Gbl.Usrs.Me.UsrDat.UsrCod); + if (mysql_query (&Gbl.mysql,Query)) + DB_ExitOnMySQLError ("can not create temporary table"); - Gbl.Usrs.Me.MyCourses.Crss[Gbl.Usrs.Me.MyCourses.Num].CrsCod = CrsCod; - Gbl.Usrs.Me.MyCourses.Crss[Gbl.Usrs.Me.MyCourses.Num].Role = Rol_ConvertUnsignedStrToRole (row[1]); - Gbl.Usrs.Me.MyCourses.Crss[Gbl.Usrs.Me.MyCourses.Num].DegCod = Str_ConvertStrCodToLongCod (row[2]); - Gbl.Usrs.Me.MyCourses.Num++; - } - } + /***** Get my courses from database *****/ + sprintf (Query,"SELECT CrsCod,Role,DegCod FROM my_courses_tmp"); + NumCrss = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get the courses you belong to"); - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); + /***** Get my courses from database *****/ + for (NumCrs = 0; + NumCrs < NumCrss; + NumCrs++) + { + /* Get next course */ + row = mysql_fetch_row (mysql_res); + + /* Get course code */ + if ((CrsCod = Str_ConvertStrCodToLongCod (row[0])) > 0) + { + if (Gbl.Usrs.Me.MyCourses.Num == Crs_MAX_COURSES_PER_USR) + Lay_ShowErrorAndExit ("Maximum number of courses of a user exceeded."); + + Gbl.Usrs.Me.MyCourses.Crss[Gbl.Usrs.Me.MyCourses.Num].CrsCod = CrsCod; + Gbl.Usrs.Me.MyCourses.Crss[Gbl.Usrs.Me.MyCourses.Num].Role = Rol_ConvertUnsignedStrToRole (row[1]); + Gbl.Usrs.Me.MyCourses.Crss[Gbl.Usrs.Me.MyCourses.Num].DegCod = Str_ConvertStrCodToLongCod (row[2]); + Gbl.Usrs.Me.MyCourses.Num++; + } + } + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + } /***** Set boolean that indicates that my courses are yet filled *****/ Gbl.Usrs.Me.MyCourses.Filled = true; } } +/*****************************************************************************/ +/************************ Free the list of my courses ************************/ +/*****************************************************************************/ + +void Usr_FreeMyCourses (void) + { + if (Gbl.Usrs.Me.MyCourses.Filled) + { + /***** Reset list *****/ + Gbl.Usrs.Me.MyCourses.Filled = false; + Gbl.Usrs.Me.MyCourses.Num = 0; + + /***** Remove temporary table with my courses *****/ + Usr_RemoveTemporaryTableMyCourses (); + } + } + +/*****************************************************************************/ +/************************ Free the list of my courses ************************/ +/*****************************************************************************/ + +static void Usr_RemoveTemporaryTableMyCourses (void) + { + char Query[128]; + + /***** Remove temporary table with my courses *****/ + sprintf (Query,"DROP TEMPORARY TABLE IF EXISTS my_courses_tmp"); + if (mysql_query (&Gbl.mysql,Query)) + DB_ExitOnMySQLError ("can not remove temporary table"); + } + /*****************************************************************************/ /**************** Check if a user belongs to an institution ******************/ /*****************************************************************************/ @@ -1434,7 +1492,7 @@ unsigned long Usr_GetCrssFromUsr (long UsrCod,long DegCod,MYSQL_RES **mysql_res) char Query[512]; /***** Get from database the courses a user belongs to *****/ - if (DegCod > 0) // Courses in a degree + if (DegCod > 0) // Courses in a degree sprintf (Query,"SELECT crs_usr.CrsCod,crs_usr.Role,courses.DegCod" " FROM crs_usr,courses" " WHERE crs_usr.UsrCod='%ld'" @@ -1442,7 +1500,7 @@ unsigned long Usr_GetCrssFromUsr (long UsrCod,long DegCod,MYSQL_RES **mysql_res) " AND courses.DegCod='%ld'" " ORDER BY courses.ShortName", UsrCod,DegCod); - else // All the courses + else // All the courses sprintf (Query,"SELECT crs_usr.CrsCod,crs_usr.Role,courses.DegCod" " FROM crs_usr,courses,degrees" " WHERE crs_usr.UsrCod='%ld'" diff --git a/swad_user.h b/swad_user.h index efb0f77fb..bec603a0d 100644 --- a/swad_user.h +++ b/swad_user.h @@ -238,6 +238,7 @@ void Usr_GetMyInstitutions (void); void Usr_GetMyCentres (void); void Usr_GetMyDegrees (void); void Usr_GetMyCourses (void); +void Usr_FreeMyCourses (void); bool Usr_CheckIfUsrBelongsToIns (long UsrCod, long InsCod, bool CountOnlyAcceptedCourses);