From 05ba149c14c7ea976539dfc97dae8bb758100b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Mon, 30 May 2016 14:27:10 +0200 Subject: [PATCH] Version 15.212 --- swad_changelog.h | 9 +- swad_degree.c | 13 -- swad_global.h | 8 - swad_info.c | 466 +++++++++++++++++++++++++++++++---------------- swad_syllabus.c | 61 ++++--- swad_syllabus.h | 4 + swad_test.c | 12 +- swad_text.c | 42 ----- 8 files changed, 372 insertions(+), 243 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index e44be32a..3cb3916b 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -133,18 +133,25 @@ // TODO: List exam announcement as a list, like assignments. When clicking on an announcement, it will be shown alone, as now. // TODO: Check value returned by setlocale in all calls // TODO: Write "Tab > Action" in title of text in most frequent actions +// TODO: Fix bug in copy-paste from Briefcase to another file browser +// TODO: Fix bug: Asignatura: Arquitectura de Computadores, Crear ZIP de todos los trabajos del grupo C3 +// TODO: Fix bug: se oculta el único descriptor de unas preguntas de test, y luego se renombra dicho descriptor --> el descriptor desaparece +// TODO: Fix bug: Student cant not see their test results +// TODO: Fix bug: button "Add a new question" in test should not be available for students /*****************************************************************************/ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 15.211.2 (2016-05-13)" +#define Log_PLATFORM_VERSION "SWAD 15.212 (2016-05-30)" #define CSS_FILE "swad15.210.css" #define JS_FILE "swad15.197.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 15.212: May 30, 2016 Fixed bug in edition of syllabus, reported by Raymon Moreno Colina and Javier Fernández Baldomero. + Code refactoring related to course info. (201471 lines) Version 15.211.2: May 13, 2016 Fixed bug in test questions, reported by Nuria Torres Rosell. (201394 lines) Version 15.211.1: May 07, 2016 Files in briefcase older than 1 year are removed automatically. (201397 lines) Version 15.211: May 07, 2016 Code refactoring related to removing old files in briefcase. diff --git a/swad_degree.c b/swad_degree.c index cdf46e6b..fdee8333 100644 --- a/swad_degree.c +++ b/swad_degree.c @@ -860,8 +860,6 @@ void Deg_WriteBigNameCtyInsCtrDegCrs (void) void Deg_InitCurrentCourse (void) { - unsigned NumInfoType; - /***** If numerical course code is available, get course data *****/ if (Gbl.CurrentCrs.Crs.CrsCod > 0) { @@ -978,17 +976,6 @@ void Deg_InitCurrentCourse (void) sprintf (Gbl.CurrentCrs.PathURLPubl,"%s/%s/%ld", Cfg_HTTPS_URL_SWAD_PUBLIC,Cfg_FOLDER_CRS,Gbl.CurrentCrs.Crs.CrsCod); - /***** Paths to files with URL or HTML for theory, practices, etc. of the course *****/ - for (NumInfoType = 0; - NumInfoType < Inf_NUM_INFO_TYPES; - NumInfoType++) - { - sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].PathRelFileURL,"%s/%s.url",Gbl.CurrentCrs.PathPriv ,Inf_FileNamesForInfoType[NumInfoType]); - sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].PathRelFileZIP,"%s/%s.zip",Gbl.CurrentCrs.PathPriv ,Inf_FileNamesForInfoType[NumInfoType]); - sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].PathRelWebPage,"%s/%s" ,Gbl.CurrentCrs.PathRelPubl,Inf_FileNamesForInfoType[NumInfoType]); - sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].URLWebPage ,"%s/%s" ,Gbl.CurrentCrs.PathURLPubl,Inf_FileNamesForInfoType[NumInfoType]); - } - /***** If any of the course directories does not exist, create it *****/ if (!Fil_CheckIfPathExists (Gbl.CurrentCrs.PathPriv)) Fil_CreateDirIfNotExists (Gbl.CurrentCrs.PathPriv); diff --git a/swad_global.h b/swad_global.h index e625aad2..97302046 100644 --- a/swad_global.h +++ b/swad_global.h @@ -456,14 +456,6 @@ struct Globals struct { Inf_InfoType_t Type; - struct - { - char URL[Cns_MAX_BYTES_URL+1]; // URL - char PathRelFileURL [PATH_MAX+1]; // Relative path to a text file of texto containing the URL - char PathRelFileZIP [PATH_MAX+1]; // Relative path to a file ZIP with the complete web page - char PathRelWebPage [PATH_MAX+1]; // Relative path to a public directory with a complete web page - char URLWebPage [PATH_MAX+1]; // URL of a web page - } Links[Inf_NUM_INFO_TYPES]; char URL[Cns_MAX_BYTES_URL+1]; bool MustBeRead[Inf_NUM_INFO_TYPES]; // Students must read info? bool ShowMsgMustBeRead; diff --git a/swad_info.c b/swad_info.c index 22451e51..893b4e01 100644 --- a/swad_info.c +++ b/swad_info.c @@ -289,15 +289,28 @@ static bool Inf_GetIfIHaveReadFromForm (void); static void Inf_SetForceReadIntoDB (bool MustBeRead); static void Inf_SetIHaveReadIntoDB (bool IHaveRead); -static void Inf_CheckAndShowPage (void); -static void Inf_CheckAndShowURL (void); +static bool Inf_CheckPage (long CrsCod,Inf_InfoType_t InfoType); +static bool Inf_CheckAndShowPage (void); +static void Inf_BuildPathPage (long CrsCod,Inf_InfoType_t InfoType,char *PathDir); + +static bool Inf_CheckURL (long CrsCod,Inf_InfoType_t InfoType); +static bool Inf_CheckAndShowURL (void); +static void Inf_BuildPathURL (long CrsCod,Inf_InfoType_t InfoType,char *PathFile); + static void Inf_ShowPage (const char *URL); + +static bool Inf_CheckIfInfoAvailable (Inf_InfoSrc_t InfoSrc); static Inf_InfoType_t Inf_AsignInfoType (void); static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD); -static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLength); -static bool Inf_CheckIfInfoTxtIsNotEmpty (long CrsCod,Inf_InfoType_t InfoType); -static void Inf_ShowPlainTxtInfo (void); -static void Inf_ShowRichTxtInfo (void); +static void Inf_GetInfoTxtFromDB (long CrsCod,Inf_InfoType_t InfoType, + char *InfoTxtHTML,char *InfoTxtMD, + size_t MaxLength); + +static bool Inf_CheckPlainTxt (long CrsCod,Inf_InfoType_t InfoType); +static bool Inf_CheckAndShowPlainTxt (void); + +static bool Inf_CheckRichTxt (long CrsCod,Inf_InfoType_t InfoType); +static bool Inf_CheckAndShowRichTxt (void); /*****************************************************************************/ /******** Show course info (theory, practices, bibliography, etc.) ***********/ @@ -356,7 +369,7 @@ void Inf_ShowInfo (void) { case Inf_LECTURES: case Inf_PRACTICALS: - Syl_EditSyllabus (); + ShowWarningNoInfo = !Syl_CheckAndEditSyllabus (); break; case Inf_INTRODUCTION: case Inf_TEACHING_GUIDE: @@ -369,18 +382,18 @@ void Inf_ShowInfo (void) } break; case Inf_INFO_SRC_PLAIN_TEXT: - Inf_ShowPlainTxtInfo (); + ShowWarningNoInfo = !Inf_CheckAndShowPlainTxt (); break; case Inf_INFO_SRC_RICH_TEXT: - Inf_ShowRichTxtInfo (); + ShowWarningNoInfo = !Inf_CheckAndShowRichTxt (); break; case Inf_INFO_SRC_PAGE: /***** Open file with web page *****/ - Inf_CheckAndShowPage (); + ShowWarningNoInfo = !Inf_CheckAndShowPage (); break; case Inf_INFO_SRC_URL: /***** Check if file with URL exists *****/ - Inf_CheckAndShowURL (); + ShowWarningNoInfo = !Inf_CheckAndShowURL (); break; } @@ -713,46 +726,90 @@ void Inf_RemoveUsrFromCrsInfoRead (long UsrCod,long CrsCod) DB_QueryDELETE (Query,"can not set that I have not read course info"); } +/*****************************************************************************/ +/************************** Check if exists a page ***************************/ +/*****************************************************************************/ +// Return true if info available + +static bool Inf_CheckPage (long CrsCod,Inf_InfoType_t InfoType) + { + char PathRelDirHTML[PATH_MAX+1]; + char PathRelFileHTML[PATH_MAX+1]; + + // TODO !!!!!!!!!!!! If the page is hosted in server ==> it should be created a temporary public directory + // and host the page in a private directory !!!!!!!!!!!!!!!!! + + /***** Build path of directory containing web page *****/ + Inf_BuildPathPage (CrsCod,InfoType,PathRelDirHTML); + + /***** Open file with web page *****/ + /* 1. Check if index.html exists */ + sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML); + if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? + return true; + + /* 2. If index.html does not exist, try index.htm */ + sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML); + if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? + return true; + + return false; + } + /*****************************************************************************/ /**************** Check if exists and show link to a page ********************/ /*****************************************************************************/ +// Return true if info available -static void Inf_CheckAndShowPage (void) +static bool Inf_CheckAndShowPage (void) { - extern const char *Txt_No_information; - const char *FileNameHTML; + char PathRelDirHTML[PATH_MAX+1]; char PathRelFileHTML[PATH_MAX+1]; char URL[PATH_MAX+1]; // TODO !!!!!!!!!!!! If the page is hosted in server ==> it should be created a temporary public directory // and host the page in a private directory !!!!!!!!!!!!!!!!! + /***** Build path of directory containing web page *****/ + Inf_BuildPathPage (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathRelDirHTML); + /***** Open file with web page *****/ /* 1. Check if index.html exists */ - FileNameHTML = "index.html"; - sprintf (PathRelFileHTML,"%s/%s", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage,FileNameHTML); - if (Fil_CheckIfPathExists (PathRelFileHTML)) + sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML); + if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? { - sprintf (URL,"%s/%s", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].URLWebPage,FileNameHTML); + sprintf (URL,"%s/%s/%ld/%s/index.html", + Cfg_HTTPS_URL_SWAD_PUBLIC,Cfg_FOLDER_CRS,Gbl.CurrentCrs.Crs.CrsCod, + Inf_FileNamesForInfoType[Gbl.CurrentCrs.Info.Type]); Inf_ShowPage (URL); + + return true; } - else + + /* 2. If index.html does not exist, try index.htm */ + sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML); + if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? { - /* 2. If index.html not exists, try index.htm */ - FileNameHTML = "index.htm"; - sprintf (PathRelFileHTML,"%s/%s", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage,FileNameHTML); - if (Fil_CheckIfPathExists (PathRelFileHTML)) - { - sprintf (URL,"%s/%s", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].URLWebPage,FileNameHTML); - Inf_ShowPage (URL); - } - else - Lay_ShowAlert (Lay_INFO,Txt_No_information); + sprintf (URL,"%s/%s/%ld/%s/index.htm", + Cfg_HTTPS_URL_SWAD_PUBLIC,Cfg_FOLDER_CRS,Gbl.CurrentCrs.Crs.CrsCod, + Inf_FileNamesForInfoType[Gbl.CurrentCrs.Info.Type]); + Inf_ShowPage (URL); + + return true; } + + return false; + } + +/*****************************************************************************/ +/* Build path inside a course for a given a info type to store web page file */ +/*****************************************************************************/ + +static void Inf_BuildPathPage (long CrsCod,Inf_InfoType_t InfoType,char *PathDir) + { + sprintf (PathDir,"%s/%s/%ld/%s", + Cfg_PATH_SWAD_PUBLIC,Cfg_FOLDER_CRS,CrsCod, + Inf_FileNamesForInfoType[InfoType]); } /*****************************************************************************/ @@ -762,6 +819,7 @@ static void Inf_CheckAndShowPage (void) int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer) { + char PathRelDirHTML[PATH_MAX+1]; char PathRelFileHTML[PATH_MAX+1]; FILE *FileHTML; bool FileExists = false; @@ -770,18 +828,19 @@ int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer) /***** Initialize buffer *****/ *HTMLBuffer = NULL; + /***** Build path of directory containing web page *****/ + Inf_BuildPathPage (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathRelDirHTML); + /***** Open file with web page *****/ /* 1. Check if index.html exists */ - sprintf (PathRelFileHTML,"%s/index.html", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage); - if (Fil_CheckIfPathExists (PathRelFileHTML)) + sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML); + if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? FileExists = true; else { /* 2. If index.html not exists, try index.htm */ - sprintf (PathRelFileHTML,"%s/index.htm", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage); - if (Fil_CheckIfPathExists (PathRelFileHTML)) + sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML); + if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? FileExists = true; } @@ -825,28 +884,73 @@ int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer) } /*****************************************************************************/ -/**************** Check if exists and show link to a page ********************/ +/********************* Check if exists link to a page ************************/ /*****************************************************************************/ +// Return true if info available -static void Inf_CheckAndShowURL (void) +static bool Inf_CheckURL (long CrsCod,Inf_InfoType_t InfoType) { - extern const char *Txt_No_information; + char PathFile[PATH_MAX+1]; FILE *FileURL; + /***** Build path to file containing URL *****/ + Inf_BuildPathURL (CrsCod,InfoType,PathFile); + /***** Check if file with URL exists *****/ - if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL ,"rb"))) + if ((FileURL = fopen (PathFile,"rb"))) { if (fgets (Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL,FileURL) == NULL) Gbl.CurrentCrs.Info.URL[0] = '\0'; /* File is not longer needed ==> close it */ fclose (FileURL); + if (Gbl.CurrentCrs.Info.URL[0]) - Inf_ShowPage (Gbl.CurrentCrs.Info.URL); - else - Lay_ShowAlert (Lay_INFO,Txt_No_information); + return true; } - else - Lay_ShowAlert (Lay_INFO,Txt_No_information); + + return false; + } + +/*****************************************************************************/ +/**************** Check if exists and show link to a page ********************/ +/*****************************************************************************/ +// Return true if info available + +static bool Inf_CheckAndShowURL (void) + { + char PathFile[PATH_MAX+1]; + FILE *FileURL; + + /***** Build path to file containing URL *****/ + Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile); + + /***** Check if file with URL exists *****/ + if ((FileURL = fopen (PathFile,"rb"))) + { + if (fgets (Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL,FileURL) == NULL) + Gbl.CurrentCrs.Info.URL[0] = '\0'; + /* File is not longer needed ==> close it */ + fclose (FileURL); + + if (Gbl.CurrentCrs.Info.URL[0]) + { + Inf_ShowPage (Gbl.CurrentCrs.Info.URL); + return true; + } + } + + return false; + } + +/*****************************************************************************/ +/*** Build path inside a course for a given a info type to store URL file ****/ +/*****************************************************************************/ + +static void Inf_BuildPathURL (long CrsCod,Inf_InfoType_t InfoType,char *PathFile) + { + sprintf (PathFile,"%s/%s/%ld/%s.url", + Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_CRS,CrsCod, + Inf_FileNamesForInfoType[InfoType]); } /*****************************************************************************/ @@ -856,13 +960,17 @@ static void Inf_CheckAndShowURL (void) void Inf_WriteURLIntoTxtBuffer (char TxtBuffer[Cns_MAX_BYTES_URL+1]) { + char PathFile[PATH_MAX+1]; FILE *FileURL; /***** Initialize buffer *****/ TxtBuffer[0] = '\0'; + /***** Build path to file containing URL *****/ + Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile); + /***** Check if file with URL exists *****/ - if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"rb"))) + if ((FileURL = fopen (PathFile,"rb"))) { if (fgets (TxtBuffer,Cns_MAX_BYTES_URL,FileURL) == NULL) TxtBuffer[0] = '\0'; @@ -929,14 +1037,30 @@ void Inf_FormsToSelSendInfo (void) extern const char *Txt_INFO_SRC_HELP[Inf_NUM_INFO_SOURCES]; Inf_InfoSrc_t InfoSrc; Inf_InfoSrc_t InfoSrcSelected; + bool InfoAvailable[Inf_NUM_INFO_SOURCES]; bool MustBeRead; /***** Set info type *****/ Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType (); - /***** Get info source from database *****/ + /***** Get current info source from database *****/ Inf_GetInfoSrcFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,&InfoSrcSelected,&MustBeRead); + /***** Check if info available *****/ + for (InfoSrc = (Inf_InfoSrc_t) 0; + InfoSrc < Inf_NUM_INFO_SOURCES; + InfoSrc++) + InfoAvailable[InfoSrc] = Inf_CheckIfInfoAvailable (InfoSrc); + + /***** Set info source to none + when no info available for the current source *****/ + if (InfoSrcSelected != Inf_INFO_SRC_NONE && + !InfoAvailable[InfoSrcSelected]) + { + InfoSrcSelected = Inf_INFO_SRC_NONE; + Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_NONE); + } + /***** Form to choice between alternatives *****/ /* Start of table */ Lay_StartRoundFrameTable (NULL,4,Txt_Source_of_information); @@ -957,8 +1081,16 @@ void Inf_FormsToSelSendInfo (void) (unsigned) InfoSrc); if (InfoSrc == InfoSrcSelected) fprintf (Gbl.F.Out," checked=\"checked\""); - fprintf (Gbl.F.Out," onclick=\"document.getElementById('%s').submit();\" />", - Gbl.Form.Id); + else + { + if (InfoSrc == Inf_INFO_SRC_NONE || + InfoAvailable[InfoSrc]) // If no info available for this source + fprintf (Gbl.F.Out," onclick=\"document.getElementById('%s').submit();\"", + Gbl.Form.Id); + else + fprintf (Gbl.F.Out," disabled=\"disabled\""); + } + fprintf (Gbl.F.Out," />"); Act_FormEnd (); fprintf (Gbl.F.Out,""); @@ -982,6 +1114,43 @@ void Inf_FormsToSelSendInfo (void) Lay_EndRoundFrameTable (); } +/*****************************************************************************/ +/* Check if there is info available for current info type and a given source */ +/*****************************************************************************/ + +static bool Inf_CheckIfInfoAvailable (Inf_InfoSrc_t InfoSrc) + { + switch (InfoSrc) + { + case Inf_INFO_SRC_NONE: + return false; + case Inf_INFO_SRC_EDITOR: + switch (Gbl.CurrentCrs.Info.Type) + { + case Inf_LECTURES: + case Inf_PRACTICALS: + return Syl_CheckSyllabus (); + default: + return false; + } + return false; // Not reached + case Inf_INFO_SRC_PLAIN_TEXT: + return Inf_CheckPlainTxt (Gbl.CurrentCrs.Crs.CrsCod, + Gbl.CurrentCrs.Info.Type); + case Inf_INFO_SRC_RICH_TEXT: + return Inf_CheckRichTxt (Gbl.CurrentCrs.Crs.CrsCod, + Gbl.CurrentCrs.Info.Type); + case Inf_INFO_SRC_PAGE: + return Inf_CheckPage (Gbl.CurrentCrs.Crs.CrsCod, + Gbl.CurrentCrs.Info.Type); + case Inf_INFO_SRC_URL: + return Inf_CheckURL (Gbl.CurrentCrs.Crs.CrsCod, + Gbl.CurrentCrs.Info.Type); + } + + return false; // Not reached + } + /*****************************************************************************/ /****************** Form to enter in integrated editor ***********************/ /*****************************************************************************/ @@ -1064,8 +1233,12 @@ void Inf_FormToSendURL (Inf_InfoSrc_t InfoSrc) extern const char *The_ClassForm[The_NUM_THEMES]; extern const char *Txt_URL; extern const char *Txt_Send_URL; + char PathFile[PATH_MAX+1]; FILE *FileURL; + /***** Build path to file containing URL *****/ + Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile); + /***** Start form *****/ Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]); @@ -1079,7 +1252,7 @@ void Inf_FormToSendURL (Inf_InfoSrc_t InfoSrc) " close it */ - fclose (File); - if (!URL[0]) - { - *InfoSrc = Inf_INFO_SRC_NONE; - *MustBeRead = false; - } - } - else - { - *InfoSrc = Inf_INFO_SRC_NONE; - *MustBeRead = false; - } + if (!Inf_CheckURL (CrsCod,InfoType)) + { + *InfoSrc = Inf_INFO_SRC_NONE; + *MustBeRead = false; + } break; } } @@ -1473,7 +1612,9 @@ static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD) /********** Get info text for a type of course info from database ************/ /*****************************************************************************/ -static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLength) +static void Inf_GetInfoTxtFromDB (long CrsCod,Inf_InfoType_t InfoType, + char *InfoTxtHTML,char *InfoTxtMD, + size_t MaxLength) { char Query[512]; MYSQL_RES *mysql_res; @@ -1484,7 +1625,7 @@ static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLe (bibliography, FAQ, links or evaluation) from database *****/ sprintf (Query,"SELECT InfoTxtHTML,InfoTxtMD FROM crs_info_txt" " WHERE CrsCod='%ld' AND InfoType='%s'", - Gbl.CurrentCrs.Crs.CrsCod,Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]); + CrsCod,Inf_NamesInDBForInfoType[InfoType]); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info text"); /***** The result of the query must have one row or none *****/ @@ -1523,54 +1664,35 @@ static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLe } /*****************************************************************************/ -/*** Check if info text for a type of course info is not empty in database ***/ +/********************* Check information about the course ********************/ /*****************************************************************************/ +// Return true if info available -static bool Inf_CheckIfInfoTxtIsNotEmpty (long CrsCod,Inf_InfoType_t InfoType) +static bool Inf_CheckPlainTxt (long CrsCod,Inf_InfoType_t InfoType) { - char Query[512]; - MYSQL_RES *mysql_res; - MYSQL_ROW row; - unsigned long NumRows; - bool Result; + char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1]; - /***** Get info source for a specific type of course information - (bibliography, FAQ, links or evaluation) from database *****/ - sprintf (Query,"SELECT InfoTxtHTML FROM crs_info_txt" - " WHERE CrsCod='%ld' AND InfoType='%s'", - CrsCod,Inf_NamesInDBForInfoType[InfoType]); - NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info text"); + /***** Get info text from database *****/ + Inf_GetInfoTxtFromDB (CrsCod,InfoType,TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); - /***** The result of the query must have one row or none *****/ - if (NumRows == 1) - { - /* Get info text */ - row = mysql_fetch_row (mysql_res); - Result = (row[0][0] != '\0'); // Is text empty? - } - else - Result = false; - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - return Result; + return (TxtHTML[0] != '\0'); } /*****************************************************************************/ /********************* Show information about the course *********************/ /*****************************************************************************/ +// Return true if info available -static void Inf_ShowPlainTxtInfo (void) +static bool Inf_CheckAndShowPlainTxt (void) { extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES]; - extern const char *Txt_No_information; char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1]; bool ICanEdit = (Gbl.Usrs.Me.LoggedRole == Rol_TEACHER || Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM); /***** Get info text from database *****/ - Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); + Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type, + TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); if (TxtHTML[0]) { @@ -1596,19 +1718,38 @@ static void Inf_ShowPlainTxtInfo (void) /***** End frame *****/ fprintf (Gbl.F.Out,""); Lay_EndRoundFrame (); + + return true; } - else - Lay_ShowAlert (Lay_INFO,Txt_No_information); + + return false; } /*****************************************************************************/ /********************* Show information about the course *********************/ /*****************************************************************************/ +// Return true if info available -static void Inf_ShowRichTxtInfo (void) +static bool Inf_CheckRichTxt (long CrsCod,Inf_InfoType_t InfoType) + { + char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1]; + char TxtMD[Cns_MAX_BYTES_LONG_TEXT+1]; + + /***** Get info text from database *****/ + Inf_GetInfoTxtFromDB (CrsCod,InfoType, + TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT); + + return (TxtMD[0] != '\0'); + } + +/*****************************************************************************/ +/********************* Show information about the course *********************/ +/*****************************************************************************/ +// Return true if info available + +static bool Inf_CheckAndShowRichTxt (void) { extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES]; - extern const char *Txt_No_information; char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1]; char TxtMD[Cns_MAX_BYTES_LONG_TEXT+1]; char PathFileMD[PATH_MAX+1]; @@ -1622,7 +1763,8 @@ static void Inf_ShowRichTxtInfo (void) Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM); /***** Get info text from database *****/ - Inf_GetInfoTxtFromDB (TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT); + Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type, + TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT); if (TxtMD[0]) { @@ -1697,9 +1839,11 @@ static void Inf_ShowRichTxtInfo (void) /***** End frame *****/ fprintf (Gbl.F.Out,""); Lay_EndRoundFrame (); + + return true; } - else - Lay_ShowAlert (Lay_INFO,Txt_No_information); + + return false; } /*****************************************************************************/ @@ -1720,7 +1864,8 @@ int Inf_WritePlainTextIntoHTMLBuffer (char **HTMLBuffer) *HTMLBuffer = NULL; /***** Get info text from database *****/ - Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); + Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type, + TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); if (TxtHTML[0]) { @@ -1817,7 +1962,8 @@ void Inf_EditPlainTxtInfo (void) Lay_WriteHeaderClassPhoto (false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod); /***** Get info text from database *****/ - Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); + Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type, + TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); /***** Edition area *****/ fprintf (Gbl.F.Out,"
"); @@ -1855,7 +2001,8 @@ void Inf_EditRichTxtInfo (void) Lay_WriteHeaderClassPhoto (false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod); /***** Get info text from database *****/ - Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); + Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type, + TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT); /***** Edition area *****/ fprintf (Gbl.F.Out,"
"); @@ -1948,6 +2095,7 @@ void Inf_RecAndChangeRichTxtInfo (void) void Inf_ReceiveURLInfo (void) { extern const char *Txt_The_URL_X_has_been_updated; + char PathFile[PATH_MAX+1]; FILE *FileURL; bool URLIsOK = false; @@ -1957,8 +2105,11 @@ void Inf_ReceiveURLInfo (void) /***** Get parameter with URL *****/ Par_GetParToText ("InfoSrcURL",Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL); + /***** Build path to file containing URL *****/ + Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile); + /***** Open file with URL *****/ - if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"wb")) != NULL) + if ((FileURL = fopen (PathFile,"wb")) != NULL) { /***** Write URL *****/ fprintf (FileURL,"%s",Gbl.CurrentCrs.Info.URL); @@ -2009,10 +2160,11 @@ void Inf_ReceivePagInfo (void) extern const char *Txt_The_file_type_should_be_HTML_or_ZIP; struct Param *Param; char SourceFileName[PATH_MAX+1]; + char PathRelDirHTML[PATH_MAX+1]; char PathRelFileHTML[PATH_MAX+1]; + char PathRelFileZIP[PATH_MAX+1]; char MIMEType[Brw_MAX_BYTES_MIME_TYPE+1]; char StrUnzip[100+PATH_MAX*2+1]; - char *PathWebPage; bool WrongType = false; bool FileIsOK = false; @@ -2041,14 +2193,16 @@ void Inf_ReceivePagInfo (void) } else { + /***** Build path of directory containing web page *****/ + Inf_BuildPathPage (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathRelDirHTML); + /***** End the reception of the data *****/ - PathWebPage = Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage; if (Str_FileIs (SourceFileName,"html") || Str_FileIs (SourceFileName,"htm" )) // .html or .htm file { - Brw_RemoveTree (PathWebPage); - Fil_CreateDirIfNotExists (PathWebPage); - sprintf (PathRelFileHTML,"%s/index.html",PathWebPage); + Brw_RemoveTree (PathRelDirHTML); + Fil_CreateDirIfNotExists (PathRelDirHTML); + sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML); if (Fil_EndReceptionOfFile (PathRelFileHTML,Param)) { Lay_ShowAlert (Lay_SUCCESS,Txt_The_HTML_file_has_been_received_successfully); @@ -2059,19 +2213,23 @@ void Inf_ReceivePagInfo (void) } else if (Str_FileIs (SourceFileName,"zip")) // .zip file { - Brw_RemoveTree (PathWebPage); - Fil_CreateDirIfNotExists (PathWebPage); - if (Fil_EndReceptionOfFile (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileZIP,Param)) + Brw_RemoveTree (PathRelDirHTML); + Fil_CreateDirIfNotExists (PathRelDirHTML); + sprintf (PathRelFileZIP,"%s/%s.zip", + Gbl.CurrentCrs.PathPriv, + Inf_FileNamesForInfoType[Gbl.CurrentCrs.Info.Type]); + + if (Fil_EndReceptionOfFile (PathRelFileZIP,Param)) { Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_received_successfully); /* Uncompress ZIP */ sprintf (StrUnzip,"unzip -qq -o %s -d %s", - Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileZIP,PathWebPage); + PathRelFileZIP,PathRelDirHTML); if (system (StrUnzip) == 0) { /* Check if uploaded file is index.html or index.htm */ - sprintf (PathRelFileHTML,"%s/index.html",PathWebPage); + sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) { Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully); @@ -2080,7 +2238,7 @@ void Inf_ReceivePagInfo (void) } else { - sprintf (PathRelFileHTML,"%s/index.htm",PathWebPage); + sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) { Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully); diff --git a/swad_syllabus.c b/swad_syllabus.c index 45db5f7f..441ddcde 100644 --- a/swad_syllabus.c +++ b/swad_syllabus.c @@ -173,17 +173,30 @@ void Syl_GetParamItemNumber (void) Lay_ShowErrorAndExit ("Item is missing."); } +/*****************************************************************************/ +/********************** Check if syllabus is not empty ***********************/ +/*****************************************************************************/ +// Return true if info available + +bool Syl_CheckSyllabus (void) + { + /***** Set syllabus type and load syllabus from XML file to memory *****/ + Syl_SetSyllabusTypeAndLoadToMemory (); + + /***** Start frame *****/ + return (LstItemsSyllabus.NumItems != 0); + } + /*****************************************************************************/ /****************************** Edit a syllabus ******************************/ /*****************************************************************************/ +// Return true if info available -void Syl_EditSyllabus (void) +bool Syl_CheckAndEditSyllabus (void) { extern const Act_Action_t Inf_ActionsSeeInfo[Inf_NUM_INFO_TYPES]; extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES]; extern const char *Txt_Done; - extern const char *Txt_The_syllabus_lectures_of_the_course_X_is_not_available; - extern const char *Txt_The_syllabus_practicals_of_the_course_X_is_not_available; bool ICanEdit; bool PutIconToEdit; @@ -194,15 +207,16 @@ void Syl_EditSyllabus (void) Gbl.Action.Act == ActEditorSylPra) Gbl.CurrentCrs.Syllabus.EditionIsActive = true; + /***** Start frame *****/ if (Gbl.CurrentCrs.Syllabus.EditionIsActive || LstItemsSyllabus.NumItems) { - /***** Start frame *****/ ICanEdit = Gbl.Usrs.Me.LoggedRole == Rol_TEACHER || - Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM; + Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM; PutIconToEdit = ICanEdit && !Gbl.CurrentCrs.Syllabus.EditionIsActive; Lay_StartRoundFrame (NULL,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type], - PutIconToEdit ? Inf_PutIconToEditInfo : - NULL); + PutIconToEdit ? Inf_PutIconToEditInfo : + NULL); + fprintf (Gbl.F.Out,""); /***** Write the current syllabus *****/ @@ -225,15 +239,21 @@ void Syl_EditSyllabus (void) /***** End frame *****/ Lay_EndRoundFrame (); + + return true; } - else - { - sprintf (Gbl.Message, - Gbl.CurrentCrs.Info.Type == Inf_LECTURES ? Txt_The_syllabus_lectures_of_the_course_X_is_not_available : - Txt_The_syllabus_practicals_of_the_course_X_is_not_available, - Gbl.CurrentCrs.Crs.FullName); - Lay_ShowAlert (Lay_WARNING,Gbl.Message); - } + + return false; + } + +/*****************************************************************************/ +/****************************** Edit a syllabus ******************************/ +/*****************************************************************************/ +// Return true if info available + +void Syl_EditSyllabus (void) + { + (void) Syl_CheckAndEditSyllabus (); } /*****************************************************************************/ @@ -300,12 +320,13 @@ static void Syl_SetSyllabusTypeAndLoadToMemory (void) break; } - /***** We are editing a syllabus with the internal editor, - so change info source to internal editor in database *****/ - Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_EDITOR); - /***** Load syllabus from XML file to memory *****/ Syl_LoadToMemory (); + + /***** We are editing a syllabus with the internal editor, + so change info source to internal editor in database *****/ + Inf_SetInfoSrcIntoDB (LstItemsSyllabus.NumItems ? Inf_INFO_SRC_EDITOR : + Inf_INFO_SRC_NONE); } /*****************************************************************************/ @@ -420,7 +441,6 @@ static void Syl_LoadToMemory (void) for (NumItem = 0; NumItem < LstItemsSyllabus.NumItems - 1; NumItem++) - { if (LstItemsSyllabus.Lst[NumItem].Level < LstItemsSyllabus.Lst[NumItem + 1].Level) { LstItemsSyllabus.Lst[NumItem].HasChildren = true; @@ -428,7 +448,6 @@ static void Syl_LoadToMemory (void) } else LstItemsSyllabus.Lst[NumItem].HasChildren = false; - } LstItemsSyllabus.Lst[LstItemsSyllabus.NumItems - 1].HasChildren = false; } LstItemsSyllabus.NumItemsWithChildren = NumItemsWithChildren; diff --git a/swad_syllabus.h b/swad_syllabus.h index 0e4dc9d1..cfee7746 100644 --- a/swad_syllabus.h +++ b/swad_syllabus.h @@ -69,7 +69,11 @@ void Syl_GetParamWhichSyllabus (void); void Syl_PutFormWhichSyllabus (void); void Syl_GetParamItemNumber (void); + +bool Syl_CheckSyllabus (void); +bool Syl_CheckAndEditSyllabus (void); void Syl_EditSyllabus (void); + void Syl_FreeListItemsSyllabus (void); int Syl_ReadLevelItemSyllabus (void); int Syl_WriteSyllabusIntoHTMLBuffer (char **HTMLBuffer); diff --git a/swad_test.c b/swad_test.c index 4bcaccd4..b3eb9cf1 100644 --- a/swad_test.c +++ b/swad_test.c @@ -1403,7 +1403,6 @@ void Tst_RenameTag (void) /***** Get old and new tags from the form *****/ Par_GetParToText ("OldTagTxt",OldTagTxt,Tst_MAX_BYTES_TAG); - Par_GetParToText ("NewTagTxt",NewTagTxt,Tst_MAX_BYTES_TAG); /***** Check that the new tag is not empty *****/ @@ -1415,12 +1414,16 @@ void Tst_RenameTag (void) } else { - /***** Check if the old tag is equal to the new one (this happens when user press INTRO without changing anything in the form) *****/ + /***** Check if the old tag is equal to the new one + (this happens when user press INTRO + without changing anything in the form) *****/ if (strcmp (OldTagTxt,NewTagTxt)) // The tag text has changed { - /***** Check if the new tag text is equal to any of the tag texts present in the database *****/ + /***** Check if the new tag text is equal + to any of the current tag texts present in the database *****/ if ((ExistingNewTagCod = Tst_GetTagCodFromTagTxt (NewTagTxt)) > 0) // The new tag was already in database { + // TODO: Fix Bug: when renaming unique tag "examen" to "Examen", tag is removed! /***** Complex update made to not repeat tags *****/ /* Step 1. Get tag code of the old tag */ if ((OldTagCod = Tst_GetTagCodFromTagTxt (OldTagTxt)) < 0) @@ -1468,7 +1471,8 @@ void Tst_RenameTag (void) { /***** Simple update replacing each instance of the old tag by the new tag *****/ sprintf (Query,"UPDATE tst_tags SET TagTxt='%s',ChangeTime=NOW()" - " WHERE tst_tags.CrsCod='%ld' AND tst_tags.TagTxt='%s'", + " WHERE tst_tags.CrsCod='%ld'" + " AND tst_tags.TagTxt='%s'", NewTagTxt,Gbl.CurrentCrs.Crs.CrsCod,OldTagTxt); DB_QueryUPDATE (Query,"can not update tag"); } diff --git a/swad_text.c b/swad_text.c index 4acd71e3..7c22ce6e 100644 --- a/swad_text.c +++ b/swad_text.c @@ -44544,48 +44544,6 @@ const char *Txt_The_survey_has_been_modified = "O inquérito foi modificado."; #endif -const char *Txt_The_syllabus_lectures_of_the_course_X_is_not_available = // Warning: it is very important to include %s in the following sentences -#if L==1 - "El programa de teoría de la asignatura %s no está disponible."; // Necessita traduccio -#elif L==2 - "The syllabus (lectures) of the course %s is not available."; // Need Übersetzung -#elif L==3 - "The syllabus (lectures) of the course %s is not available."; -#elif L==4 - "El programa de teoría de la asignatura %s no está disponible."; -#elif L==5 - "The syllabus (lectures) of the course %s is not available."; // Besoin de traduction -#elif L==6 - "El programa de teoría de la asignatura %s no está disponible."; // Okoteve traducción -#elif L==7 - "Il programma di teoria del corso %s non è disponibile."; -#elif L==8 - "The syllabus (lectures) of the course %s is not available."; // Potrzebujesz tlumaczenie -#elif L==9 - "The syllabus (lectures) of the course %s is not available."; // Necessita de tradução -#endif - -const char *Txt_The_syllabus_practicals_of_the_course_X_is_not_available = // Warning: it is very important to include %s in the following sentences -#if L==1 - "El programa de prácticas de la asignatura %s no está disponible."; // Necessita traduccio -#elif L==2 - "The syllabus (practicals) of the course %s is not available."; // Need Übersetzung -#elif L==3 - "The syllabus (practicals) of the course %s is not available."; -#elif L==4 - "El programa de prácticas de la asignatura %s no está disponible."; -#elif L==5 - "The syllabus (practicals) of the course %s is not available."; // Besoin de traduction -#elif L==6 - "El programa de prácticas de la asignatura %s no está disponible."; // Okoteve traducción -#elif L==7 - "Il programma della pratica %s non è disponibile."; -#elif L==8 - "The syllabus (practicals) of the course %s is not available."; // Potrzebujesz tlumaczenie -#elif L==9 - "The syllabus (practicals) of the course %s is not available."; // Necessita de tradução -#endif - const char *Txt_The_tag_X_has_been_renamed_as_Y = // Warning: it is very important to include two %s in the following sentences #if L==1 "El descriptor %s ha pasado a denominarse %s."; // Necessita traduccio