// swad_institution.c: institutions /* 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 ***********************************/ /*****************************************************************************/ #include // For NULL #include // For calloc #include // For string functions #include "swad_box.h" #include "swad_config.h" #include "swad_constant.h" #include "swad_database.h" #include "swad_form.h" #include "swad_global.h" #include "swad_help.h" #include "swad_hierarchy.h" #include "swad_HTML.h" #include "swad_institution.h" #include "swad_language.h" #include "swad_logo.h" #include "swad_parameter.h" #include "swad_QR.h" #include "swad_user.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /***************************** Private constants *****************************/ /*****************************************************************************/ /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private variables *****************************/ /*****************************************************************************/ static struct Instit *Ins_EditingIns = NULL; // Static variable to keep the institution being edited /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Ins_Configuration (bool PrintView); static void Ins_PutIconsToPrintAndUpload (void); static void Ins_ShowNumUsrsInCrssOfIns (Rol_Role_t Role); static void Ins_ListInstitutions (void); static bool Ins_CheckIfICanCreateInstitutions (void); static void Ins_PutIconsListingInstitutions (void); static void Ins_PutIconToEditInstitutions (void); static void Ins_ListOneInstitutionForSeeing (struct Instit *Ins,unsigned NumIns); static void Ins_PutHeadInstitutionsForSeeing (bool OrderSelectable); static void Ins_GetParamInsOrder (void); static void Ins_EditInstitutionsInternal (void); static void Ins_PutIconsEditingInstitutions (void); static void Ins_PutIconToViewInstitutions (void); static void Ins_GetShrtNameAndCtyOfInstitution (struct Instit *Ins, char CtyName[Hie_MAX_BYTES_FULL_NAME + 1]); static void Ins_ListInstitutionsForEdition (void); static bool Ins_CheckIfICanEdit (struct Instit *Ins); static Ins_StatusTxt_t Ins_GetStatusTxtFromStatusBits (Ins_Status_t Status); static Ins_Status_t Ins_GetStatusBitsFromStatusTxt (Ins_StatusTxt_t StatusTxt); static void Ins_PutParamOtherInsCod (long InsCod); static long Ins_GetParamOtherInsCod (void); static void Ins_RenameInstitution (struct Instit *Ins,Cns_ShrtOrFullName_t ShrtOrFullName); static bool Ins_CheckIfInsNameExistsInCty (const char *FieldName, const char *Name, long InsCod, long CtyCod); static void Ins_UpdateInsNameDB (long InsCod,const char *FieldName,const char *NewInsName); static void Ins_UpdateInsCtyDB (long InsCod,long CtyCod); static void Ins_UpdateInsWWWDB (long InsCod,const char NewWWW[Cns_MAX_BYTES_WWW + 1]); static void Ins_ShowAlertAndButtonToGoToIns (void); static void Ins_PutParamGoToIns (void); static void Ins_PutFormToCreateInstitution (void); static void Ins_PutHeadInstitutionsForEdition (void); static void Ins_RecFormRequestOrCreateIns (unsigned Status); static void Ins_CreateInstitution (unsigned Status); static void Ins_EditingInstitutionConstructor (); static void Ins_EditingInstitutionDestructor (); /*****************************************************************************/ /***************** List institutions with pending centres ********************/ /*****************************************************************************/ void Ins_SeeInsWithPendingCtrs (void) { extern const char *Hlp_SYSTEM_Hierarchy_pending; extern const char *Txt_Institutions_with_pending_centres; extern const char *Txt_Institution; extern const char *Txt_Centres_ABBREVIATION; extern const char *Txt_There_are_no_institutions_with_requests_for_centres_to_be_confirmed; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumInss; unsigned NumIns; struct Instit Ins; const char *BgColor; /***** Get institutions with pending centres *****/ switch (Gbl.Usrs.Me.Role.Logged) { case Rol_INS_ADM: NumInss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions" " with pending centres", "SELECT centres.InsCod,COUNT(*)" " FROM centres,ins_admin,institutions" " WHERE (centres.Status & %u)<>0" " AND centres.InsCod=ins_admin.InsCod AND ins_admin.UsrCod=%ld" " AND centres.InsCod=institutions.InsCod" " GROUP BY centres.InsCod ORDER BY institutions.ShortName", (unsigned) Ctr_STATUS_BIT_PENDING, Gbl.Usrs.Me.UsrDat.UsrCod); break; case Rol_SYS_ADM: NumInss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions" " with pending centres", "SELECT centres.InsCod,COUNT(*)" " FROM centres,institutions" " WHERE (centres.Status & %u)<>0" " AND centres.InsCod=institutions.InsCod" " GROUP BY centres.InsCod ORDER BY institutions.ShortName", (unsigned) Ctr_STATUS_BIT_PENDING); break; default: // Forbidden for other users return; } /***** Get institutions *****/ if (NumInss) { /***** Begin box and table *****/ Box_StartBoxTable (NULL,Txt_Institutions_with_pending_centres,NULL, Hlp_SYSTEM_Hierarchy_pending,Box_NOT_CLOSABLE,2); /***** Write heading *****/ HTM_TR_Begin (NULL); HTM_TH (1,1,"LM",Txt_Institution); HTM_TH (1,1,"RM",Txt_Centres_ABBREVIATION); HTM_TR_End (); /***** List the institutions *****/ for (NumIns = 0; NumIns < NumInss; NumIns++) { /* Get next centre */ row = mysql_fetch_row (mysql_res); /* Get institution code (row[0]) */ Ins.InsCod = Str_ConvertStrCodToLongCod (row[0]); BgColor = (Ins.InsCod == Gbl.Hierarchy.Ins.InsCod) ? "LIGHT_BLUE" : Gbl.ColorRows[Gbl.RowEvenOdd]; /* Get data of institution */ Ins_GetDataOfInstitutionByCod (&Ins,Ins_GET_BASIC_DATA); /* Institution logo and name */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"LM %s\"",BgColor); Ins_DrawInstitutionLogoAndNameWithLink (&Ins,ActSeeCtr, "DAT_NOBR","CM"); HTM_TD_End (); /* Number of pending centres (row[1]) */ HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%s",row[1]); HTM_TD_End (); HTM_TR_End (); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } /***** End table and box *****/ Box_EndBoxTable (); } else Ale_ShowAlert (Ale_INFO,Txt_There_are_no_institutions_with_requests_for_centres_to_be_confirmed); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /********************** Draw institution logo with link **********************/ /*****************************************************************************/ void Ins_DrawInstitutionLogoWithLink (struct Instit *Ins,unsigned Size) { bool PutLink = !Gbl.Form.Inside; // Don't put link to institution if already inside a form if (PutLink) { Frm_StartForm (ActSeeInsInf); Ins_PutParamInsCod (Ins->InsCod); Frm_LinkFormSubmit (Ins->FullName,NULL,NULL); } Log_DrawLogo (Hie_INS,Ins->InsCod,Ins->FullName, Size,NULL,true); if (PutLink) { Frm_LinkFormEnd (); Frm_EndForm (); } } /*****************************************************************************/ /****************** Draw institution logo and name with link *****************/ /*****************************************************************************/ void Ins_DrawInstitutionLogoAndNameWithLink (struct Instit *Ins,Act_Action_t Action, const char *ClassLink,const char *ClassLogo) { extern const char *Txt_Go_to_X; /***** Begin form *****/ Frm_StartFormGoTo (Action); Ins_PutParamInsCod (Ins->InsCod); /***** Link to action *****/ snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Go_to_X, Ins->FullName); Frm_LinkFormSubmit (Gbl.Title,ClassLink,NULL); /***** Institution logo and name *****/ Log_DrawLogo (Hie_INS,Ins->InsCod,Ins->ShrtName,16,ClassLogo,true); fprintf (Gbl.F.Out," %s",Ins->FullName); /***** End link *****/ Frm_LinkFormEnd (); /***** End form *****/ Frm_EndForm (); } /*****************************************************************************/ /*************** Show information of the current institution *****************/ /*****************************************************************************/ void Ins_ShowConfiguration (void) { Ins_Configuration (false); /***** Show help to enrol me *****/ Hlp_ShowHelpWhatWouldYouLikeToDo (); } /*****************************************************************************/ /*************** Print information of the current institution ****************/ /*****************************************************************************/ void Ins_PrintConfiguration (void) { Ins_Configuration (true); } /*****************************************************************************/ /***************** Information of the current institution ********************/ /*****************************************************************************/ static void Ins_Configuration (bool PrintView) { extern const char *Hlp_INSTITUTION_Information; extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Country; extern const char *Txt_Institution; extern const char *Txt_Short_name; extern const char *Txt_Web; 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_Centres; extern const char *Txt_Centres_of_INSTITUTION_X; extern const char *Txt_Degrees; extern const char *Txt_Courses; extern const char *Txt_Departments; extern const char *Txt_Users_of_the_institution; unsigned NumCty; bool PutLink; /***** Trivial check *****/ if (Gbl.Hierarchy.Ins.InsCod <= 0) // No institution selected return; /***** Begin box *****/ if (PrintView) Box_BoxBegin (NULL,NULL,NULL, NULL,Box_NOT_CLOSABLE); else Box_BoxBegin (NULL,NULL,Ins_PutIconsToPrintAndUpload, Hlp_INSTITUTION_Information,Box_NOT_CLOSABLE); /***** Title *****/ PutLink = !PrintView && Gbl.Hierarchy.Ins.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.Ins.WWW, Gbl.Hierarchy.Ins.FullName); Log_DrawLogo (Hie_INS,Gbl.Hierarchy.Ins.InsCod, Gbl.Hierarchy.Ins.ShrtName,64,NULL,true); fprintf (Gbl.F.Out,"
%s",Gbl.Hierarchy.Ins.FullName); if (PutLink) HTM_A_End (); HTM_DIV_End (); /***** Begin table *****/ HTM_TABLE_BeginWidePadding (2); /***** Country *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); HTM_LABEL_Begin ("for=\"OthCtyCod\" class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Country); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); if (!PrintView && Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM) // Only system admins can move an institution to another country { /* Get list of countries */ Cty_GetListCountries (Cty_GET_BASIC_DATA); /* Put form to select country */ Frm_StartForm (ActChgInsCtyCfg); fprintf (Gbl.F.Out," 0) fprintf (Gbl.F.Out," onchange=\"document.getElementById('%s').submit();return false;\"", Gbl.Form.Id); else fprintf (Gbl.F.Out," disabled=\"disabled\""); fprintf (Gbl.F.Out,">"); fprintf (Gbl.F.Out,"", Txt_Institution); if (Gbl.Hierarchy.Cty.CtyCod > 0) { /***** Get institutions of selected country from database *****/ NumInss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions", "SELECT DISTINCT InsCod,ShortName" " FROM institutions" " WHERE CtyCod=%ld" " ORDER BY ShortName", Gbl.Hierarchy.Cty.CtyCod); /***** List institutions *****/ for (NumIns = 0; NumIns < NumInss; NumIns++) { /* Get next institution */ row = mysql_fetch_row (mysql_res); /* Get institution code (row[0]) */ if ((InsCod = Str_ConvertStrCodToLongCod (row[0])) < 0) Lay_ShowErrorAndExit ("Wrong code of institution."); /* Write option */ fprintf (Gbl.F.Out,"",row[1]); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /***** End form *****/ HTM_SELECT_End (); Frm_EndForm (); } /*****************************************************************************/ /************************* List all the institutions *************************/ /*****************************************************************************/ static void Ins_ListInstitutionsForEdition (void) { extern const char *Txt_INSTITUTION_STATUS[Ins_NUM_STATUS_TXT]; unsigned NumIns; struct Instit *Ins; char WWW[Cns_MAX_BYTES_WWW + 1]; struct UsrData UsrDat; bool ICanEdit; Ins_StatusTxt_t StatusTxt; /***** Initialize structure with user's data *****/ Usr_UsrDataConstructor (&UsrDat); /***** Write heading *****/ HTM_TABLE_BeginWidePadding (2); Ins_PutHeadInstitutionsForEdition (); /***** Write all the institutions *****/ for (NumIns = 0; NumIns < Gbl.Hierarchy.Cty.Inss.Num; NumIns++) { Ins = &Gbl.Hierarchy.Cty.Inss.Lst[NumIns]; ICanEdit = Ins_CheckIfICanEdit (Ins); HTM_TR_Begin (NULL); /* Put icon to remove institution */ HTM_TD_Begin ("class=\"BM\""); if (Ins->Ctrs.Num || Ins->NumUsrsWhoClaimToBelongToIns || Ins->NumUsrs || // Institution has centres or users ==> deletion forbidden !ICanEdit) Ico_PutIconRemovalNotAllowed (); else { Frm_StartForm (ActRemIns); Ins_PutParamOtherInsCod (Ins->InsCod); Ico_PutIconRemove (); Frm_EndForm (); } HTM_TD_End (); /* Institution code */ HTM_TD_Begin ("class=\"DAT CODE\""); fprintf (Gbl.F.Out,"%ld",Ins->InsCod); HTM_TD_End (); /* Institution logo */ HTM_TD_Begin ("title=\"%s\" class=\"HIE_LOGO\"",Ins->FullName); Log_DrawLogo (Hie_INS,Ins->InsCod,Ins->ShrtName,20,NULL,true); HTM_TD_End (); /* Institution short name */ HTM_TD_Begin ("class=\"DAT LM\""); if (ICanEdit) { Frm_StartForm (ActRenInsSho); Ins_PutParamOtherInsCod (Ins->InsCod); HTM_INPUT_TEXT ("ShortName",Hie_MAX_CHARS_SHRT_NAME,Ins->ShrtName,true, "class=\"INPUT_SHORT_NAME\""); Frm_EndForm (); } else fprintf (Gbl.F.Out,"%s",Ins->ShrtName); HTM_TD_End (); /* Institution full name */ HTM_TD_Begin ("class=\"DAT LM\""); if (ICanEdit) { Frm_StartForm (ActRenInsFul); Ins_PutParamOtherInsCod (Ins->InsCod); HTM_INPUT_TEXT ("FullName",Hie_MAX_CHARS_FULL_NAME,Ins->FullName,true, "class=\"INPUT_FULL_NAME\""); Frm_EndForm (); } else fprintf (Gbl.F.Out,"%s",Ins->FullName); HTM_TD_End (); /* Institution WWW */ HTM_TD_Begin ("class=\"DAT LM\""); if (ICanEdit) { Frm_StartForm (ActChgInsWWW); Ins_PutParamOtherInsCod (Ins->InsCod); HTM_INPUT_URL ("WWW",Ins->WWW,true, "class=\"INPUT_WWW\""); Frm_EndForm (); HTM_TD_End (); } else { Str_Copy (WWW,Ins->WWW, Cns_MAX_BYTES_WWW); HTM_DIV_Begin ("class=\"EXTERNAL_WWW_SHORT\""); HTM_A_Begin ("href=\"%s\" target=\"_blank\" class=\"DAT\" title=\"%s\"", Ins->WWW,Ins->WWW); fprintf (Gbl.F.Out,"%s",WWW); HTM_A_End (); HTM_DIV_End (); } HTM_TD_End (); /* Number of users who claim to belong to this institution */ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ins->NumUsrsWhoClaimToBelongToIns); HTM_TD_End (); /* Number of centres */ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ins->Ctrs.Num); HTM_TD_End (); /* Number of users in courses of this institution */ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ins->NumUsrs); HTM_TD_End (); /* Institution requester */ UsrDat.UsrCod = Ins->RequesterUsrCod; Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS); HTM_TD_Begin ("class=\"DAT INPUT_REQUESTER LT\""); Msg_WriteMsgAuthor (&UsrDat,true,NULL); HTM_TD_End (); /* Institution status */ StatusTxt = Ins_GetStatusTxtFromStatusBits (Ins->Status); HTM_TD_Begin ("class=\"DAT LM\""); if (Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM && StatusTxt == Ins_STATUS_PENDING) { Frm_StartForm (ActChgInsSta); Ins_PutParamOtherInsCod (Ins->InsCod); fprintf (Gbl.F.Out,"