// swad_course.c: edition of courses /* SWAD (Shared Workspace At a Distance), is a web platform developed at the University of Granada (Spain), and used to support university teaching. This file is part of SWAD core. Copyright (C) 1999-2019 Antonio Caņas Vargas This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ /*****************************************************************************/ /********************************* Headers ***********************************/ /*****************************************************************************/ #define _GNU_SOURCE // For asprintf #include // For PATH_MAX #include // For NULL #include // For maximum values #include // For asprintf #include // For getenv, etc. #include // For string functions #include "swad_box.h" #include "swad_course.h" #include "swad_constant.h" #include "swad_database.h" #include "swad_degree.h" #include "swad_enrolment.h" #include "swad_exam.h" #include "swad_form.h" #include "swad_global.h" #include "swad_help.h" #include "swad_hierarchy.h" #include "swad_HTML.h" #include "swad_indicator.h" #include "swad_logo.h" #include "swad_notification.h" #include "swad_parameter.h" #include "swad_QR.h" #include "swad_role.h" #include "swad_RSS.h" #include "swad_tab.h" #include "swad_theme.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /*************************** Public constants ********************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private types *********************************/ /*****************************************************************************/ /*****************************************************************************/ /**************************** Private variables ******************************/ /*****************************************************************************/ static struct Course *Crs_EditingCrs = NULL; // Static variable to keep the course being edited /*****************************************************************************/ /**************************** Private prototypes *****************************/ /*****************************************************************************/ static void Crs_Configuration (bool PrintView); static void Crs_PutIconToPrint (void); static void Crs_ShowNumUsrsInCrs (Rol_Role_t Role); static void Crs_WriteListMyCoursesToSelectOne (void); static void Crs_GetListCoursesInCurrentDegree (Crs_WhatCourses_t WhatCourses); static void Crs_ListCourses (void); static bool Crs_CheckIfICanCreateCourses (void); static void Crs_PutIconsListCourses (void); static void Crs_PutIconToEditCourses (void); static bool Crs_ListCoursesOfAYearForSeeing (unsigned Year); static void Crs_EditCoursesInternal (void); static void Crs_PutIconsEditingCourses (void); static void Crs_PutIconToViewCourses (void); static void Crs_ListCoursesForEdition (void); static void Crs_ListCoursesOfAYearForEdition (unsigned Year); static bool Crs_CheckIfICanEdit (struct Course *Crs); static Crs_StatusTxt_t Crs_GetStatusTxtFromStatusBits (Crs_Status_t Status); static Crs_Status_t Crs_GetStatusBitsFromStatusTxt (Crs_StatusTxt_t StatusTxt); static void Crs_PutFormToCreateCourse (void); static void Crs_PutHeadCoursesForSeeing (void); static void Crs_PutHeadCoursesForEdition (void); static void Crs_RecFormRequestOrCreateCrs (unsigned Status); static void Crs_GetParamsNewCourse (struct Course *Crs); static void Crs_CreateCourse (unsigned Status); static void Crs_GetDataOfCourseFromRow (struct Course *Crs,MYSQL_ROW row); static void Crs_UpdateCrsDegDB (long CrsCod,long DegCod); static void Crs_UpdateCrsYear (struct Course *Crs,unsigned NewYear); static void Crs_GetShortNamesByCod (long CrsCod, char CrsShortName[Hie_MAX_BYTES_SHRT_NAME + 1], char DegShortName[Hie_MAX_BYTES_SHRT_NAME + 1]); static void Crs_EmptyCourseCompletely (long CrsCod); static void Crs_RenameCourse (struct Course *Crs,Cns_ShrtOrFullName_t ShrtOrFullName); static bool Crs_CheckIfCrsNameExistsInYearOfDeg (const char *FieldName,const char *Name,long CrsCod, long DegCod,unsigned Year); static void Crs_UpdateCrsNameDB (long CrsCod,const char *FieldName,const char *NewCrsName); static void Crs_PutButtonToGoToCrs (void); static void Crs_PutButtonToRegisterInCrs (void); static void Crs_PutIconToSearchCourses (void); static void Sch_PutLinkToSearchCoursesParams (void); static void Crs_PutParamOtherCrsCod (long CrsCod); static long Crs_GetAndCheckParamOtherCrsCod (long MinCodAllowed); static void Crs_WriteRowCrsData (unsigned NumCrs,MYSQL_ROW row,bool WriteColumnAccepted); static void Crs_EditingCourseConstructor (void); static void Crs_EditingCourseDestructor (void); /*****************************************************************************/ /***************** Show introduction to the current course *******************/ /*****************************************************************************/ void Crs_ShowIntroduction (void) { /***** Course configuration *****/ HTM_DIV_Begin ("class=\"CM\""); Crs_Configuration (false); HTM_DIV_End (); /***** Course introduction *****/ Inf_ShowInfo (); /***** Show help to enrol me *****/ Hlp_ShowHelpWhatWouldYouLikeToDo (); } /*****************************************************************************/ /***************** Print configuration of the current course *****************/ /*****************************************************************************/ void Crs_PrintConfiguration (void) { Crs_Configuration (true); } /*****************************************************************************/ /***************** Configuration of the current course ***********************/ /*****************************************************************************/ static void Crs_Configuration (bool PrintView) { extern const char *Hlp_COURSE_Information; extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Degree; extern const char *Txt_Course; extern const char *Txt_Short_name; extern const char *Txt_Year_OF_A_DEGREE; extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE]; extern const char *Txt_Not_applicable; extern const char *Txt_Institutional_code; extern const char *Txt_Internal_code; extern const char *Txt_Shortcut; extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; extern const char *Txt_QR_code; extern const char *Txt_Indicators; extern const char *Txt_of_PART_OF_A_TOTAL; unsigned NumDeg; unsigned Year; int NumIndicatorsFromDB; struct Ind_IndicatorsCrs Indicators; bool IsForm; bool PutLink; /***** Trivial check *****/ if (Gbl.Hierarchy.Crs.CrsCod <= 0) // No course selected return; /***** Contextual menu *****/ if (!PrintView) if (Gbl.Usrs.Me.Role.Logged == Rol_GST || Gbl.Usrs.Me.Role.Logged == Rol_USR) { Mnu_ContextMenuBegin (); Enr_PutLinkToRequestSignUp (); // Request enrolment in the current course Mnu_ContextMenuEnd (); } /***** Begin box *****/ if (PrintView) Box_BoxBegin (NULL,NULL,NULL, NULL,Box_NOT_CLOSABLE); else Box_BoxBegin (NULL,NULL,Crs_PutIconToPrint, Hlp_COURSE_Information,Box_NOT_CLOSABLE); /***** Title *****/ PutLink = !PrintView && Gbl.Hierarchy.Deg.WWW[0]; HTM_DIV_Begin ("class=\"FRAME_TITLE FRAME_TITLE_BIG\""); if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\"" " class=\"FRAME_TITLE_BIG\" title=\"%s\"", Gbl.Hierarchy.Deg.WWW, Gbl.Hierarchy.Deg.FullName); Log_DrawLogo (Hie_DEG,Gbl.Hierarchy.Deg.DegCod, Gbl.Hierarchy.Deg.ShrtName,64,NULL,true); if (PutLink) HTM_A_End (); fprintf (Gbl.F.Out,"
%s",Gbl.Hierarchy.Crs.FullName); HTM_DIV_End (); /***** Begin table *****/ HTM_TABLE_BeginWidePadding (2); /***** Degree *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); fprintf (Gbl.F.Out,"