diff --git a/Makefile b/Makefile
index ff38c796..b954fc18 100644
--- a/Makefile
+++ b/Makefile
@@ -73,7 +73,7 @@ OBJS = swad_account.o swad_account_database.o swad_action.o swad_admin.o \
swad_password_database.o swad_photo.o swad_photo_database.o \
swad_place.o swad_place_database.o swad_plugin.o swad_plugin_database.o \
swad_privacy.o swad_profile.o swad_profile_database.o swad_program.o \
- swad_program_database.o swad_project.o \
+ swad_program_database.o swad_project.o swad_project_database.o \
swad_QR.o \
swad_record.o swad_report.o swad_role.o swad_room.o swad_RSS.o \
swad_scope.o swad_search.o swad_session.o swad_setting.o \
diff --git a/swad_browser.c b/swad_browser.c
index bd9c2d73..ce1129ca 100644
--- a/swad_browser.c
+++ b/swad_browser.c
@@ -65,6 +65,7 @@
#include "swad_profile.h"
#include "swad_profile_database.h"
#include "swad_project.h"
+#include "swad_project_database.h"
#include "swad_role.h"
#include "swad_setting.h"
#include "swad_string.h"
@@ -6436,7 +6437,7 @@ static void Brw_PasteClipboard (void)
case Brw_ADMI_DOC_PRJ:
case Brw_ADMI_ASS_PRJ:
PrjCod = Gbl.FileBrowser.Clipboard.Cod;
- Hie.Crs.CrsCod = Prj_GetCourseOfProject (PrjCod);
+ Hie.Crs.CrsCod = Prj_DB_GetCrsOfPrj (PrjCod);
if (Crs_GetDataOfCourseByCod (&Hie.Crs))
snprintf (PathOrg,sizeof (PathOrg),"%s/%ld/%s/%02u/%ld/%s",
Cfg_PATH_CRS_PRIVATE,Hie.Crs.CrsCod,Cfg_FOLDER_PRJ,
@@ -9226,7 +9227,7 @@ void Brw_GetCrsGrpFromFileMetadata (Brw_FileBrowser_t FileBrowser,long Cod,
case Brw_ADMI_ASS_PRJ:
/* Cod stores the project code */
*GrpCod = -1L;
- *CrsCod = Crs.CrsCod = Prj_GetCourseOfProject (Cod);
+ *CrsCod = Crs.CrsCod = Prj_DB_GetCrsOfPrj (Cod);
Crs_GetDataOfCourseByCod (&Crs);
*DegCod = Deg.DegCod = Crs.DegCod;
Deg_GetDataOfDegreeByCod (&Deg);
diff --git a/swad_changelog.h b/swad_changelog.h
index 486a7c07..724ee1a8 100644
--- a/swad_changelog.h
+++ b/swad_changelog.h
@@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
*/
-#define Log_PLATFORM_VERSION "SWAD 21.28.1 (2021-10-10)"
+#define Log_PLATFORM_VERSION "SWAD 21.29 (2021-10-11)"
#define CSS_FILE "swad20.45.css"
#define JS_FILE "swad20.69.1.js"
/*
TODO: Rename CENTRE to CENTER in help wiki.
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
+ Version 21.29: Oct 11, 2021 New module swad_peoject_database for database queries related to projects. (319208 lines)
Version 21.28.1: Oct 10, 2021 Code refactoring in projects. (318975 lines)
Version 21.28: Oct 09, 2021 New module swad_program_database for database queries related to course program. (319013 lines)
Version 21.27.1: Oct 07, 2021 Queries moved to module swad_profile_database. (318855 lines)
diff --git a/swad_figure.c b/swad_figure.c
index 7167fdf1..94935dc4 100644
--- a/swad_figure.c
+++ b/swad_figure.c
@@ -63,6 +63,7 @@
#include "swad_program.h"
#include "swad_program_database.h"
#include "swad_project.h"
+#include "swad_project_database.h"
#include "swad_role.h"
#include "swad_survey.h"
#include "swad_test.h"
diff --git a/swad_project.c b/swad_project.c
index ce6b67de..0b5e2251 100644
--- a/swad_project.c
+++ b/swad_project.c
@@ -48,6 +48,7 @@
#include "swad_parameter.h"
#include "swad_photo.h"
#include "swad_project.h"
+#include "swad_project_database.h"
#include "swad_role.h"
#include "swad_setting.h"
#include "swad_string.h"
@@ -86,14 +87,6 @@ static const Prj_RoleInProject_t Prj_RolesToShow[] =
static const unsigned Brw_NUM_ROLES_TO_SHOW = sizeof (Prj_RolesToShow) /
sizeof (Prj_RolesToShow[0]);
-/***** Enum field in database for types of proposal *****/
-static const char *Prj_Proposal_DB[Prj_NUM_PROPOSAL_TYPES] =
- {
- [Prj_PROPOSAL_NEW ] = "new",
- [Prj_PROPOSAL_MODIFIED ] = "modified",
- [Prj_PROPOSAL_UNMODIFIED] = "unmodified",
- };
-
/***** Assigned/non-assigned project *****/
static const char *AssignedNonassigImage[Prj_NUM_ASSIGNED_NONASSIG] =
{
@@ -219,13 +212,9 @@ static void Prj_ShowOneProjectMembers (struct Prj_Projects *Projects,
static void Prj_ShowOneProjectMembersWithARole (struct Prj_Projects *Projects,
const struct Prj_Project *Prj,
Prj_ProjectView_t ProjectView,
- Prj_RoleInProject_t RoleInProject);
+ Prj_RoleInProject_t RoleInPrj);
static void Prj_ShowTableAllProjectsMembersWithARole (const struct Prj_Project *Prj,
- Prj_RoleInProject_t RoleInProject);
-
-static unsigned Prj_GetNumUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject);
-static unsigned Prj_GetUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject,
- MYSQL_RES **mysql_res);
+ Prj_RoleInProject_t RoleInPrj);
static Prj_RoleInProject_t Prj_ConvertUnsignedStrToRoleInProject (const char *UnsignedStr);
@@ -233,14 +222,14 @@ static void Prj_FormToSelectStds (void *Projects);
static void Prj_FormToSelectTuts (void *Projects);
static void Prj_FormToSelectEvls (void *Projects);
static void Prj_FormToSelectUsrs (struct Prj_Projects *Projects,
- Prj_RoleInProject_t RoleInProject);
+ Prj_RoleInProject_t RoleInPrj);
static void Prj_AddStds (__attribute__((unused)) void *Args);
static void Prj_AddTuts (__attribute__((unused)) void *Args);
static void Prj_AddEvls (__attribute__((unused)) void *Args);
-static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInProject);
+static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInPrj);
static void Prj_ReqRemUsrFromPrj (struct Prj_Projects *Projects,
- Prj_RoleInProject_t RoleInProject);
-static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInProject);
+ Prj_RoleInProject_t RoleInPrj);
+static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInPrj);
static Prj_Order_t Prj_GetParamPrjOrder (void);
@@ -267,7 +256,7 @@ static void Prj_CreateProject (struct Prj_Project *Prj);
static void Prj_UpdateProject (struct Prj_Project *Prj);
static bool Prj_CheckIfICanConfigAllProjects (void);
-static void Prj_GetConfigPrjFromDB (struct Prj_Projects *Projects);
+static void Prj_GetCrsPrjsConfig (struct Prj_Projects *Projects);
static void Prj_GetConfigFromRow (struct Prj_Projects *Projects,MYSQL_ROW row);
static bool Prj_GetEditableFromForm (void);
static void Prj_PutIconsToLockUnlockAllProjects (struct Prj_Projects *Projects);
@@ -275,10 +264,6 @@ static void Prj_PutIconsToLockUnlockAllProjects (struct Prj_Projects *Projects);
static void Prj_FormLockUnlock (const struct Prj_Project *Prj);
static void Prj_PutIconOffLockedUnlocked (const struct Prj_Project *Prj);
-static void Prj_DB_LockProjectEdition (long PrjCod);
-static void Prj_DB_UnlockProjectEdition (long PrjCod);
-
-
/*****************************************************************************/
/******* Set/get project code (used to pass parameter to file browser) *******/
/*****************************************************************************/
@@ -876,12 +861,12 @@ static Prj_HiddenVisibl_t Prj_GetHiddenParamHidVis (void)
case Rol_TCH:
case Rol_SYS_ADM:
return (Prj_HiddenVisibl_t)
- Par_GetParToUnsignedLong (Prj_PARAM_HID_VIS_NAME,
- 0,
- (1 << Prj_HIDDEN) |
- (1 << Prj_VISIBL),
- (unsigned) Prj_FILTER_HIDDEN_DEFAULT |
- (unsigned) Prj_FILTER_VISIBL_DEFAULT);
+ Par_GetParToUnsignedLong (Prj_PARAM_HID_VIS_NAME,
+ 0,
+ (1 << Prj_HIDDEN) |
+ (1 << Prj_VISIBL),
+ (unsigned) Prj_FILTER_HIDDEN_DEFAULT |
+ (unsigned) Prj_FILTER_VISIBL_DEFAULT);
default:
Err_WrongRoleExit ();
return Prj_NEW_PRJ_HIDDEN_VISIBL_DEFAULT; // Not reached
@@ -958,59 +943,61 @@ static void Prj_ShowProjectsHead (struct Prj_Projects *Projects,
HTM_TR_Begin (NULL);
- /***** Column for number of project *****/
- switch (ProjectView)
- {
- case Prj_LIST_PROJECTS:
- HTM_TH (1,1,"CM",Txt_No_INDEX);
- break;
- default:
- break;
- }
-
- /***** Column for contextual icons *****/
- switch (ProjectView)
- {
- case Prj_LIST_PROJECTS:
- case Prj_FILE_BROWSER_PROJECT:
- HTM_TH (1,1,"CONTEXT_COL",NULL);
- break;
- default:
- break;
- }
-
- /***** Rest of columns *****/
- for (Order = (Prj_Order_t) 0;
- Order <= (Prj_Order_t) (Prj_NUM_ORDERS - 1);
- Order++)
- {
- HTM_TH_Begin (1,1,"LM");
+ /***** Column for number of project *****/
+ switch (ProjectView)
+ {
+ case Prj_LIST_PROJECTS:
+ HTM_TH (1,1,"CM",Txt_No_INDEX);
+ break;
+ default:
+ break;
+ }
+ /***** Column for contextual icons *****/
switch (ProjectView)
{
case Prj_LIST_PROJECTS:
case Prj_FILE_BROWSER_PROJECT:
- Frm_BeginForm (ActSeePrj);
- Prj_PutParams (&Projects->Filter,
- Order,
- Projects->CurrentPage,
- -1L);
- HTM_BUTTON_SUBMIT_Begin (Txt_PROJECT_ORDER_HELP[Order],"BT_LINK TIT_TBL",NULL);
- if (Order == Projects->SelectedOrder)
- HTM_U_Begin ();
- HTM_Txt (Txt_PROJECT_ORDER[Order]);
- if (Order == Projects->SelectedOrder)
- HTM_U_End ();
- HTM_BUTTON_End ();
- Frm_EndForm ();
+ HTM_TH (1,1,"CONTEXT_COL",NULL);
break;
default:
- HTM_Txt (Txt_PROJECT_ORDER[Order]);
break;
}
- HTM_TH_End ();
- }
+ /***** Rest of columns *****/
+ for (Order = (Prj_Order_t) 0;
+ Order <= (Prj_Order_t) (Prj_NUM_ORDERS - 1);
+ Order++)
+ {
+ HTM_TH_Begin (1,1,"LM");
+
+ switch (ProjectView)
+ {
+ case Prj_LIST_PROJECTS:
+ case Prj_FILE_BROWSER_PROJECT:
+ Frm_BeginForm (ActSeePrj);
+ Prj_PutParams (&Projects->Filter,
+ Order,
+ Projects->CurrentPage,
+ -1L);
+ HTM_BUTTON_SUBMIT_Begin (Txt_PROJECT_ORDER_HELP[Order],"BT_LINK TIT_TBL",NULL);
+ if (Order == Projects->SelectedOrder)
+ HTM_U_Begin ();
+ HTM_Txt (Txt_PROJECT_ORDER[Order]);
+ if (Order == Projects->SelectedOrder)
+ HTM_U_End ();
+ HTM_BUTTON_End ();
+ Frm_EndForm ();
+ break;
+ default:
+ HTM_Txt (Txt_PROJECT_ORDER[Order]);
+ break;
+ }
+
+ HTM_TH_End ();
+ }
+
+ HTM_TR_End ();
}
static void Prj_ShowTableAllProjectsHead (void)
@@ -1134,7 +1121,7 @@ static void Prj_PutButtonToCreateNewPrj (struct Prj_Projects *Projects)
Projects->PrjCod = -1L;
Frm_BeginForm (ActFrmNewPrj);
Prj_PutCurrentParams (Projects);
- Btn_PutConfirmButton (Txt_New_project);
+ Btn_PutConfirmButton (Txt_New_project);
Frm_EndForm ();
}
@@ -1579,14 +1566,7 @@ static bool Prj_CheckIfPrjIsFaulty (long PrjCod,struct Prj_Faults *Faults)
if (PrjCod > 0)
{
/***** Query database *****/
- if (DB_QuerySELECT (&mysql_res,"can not get project data",
- "SELECT Assigned='Y'," // row[0] = 0 / 1
- "NumStds," // row[1] =
- "Title<>''," // row[2] = 0 / 1
- "Description<>''" // row[3] = 0 / 1
- " FROM prj_projects"
- " WHERE PrjCod=%ld",
- PrjCod)) // Project found...
+ if (Prj_DB_GetPrjDataToCheckFaults (&mysql_res,PrjCod)) // Project found...
{
/***** Get some data of project *****/
/* Get row */
@@ -1595,13 +1575,12 @@ static bool Prj_CheckIfPrjIsFaulty (long PrjCod,struct Prj_Faults *Faults)
/* Get if project is assigned or not (row[0]) */
IsAssigned = (row[0][0] != '0');
- /* Get if project is assigned or not (row[1]) */
+ /* Get number of proposed students (row[1]) */
NumProposedStds = Str_ConvertStrToUnsigned (row[1]);
- /* Get the title of the project (row[2]) */
- HasTitle = (row[2][0] != '0');
-
- /* Get the description of the project (row[3]) */
+ /* Get if title is not empty (row[2])
+ and if description is not empty (row[3]) */
+ HasTitle = (row[2][0] != '0');
HasDescription = (row[3][0] != '0');
/***** Check faults *****/
@@ -1617,7 +1596,7 @@ static bool Prj_CheckIfPrjIsFaulty (long PrjCod,struct Prj_Faults *Faults)
Faults->WrongNumStds = true;
else
{
- NumStdsRegisteredInPrj = Prj_GetNumUsrsInPrj (PrjCod,Prj_ROLE_STD);
+ NumStdsRegisteredInPrj = Prj_DB_GetNumUsrsInPrj (PrjCod,Prj_ROLE_STD);
if (IsAssigned) // Assigned
// In an assigned project the number of proposed students...
// ...should match the number of students registered in it
@@ -1845,15 +1824,16 @@ static void Prj_ShowOneProjectTxtField (struct Prj_Project *Prj,
/***** Set CSS classes *****/
ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" :
"ASG_LABEL";
- ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" :
- "DAT";
+ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" :
+ "DAT";
/***** Label *****/
switch (ProjectView)
{
case Prj_LIST_PROJECTS:
HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId);
- HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",ClassLabel,Gbl.RowEvenOdd);
+ HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",
+ ClassLabel,Gbl.RowEvenOdd);
break;
case Prj_FILE_BROWSER_PROJECT:
HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId);
@@ -1940,15 +1920,16 @@ static void Prj_ShowOneProjectURL (const struct Prj_Project *Prj,
/***** Set CSS classes *****/
ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" :
"ASG_LABEL";
- ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" :
- "DAT";
+ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" :
+ "DAT";
/***** Write row with label and text *****/
switch (ProjectView)
{
case Prj_LIST_PROJECTS:
HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId);
- HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",ClassLabel,Gbl.RowEvenOdd);
+ HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",
+ ClassLabel,Gbl.RowEvenOdd);
break;
case Prj_FILE_BROWSER_PROJECT:
HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId);
@@ -2025,7 +2006,7 @@ static void Prj_ShowOneProjectMembers (struct Prj_Projects *Projects,
static void Prj_ShowOneProjectMembersWithARole (struct Prj_Projects *Projects,
const struct Prj_Project *Prj,
Prj_ProjectView_t ProjectView,
- Prj_RoleInProject_t RoleInProject)
+ Prj_RoleInProject_t RoleInPrj)
{
extern const char *Txt_PROJECT_ROLES_SINGUL_Abc[Prj_NUM_ROLES_IN_PROJECT];
extern const char *Txt_PROJECT_ROLES_PLURAL_Abc[Prj_NUM_ROLES_IN_PROJECT];
@@ -2057,11 +2038,11 @@ static void Prj_ShowOneProjectMembersWithARole (struct Prj_Projects *Projects,
/***** Set CSS classes *****/
ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" :
"ASG_LABEL";
- ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" :
- "DAT";
+ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" :
+ "DAT";
/***** Get users in project from database *****/
- NumUsrs = Prj_GetUsrsInPrj (Prj->PrjCod,RoleInProject,&mysql_res);
+ NumUsrs = Prj_DB_GetUsrsInPrj (&mysql_res,Prj->PrjCod,RoleInPrj);
WriteRow = (NumUsrs != 0 ||
ProjectView == Prj_EDIT_ONE_PROJECT);
@@ -2076,22 +2057,22 @@ static void Prj_ShowOneProjectMembersWithARole (struct Prj_Projects *Projects,
case Prj_LIST_PROJECTS:
HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",
ClassLabel,Gbl.RowEvenOdd);
- HTM_TxtColon (NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInProject] :
- Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]);
+ HTM_TxtColon (NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInPrj] :
+ Txt_PROJECT_ROLES_PLURAL_Abc[RoleInPrj]);
break;
case Prj_FILE_BROWSER_PROJECT:
HTM_TD_Begin ("colspan=\"3\" class=\"RT %s\"",ClassLabel);
- HTM_TxtColon (NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInProject] :
- Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]);
+ HTM_TxtColon (NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInPrj] :
+ Txt_PROJECT_ROLES_PLURAL_Abc[RoleInPrj]);
break;
case Prj_PRINT_ONE_PROJECT:
HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"",ClassLabel);
- HTM_TxtColon (NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInProject] :
- Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]);
+ HTM_TxtColon (NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInPrj] :
+ Txt_PROJECT_ROLES_PLURAL_Abc[RoleInPrj]);
break;
case Prj_EDIT_ONE_PROJECT:
HTM_TD_Begin ("class=\"RT ASG_LABEL\"");
- HTM_TxtColon (Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]);
+ HTM_TxtColon (Txt_PROJECT_ROLES_PLURAL_Abc[RoleInPrj]);
break;
}
HTM_TD_End ();
@@ -2113,80 +2094,80 @@ static void Prj_ShowOneProjectMembersWithARole (struct Prj_Projects *Projects,
break;
}
- /***** Begin table with all members with this role *****/
- HTM_TABLE_BeginPadding (2);
+ /***** Begin table with all members with this role *****/
+ HTM_TABLE_BeginPadding (2);
- /***** Write users *****/
- for (NumUsr = 0;
- NumUsr < NumUsrs;
- NumUsr++)
- {
- /* Get user's code */
- row = mysql_fetch_row (mysql_res);
- Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
-
- /* Get user's data */
- if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,
- Usr_DONT_GET_PREFS,
- Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
+ /***** Write users *****/
+ for (NumUsr = 0;
+ NumUsr < NumUsrs;
+ NumUsr++)
{
- /* Begin row for this user */
- HTM_TR_Begin (NULL);
+ /* Get user's code */
+ row = mysql_fetch_row (mysql_res);
+ Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
- /* Icon to remove user */
- if (ProjectView == Prj_EDIT_ONE_PROJECT)
- {
- HTM_TD_Begin ("class=\"PRJ_MEMBER_ICO\"");
- Lay_PutContextualLinkOnlyIcon (ActionReqRemUsr[RoleInProject],NULL,
- Prj_PutCurrentParams,Projects,
- "trash.svg",
- Txt_Remove);
+ /* Get user's data */
+ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,
+ Usr_DONT_GET_PREFS,
+ Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
+ {
+ /* Begin row for this user */
+ HTM_TR_Begin (NULL);
+
+ /* Icon to remove user */
+ if (ProjectView == Prj_EDIT_ONE_PROJECT)
+ {
+ HTM_TD_Begin ("class=\"PRJ_MEMBER_ICO\"");
+ Lay_PutContextualLinkOnlyIcon (ActionReqRemUsr[RoleInPrj],NULL,
+ Prj_PutCurrentParams,Projects,
+ "trash.svg",
+ Txt_Remove);
+ HTM_TD_End ();
+ }
+
+ /* Put user's photo */
+ HTM_TD_Begin ("class=\"PRJ_MEMBER_PHO\"");
+ Pho_ShowUsrPhotoIfAllowed (&Gbl.Usrs.Other.UsrDat,"PHOTO21x28",Pho_ZOOM,false);
HTM_TD_End ();
- }
- /* Put user's photo */
- HTM_TD_Begin ("class=\"PRJ_MEMBER_PHO\"");
- Pho_ShowUsrPhotoIfAllowed (&Gbl.Usrs.Other.UsrDat,"PHOTO21x28",Pho_ZOOM,false);
- HTM_TD_End ();
+ /* Write user's name */
+ HTM_TD_Begin ("class=\"PRJ_MEMBER_NAM\"");
+ HTM_Txt (Gbl.Usrs.Other.UsrDat.FullName);
+ HTM_TD_End ();
- /* Write user's name */
- HTM_TD_Begin ("class=\"PRJ_MEMBER_NAM\"");
- HTM_Txt (Gbl.Usrs.Other.UsrDat.FullName);
- HTM_TD_End ();
-
- /* End row for this user */
- HTM_TR_End ();
+ /* End row for this user */
+ HTM_TR_End ();
+ }
}
- }
- /***** Row to add a new user *****/
- switch (ProjectView)
- {
- case Prj_EDIT_ONE_PROJECT:
- HTM_TR_Begin (NULL);
- HTM_TD_Begin ("class=\"PRJ_MEMBER_ICO\"");
- Projects->PrjCod = Prj->PrjCod; // Used to pass project code as a parameter
- Ico_PutContextualIconToAdd (ActionReqAddUsr[RoleInProject],NULL,
- Prj_PutCurrentParams,Projects,
- Str_BuildStringStr (Txt_Add_USERS,
- Txt_PROJECT_ROLES_PLURAL_abc[RoleInProject]));
- Str_FreeString ();
- HTM_TD_End ();
+ /***** Row to add a new user *****/
+ switch (ProjectView)
+ {
+ case Prj_EDIT_ONE_PROJECT:
+ HTM_TR_Begin (NULL);
+ HTM_TD_Begin ("class=\"PRJ_MEMBER_ICO\"");
+ Projects->PrjCod = Prj->PrjCod; // Used to pass project code as a parameter
+ Ico_PutContextualIconToAdd (ActionReqAddUsr[RoleInPrj],NULL,
+ Prj_PutCurrentParams,Projects,
+ Str_BuildStringStr (Txt_Add_USERS,
+ Txt_PROJECT_ROLES_PLURAL_abc[RoleInPrj]));
+ Str_FreeString ();
+ HTM_TD_End ();
- HTM_TD_Begin ("class=\"PRJ_MEMBER_PHO\""); // Column for photo
- HTM_TD_End ();
+ HTM_TD_Begin ("class=\"PRJ_MEMBER_PHO\""); // Column for photo
+ HTM_TD_End ();
- HTM_TD_Begin ("class=\"PRJ_MEMBER_NAM\""); // Column for name
- HTM_TD_End ();
+ HTM_TD_Begin ("class=\"PRJ_MEMBER_NAM\""); // Column for name
+ HTM_TD_End ();
- HTM_TR_End ();
- break;
- default:
- break;
- }
+ HTM_TR_End ();
+ break;
+ default:
+ break;
+ }
- /***** End table with all members with this role *****/
- HTM_TABLE_End ();
+ /***** End table with all members with this role *****/
+ HTM_TABLE_End ();
/***** End row with label and listing of users *****/
HTM_TD_End ();
@@ -2198,7 +2179,7 @@ static void Prj_ShowOneProjectMembersWithARole (struct Prj_Projects *Projects,
}
static void Prj_ShowTableAllProjectsMembersWithARole (const struct Prj_Project *Prj,
- Prj_RoleInProject_t RoleInProject)
+ Prj_RoleInProject_t RoleInPrj)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@@ -2211,7 +2192,7 @@ static void Prj_ShowTableAllProjectsMembersWithARole (const struct Prj_Project *
"DAT";
/***** Get users in project from database *****/
- NumUsrs = Prj_GetUsrsInPrj (Prj->PrjCod,RoleInProject,&mysql_res);
+ NumUsrs = Prj_DB_GetUsrsInPrj (&mysql_res,Prj->PrjCod,RoleInPrj);
/***** Begin column with list of all members with this role *****/
HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd);
@@ -2254,48 +2235,6 @@ static void Prj_ShowTableAllProjectsMembersWithARole (const struct Prj_Project *
HTM_TD_End ();
}
-/*****************************************************************************/
-/*************** Get number of users with a role in a project ****************/
-/*****************************************************************************/
-
-static unsigned Prj_GetNumUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject)
- {
- /***** Get users in project from database *****/
- return (unsigned)
- DB_QueryCOUNT ("can not get number of users in project",
- "SELECT COUNT(UsrCod)"
- " FROM prj_users"
- " WHERE PrjCod=%ld"
- " AND RoleInProject=%u",
- PrjCod,
- (unsigned) RoleInProject);
- }
-
-/*****************************************************************************/
-/*************** Get number of users with a role in a project ****************/
-/*****************************************************************************/
-
-static unsigned Prj_GetUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject,
- MYSQL_RES **mysql_res)
- {
- /***** Get users in project from database *****/
- return (unsigned)
- DB_QuerySELECT (mysql_res,"can not get users in project",
- "SELECT prj_users.UsrCod," // row[0]
- "usr_data.Surname1 AS S1," // row[1]
- "usr_data.Surname2 AS S2," // row[2]
- "usr_data.FirstName AS FN" // row[3]
- " FROM prj_users,"
- "usr_data"
- " WHERE prj_users.PrjCod=%ld"
- " AND prj_users.RoleInProject=%u"
- " AND prj_users.UsrCod=usr_data.UsrCod"
- " ORDER BY S1,"
- "S2,"
- "FN",
- PrjCod,(unsigned) RoleInProject);
- }
-
/*****************************************************************************/
/************************** Get my role in a project *************************/
/*****************************************************************************/
@@ -2310,9 +2249,9 @@ unsigned Prj_GetMyRolesInProject (long PrjCod)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
- unsigned NumRows;
- unsigned NumRow;
- Prj_RoleInProject_t RoleInProject;
+ unsigned NumRoles;
+ unsigned NumRole;
+ Prj_RoleInProject_t RoleInPrj;
/***** 1. Fast check: trivial cases *****/
if (Gbl.Usrs.Me.UsrDat.UsrCod <= 0 ||
@@ -2324,25 +2263,18 @@ unsigned Prj_GetMyRolesInProject (long PrjCod)
return Gbl.Cache.MyRolesInProject.RolesInProject;
/***** 3. Slow check: Get my role in project from database.
- The result of the query will have one row or none *****/
+ The result of the query should have one row or none *****/
Gbl.Cache.MyRolesInProject.PrjCod = PrjCod;
Gbl.Cache.MyRolesInProject.RolesInProject = 0;
- NumRows = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get my roles in project",
- "SELECT RoleInProject" // row[0]
- " FROM prj_users"
- " WHERE PrjCod=%ld"
- " AND UsrCod=%ld",
- PrjCod,
- Gbl.Usrs.Me.UsrDat.UsrCod);
- for (NumRow = 0;
- NumRow < NumRows;
- NumRow++)
+ NumRoles = Prj_DB_GetMyRolesInPrj (&mysql_res,PrjCod);
+ for (NumRole = 0;
+ NumRole < NumRoles;
+ NumRole++)
{
row = mysql_fetch_row (mysql_res);
- RoleInProject = Prj_ConvertUnsignedStrToRoleInProject (row[0]);
- if (RoleInProject != Prj_ROLE_UNK)
- Gbl.Cache.MyRolesInProject.RolesInProject |= (1 << RoleInProject);
+ RoleInPrj = Prj_ConvertUnsignedStrToRoleInProject (row[0]);
+ if (RoleInPrj != Prj_ROLE_UNK)
+ Gbl.Cache.MyRolesInProject.RolesInProject |= (1 << RoleInPrj);
}
DB_FreeMySQLResult (&mysql_res);
@@ -2417,7 +2349,7 @@ static void Prj_FormToSelectEvls (void *Projects)
}
static void Prj_FormToSelectUsrs (struct Prj_Projects *Projects,
- Prj_RoleInProject_t RoleInProject)
+ Prj_RoleInProject_t RoleInPrj)
{
extern const char *Hlp_ASSESSMENT_Projects_add_user;
extern const char *Txt_Add_USERS;
@@ -2439,10 +2371,10 @@ static void Prj_FormToSelectUsrs (struct Prj_Projects *Projects,
/***** Put form to select users *****/
if (asprintf (&TxtButton,Txt_Add_USERS,
- Txt_PROJECT_ROLES_PLURAL_abc[RoleInProject]) < 0)
+ Txt_PROJECT_ROLES_PLURAL_abc[RoleInPrj]) < 0)
Err_NotEnoughMemoryExit ();
Usr_PutFormToSelectUsrsToGoToAct (&Prj_MembersToAdd,
- ActionAddUsr[RoleInProject],
+ ActionAddUsr[RoleInPrj],
Prj_PutCurrentParams,Projects,
TxtButton,
Hlp_ASSESSMENT_Projects_add_user,
@@ -2498,7 +2430,7 @@ static void Prj_AddEvls (__attribute__((unused)) void *Args)
Prj_AddUsrsToProject (Prj_ROLE_EVL);
}
-static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInProject)
+static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInPrj)
{
extern const char *Txt_THE_USER_X_has_been_enroled_as_a_Y_in_the_project;
extern const char *Txt_PROJECT_ROLES_SINGUL_abc[Prj_NUM_ROLES_IN_PROJECT][Usr_NUM_SEXS];
@@ -2529,14 +2461,7 @@ static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInProject)
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
{
/* Add user to project */
- DB_QueryREPLACE ("can not add user to project",
- "REPLACE INTO prj_users"
- " (PrjCod,RoleInProject,UsrCod)"
- " VALUES"
- " (%ld,%u,%ld)",
- Projects.PrjCod,
- (unsigned) RoleInProject,
- Gbl.Usrs.Other.UsrDat.UsrCod);
+ Prj_DB_AddUsrToPrj (Projects.PrjCod,RoleInPrj,Gbl.Usrs.Other.UsrDat.UsrCod);
/* Flush cache */
if (Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod))
@@ -2545,7 +2470,7 @@ static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInProject)
/* Show success alert */
Ale_ShowAlert (Ale_SUCCESS,Txt_THE_USER_X_has_been_enroled_as_a_Y_in_the_project,
Gbl.Usrs.Other.UsrDat.FullName,
- Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex]);
+ Txt_PROJECT_ROLES_SINGUL_abc[RoleInPrj][Gbl.Usrs.Other.UsrDat.Sex]);
}
}
@@ -2591,7 +2516,7 @@ void Prj_ReqRemEvl (void)
}
static void Prj_ReqRemUsrFromPrj (struct Prj_Projects *Projects,
- Prj_RoleInProject_t RoleInProject)
+ Prj_RoleInProject_t RoleInPrj)
{
extern const char *Txt_Do_you_really_want_to_be_removed_as_a_X_from_the_project_Y;
extern const char *Txt_Do_you_really_want_to_remove_the_following_user_as_a_X_from_the_project_Y;
@@ -2629,18 +2554,18 @@ static void Prj_ReqRemUsrFromPrj (struct Prj_Projects *Projects,
/* Begin alert */
Ale_ShowAlertAndButton1 (Ale_QUESTION,ItsMe ? Txt_Do_you_really_want_to_be_removed_as_a_X_from_the_project_Y :
Txt_Do_you_really_want_to_remove_the_following_user_as_a_X_from_the_project_Y,
- Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex],
+ Txt_PROJECT_ROLES_SINGUL_abc[RoleInPrj][Gbl.Usrs.Other.UsrDat.Sex],
Prj.Title);
/* Show user's record */
Rec_ShowSharedRecordUnmodifiable (&Gbl.Usrs.Other.UsrDat);
/* Show form to request confirmation */
- Frm_BeginForm (ActionRemUsr[RoleInProject]);
+ Frm_BeginForm (ActionRemUsr[RoleInPrj]);
Projects->PrjCod = Prj.PrjCod;
Prj_PutCurrentParams (Projects);
Btn_PutRemoveButton (Str_BuildStringStr (Txt_Remove_USER_from_this_project,
- Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex]));
+ Txt_PROJECT_ROLES_SINGUL_abc[RoleInPrj][Gbl.Usrs.Other.UsrDat.Sex]));
Str_FreeString ();
Frm_EndForm ();
@@ -2681,13 +2606,12 @@ void Prj_RemEvl (void)
Prj_RemUsrFromPrj (Prj_ROLE_EVL);
}
-static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInProject)
+static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInPrj)
{
extern const char *Txt_THE_USER_X_has_been_removed_as_a_Y_from_the_project_Z;
extern const char *Txt_PROJECT_ROLES_SINGUL_abc[Prj_NUM_ROLES_IN_PROJECT][Usr_NUM_SEXS];
struct Prj_Projects Projects;
struct Prj_Project Prj;
- bool ItsMe;
/***** Reset projects *****/
Prj_ResetProjects (&Projects);
@@ -2709,24 +2633,16 @@ static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInProject)
if (Prj_CheckIfICanEditProject (&Prj))
{
/***** Remove user from the table of project-users *****/
- DB_QueryDELETE ("can not remove a user from a project",
- "DELETE FROM prj_users"
- " WHERE PrjCod=%ld"
- " AND RoleInProject=%u"
- " AND UsrCod=%ld",
- Prj.PrjCod,
- (unsigned) RoleInProject,
- Gbl.Usrs.Other.UsrDat.UsrCod);
+ Prj_DB_RemoveUsrFromPrj (Prj.PrjCod,RoleInPrj,Gbl.Usrs.Other.UsrDat.UsrCod);
/***** Flush cache *****/
- ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod);
- if (ItsMe)
+ if (Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod))
Prj_FlushCacheMyRolesInProject ();
/***** Show success alert *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_THE_USER_X_has_been_removed_as_a_Y_from_the_project_Z,
Gbl.Usrs.Other.UsrDat.FullName,
- Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex],
+ Txt_PROJECT_ROLES_SINGUL_abc[RoleInPrj][Gbl.Usrs.Other.UsrDat.Sex],
Prj.Title);
}
else
@@ -2839,30 +2755,11 @@ static bool Prj_CheckIfICanEditProject (const struct Prj_Project *Prj)
static void Prj_GetListProjects (struct Prj_Projects *Projects)
{
- char *PreNonSubQuery;
- char *HidVisSubQuery;
- char *DptCodSubQuery;
- static const char *OrderBySubQuery[Prj_NUM_ORDERS] =
- {
- [Prj_ORDER_START_TIME] = "prj_projects.CreatTime DESC,"
- "prj_projects.ModifTime DESC,"
- "prj_projects.Title",
- [Prj_ORDER_END_TIME ] = "prj_projects.ModifTime DESC,"
- "prj_projects.CreatTime DESC,"
- "prj_projects.Title",
- [Prj_ORDER_TITLE ] = "prj_projects.Title,"
- "prj_projects.CreatTime DESC,"
- "prj_projects.ModifTime DESC",
- [Prj_ORDER_DEPARTMENT] = "dpt_departments.FullName,"
- "prj_projects.CreatTime DESC,"
- "prj_projects.ModifTime DESC,"
- "prj_projects.Title",
- };
MYSQL_RES *mysql_res = NULL; // Initialized to avoid freeing when not assigned
- unsigned NumUsrsInList;
- long *LstSelectedUsrCods;
- char *SubQueryUsrs;
- unsigned NumPrjsFromDB = 0;
+ unsigned NumUsrsInList = 0;
+ long *LstSelectedUsrCods = NULL;
+ char *UsrsSubQuery = NULL;
+ unsigned NumPrjsFromDB;
unsigned NumPrjsAfterFilter = 0;
unsigned NumPrj;
struct Prj_Faults Faults;
@@ -2876,241 +2773,37 @@ static void Prj_GetListProjects (struct Prj_Projects *Projects)
Projects->Filter.Hidden && // Any selector is on
Projects->Filter.Faulti) // Any selector is on
{
- /* Assigned subquery */
- switch (Projects->Filter.Assign)
+ /****** Get users selected *****/
+ if (Projects->Filter.Who == Usr_WHO_SELECTED)
{
- case (1 << Prj_ASSIGNED): // Assigned projects
- if (asprintf (&PreNonSubQuery," AND prj_projects.Assigned='Y'") < 0)
- Err_NotEnoughMemoryExit ();
- break;
- case (1 << Prj_NONASSIG): // Non-assigned projects
- if (asprintf (&PreNonSubQuery," AND prj_projects.Assigned='N'") < 0)
- Err_NotEnoughMemoryExit ();
- break;
- default: // All projects
- if (asprintf (&PreNonSubQuery,"%s","") < 0)
- Err_NotEnoughMemoryExit ();
- break;
+ /* Count number of valid users in list of encrypted user codes */
+ NumUsrsInList = Usr_CountNumUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected);
+
+ if (NumUsrsInList)
+ {
+ /* Get list of users selected to show their projects */
+ Usr_GetListSelectedUsrCods (&Gbl.Usrs.Selected,NumUsrsInList,&LstSelectedUsrCods);
+
+ /* Create subquery string */
+ Usr_CreateSubqueryUsrCods (LstSelectedUsrCods,NumUsrsInList,
+ &UsrsSubQuery);
+ }
}
- /* Hidden subquery */
- switch (Gbl.Usrs.Me.Role.Logged)
- {
- case Rol_STD: // Students can view only visible projects
- if (asprintf (&HidVisSubQuery," AND prj_projects.Hidden='N'") < 0)
- Err_NotEnoughMemoryExit ();
- break;
- case Rol_NET:
- case Rol_TCH:
- case Rol_SYS_ADM:
- switch (Projects->Filter.Hidden)
- {
- case (1 << Prj_HIDDEN): // Hidden projects
- if (asprintf (&HidVisSubQuery," AND prj_projects.Hidden='Y'") < 0)
- Err_NotEnoughMemoryExit ();
- break;
- case (1 << Prj_VISIBL): // Visible projects
- if (asprintf (&HidVisSubQuery," AND prj_projects.Hidden='N'") < 0)
- Err_NotEnoughMemoryExit ();
- break;
- default: // All projects
- if (asprintf (&HidVisSubQuery,"%s","") < 0)
- Err_NotEnoughMemoryExit ();
- break;
- }
- break;
- default:
- Err_WrongRoleExit ();
- break;
- }
+ /***** Query database *****/
+ NumPrjsFromDB = Prj_DB_GetListProjects (&mysql_res,Projects,
+ UsrsSubQuery);
- /* Department subquery */
- if (Projects->Filter.DptCod >= 0)
- {
- if (asprintf (&DptCodSubQuery," AND prj_projects.DptCod=%ld",
- Projects->Filter.DptCod) < 0)
- Err_NotEnoughMemoryExit ();
- }
- else // Any department
- {
- if (asprintf (&DptCodSubQuery,"%s","") < 0)
- Err_NotEnoughMemoryExit ();
- }
+ /****** Free users selected *****/
+ if (Projects->Filter.Who == Usr_WHO_SELECTED)
+ if (NumUsrsInList)
+ {
+ /* Free memory for subquery string */
+ Usr_FreeSubqueryUsrCods (UsrsSubQuery);
- /* Query */
- switch (Projects->Filter.Who)
- {
- case Usr_WHO_ME:
- /* Get list of projects */
- switch (Projects->SelectedOrder)
- {
- case Prj_ORDER_START_TIME:
- case Prj_ORDER_END_TIME:
- case Prj_ORDER_TITLE:
- NumPrjsFromDB = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get projects",
- "SELECT prj_projects.PrjCod"
- " FROM prj_projects,"
- "prj_users"
- " WHERE prj_projects.CrsCod=%ld"
- "%s"
- "%s"
- "%s"
- " AND prj_projects.PrjCod=prj_users.PrjCod"
- " AND prj_users.UsrCod=%ld"
- " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
- " ORDER BY %s",
- Gbl.Hierarchy.Crs.CrsCod,
- PreNonSubQuery,
- HidVisSubQuery,
- DptCodSubQuery,
- Gbl.Usrs.Me.UsrDat.UsrCod,
- OrderBySubQuery[Projects->SelectedOrder]);
- break;
- case Prj_ORDER_DEPARTMENT:
- NumPrjsFromDB = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get projects",
- "SELECT prj_projects.PrjCod"
- " FROM prj_projects LEFT JOIN dpt_departments,"
- "prj_users"
- " ON prj_projects.DptCod=dpt_departments.DptCod"
- " WHERE prj_projects.CrsCod=%ld"
- "%s"
- "%s"
- "%s"
- " AND prj_projects.PrjCod=prj_users.PrjCod"
- " AND prj_users.UsrCod=%ld"
- " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
- " ORDER BY %s",
- Gbl.Hierarchy.Crs.CrsCod,
- PreNonSubQuery,
- HidVisSubQuery,
- DptCodSubQuery,
- Gbl.Usrs.Me.UsrDat.UsrCod,
- OrderBySubQuery[Projects->SelectedOrder]);
- break;
- }
- break;
- case Usr_WHO_SELECTED:
- /* Count number of valid users in list of encrypted user codes */
- NumUsrsInList = Usr_CountNumUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected);
-
- if (NumUsrsInList)
- {
- /* Get list of users selected to show their projects */
- Usr_GetListSelectedUsrCods (&Gbl.Usrs.Selected,NumUsrsInList,&LstSelectedUsrCods);
-
- /* Create subquery string */
- Usr_CreateSubqueryUsrCods (LstSelectedUsrCods,NumUsrsInList,
- &SubQueryUsrs);
-
- /* Get list of projects */
- switch (Projects->SelectedOrder)
- {
- case Prj_ORDER_START_TIME:
- case Prj_ORDER_END_TIME:
- case Prj_ORDER_TITLE:
- NumPrjsFromDB = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get projects",
- "SELECT prj_projects.PrjCod"
- " FROM prj_projects,"
- "prj_users"
- " WHERE prj_projects.CrsCod=%ld"
- "%s"
- "%s"
- "%s"
- " AND prj_projects.PrjCod=prj_users.PrjCod"
- " AND prj_users.UsrCod IN (%s)"
- " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
- " ORDER BY %s",
- Gbl.Hierarchy.Crs.CrsCod,
- PreNonSubQuery,
- HidVisSubQuery,
- DptCodSubQuery,
- SubQueryUsrs,
- OrderBySubQuery[Projects->SelectedOrder]);
- break;
- case Prj_ORDER_DEPARTMENT:
- NumPrjsFromDB = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get projects",
- "SELECT prj_projects.PrjCod"
- " FROM prj_projects LEFT JOIN dpt_departments,"
- "prj_users"
- " ON prj_projects.DptCod=dpt_departments.DptCod"
- " WHERE prj_projects.CrsCod=%ld"
- "%s"
- "%s"
- "%s"
- " AND prj_projects.PrjCod=prj_users.PrjCod"
- " AND prj_users.UsrCod IN (%s)"
- " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
- " ORDER BY %s",
- Gbl.Hierarchy.Crs.CrsCod,
- PreNonSubQuery,
- HidVisSubQuery,
- DptCodSubQuery,
- SubQueryUsrs,
- OrderBySubQuery[Projects->SelectedOrder]);
- break;
- }
-
- /* Free memory for subquery string */
- Usr_FreeSubqueryUsrCods (SubQueryUsrs);
-
- /* Free list of user codes */
- Usr_FreeListSelectedUsrCods (LstSelectedUsrCods);
- }
- break;
- case Usr_WHO_ALL:
- /* Get list of projects */
- switch (Projects->SelectedOrder)
- {
- case Prj_ORDER_START_TIME:
- case Prj_ORDER_END_TIME:
- case Prj_ORDER_TITLE:
- NumPrjsFromDB = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get projects",
- "SELECT prj_projects.PrjCod"
- " FROM prj_projects"
- " WHERE prj_projects.CrsCod=%ld"
- "%s"
- "%s"
- "%s"
- " ORDER BY %s",
- Gbl.Hierarchy.Crs.CrsCod,
- PreNonSubQuery,
- HidVisSubQuery,
- DptCodSubQuery,
- OrderBySubQuery[Projects->SelectedOrder]);
- break;
- case Prj_ORDER_DEPARTMENT:
- NumPrjsFromDB = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get projects",
- "SELECT prj_projects.PrjCod"
- " FROM prj_projects LEFT JOIN dpt_departments"
- " ON prj_projects.DptCod=dpt_departments.DptCod"
- " WHERE prj_projects.CrsCod=%ld"
- "%s"
- "%s"
- "%s"
- " ORDER BY %s",
- Gbl.Hierarchy.Crs.CrsCod,
- PreNonSubQuery,
- HidVisSubQuery,
- DptCodSubQuery,
- OrderBySubQuery[Projects->SelectedOrder]);
- break;
- }
- break;
- default:
- Err_WrongWhoExit ();
- break;
- }
-
- /* Free allocated memory for subqueries */
- free (PreNonSubQuery);
- free (HidVisSubQuery);
- free (DptCodSubQuery);
+ /* Free list of user codes */
+ Usr_FreeListSelectedUsrCods (LstSelectedUsrCods);
+ }
if (NumPrjsFromDB) // Projects found...
{
@@ -3154,30 +2847,13 @@ static void Prj_GetListProjects (struct Prj_Projects *Projects)
Projects->LstIsRead = true;
}
-/*****************************************************************************/
-/****************** Check if a project exists in a course ********************/
-/*****************************************************************************/
-
-long Prj_GetCourseOfProject (long PrjCod)
- {
- /***** Trivial check: project code should be > 0 *****/
- if (PrjCod <= 0)
- return -1L;
-
- /***** Get course code from database *****/
- return DB_QuerySELECTCode ("can not get project course",
- "SELECT CrsCod" // row[0]
- " FROM prj_projects"
- " WHERE PrjCod=%ld",
- PrjCod); // Project found...
- }
-
/*****************************************************************************/
/********************* Get project data using its code ***********************/
/*****************************************************************************/
void Prj_GetDataOfProjectByCod (struct Prj_Project *Prj)
{
+ extern const char *Prj_Proposal_DB[Prj_NUM_PROPOSAL_TYPES];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
Prj_Proposal_t Proposal;
@@ -3188,27 +2864,7 @@ void Prj_GetDataOfProjectByCod (struct Prj_Project *Prj)
Prj_ResetProject (Prj);
/***** Get data of project *****/
- if (DB_QuerySELECT (&mysql_res,"can not get project data",
- "SELECT PrjCod," // row[ 0]
- "CrsCod," // row[ 1]
- "DptCod," // row[ 2]
- "Locked," // row[ 3]
- "Hidden," // row[ 4]
- "Assigned," // row[ 5]
- "NumStds," // row[ 6]
- "Proposal," // row[ 7]
- "UNIX_TIMESTAMP(CreatTime)," // row[ 8]
- "UNIX_TIMESTAMP(ModifTime)," // row[ 9]
- "Title," // row[10]
- "Description," // row[11]
- "Knowledge," // row[12]
- "Materials," // row[13]
- "URL" // row[14]
- " FROM prj_projects"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- Prj->PrjCod,
- Gbl.Hierarchy.Crs.CrsCod)) // Project found...
+ if (Prj_DB_GetDataOfProjectByCod (&mysql_res,Prj->PrjCod)) // Project found...
{
/* Get row */
row = mysql_fetch_row (mysql_res);
@@ -3401,26 +3057,13 @@ void Prj_RemoveProject (void)
if (Prj_CheckIfICanEditProject (&Prj))
{
/***** Remove users in project *****/
- DB_QueryDELETE ("can not remove project",
- "DELETE FROM prj_users"
- " USING prj_projects,"
- "prj_users"
- " WHERE prj_projects.PrjCod=%ld"
- " AND prj_projects.CrsCod=%ld"
- " AND prj_projects.PrjCod=prj_users.PrjCod",
- Prj.PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
+ Prj_DB_RemoveUsrsFromPrj (Prj.PrjCod);
/***** Flush cache *****/
Prj_FlushCacheMyRolesInProject ();
/***** Remove project *****/
- DB_QueryDELETE ("can not remove project",
- "DELETE FROM prj_projects"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- Prj.PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
+ Prj_DB_RemovePrj (Prj.PrjCod);
/***** Remove information related to files in project *****/
Brw_DB_RemovePrjFiles (Prj.PrjCod);
@@ -3468,15 +3111,9 @@ void Prj_HideProject (void)
/***** Get data of the project from database *****/
Prj_GetDataOfProjectByCod (&Prj);
+ /***** Hide project *****/
if (Prj_CheckIfICanEditProject (&Prj))
- /***** Hide project *****/
- DB_QueryUPDATE ("can not hide project",
- "UPDATE prj_projects"
- " SET Hidden='Y'"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- Prj.PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
+ Prj_DB_HideUnhideProject (Prj.PrjCod,'Y');
else
Err_NoPermissionExit ();
@@ -3510,15 +3147,9 @@ void Prj_UnhideProject (void)
/***** Get data of the project from database *****/
Prj_GetDataOfProjectByCod (&Prj);
+ /***** Unhide project *****/
if (Prj_CheckIfICanEditProject (&Prj))
- /***** Show project *****/
- DB_QueryUPDATE ("can not show project",
- "UPDATE prj_projects"
- " SET Hidden='N'"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- Prj.PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
+ Prj_DB_HideUnhideProject (Prj.PrjCod,'N');
else
Err_NoPermissionExit ();
@@ -3991,46 +3622,17 @@ void Prj_ReceiveFormProject (void)
static void Prj_CreateProject (struct Prj_Project *Prj)
{
+ extern const char *Prj_Proposal_DB[Prj_NUM_PROPOSAL_TYPES];
+
/***** Set dates to now *****/
Prj->CreatTime =
Prj->ModifTime = Gbl.StartExecutionTimeUTC;
/***** Create a new project *****/
- Prj->PrjCod =
- DB_QueryINSERTandReturnCode ("can not create new project",
- "INSERT INTO prj_projects"
- " (CrsCod,DptCod,Hidden,Assigned,NumStds,Proposal,"
- "CreatTime,ModifTime,"
- "Title,Description,Knowledge,Materials,URL)"
- " VALUES"
- " (%ld,%ld,'%c','%c',%u,'%s',"
- "FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld),"
- "'%s','%s','%s','%s','%s')",
- Gbl.Hierarchy.Crs.CrsCod,
- Prj->DptCod,
- Prj->Hidden == Prj_HIDDEN ? 'Y' :
- 'N',
- Prj->Assigned == Prj_ASSIGNED ? 'Y' :
- 'N',
- Prj->NumStds,
- Prj_Proposal_DB[Prj->Proposal],
- Prj->CreatTime,
- Prj->ModifTime,
- Prj->Title,
- Prj->Description,
- Prj->Knowledge,
- Prj->Materials,
- Prj->URL);
+ Prj->PrjCod = Prj_DB_CreateProject (Prj);
/***** Insert creator as first tutor *****/
- DB_QueryINSERT ("can not add tutor",
- "INSERT INTO prj_users"
- " (PrjCod,RoleInProject,UsrCod)"
- " VALUES"
- " (%ld,%u,%ld)",
- Prj->PrjCod,
- (unsigned) Prj_ROLE_TUT,
- Gbl.Usrs.Me.UsrDat.UsrCod);
+ Prj_DB_AddUsrToPrj (Prj->PrjCod,Prj_ROLE_TUT,Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Flush cache *****/
Prj_FlushCacheMyRolesInProject ();
@@ -4042,40 +3644,13 @@ static void Prj_CreateProject (struct Prj_Project *Prj)
static void Prj_UpdateProject (struct Prj_Project *Prj)
{
+ extern const char *Prj_Proposal_DB[Prj_NUM_PROPOSAL_TYPES];
+
/***** Adjust date of last edition to now *****/
Prj->ModifTime = Gbl.StartExecutionTimeUTC;
/***** Update the data of the project *****/
- DB_QueryUPDATE ("can not update project",
- "UPDATE prj_projects"
- " SET DptCod=%ld,"
- "Hidden='%c',"
- "Assigned='%c',"
- "NumStds=%u,"
- "Proposal='%s',"
- "ModifTime=FROM_UNIXTIME(%ld),"
- "Title='%s',"
- "Description='%s',"
- "Knowledge='%s',"
- "Materials='%s',"
- "URL='%s'"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- Prj->DptCod,
- Prj->Hidden == Prj_HIDDEN ? 'Y' :
- 'N',
- Prj->Assigned == Prj_ASSIGNED ? 'Y' :
- 'N',
- Prj->NumStds,
- Prj_Proposal_DB[Prj->Proposal],
- Prj->ModifTime,
- Prj->Title,
- Prj->Description,
- Prj->Knowledge,
- Prj->Materials,
- Prj->URL,
- Prj->PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
+ Prj_DB_UpdateProject (Prj);
}
/*****************************************************************************/
@@ -4112,7 +3687,7 @@ void Prj_ShowFormConfig (void)
Prj_ResetProjects (&Projects);
/***** Read projects configuration from database *****/
- Prj_GetConfigPrjFromDB (&Projects);
+ Prj_GetCrsPrjsConfig (&Projects);
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_Configure_projects,
@@ -4155,24 +3730,19 @@ void Prj_ShowFormConfig (void)
/************** Get configuration of projects for current course *************/
/*****************************************************************************/
-static void Prj_GetConfigPrjFromDB (struct Prj_Projects *Projects)
+static void Prj_GetCrsPrjsConfig (struct Prj_Projects *Projects)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Get configuration of projects for current course from database *****/
- if (DB_QuerySELECT (&mysql_res,"can not get configuration of test",
- "SELECT Editable" // row[0]
- " FROM prj_config"
- " WHERE CrsCod=%ld",
- Gbl.Hierarchy.Crs.CrsCod) == 0)
- Projects->Config.Editable = Prj_EDITABLE_DEFAULT;
- else // NumRows == 1
+ if (Prj_DB_GetCrsPrjsConfig (&mysql_res))
{
- /***** Get configuration *****/
row = mysql_fetch_row (mysql_res);
Prj_GetConfigFromRow (Projects,row);
}
+ else
+ Projects->Config.Editable = Prj_EDITABLE_DEFAULT;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@@ -4204,14 +3774,7 @@ void Prj_ReceiveConfigPrj (void)
Projects.Config.Editable = Prj_GetEditableFromForm ();
/***** Update database *****/
- DB_QueryREPLACE ("can not save configuration of projects",
- "REPLACE INTO prj_config"
- " (CrsCod,Editable)"
- " VALUES"
- " (%ld,'%c')",
- Gbl.Hierarchy.Crs.CrsCod,
- Projects.Config.Editable ? 'Y' :
- 'N');
+ Prj_DB_UpdateCrsPrjsConfig (Projects.Config.Editable);
/***** Show confirmation message *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_The_configuration_of_the_projects_has_been_updated);
@@ -4499,17 +4062,6 @@ void Prj_LockProjectEdition (void)
Prj_FreeMemProject (&Prj);
}
-static void Prj_DB_LockProjectEdition (long PrjCod)
- {
- DB_QueryUPDATE ("can not lock project edition",
- "UPDATE prj_projects"
- " SET Locked='Y'"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
- }
-
/*****************************************************************************/
/************************* Unlock edition of a project ***********************/
/*****************************************************************************/
@@ -4549,17 +4101,6 @@ void Prj_UnloProjectEdition (void)
Prj_FreeMemProject (&Prj);
}
-static void Prj_DB_UnlockProjectEdition (long PrjCod)
- {
- DB_QueryUPDATE ("can not lock project edition",
- "UPDATE prj_projects"
- " SET Locked='N'"
- " WHERE PrjCod=%ld"
- " AND CrsCod=%ld",
- PrjCod,
- Gbl.Hierarchy.Crs.CrsCod);
- }
-
/*****************************************************************************/
/******************** Remove all the projects in a course ********************/
/*****************************************************************************/
@@ -4567,28 +4108,16 @@ static void Prj_DB_UnlockProjectEdition (long PrjCod)
void Prj_RemoveCrsProjects (long CrsCod)
{
/***** Remove users in projects of the course *****/
- DB_QueryDELETE ("can not remove all the projects of a course",
- "DELETE FROM prj_users"
- " USING prj_projects,"
- "prj_users"
- " WHERE prj_projects.CrsCod=%ld"
- " AND prj_projects.PrjCod=prj_users.PrjCod",
- CrsCod);
+ Prj_DB_RemoveUsrsFromCrsPrjs (CrsCod);
/***** Flush cache *****/
Prj_FlushCacheMyRolesInProject ();
/***** Remove configuration of projects in the course *****/
- DB_QueryDELETE ("can not remove configuration of projects of a course",
- "DELETE FROM prj_config"
- " WHERE CrsCod=%ld",
- CrsCod);
+ Prj_DB_RemoveConfigOfCrsPrjs (CrsCod);
/***** Remove projects *****/
- DB_QueryDELETE ("can not remove all the projects of a course",
- "DELETE FROM prj_projects"
- " WHERE CrsCod=%ld",
- CrsCod);
+ Prj_DB_RemoveCrsPrjs (CrsCod);
}
/*****************************************************************************/
@@ -4598,167 +4127,9 @@ void Prj_RemoveCrsProjects (long CrsCod)
void Prj_RemoveUsrFromProjects (long UsrCod)
{
/***** Remove user from projects *****/
- DB_QueryDELETE ("can not remove user from projects",
- "DELETE FROM prj_users"
- " WHERE UsrCod=%ld",
- UsrCod);
+ Prj_DB_RemoveUsrFromProjects (UsrCod);
/***** Flush cache *****/
if (Usr_ItsMe (UsrCod))
Prj_FlushCacheMyRolesInProject ();
}
-
-/*****************************************************************************/
-/******************** Get number of courses with projects ********************/
-/*****************************************************************************/
-// Returns the number of courses with projects
-// in this location (all the platform, current degree or current course)
-
-unsigned Prj_DB_GetNumCoursesWithProjects (HieLvl_Level_t Scope)
- {
- /***** Get number of courses with projects from database *****/
- switch (Scope)
- {
- case HieLvl_SYS:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of courses with projects",
- "SELECT COUNT(DISTINCT CrsCod)"
- " FROM prj_projects"
- " WHERE CrsCod>0");
- case HieLvl_CTY:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of courses with projects",
- "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
- " FROM ins_instits,"
- "ctr_centers,"
- "deg_degrees,"
- "crs_courses,"
- "prj_projects"
- " WHERE ins_instits.CtyCod=%ld"
- " AND ins_instits.InsCod=ctr_centers.InsCod"
- " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
- " AND deg_degrees.DegCod=crs_courses.DegCod"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Cty.CtyCod);
- case HieLvl_INS:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of courses with projects",
- "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
- " FROM ctr_centers,"
- "deg_degrees,"
- "crs_courses,"
- "prj_projects"
- " WHERE ctr_centers.InsCod=%ld"
- " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
- " AND deg_degrees.DegCod=crs_courses.DegCod"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Ins.InsCod);
- case HieLvl_CTR:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of courses with projects",
- "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
- " FROM deg_degrees,"
- "crs_courses,"
- "prj_projects"
- " WHERE deg_degrees.CtrCod=%ld"
- " AND deg_degrees.DegCod=crs_courses.DegCod"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Ctr.CtrCod);
- case HieLvl_DEG:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of courses with projects",
- "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
- " FROM crs_courses,"
- "prj_projects"
- " WHERE crs_courses.DegCod=%ld"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Deg.DegCod);
- case HieLvl_CRS:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of courses with projects",
- "SELECT COUNT(DISTINCT CrsCod)"
- " FROM prj_projects"
- " WHERE CrsCod=%ld",
- Gbl.Hierarchy.Crs.CrsCod);
- default:
- Err_WrongScopeExit ();
- return 0; // Not reached
- }
- }
-
-/*****************************************************************************/
-/************************** Get number of projects ***************************/
-/*****************************************************************************/
-// Returns the number of projects in this location
-
-unsigned Prj_DB_GetNumProjects (HieLvl_Level_t Scope)
- {
- /***** Get number of projects from database *****/
- switch (Scope)
- {
- case HieLvl_SYS:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of projects",
- "SELECT COUNT(*)"
- " FROM prj_projects"
- " WHERE CrsCod>0");
- case HieLvl_CTY:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of projects",
- "SELECT COUNT(*)"
- " FROM ins_instits,"
- "ctr_centers,"
- "deg_degrees,"
- "crs_courses,"
- "prj_projects"
- " WHERE ins_instits.CtyCod=%ld"
- " AND ins_instits.InsCod=ctr_centers.InsCod"
- " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
- " AND deg_degrees.DegCod=crs_courses.DegCod"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Cty.CtyCod);
- case HieLvl_INS:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of projects",
- "SELECT COUNT(*)"
- " FROM ctr_centers,"
- "deg_degrees,"
- "crs_courses,"
- "prj_projects"
- " WHERE ctr_centers.InsCod=%ld"
- " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
- " AND deg_degrees.DegCod=crs_courses.DegCod"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Ins.InsCod);
- case HieLvl_CTR:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of projects",
- "SELECT COUNT(*)"
- " FROM deg_degrees,"
- "crs_courses,"
- "prj_projects"
- " WHERE deg_degrees.CtrCod=%ld"
- " AND deg_degrees.DegCod=crs_courses.DegCod"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Ctr.CtrCod);
- case HieLvl_DEG:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of projects",
- "SELECT COUNT(*)"
- " FROM crs_courses,"
- "prj_projects"
- " WHERE crs_courses.DegCod=%ld"
- " AND crs_courses.CrsCod=prj_projects.CrsCod",
- Gbl.Hierarchy.Deg.DegCod);
- case HieLvl_CRS:
- return (unsigned)
- DB_QueryCOUNT ("can not get number of projects",
- "SELECT COUNT(*)"
- " FROM prj_projects"
- " WHERE CrsCod=%ld",
- Gbl.Hierarchy.Crs.CrsCod);
- default:
- Err_WrongScopeExit ();
- return 0; // Not reached
- }
- }
diff --git a/swad_project.h b/swad_project.h
index 60fb8258..1ccb693d 100644
--- a/swad_project.h
+++ b/swad_project.h
@@ -214,7 +214,6 @@ void Prj_AllocMemProject (struct Prj_Project *Prj);
void Prj_FreeMemProject (struct Prj_Project *Prj);
void Prj_GetDataOfProjectByCod (struct Prj_Project *Prj);
-long Prj_GetCourseOfProject (long PrjCod);
void Prj_FreeListProjects (struct Prj_Projects *Projects);
void Prj_PutParamPrjCod (long PrjCod);
@@ -238,7 +237,4 @@ void Prj_UnloProjectEdition (void);
void Prj_RemoveCrsProjects (long CrsCod);
void Prj_RemoveUsrFromProjects (long UsrCod);
-unsigned Prj_DB_GetNumCoursesWithProjects (HieLvl_Level_t Scope);
-unsigned Prj_DB_GetNumProjects (HieLvl_Level_t Scope);
-
#endif
diff --git a/swad_project_database.c b/swad_project_database.c
new file mode 100644
index 00000000..81c8493a
--- /dev/null
+++ b/swad_project_database.c
@@ -0,0 +1,854 @@
+// swad_project_database.c: projects (final degree projects, thesis), operations with database
+
+/*
+ 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-2021 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 asprintf
+
+#include "swad_database.h"
+#include "swad_error.h"
+#include "swad_global.h"
+#include "swad_project.h"
+
+/*****************************************************************************/
+/************** External global variables from others modules ****************/
+/*****************************************************************************/
+
+extern struct Globals Gbl;
+
+/*****************************************************************************/
+/************************** Public constants and types ***********************/
+/*****************************************************************************/
+
+/***** Enum field in database for types of proposal *****/
+const char *Prj_Proposal_DB[Prj_NUM_PROPOSAL_TYPES] =
+ {
+ [Prj_PROPOSAL_NEW ] = "new",
+ [Prj_PROPOSAL_MODIFIED ] = "modified",
+ [Prj_PROPOSAL_UNMODIFIED] = "unmodified",
+ };
+
+/*****************************************************************************/
+/************************* Private constants and types ***********************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/***************************** Private variables *****************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/***************************** Private prototypes ****************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/************ Update configuration of projects for current course ************/
+/*****************************************************************************/
+
+void Prj_DB_UpdateCrsPrjsConfig (bool Editable)
+ {
+ DB_QueryREPLACE ("can not save configuration of projects",
+ "REPLACE INTO prj_config"
+ " (CrsCod,Editable)"
+ " VALUES"
+ " (%ld,'%c')",
+ Gbl.Hierarchy.Crs.CrsCod,
+ Editable ? 'Y' :
+ 'N');
+ }
+
+/*****************************************************************************/
+/**************************** Lock project edition ***************************/
+/*****************************************************************************/
+
+void Prj_DB_LockProjectEdition (long PrjCod)
+ {
+ DB_QueryUPDATE ("can not lock project edition",
+ "UPDATE prj_projects"
+ " SET Locked='Y'"
+ " WHERE PrjCod=%ld"
+ " AND CrsCod=%ld",
+ PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/************************** Unlock project edition ***************************/
+/*****************************************************************************/
+
+void Prj_DB_UnlockProjectEdition (long PrjCod)
+ {
+ DB_QueryUPDATE ("can not lock project edition",
+ "UPDATE prj_projects"
+ " SET Locked='N'"
+ " WHERE PrjCod=%ld"
+ " AND CrsCod=%ld", // Extra check
+ PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/************************** Create a new project *****************************/
+/*****************************************************************************/
+
+long Prj_DB_CreateProject (const struct Prj_Project *Prj)
+ {
+ return
+ DB_QueryINSERTandReturnCode ("can not create new project",
+ "INSERT INTO prj_projects"
+ " (CrsCod,DptCod,Hidden,Assigned,NumStds,Proposal,"
+ "CreatTime,ModifTime,"
+ "Title,Description,Knowledge,Materials,URL)"
+ " VALUES"
+ " (%ld,%ld,'%c','%c',%u,'%s',"
+ "FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld),"
+ "'%s','%s','%s','%s','%s')",
+ Gbl.Hierarchy.Crs.CrsCod,
+ Prj->DptCod,
+ Prj->Hidden == Prj_HIDDEN ? 'Y' :
+ 'N',
+ Prj->Assigned == Prj_ASSIGNED ? 'Y' :
+ 'N',
+ Prj->NumStds,
+ Prj_Proposal_DB[Prj->Proposal],
+ Prj->CreatTime,
+ Prj->ModifTime,
+ Prj->Title,
+ Prj->Description,
+ Prj->Knowledge,
+ Prj->Materials,
+ Prj->URL);
+ }
+
+/*****************************************************************************/
+/*********************** Update an existing project **************************/
+/*****************************************************************************/
+
+void Prj_DB_UpdateProject (const struct Prj_Project *Prj)
+ {
+ DB_QueryUPDATE ("can not update project",
+ "UPDATE prj_projects"
+ " SET DptCod=%ld,"
+ "Hidden='%c',"
+ "Assigned='%c',"
+ "NumStds=%u,"
+ "Proposal='%s',"
+ "ModifTime=FROM_UNIXTIME(%ld),"
+ "Title='%s',"
+ "Description='%s',"
+ "Knowledge='%s',"
+ "Materials='%s',"
+ "URL='%s'"
+ " WHERE PrjCod=%ld"
+ " AND CrsCod=%ld", // Extra check
+ Prj->DptCod,
+ Prj->Hidden == Prj_HIDDEN ? 'Y' :
+ 'N',
+ Prj->Assigned == Prj_ASSIGNED ? 'Y' :
+ 'N',
+ Prj->NumStds,
+ Prj_Proposal_DB[Prj->Proposal],
+ Prj->ModifTime,
+ Prj->Title,
+ Prj->Description,
+ Prj->Knowledge,
+ Prj->Materials,
+ Prj->URL,
+ Prj->PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/****************************** Add user to project **************************/
+/*****************************************************************************/
+
+void Prj_DB_AddUsrToPrj (long PrjCod,Prj_RoleInProject_t RoleInProject,long UsrCod)
+ {
+ DB_QueryREPLACE ("can not add user to project",
+ "REPLACE INTO prj_users"
+ " (PrjCod,RoleInProject,UsrCod)"
+ " VALUES"
+ " (%ld,%u,%ld)",
+ PrjCod,
+ (unsigned) RoleInProject,
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/****************************** Hide a project *******************************/
+/*****************************************************************************/
+
+void Prj_DB_HideUnhideProject (long PrjCod,char YN)
+ {
+ DB_QueryUPDATE ("can not hide project",
+ "UPDATE prj_projects"
+ " SET Hidden='%c'"
+ " WHERE PrjCod=%ld"
+ " AND CrsCod=%ld", // Extra check
+ YN,
+ PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/******************************** Get projects *******************************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetListProjects (MYSQL_RES **mysql_res,
+ const struct Prj_Projects *Projects,
+ const char *UsrsSubQuery) // NULL if no users
+ {
+ char *AssignSubQuery;
+ char *HidVisSubQuery;
+ char *DptCodSubQuery;
+ static const char *OrderBySubQuery[Prj_NUM_ORDERS] =
+ {
+ [Prj_ORDER_START_TIME] = "prj_projects.CreatTime DESC,"
+ "prj_projects.ModifTime DESC,"
+ "prj_projects.Title",
+ [Prj_ORDER_END_TIME ] = "prj_projects.ModifTime DESC,"
+ "prj_projects.CreatTime DESC,"
+ "prj_projects.Title",
+ [Prj_ORDER_TITLE ] = "prj_projects.Title,"
+ "prj_projects.CreatTime DESC,"
+ "prj_projects.ModifTime DESC",
+ [Prj_ORDER_DEPARTMENT] = "dpt_departments.FullName,"
+ "prj_projects.CreatTime DESC,"
+ "prj_projects.ModifTime DESC,"
+ "prj_projects.Title",
+ };
+ unsigned NumPrjsFromDB = 0;
+
+ /* Assigned subquery */
+ switch (Projects->Filter.Assign)
+ {
+ case (1 << Prj_ASSIGNED): // Assigned projects
+ if (asprintf (&AssignSubQuery," AND prj_projects.Assigned='Y'") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ case (1 << Prj_NONASSIG): // Non-assigned projects
+ if (asprintf (&AssignSubQuery," AND prj_projects.Assigned='N'") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ default: // All projects
+ if (asprintf (&AssignSubQuery,"%s","") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ }
+
+ /* Hidden subquery */
+ switch (Gbl.Usrs.Me.Role.Logged)
+ {
+ case Rol_STD: // Students can view only visible projects
+ if (asprintf (&HidVisSubQuery," AND prj_projects.Hidden='N'") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ case Rol_NET:
+ case Rol_TCH:
+ case Rol_SYS_ADM:
+ switch (Projects->Filter.Hidden)
+ {
+ case (1 << Prj_HIDDEN): // Hidden projects
+ if (asprintf (&HidVisSubQuery," AND prj_projects.Hidden='Y'") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ case (1 << Prj_VISIBL): // Visible projects
+ if (asprintf (&HidVisSubQuery," AND prj_projects.Hidden='N'") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ default: // All projects
+ if (asprintf (&HidVisSubQuery,"%s","") < 0)
+ Err_NotEnoughMemoryExit ();
+ break;
+ }
+ break;
+ default:
+ Err_WrongRoleExit ();
+ break;
+ }
+
+ /* Department subquery */
+ if (Projects->Filter.DptCod >= 0)
+ {
+ if (asprintf (&DptCodSubQuery," AND prj_projects.DptCod=%ld",
+ Projects->Filter.DptCod) < 0)
+ Err_NotEnoughMemoryExit ();
+ }
+ else // Any department
+ {
+ if (asprintf (&DptCodSubQuery,"%s","") < 0)
+ Err_NotEnoughMemoryExit ();
+ }
+
+ /* Query */
+ switch (Projects->Filter.Who)
+ {
+ case Usr_WHO_ME:
+ /* Get list of projects */
+ switch (Projects->SelectedOrder)
+ {
+ case Prj_ORDER_START_TIME:
+ case Prj_ORDER_END_TIME:
+ case Prj_ORDER_TITLE:
+ NumPrjsFromDB = (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get projects",
+ "SELECT prj_projects.PrjCod"
+ " FROM prj_projects,"
+ "prj_users"
+ " WHERE prj_projects.CrsCod=%ld"
+ "%s"
+ "%s"
+ "%s"
+ " AND prj_projects.PrjCod=prj_users.PrjCod"
+ " AND prj_users.UsrCod=%ld"
+ " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
+ " ORDER BY %s",
+ Gbl.Hierarchy.Crs.CrsCod,
+ AssignSubQuery,
+ HidVisSubQuery,
+ DptCodSubQuery,
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ OrderBySubQuery[Projects->SelectedOrder]);
+ break;
+ case Prj_ORDER_DEPARTMENT:
+ NumPrjsFromDB = (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get projects",
+ "SELECT prj_projects.PrjCod"
+ " FROM prj_projects LEFT JOIN dpt_departments,"
+ "prj_users"
+ " ON prj_projects.DptCod=dpt_departments.DptCod"
+ " WHERE prj_projects.CrsCod=%ld"
+ "%s"
+ "%s"
+ "%s"
+ " AND prj_projects.PrjCod=prj_users.PrjCod"
+ " AND prj_users.UsrCod=%ld"
+ " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
+ " ORDER BY %s",
+ Gbl.Hierarchy.Crs.CrsCod,
+ AssignSubQuery,
+ HidVisSubQuery,
+ DptCodSubQuery,
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ OrderBySubQuery[Projects->SelectedOrder]);
+ break;
+ }
+ break;
+ case Usr_WHO_SELECTED:
+ if (UsrsSubQuery)
+ {
+ /* Get list of projects */
+ switch (Projects->SelectedOrder)
+ {
+ case Prj_ORDER_START_TIME:
+ case Prj_ORDER_END_TIME:
+ case Prj_ORDER_TITLE:
+ NumPrjsFromDB = (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get projects",
+ "SELECT prj_projects.PrjCod"
+ " FROM prj_projects,"
+ "prj_users"
+ " WHERE prj_projects.CrsCod=%ld"
+ "%s"
+ "%s"
+ "%s"
+ " AND prj_projects.PrjCod=prj_users.PrjCod"
+ " AND prj_users.UsrCod IN (%s)"
+ " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
+ " ORDER BY %s",
+ Gbl.Hierarchy.Crs.CrsCod,
+ AssignSubQuery,
+ HidVisSubQuery,
+ DptCodSubQuery,
+ UsrsSubQuery,
+ OrderBySubQuery[Projects->SelectedOrder]);
+ break;
+ case Prj_ORDER_DEPARTMENT:
+ NumPrjsFromDB = (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get projects",
+ "SELECT prj_projects.PrjCod"
+ " FROM prj_projects LEFT JOIN dpt_departments,"
+ "prj_users"
+ " ON prj_projects.DptCod=dpt_departments.DptCod"
+ " WHERE prj_projects.CrsCod=%ld"
+ "%s"
+ "%s"
+ "%s"
+ " AND prj_projects.PrjCod=prj_users.PrjCod"
+ " AND prj_users.UsrCod IN (%s)"
+ " GROUP BY prj_projects.PrjCod" // To not repeat projects (DISTINCT can not be used)
+ " ORDER BY %s",
+ Gbl.Hierarchy.Crs.CrsCod,
+ AssignSubQuery,
+ HidVisSubQuery,
+ DptCodSubQuery,
+ UsrsSubQuery,
+ OrderBySubQuery[Projects->SelectedOrder]);
+ break;
+ }
+ }
+ break;
+ case Usr_WHO_ALL:
+ /* Get list of projects */
+ switch (Projects->SelectedOrder)
+ {
+ case Prj_ORDER_START_TIME:
+ case Prj_ORDER_END_TIME:
+ case Prj_ORDER_TITLE:
+ NumPrjsFromDB = (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get projects",
+ "SELECT prj_projects.PrjCod"
+ " FROM prj_projects"
+ " WHERE prj_projects.CrsCod=%ld"
+ "%s"
+ "%s"
+ "%s"
+ " ORDER BY %s",
+ Gbl.Hierarchy.Crs.CrsCod,
+ AssignSubQuery,
+ HidVisSubQuery,
+ DptCodSubQuery,
+ OrderBySubQuery[Projects->SelectedOrder]);
+ break;
+ case Prj_ORDER_DEPARTMENT:
+ NumPrjsFromDB = (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get projects",
+ "SELECT prj_projects.PrjCod"
+ " FROM prj_projects LEFT JOIN dpt_departments"
+ " ON prj_projects.DptCod=dpt_departments.DptCod"
+ " WHERE prj_projects.CrsCod=%ld"
+ "%s"
+ "%s"
+ "%s"
+ " ORDER BY %s",
+ Gbl.Hierarchy.Crs.CrsCod,
+ AssignSubQuery,
+ HidVisSubQuery,
+ DptCodSubQuery,
+ OrderBySubQuery[Projects->SelectedOrder]);
+ break;
+ }
+ break;
+ default:
+ Err_WrongWhoExit ();
+ break;
+ }
+
+ /* Free allocated memory for subqueries */
+ free (AssignSubQuery);
+ free (HidVisSubQuery);
+ free (DptCodSubQuery);
+
+ return NumPrjsFromDB;
+ }
+
+/*****************************************************************************/
+/************** Get configuration of projects for current course *************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetCrsPrjsConfig (MYSQL_RES **mysql_res)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get configuration of test",
+ "SELECT Editable" // row[0]
+ " FROM prj_config"
+ " WHERE CrsCod=%ld",
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/********************* Get project data using its code ***********************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetDataOfProjectByCod (MYSQL_RES **mysql_res,long PrjCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get project data",
+ "SELECT PrjCod," // row[ 0]
+ "CrsCod," // row[ 1]
+ "DptCod," // row[ 2]
+ "Locked," // row[ 3]
+ "Hidden," // row[ 4]
+ "Assigned," // row[ 5]
+ "NumStds," // row[ 6]
+ "Proposal," // row[ 7]
+ "UNIX_TIMESTAMP(CreatTime)," // row[ 8]
+ "UNIX_TIMESTAMP(ModifTime)," // row[ 9]
+ "Title," // row[10]
+ "Description," // row[11]
+ "Knowledge," // row[12]
+ "Materials," // row[13]
+ "URL" // row[14]
+ " FROM prj_projects"
+ " WHERE PrjCod=%ld"
+ " AND CrsCod=%ld", // Extra check
+ PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/******************* Get some project data to check faults *******************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetPrjDataToCheckFaults (MYSQL_RES **mysql_res,long PrjCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get project data",
+ "SELECT Assigned='Y'," // row[0] = 0 / 1
+ "NumStds," // row[1] =
+ "Title<>''," // row[2] = 0 / 1
+ "Description<>''" // row[3] = 0 / 1
+ " FROM prj_projects"
+ " WHERE PrjCod=%ld",
+ PrjCod);
+ }
+
+/*****************************************************************************/
+/*************** Get number of users with a role in a project ****************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetNumUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject)
+ {
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of users in project",
+ "SELECT COUNT(UsrCod)"
+ " FROM prj_users"
+ " WHERE PrjCod=%ld"
+ " AND RoleInProject=%u",
+ PrjCod,
+ (unsigned) RoleInProject);
+ }
+
+/*****************************************************************************/
+/******************** Get users with a role in a project *********************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetUsrsInPrj (MYSQL_RES **mysql_res,
+ long PrjCod,Prj_RoleInProject_t RoleInProject)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get users in project",
+ "SELECT prj_users.UsrCod," // row[0]
+ "usr_data.Surname1 AS S1," // row[1]
+ "usr_data.Surname2 AS S2," // row[2]
+ "usr_data.FirstName AS FN" // row[3]
+ " FROM prj_users,"
+ "usr_data"
+ " WHERE prj_users.PrjCod=%ld"
+ " AND prj_users.RoleInProject=%u"
+ " AND prj_users.UsrCod=usr_data.UsrCod"
+ " ORDER BY S1,"
+ "S2,"
+ "FN",
+ PrjCod,
+ (unsigned) RoleInProject);
+ }
+
+/*****************************************************************************/
+/************************ Get my roles in a project **************************/
+/*****************************************************************************/
+
+unsigned Prj_DB_GetMyRolesInPrj (MYSQL_RES **mysql_res,long PrjCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get my roles in project",
+ "SELECT RoleInProject" // row[0]
+ " FROM prj_users"
+ " WHERE PrjCod=%ld"
+ " AND UsrCod=%ld",
+ PrjCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ }
+
+/*****************************************************************************/
+/************************** Get course of a project **************************/
+/*****************************************************************************/
+
+long Prj_DB_GetCrsOfPrj (long PrjCod)
+ {
+ /***** Trivial check: project code should be > 0 *****/
+ if (PrjCod <= 0)
+ return -1L;
+
+ /***** Get course code from database *****/
+ return DB_QuerySELECTCode ("can not get project course",
+ "SELECT CrsCod" // row[0]
+ " FROM prj_projects"
+ " WHERE PrjCod=%ld",
+ PrjCod); // Project found...
+ }
+
+/*****************************************************************************/
+/******************** Get number of courses with projects ********************/
+/*****************************************************************************/
+// Returns the number of courses with projects
+// in this location (all the platform, current degree or current course)
+
+unsigned Prj_DB_GetNumCoursesWithProjects (HieLvl_Level_t Scope)
+ {
+ /***** Get number of courses with projects from database *****/
+ switch (Scope)
+ {
+ case HieLvl_SYS:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of courses with projects",
+ "SELECT COUNT(DISTINCT CrsCod)"
+ " FROM prj_projects"
+ " WHERE CrsCod>0");
+ case HieLvl_CTY:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of courses with projects",
+ "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
+ " FROM ins_instits,"
+ "ctr_centers,"
+ "deg_degrees,"
+ "crs_courses,"
+ "prj_projects"
+ " WHERE ins_instits.CtyCod=%ld"
+ " AND ins_instits.InsCod=ctr_centers.InsCod"
+ " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
+ " AND deg_degrees.DegCod=crs_courses.DegCod"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Cty.CtyCod);
+ case HieLvl_INS:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of courses with projects",
+ "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
+ " FROM ctr_centers,"
+ "deg_degrees,"
+ "crs_courses,"
+ "prj_projects"
+ " WHERE ctr_centers.InsCod=%ld"
+ " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
+ " AND deg_degrees.DegCod=crs_courses.DegCod"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Ins.InsCod);
+ case HieLvl_CTR:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of courses with projects",
+ "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
+ " FROM deg_degrees,"
+ "crs_courses,"
+ "prj_projects"
+ " WHERE deg_degrees.CtrCod=%ld"
+ " AND deg_degrees.DegCod=crs_courses.DegCod"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Ctr.CtrCod);
+ case HieLvl_DEG:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of courses with projects",
+ "SELECT COUNT(DISTINCT prj_projects.CrsCod)"
+ " FROM crs_courses,"
+ "prj_projects"
+ " WHERE crs_courses.DegCod=%ld"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Deg.DegCod);
+ case HieLvl_CRS:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of courses with projects",
+ "SELECT COUNT(DISTINCT CrsCod)"
+ " FROM prj_projects"
+ " WHERE CrsCod=%ld",
+ Gbl.Hierarchy.Crs.CrsCod);
+ default:
+ Err_WrongScopeExit ();
+ return 0; // Not reached
+ }
+ }
+
+/*****************************************************************************/
+/************************** Get number of projects ***************************/
+/*****************************************************************************/
+// Returns the number of projects in this location
+
+unsigned Prj_DB_GetNumProjects (HieLvl_Level_t Scope)
+ {
+ /***** Get number of projects from database *****/
+ switch (Scope)
+ {
+ case HieLvl_SYS:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of projects",
+ "SELECT COUNT(*)"
+ " FROM prj_projects"
+ " WHERE CrsCod>0");
+ case HieLvl_CTY:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of projects",
+ "SELECT COUNT(*)"
+ " FROM ins_instits,"
+ "ctr_centers,"
+ "deg_degrees,"
+ "crs_courses,"
+ "prj_projects"
+ " WHERE ins_instits.CtyCod=%ld"
+ " AND ins_instits.InsCod=ctr_centers.InsCod"
+ " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
+ " AND deg_degrees.DegCod=crs_courses.DegCod"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Cty.CtyCod);
+ case HieLvl_INS:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of projects",
+ "SELECT COUNT(*)"
+ " FROM ctr_centers,"
+ "deg_degrees,"
+ "crs_courses,"
+ "prj_projects"
+ " WHERE ctr_centers.InsCod=%ld"
+ " AND ctr_centers.CtrCod=deg_degrees.CtrCod"
+ " AND deg_degrees.DegCod=crs_courses.DegCod"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Ins.InsCod);
+ case HieLvl_CTR:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of projects",
+ "SELECT COUNT(*)"
+ " FROM deg_degrees,"
+ "crs_courses,"
+ "prj_projects"
+ " WHERE deg_degrees.CtrCod=%ld"
+ " AND deg_degrees.DegCod=crs_courses.DegCod"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Ctr.CtrCod);
+ case HieLvl_DEG:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of projects",
+ "SELECT COUNT(*)"
+ " FROM crs_courses,"
+ "prj_projects"
+ " WHERE crs_courses.DegCod=%ld"
+ " AND crs_courses.CrsCod=prj_projects.CrsCod",
+ Gbl.Hierarchy.Deg.DegCod);
+ case HieLvl_CRS:
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of projects",
+ "SELECT COUNT(*)"
+ " FROM prj_projects"
+ " WHERE CrsCod=%ld",
+ Gbl.Hierarchy.Crs.CrsCod);
+ default:
+ Err_WrongScopeExit ();
+ return 0; // Not reached
+ }
+ }
+
+/*****************************************************************************/
+/************************ Remove user from a project *************************/
+/*****************************************************************************/
+
+void Prj_DB_RemoveUsrFromPrj (long PrjCod,Prj_RoleInProject_t RoleInPrj,long UsrCod)
+ {
+ DB_QueryDELETE ("can not remove a user from a project",
+ "DELETE FROM prj_users"
+ " WHERE PrjCod=%ld"
+ " AND RoleInProject=%u"
+ " AND UsrCod=%ld",
+ PrjCod,
+ (unsigned) RoleInPrj,
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/******************* Remove user from all his/her projects *******************/
+/*****************************************************************************/
+
+void Prj_DB_RemoveUsrFromProjects (long UsrCod)
+ {
+ DB_QueryDELETE ("can not remove user from projects",
+ "DELETE FROM prj_users"
+ " WHERE UsrCod=%ld",
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/********************* Remove all users from a project ***********************/
+/*****************************************************************************/
+
+void Prj_DB_RemoveUsrsFromPrj (long PrjCod)
+ {
+ DB_QueryDELETE ("can not remove project",
+ "DELETE FROM prj_users"
+ " USING prj_projects,"
+ "prj_users"
+ " WHERE prj_projects.PrjCod=%ld"
+ " AND prj_projects.CrsCod=%ld" // Extra check
+ " AND prj_projects.PrjCod=prj_users.PrjCod",
+ PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/************** Remove all users from all projects in a course ***************/
+/*****************************************************************************/
+
+void Prj_DB_RemoveUsrsFromCrsPrjs (long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove all the projects in a course",
+ "DELETE FROM prj_users"
+ " USING prj_projects,"
+ "prj_users"
+ " WHERE prj_projects.CrsCod=%ld"
+ " AND prj_projects.PrjCod=prj_users.PrjCod",
+ CrsCod);
+ }
+
+/*****************************************************************************/
+/*************** Remove configuration of projects in the course **************/
+/*****************************************************************************/
+
+void Prj_DB_RemoveConfigOfCrsPrjs (long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove configuration of projects in a course",
+ "DELETE FROM prj_config"
+ " WHERE CrsCod=%ld",
+ CrsCod);
+ }
+
+/*****************************************************************************/
+/******************************* Remove project ******************************/
+/*****************************************************************************/
+
+void Prj_DB_RemovePrj (long PrjCod)
+ {
+ DB_QueryDELETE ("can not remove project",
+ "DELETE FROM prj_projects"
+ " WHERE PrjCod=%ld"
+ " AND CrsCod=%ld", // Extra check
+ PrjCod,
+ Gbl.Hierarchy.Crs.CrsCod);
+ }
+
+/*****************************************************************************/
+/********************* Remove all projects in a course ***********************/
+/*****************************************************************************/
+
+void Prj_DB_RemoveCrsPrjs (long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove all the projects of a course",
+ "DELETE FROM prj_projects"
+ " WHERE CrsCod=%ld",
+ CrsCod);
+ }
diff --git a/swad_project_database.h b/swad_project_database.h
new file mode 100644
index 00000000..01a433bf
--- /dev/null
+++ b/swad_project_database.h
@@ -0,0 +1,70 @@
+// swad_project_database.h: projects (final degree projects, thesis), operations with database
+
+#ifndef _SWAD_PRJ_DB
+#define _SWAD_PRJ_DB
+/*
+ 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-2021 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 "swad_hierarchy_level.h"
+
+/*****************************************************************************/
+/************************** Public types and constants ***********************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/***************************** Public prototypes *****************************/
+/*****************************************************************************/
+
+void Prj_DB_UpdateCrsPrjsConfig (bool Editable);
+void Prj_DB_LockProjectEdition (long PrjCod);
+void Prj_DB_UnlockProjectEdition (long PrjCod);
+long Prj_DB_CreateProject (const struct Prj_Project *Prj);
+void Prj_DB_UpdateProject (const struct Prj_Project *Prj);
+void Prj_DB_AddUsrToPrj (long PrjCod,Prj_RoleInProject_t RoleInProject,long UsrCod);
+void Prj_DB_HideUnhideProject (long PrjCod,char YN);
+
+unsigned Prj_DB_GetListProjects (MYSQL_RES **mysql_res,
+ const struct Prj_Projects *Projects,
+ const char *UsrsSubQuery); // NULL if no users
+unsigned Prj_DB_GetCrsPrjsConfig (MYSQL_RES **mysql_res);
+unsigned Prj_DB_GetDataOfProjectByCod (MYSQL_RES **mysql_res,long PrjCod);
+unsigned Prj_DB_GetPrjDataToCheckFaults (MYSQL_RES **mysql_res,long PrjCod);
+unsigned Prj_DB_GetNumUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject);
+unsigned Prj_DB_GetUsrsInPrj (MYSQL_RES **mysql_res,
+ long PrjCod,Prj_RoleInProject_t RoleInProject);
+unsigned Prj_DB_GetMyRolesInPrj (MYSQL_RES **mysql_res,long PrjCod);
+long Prj_DB_GetCrsOfPrj (long PrjCod);
+unsigned Prj_DB_GetNumCoursesWithProjects (HieLvl_Level_t Scope);
+unsigned Prj_DB_GetNumProjects (HieLvl_Level_t Scope);
+
+void Prj_DB_RemoveUsrFromPrj (long PrjCod,Prj_RoleInProject_t RoleInPrj,long UsrCod);
+void Prj_DB_RemoveUsrFromProjects (long UsrCod);
+void Prj_DB_RemoveUsrsFromPrj (long PrjCod);
+void Prj_DB_RemoveUsrsFromCrsPrjs (long CrsCod);
+void Prj_DB_RemoveConfigOfCrsPrjs (long CrsCod);
+void Prj_DB_RemovePrj (long PrjCod);
+void Prj_DB_RemoveCrsPrjs (long CrsCod);
+
+#endif
diff --git a/swad_user.c b/swad_user.c
index b2d39cc9..f7fdf21f 100644
--- a/swad_user.c
+++ b/swad_user.c
@@ -6317,7 +6317,7 @@ void Usr_FreeListSelectedUsrCods (long *LstSelectedUsrCods)
void Usr_CreateSubqueryUsrCods (long LstSelectedUsrCods[],
unsigned NumUsrsInList,
- char **SubQueryUsrs)
+ char **UsrsSubQuery)
{
char SubQueryOneUsr[1 + Cns_MAX_DECIMAL_DIGITS_LONG + 1];
unsigned NumUsr;
@@ -6325,9 +6325,9 @@ void Usr_CreateSubqueryUsrCods (long LstSelectedUsrCods[],
/***** Allocate space for subquery *****/
MaxLength = NumUsrsInList * (1 + Cns_MAX_DECIMAL_DIGITS_LONG);
- if ((*SubQueryUsrs = malloc (MaxLength + 1)) == NULL)
+ if ((*UsrsSubQuery = malloc (MaxLength + 1)) == NULL)
Err_NotEnoughMemoryExit ();
- (*SubQueryUsrs)[0] = '\0';
+ (*UsrsSubQuery)[0] = '\0';
/***** Build subquery *****/
for (NumUsr = 0;
@@ -6337,10 +6337,10 @@ void Usr_CreateSubqueryUsrCods (long LstSelectedUsrCods[],
{
snprintf (SubQueryOneUsr,sizeof (SubQueryOneUsr),",%ld",
LstSelectedUsrCods[NumUsr]);
- Str_Concat (*SubQueryUsrs,SubQueryOneUsr,MaxLength);
+ Str_Concat (*UsrsSubQuery,SubQueryOneUsr,MaxLength);
}
else
- snprintf (*SubQueryUsrs,sizeof (SubQueryOneUsr),"%ld",
+ snprintf (*UsrsSubQuery,sizeof (SubQueryOneUsr),"%ld",
LstSelectedUsrCods[NumUsr]);
}