// 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,"