Version18.81

This commit is contained in:
Antonio Cañas Vargas 2019-03-18 15:42:22 +01:00
parent 550d2899a4
commit 12b56ef03c
14 changed files with 792 additions and 708 deletions

View File

@ -2991,7 +2991,7 @@ a:hover img.CENTRE_PHOTO_SHOW
.TL_POST_MED
{
box-sizing:border-box;
border-radius:8px;
border-radius:4px;
}
.TL_COMMENT_CONTAINER
{
@ -3017,7 +3017,7 @@ a:hover img.CENTRE_PHOTO_SHOW
.TL_COMMENT_MED
{
box-sizing:border-box;
border-radius:8px;
border-radius:4px;
}
.TL_FORM_NEW_COMMENT
{

View File

@ -1334,6 +1334,7 @@ CREATE TABLE IF NOT EXISTS usr_data (
Comments TEXT NOT NULL DEFAULT '',
Menu TINYINT NOT NULL DEFAULT 0,
SideCols TINYINT NOT NULL DEFAULT 3,
ThirdPartyCookies ENUM('N','Y') NOT NULL DEFAULT 'N',
NotifNtfEvents INT NOT NULL DEFAULT 0,
EmailNtfEvents INT NOT NULL DEFAULT 0,
PRIMARY KEY(UsrCod),
@ -1351,7 +1352,8 @@ CREATE TABLE IF NOT EXISTS usr_data (
INDEX(DptCod),
INDEX(CtrCod),
INDEX(Menu),
INDEX(SideCols));
INDEX(SideCols),
INDEX(ThirdPartyCookies));
--
-- Table usr_duplicated: stores informs of users possibly duplicated
--

View File

@ -436,6 +436,8 @@ Lo de mutear anuncios, en principio prefiero hacer una opci
// TODO: Los usuarios que no tienes permiso para ver su perfil público, se debería mostrar algo, una mínima ficha sin tinmeline o algo así
// TODO: Para acelerar la carga, todas las preferencias de usuarios no deberían obtenerse siempre, sino en una llamada especial pues en general sólo interesan para el usuario identificado
// TODO: Allow timeline posting only for users belonging to courses or admins to avoid user who create accounts only to post
/*****************************************************************************/
@ -457,10 +459,51 @@ En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 18.80 (2019-03-17)"
#define Log_PLATFORM_VERSION "SWAD 18.81 (2019-03-18)"
#define CSS_FILE "swad18.80.css"
#define JS_FILE "swad18.80.js"
/*
TODO: Remove unused fields MediaName,MediaType,MediaTitle,MediaURL,Media from tables:
// ALTER TABLE forum_post DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE msg_content DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE msg_content_deleted DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE social_comments DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE social_posts DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE tst_answers DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE tst_questions DROP COLUMN MediaName,DROP COLUMN MediaType,DROP COLUMN MediaTitle,DROP COLUMN MediaURL;
// ALTER TABLE media DROP COLUMN T,DROP COLUMN Cod;
Version 18.81: Mar 18, 2019 New database table media to store images and videos.
Fixed bugs in removal of publications in timeline. (240704 lines)
1 change necessary in database:
CREATE TABLE IF NOT EXISTS media (MedCod INT NOT NULL AUTO_INCREMENT,Type ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',Name VARCHAR(43) NOT NULL DEFAULT '',URL VARCHAR(255) NOT NULL DEFAULT '',Title VARCHAR(2047) NOT NULL DEFAULT '',T VARCHAR (2047) NOT NULL DEFAULT '',Cod INT NOT NULL DEFAULT -1,UNIQUE INDEX(MedCod),INDEX(Type));
Only if you use MyISAM:
ALTER TABLE media ENGINE=MyISAM;
21 changes necessary in database:
ALTER TABLE forum_post ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Content,ADD INDEX (MedCod);
ALTER TABLE msg_content ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Content,ADD INDEX (MedCod);
ALTER TABLE msg_content_deleted ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Content,ADD INDEX (MedCod);
ALTER TABLE social_comments ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Content,ADD INDEX (MedCod);
ALTER TABLE social_posts ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Content,ADD INDEX (MedCod);
ALTER TABLE tst_answers ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Feedback,ADD INDEX (MedCod);
ALTER TABLE tst_questions ADD COLUMN MedCod INT NOT NULL DEFAULT -1 AFTER Feedback,ADD INDEX (MedCod);
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'forum_post',PstCod FROM forum_post WHERE MediaType<>'none';
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'msg_content',MsgCod FROM msg_content WHERE MediaType<>'none';
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'msg_content_deleted',MsgCod FROM msg_content_deleted WHERE MediaType<>'none';
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'social_comments',PubCod FROM social_comments WHERE MediaType<>'none';
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'social_posts',PstCod FROM social_posts WHERE MediaType<>'none';
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'tst_answers',QstCod*10+AnsInd FROM tst_answers WHERE MediaType<>'none';
INSERT INTO media (Type,Name,URL,Title,T,Cod) SELECT MediaType,MediaName,MediaURL,MediaTitle,'tst_questions',QstCod FROM tst_questions WHERE MediaType<>'none';
UPDATE forum_post,media SET forum_post.MedCod=media.MedCod WHERE media.T='forum_post' AND forum_post.PstCod=media.Cod;
UPDATE msg_content,media SET msg_content.MedCod=media.MedCod WHERE media.T='msg_content' AND msg_content.MsgCod=media.Cod;
UPDATE msg_content_deleted,media SET msg_content_deleted.MedCod=media.MedCod WHERE media.T='msg_content_deleted' AND msg_content_deleted.MsgCod=media.Cod;
UPDATE social_comments,media SET social_comments.MedCod=media.MedCod WHERE media.T='social_comments' AND social_comments.PubCod=media.Cod;
UPDATE social_posts,media SET social_posts.MedCod=media.MedCod WHERE media.T='social_posts' AND social_posts.PstCod=media.Cod;
UPDATE tst_answers,media SET tst_answers.MedCod=media.MedCod WHERE media.T='tst_answers' AND tst_answers.QstCod*10+AnsInd=media.Cod;
UPDATE tst_questions,media SET tst_questions.MedCod=media.MedCod WHERE media.T='tst_questions' AND tst_questions.QstCod=media.Cod;
Version 18.80: Mar 17, 2019 Figure about cookies. (240647 lines)
Version 18.79.1: Mar 17, 2019 YouTube videos are not shown if user doesn't accept third party cookies. (240541 lines)
Version 18.79: Mar 17, 2019 New module swad_cookies for user's preference about cookies. (240494 lines)

View File

@ -1218,12 +1218,13 @@ mysql> DESCRIBE forum_post;
| NumNotif | int(11) | NO | | 0 | |
| Subject | text | NO | | NULL | |
| Content | longtext | NO | | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
| MediaURL | varchar(255) | NO | | | |
+------------+-------------------------------------------------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)
13 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS forum_post ("
"PstCod INT NOT NULL AUTO_INCREMENT,"
@ -1234,6 +1235,7 @@ mysql> DESCRIBE forum_post;
"NumNotif INT NOT NULL DEFAULT 0,"
"Subject TEXT NOT NULL," // Cns_MAX_BYTES_SUBJECT
"Content LONGTEXT NOT NULL," // Cns_MAX_BYTES_LONG_TEXT
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
@ -1242,7 +1244,8 @@ mysql> DESCRIBE forum_post;
"INDEX(ThrCod),"
"INDEX(UsrCod),"
"INDEX(CreatTime),"
"INDEX(ModifTime))");
"INDEX(ModifTime),"
"INDEX(MedCod))");
/***** Table forum_thr_clip *****/
/*
@ -1714,6 +1717,29 @@ mysql> DESCRIBE marks_properties;
"Footer INT NOT NULL,"
"UNIQUE INDEX(FilCod))");
/***** Table media *****/
/*
mysql> DESCRIBE media;
+--------+-------------------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------------------------------------------+------+-----+---------+----------------+
| MedCod | int(11) | NO | PRI | NULL | auto_increment |
| Type | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | MUL | none | |
| Name | varchar(43) | NO | | | |
| URL | varchar(255) | NO | | | |
| Title | varchar(2047) | NO | | | |
+--------+-------------------------------------------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS media ("
"MedCod INT NOT NULL AUTO_INCREMENT,"
"Type ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"Name VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"URL VARCHAR(255) NOT NULL DEFAULT ''," // Cns_MAX_BYTES_WWW
"Title VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
"UNIQUE INDEX(MedCod),"
"INDEX(Type))");
/***** Table msg_banned *****/
/*
mysql> DESCRIBE msg_banned;
@ -1739,23 +1765,26 @@ mysql> DESCRIBE msg_content;
| MsgCod | int(11) | NO | PRI | NULL | auto_increment |
| Subject | text | NO | MUL | NULL | |
| Content | longtext | NO | | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
| MediaURL | varchar(255) | NO | | | |
+------------+-------------------------------------------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
8 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS msg_content ("
"MsgCod INT NOT NULL AUTO_INCREMENT,"
"Subject TEXT NOT NULL,"
"Content LONGTEXT NOT NULL,"
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
"MediaURL VARCHAR(255) NOT NULL DEFAULT ''," // Cns_MAX_BYTES_WWW
"UNIQUE INDEX(MsgCod),"
"FULLTEXT(Subject,Content)) ENGINE = MYISAM;");
"FULLTEXT(Subject,Content),"
"INDEX(MedCod)) ENGINE = MYISAM;");
/***** Table msg_content_deleted *****/
/*
@ -1766,23 +1795,26 @@ mysql> DESCRIBE msg_content_deleted;
| MsgCod | int(11) | NO | PRI | NULL | |
| Subject | text | NO | MUL | NULL | |
| Content | longtext | NO | | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
| MediaURL | varchar(255) | NO | | | |
+------------+-------------------------------------------------------+------+-----+---------+-------+
7 rows in set (0.00 sec)
8 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS msg_content_deleted ("
"MsgCod INT NOT NULL,"
"Subject TEXT NOT NULL,"
"Content LONGTEXT NOT NULL,"
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
"MediaURL VARCHAR(255) NOT NULL DEFAULT ''," // Cns_MAX_BYTES_WWW
"UNIQUE INDEX(MsgCod),"
"FULLTEXT(Subject,Content)) ENGINE = MYISAM;");
"FULLTEXT(Subject,Content),"
"INDEX(MedCod)) ENGINE = MYISAM;");
/***** Table msg_rcv *****/
/*
@ -2181,22 +2213,25 @@ mysql> DESCRIBE social_comments;
+------------+-------------------------------------------------------+------+-----+---------+-------+
| PubCod | bigint(20) | NO | PRI | NULL | |
| Content | longtext | NO | MUL | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
| MediaURL | varchar(255) | NO | | | |
+------------+-------------------------------------------------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
7 rows in set (0.01 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS social_comments ("
"PubCod BIGINT NOT NULL,"
"Content LONGTEXT NOT NULL,"
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
"MediaURL VARCHAR(255) NOT NULL DEFAULT ''," // Cns_MAX_BYTES_WWW
"UNIQUE INDEX(PubCod),"
"FULLTEXT(Content)) ENGINE = MYISAM;");
"FULLTEXT(Content),"
"INDEX(MedCod)) ENGINE = MYISAM;");
/***** Table social_comments_fav *****/
/*
@ -2279,22 +2314,25 @@ mysql> DESCRIBE social_posts;
+------------+-------------------------------------------------------+------+-----+---------+----------------+
| PstCod | int(11) | NO | PRI | NULL | auto_increment |
| Content | longtext | NO | MUL | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
| MediaURL | varchar(255) | NO | | | |
+------------+-------------------------------------------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
7 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS social_posts ("
"PubCod INT NOT NULL AUTO_INCREMENT,"
"Content LONGTEXT NOT NULL,"
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
"MediaURL VARCHAR(255) NOT NULL DEFAULT ''," // Cns_MAX_BYTES_WWW
"UNIQUE INDEX(PubCod),"
"FULLTEXT(Content)) ENGINE = MYISAM;");
"FULLTEXT(Content),"
"INDEX(MedCod)) ENGINE = MYISAM;");
/***** Table social_pubs *****/
/*
@ -2554,25 +2592,28 @@ mysql> DESCRIBE tst_answers;
| AnsInd | tinyint(4) | NO | | NULL | |
| Answer | text | NO | | NULL | |
| Feedback | text | NO | | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
| MediaURL | varchar(255) | NO | | | |
| Correct | enum('N','Y') | NO | | NULL | |
+------------+-------------------------------------------------------+------+-----+---------+-------+
9 rows in set (0.00 sec)
10 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_answers ("
"QstCod INT NOT NULL,"
"AnsInd TINYINT NOT NULL,"
"Answer TEXT NOT NULL," // Tst_MAX_BYTES_ANSWER_OR_FEEDBACK
"Feedback TEXT NOT NULL," // Tst_MAX_BYTES_ANSWER_OR_FEEDBACK
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
"MediaURL VARCHAR(255) NOT NULL DEFAULT ''," // Cns_MAX_BYTES_WWW
"Correct ENUM('N','Y') NOT NULL,"
"INDEX(QstCod))");
"INDEX(QstCod),"
"INDEX(MedCod))");
/***** Table tst_config *****/
/*
@ -2684,6 +2725,7 @@ mysql> DESCRIBE tst_questions;
| Shuffle | enum('N','Y') | NO | | NULL | |
| Stem | text | NO | | NULL | |
| Feedback | text | NO | | NULL | |
| MedCod | int(11) | NO | MUL | -1 | |
| MediaName | varchar(43) | NO | | | |
| MediaType | enum('none','jpg','gif','mp4','webm','ogg','youtube') | NO | | none | |
| MediaTitle | varchar(2047) | NO | | | |
@ -2692,7 +2734,7 @@ mysql> DESCRIBE tst_questions;
| NumHitsNotBlank | int(11) | NO | | 0 | |
| Score | double | NO | | 0 | |
+-----------------+---------------------------------------------------------------------------+------+-----+---------+----------------+
14 rows in set (0.00 sec)
15 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_questions ("
"QstCod INT NOT NULL AUTO_INCREMENT,"
@ -2702,6 +2744,7 @@ mysql> DESCRIBE tst_questions;
"Shuffle ENUM('N','Y') NOT NULL,"
"Stem TEXT NOT NULL," // Cns_MAX_BYTES_TEXT
"Feedback TEXT NOT NULL," // Cns_MAX_BYTES_TEXT
"MedCod INT NOT NULL DEFAULT -1,"
"MediaName VARCHAR(43) NOT NULL DEFAULT ''," // Med_BYTES_NAME
"MediaType ENUM('none','jpg','gif','mp4','webm','ogg','youtube') NOT NULL DEFAULT 'none',"
"MediaTitle VARCHAR(2047) NOT NULL DEFAULT ''," // Med_MAX_BYTES_TITLE
@ -2710,7 +2753,8 @@ mysql> DESCRIBE tst_questions;
"NumHitsNotBlank INT NOT NULL DEFAULT 0,"
"Score DOUBLE PRECISION NOT NULL DEFAULT 0,"
"UNIQUE INDEX(QstCod),"
"INDEX(CrsCod,EditTime))");
"INDEX(CrsCod,EditTime),"
"INDEX(MedCod))");
/***** Table tst_status *****/
/*
@ -2865,7 +2909,7 @@ mysql> DESCRIBE usr_data;
"INDEX(CtrCod),"
"INDEX(Menu),"
"INDEX(SideCols),"
"INDEX(ThirdPartyCookies)");
"INDEX(ThirdPartyCookies))");
/***** Table usr_duplicated *****/
/*

View File

@ -283,7 +283,7 @@ static void For_InsertPstIntoBannedPstTable (long PstCod);
static long For_InsertForumPst (long ThrCod,long UsrCod,
const char *Subject,const char *Content,
struct Media *Media);
static bool For_RemoveForumPst (long PstCod,struct Media *Media);
static bool For_RemoveForumPst (long PstCod,long MedCod);
static unsigned For_NumPstsInThrWithPstCod (long PstCod,long *ThrCod);
static long For_InsertForumThread (long FirstPstCod);
@ -501,28 +501,29 @@ static long For_InsertForumPst (long ThrCod,long UsrCod,
long PstCod;
/***** Check if image is received and processed *****/
Media->MedCod = -1L;
if (Media->Action == Med_ACTION_NEW_MEDIA && // New media
Media->Status == Med_PROCESSED) // The new media received has been processed
{
/* Move processed media to definitive directory */
Med_MoveMediaToDefinitiveDir (Media);
/* Store media in database */
if (Media->Status == Med_MOVED)
Med_StoreMediaInDB (Media); // Set Media->MedCod
}
/***** Insert forum post in the database *****/
PstCod =
DB_QueryINSERTandReturnCode ("can not create a new post in a forum",
"INSERT INTO forum_post"
" (ThrCod,UsrCod,CreatTime,ModifTime,NumNotif,"
"Subject,Content,"
"MediaName,MediaType,MediaTitle,MediaURL)"
"Subject,Content,MedCod)"
" VALUES"
" (%ld,%ld,NOW(),NOW(),0,"
"'%s','%s',"
"'%s','%s','%s','%s')",
"'%s','%s',%ld)",
ThrCod,UsrCod,
Subject,Content,
Media->Name,
Med_GetStringTypeForDB (Media->Type),
Media->Title ? Media->Title : "",
Media->URL ? Media->URL : "");
Subject,Content,Media->MedCod);
return PstCod;
}
@ -532,13 +533,13 @@ static long For_InsertForumPst (long ThrCod,long UsrCod,
/*****************************************************************************/
// Return true if the post thread is deleted
static bool For_RemoveForumPst (long PstCod,struct Media *Media)
static bool For_RemoveForumPst (long PstCod,long MedCod)
{
long ThrCod;
bool ThreadDeleted = false;
/***** Remove media file attached to forum post *****/
Med_RemoveMediaFiles (Media->Name,Media->Type);
Med_RemoveMedia (MedCod);
/***** If the post is the only one in its thread, delete that thread *****/
if (For_NumPstsInThrWithPstCod (PstCod,&ThrCod) < 2)
@ -1345,10 +1346,7 @@ static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC,
"UNIX_TIMESTAMP(CreatTime)," // row[1]
"Subject," // row[2]
"Content," // row[3]
"MediaName," // row[4]
"MediaType," // row[5]
"MediaTitle," // row[6]
"MediaURL" // row[7]
"MedCod" // row[4]
" FROM forum_post WHERE PstCod=%ld",
PstCod);
@ -1359,22 +1357,23 @@ static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC,
/***** Get number of rows *****/
row = mysql_fetch_row (mysql_res);
/****** Get author code (row[1]) *****/
/***** Get author code (row[1]) *****/
*UsrCod = Str_ConvertStrCodToLongCod (row[0]);
/****** Get creation time (row[1]) *****/
/***** Get creation time (row[1]) *****/
*CreatTimeUTC = Dat_GetUNIXTimeFromStr (row[1]);
/****** Get subject (row[2]) *****/
/***** Get subject (row[2]) *****/
Str_Copy (Subject,row[2],
Cns_MAX_BYTES_SUBJECT);
/****** Get location (row[3]) *****/
/***** Get location (row[3]) *****/
Str_Copy (Content,row[3],
Cns_MAX_BYTES_LONG_TEXT);
/****** Get media data (row[4], row[5], row[6], row[7]) *****/
Med_GetMediaDataFromRow (row[4],row[5],row[6],row[7],Media);
/***** Get media (row[4]) *****/
Media->MedCod = Str_ConvertStrCodToLongCod (row[4]);
Med_GetMediaDataByCod (Media);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -4089,7 +4088,7 @@ void For_ReceiveForumPost (void)
For_UpdateThrFirstAndLastPst (Gbl.Forum.ForumSelected.ThrCod,PstCod,PstCod);
}
/***** Free image *****/
/***** Free media *****/
Med_MediaDestructor (&Media);
/***** Increment number of forum posts in my user's figures *****/
@ -4188,7 +4187,7 @@ void For_RemovePost (void)
Lay_ShowErrorAndExit ("You can not remove post because it is not the last of the thread.");
/***** Remove the post *****/
ThreadDeleted = For_RemoveForumPst (Gbl.Forum.ForumSelected.PstCod,&Media);
ThreadDeleted = For_RemoveForumPst (Gbl.Forum.ForumSelected.PstCod,Media.MedCod);
/***** Free image *****/
Med_MediaDestructor (&Media);

View File

@ -2734,10 +2734,7 @@ static void Gam_ListGameQuestions (struct Game *Game)
"tst_questions.AnsType," // row[1]
"tst_questions.Stem," // row[2]
"tst_questions.Feedback," // row[3]
"tst_questions.MediaName," // row[4]
"tst_questions.MediaType," // row[5]
"tst_questions.MediaTitle," // row[6]
"tst_questions.MediaURL" // row[7]
"tst_questions.MedCod" // row[4]
" FROM gam_questions,tst_questions"
" WHERE gam_questions.GamCod=%ld"
" AND gam_questions.QstCod=tst_questions.QstCod"
@ -2842,10 +2839,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Game *Game,
row[1] AnsType
row[2] Stem
row[3] Feedback
row[4] MediaName
row[5] MediaType
row[6] MediaTitle
row[7] MediaURL
row[4] MedCod
*/
/***** Create test question *****/
Tst_QstConstructor ();
@ -2923,16 +2917,24 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Game *Game,
Tst_GetAndWriteTagsQst (Gbl.Test.QstCod);
fprintf (Gbl.F.Out,"</td>");
/* Write stem (row[2]), media data (row[4], row[5], row[6], row[7]),
feedback (row[3]) and answers */
/* Write stem (row[2]) */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
Tst_WriteQstStem (row[2],"TEST_EDI");
Med_GetMediaDataFromRow (row[4],row[5],row[6],row[7],&Gbl.Test.Media);
/* Get media (row[4]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[4]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Show media */
Med_ShowMedia (&Gbl.Test.Media,
"TEST_IMG_EDIT_LIST_STEM_CONTAINER",
"TEST_IMG_EDIT_LIST_STEM");
/* Show feedback (row[3]) */
Tst_WriteQstFeedback (row[3],"TEST_EDI_LIGHT");
/* Show answers */
Tst_WriteAnswersGameResult (Game,NumQst,QstCod,
"TEST_EDI",true); // Show result
@ -3531,10 +3533,7 @@ static void Gam_PlayGameShowQuestionAndAnswers (bool ShowAnswers)
"SELECT tst_questions.QstCod," // row[0]
"tst_questions.AnsType," // row[1]
"tst_questions.Stem," // row[2]
"tst_questions.MediaName," // row[3]
"tst_questions.MediaType," // row[4]
"tst_questions.MediaTitle," // row[5]
"tst_questions.MediaURL" // row[6]
"tst_questions.MedCod" // row[3]
" FROM gam_questions,tst_questions"
" WHERE gam_questions.GamCod=%ld"
" AND gam_questions.QstInd=%u"
@ -3553,9 +3552,14 @@ static void Gam_PlayGameShowQuestionAndAnswers (bool ShowAnswers)
fprintf (Gbl.F.Out,"<div class=\"GAM_PLAY_QST_CONTAINER\">");
/* Write stem (row[2]) and media data (row[3], row[4], row[5], row[6]) */
/* Write stem (row[2]) */
Tst_WriteQstStem (row[2],"GAM_PLAY_QST");
Med_GetMediaDataFromRow (row[3],row[4],row[5],row[6],&Gbl.Test.Media);
/* Get media (row[3]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Show media */
Med_ShowMedia (&Gbl.Test.Media,
"TEST_IMG_EDIT_LIST_STEM_CONTAINER",
"TEST_IMG_EDIT_LIST_STEM");

View File

@ -38,6 +38,7 @@
#include "swad_config.h"
#include "swad_cookie.h"
#include "swad_database.h"
#include "swad_global.h"
#include "swad_file.h"
#include "swad_file_browser.h"
@ -153,8 +154,10 @@ static void Med_ShowVideo (struct Media *Media,
const char *ClassMedia);
static void Med_ShowYoutube (struct Media *Media,const char *ClassMedia);
static Med_Type_t Med_GetTypeFromStrInDB (const char *Str);
static Med_Type_t Med_GetTypeFromExtAndMIME (const char *Extension,
const char *MIMEType);
static const char *Med_GetStringTypeForDB (Med_Type_t Type);
/*****************************************************************************/
/********************** Media (image/video) constructor **********************/
@ -197,6 +200,7 @@ void Med_ResetMedia (struct Media *Media)
static void Med_ResetMediaExceptURLAndTitle (struct Media *Media)
{
Media->MedCod = -1L;
Media->Action = Med_ACTION_NO_MEDIA;
Media->Status = Med_STATUS_NONE;
Media->Name[0] = '\0';
@ -235,59 +239,82 @@ static void Med_FreeMediaTitle (struct Media *Media)
/**** Get media name, title and URL from a query result and copy to struct ***/
/*****************************************************************************/
void Med_GetMediaDataFromRow (const char *Name,
const char *TypeStr,
const char *Title,
const char *URL,
struct Media *Media)
void Med_GetMediaDataByCod (struct Media *Media)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRows;
size_t Length;
/***** Copy image name to struct *****/
Str_Copy (Media->Name,Name,
Med_BYTES_NAME);
/***** Get data of a media from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get data of a post",
"SELECT Type," // row[0]
"Name," // row[1]
"URL," // row[2]
"Title" // row[3]
" FROM media WHERE MedCod=%ld",
Media->MedCod);
/***** Convert type string to type *****/
Media->Type = Med_GetTypeFromStrInDB (TypeStr);
/***** Result should have a unique row *****/
if (NumRows == 0) // Media not found
/***** Reset media data *****/
Med_ResetMedia (Media);
else if (NumRows == 1)
{
/***** Get row *****/
row = mysql_fetch_row (mysql_res);
/***** Convert type string (row[0]) to type *****/
Media->Type = Med_GetTypeFromStrInDB (row[0]);
/***** Set status of media file *****/
Media->Status = (Media->Type != Med_TYPE_NONE) ? Med_STORED_IN_DB :
Med_STATUS_NONE;
/***** Copy image URL to struct *****/
/***** Copy media name (row[1]) to struct *****/
Str_Copy (Media->Name,row[1],
Med_BYTES_NAME);
/***** Copy media URL (row[2]) to struct *****/
// Media->URL can be empty or filled with previous value
// If filled ==> free it
Med_FreeMediaURL (Media);
if (URL[0])
if (row[2][0])
{
/* Get and limit length of the URL */
Length = strlen (URL);
Length = strlen (row[2]);
if (Length > Cns_MAX_BYTES_WWW)
Length = Cns_MAX_BYTES_WWW;
if ((Media->URL = (char *) malloc (Length + 1)) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for image URL.");
Str_Copy (Media->URL,URL,
Str_Copy (Media->URL,row[2],
Length);
}
/***** Copy image title to struct *****/
/***** Copy media title (row[3]) to struct *****/
// Media->Title can be empty or filled with previous value
// If filled ==> free it
Med_FreeMediaTitle (Media);
if (Title[0])
if (row[3][0])
{
/* Get and limit length of the title */
Length = strlen (Title);
Length = strlen (row[3]);
if (Length > Med_MAX_BYTES_TITLE)
Length = Med_MAX_BYTES_TITLE;
if ((Media->Title = (char *) malloc (Length + 1)) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
Str_Copy (Media->Title,Title,
Str_Copy (Media->Title,row[3],
Length);
}
}
else
Lay_ShowErrorAndExit ("Internal error in database when getting media data.");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********* Draw input fields to upload an image/video inside a form **********/
@ -980,7 +1007,6 @@ static void Med_GetAndProcessEmbedFromForm (const char *ParamURL,
/***** Get embed URL from form *****/
Usr_GetURLFromForm (ParamURL,Media);
// Ale_ShowAlert (Ale_INFO,"DEBUG: Media->URL = '%s'",Media->URL);
/***** Process URL trying to convert it to a YouTube embed URL *****/
if (Media->URL)
@ -1007,7 +1033,6 @@ static void Med_GetAndProcessEmbedFromForm (const char *ParamURL,
if (PtrHost[0])
{
/***** Step 2: Skip host *****/
// Ale_ShowAlert (Ale_INFO,"DEBUG: PtrHost = '%s'",PtrHost);
if (!strncasecmp (PtrHost,"youtu.be/" , 9)) // Host starts by youtu.be/
{
YouTube = SHORT;
@ -1035,7 +1060,6 @@ static void Med_GetAndProcessEmbedFromForm (const char *ParamURL,
if (YouTube != WRONG)
{
// Ale_ShowAlert (Ale_INFO,"DEBUG: PtrPath = '%s'",PtrPath);
/***** Step 3: Skip path *****/
if (YouTube == FULL)
{
@ -1063,7 +1087,6 @@ static void Med_GetAndProcessEmbedFromForm (const char *ParamURL,
if (YouTube != WRONG)
{
// Ale_ShowAlert (Ale_INFO,"DEBUG: PtrParams = '%s'",PtrParams);
/***** Step 4: Search for video code *****/
switch (YouTube)
{
@ -1095,7 +1118,6 @@ static void Med_GetAndProcessEmbedFromForm (const char *ParamURL,
if (YouTube != WRONG)
{
// Ale_ShowAlert (Ale_INFO,"DEBUG: PtrCode = '%s'",PtrCode);
/***** Step 5: Get video code *****/
CodeLength = strspn (PtrCode,Str_BIN_TO_BASE64URL);
if (CodeLength > 0 &&
@ -1105,7 +1127,6 @@ static void Med_GetAndProcessEmbedFromForm (const char *ParamURL,
/* Copy code */
strncpy (Media->Name,PtrCode,CodeLength);
Media->Name[CodeLength] = '\0';
// Ale_ShowAlert (Ale_INFO,"DEBUG: Media->Name = '%s'",Media->Name);
Media->Type = Med_YOUTUBE;
Media->Status = Med_PROCESSED;
@ -1126,12 +1147,14 @@ void Med_MoveMediaToDefinitiveDir (struct Media *Media)
char PathMedPrivTmp[PATH_MAX + 1];
char PathMedPriv[PATH_MAX + 1];
/***** Check trivial cases *****/
if (Media->Status != Med_PROCESSED)
return;
/***** Check trivial case *****/
if (Media->Status == Med_PROCESSED)
{
if (Media->Type == Med_YOUTUBE)
return; // Nothing to do with files
// Nothing to do with files ==> Processing successfully finished
Media->Status = Med_MOVED; // Success
else
{
/***** Build temporary path *****/
snprintf (PathMedPrivTmp,sizeof (PathMedPrivTmp),
"%s/%s/%s",
@ -1150,33 +1173,38 @@ void Med_MoveMediaToDefinitiveDir (struct Media *Media)
{
case Med_JPG:
/* Move JPG */
if (!Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
if (Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
Med_Extensions[Med_JPG]))
return; // Fail
Media->Status = Med_MOVED; // Success
break;
case Med_GIF:
/* Move PNG */
if (!Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
if (Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
"png"))
return; // Fail
/* Move GIF */
if (!Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
if (Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
Med_Extensions[Med_GIF]))
return; // Fail
Media->Status = Med_MOVED; // Success
break;
case Med_MP4:
case Med_WEBM:
case Med_OGG:
/* Move MP4 or WEBM or OGG */
if (!Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
if (Med_MoveTmpFileToDefDir (Media,PathMedPrivTmp,PathMedPriv,
Med_Extensions[Media->Type]))
return; // Fail
Media->Status = Med_MOVED; // Success
break;
default:
Lay_ShowErrorAndExit ("Wrong media type.");
break;
break; // Not reached
}
}
}
/***** If fail ==> reset media *****/
if (Media->Status != Med_MOVED) // Fail
Med_ResetMedia (Media);
}
/*****************************************************************************/
/******* Move temporary processed file to definitive private directory *******/
@ -1212,6 +1240,32 @@ static bool Med_MoveTmpFileToDefDir (struct Media *Media,
return true; // Success
}
/*****************************************************************************/
/************************ Store media into database **************************/
/*****************************************************************************/
void Med_StoreMediaInDB (struct Media *Media)
{
/***** Trivial case *****/
if (Media->Status != Med_MOVED)
{
Med_ResetMedia (Media); // No media inserted in database
return;
}
/***** Insert media into database *****/
Media->MedCod = DB_QueryINSERTandReturnCode ("can not create media",
"INSERT INTO media"
" (Type,Name,URL,Title)"
" VALUES"
" ('%s','%s','%s','%s')",
Med_GetStringTypeForDB (Media->Type),
Media->Name,
Media->URL ? Media->URL : "",
Media->Title ? Media->Title : "");
Media->Status = Med_STORED_IN_DB;
}
/*****************************************************************************/
/****** Show a user uploaded media (in a test question, timeline, etc.) ******/
/*****************************************************************************/
@ -1542,10 +1596,10 @@ static void Med_ShowYoutube (struct Media *Media,const char *ClassMedia)
}
/*****************************************************************************/
/*** Remove private files with an image/video, given the image/video name ****/
/**************** Remove media files and entries in database *****************/
/*****************************************************************************/
void Med_RemoveMediaFilesFromAllRows (unsigned NumMedia,MYSQL_RES *mysql_res)
void Med_RemoveMediaFromAllRows (unsigned NumMedia,MYSQL_RES *mysql_res)
{
unsigned NumMed;
@ -1553,48 +1607,59 @@ void Med_RemoveMediaFilesFromAllRows (unsigned NumMedia,MYSQL_RES *mysql_res)
for (NumMed = 0;
NumMed < NumMedia;
NumMed++)
Med_RemoveMediaFilesFromRow (mysql_res);
Med_RemoveMediaFromRow (mysql_res);
}
void Med_RemoveMediaFilesFromRow (MYSQL_RES *mysql_res)
void Med_RemoveMediaFromRow (MYSQL_RES *mysql_res)
{
MYSQL_ROW row;
long MedCod;
/***** Get media name (row[0]) and type (row[1]) *****/
/***** Get media code (row[0]) *****/
row = mysql_fetch_row (mysql_res);
MedCod = Str_ConvertStrCodToLongCod (row[0]);
/***** Remove image file *****/
Med_RemoveMediaFiles (row[0],Med_GetTypeFromStrInDB (row[1]));
/***** Remove media files *****/
Med_RemoveMedia (MedCod);
}
void Med_RemoveMediaFiles (const char *Name,Med_Type_t Type)
void Med_RemoveMedia (long MedCod)
{
char PathMedPriv[PATH_MAX + 1];
char FullPathMediaPriv[PATH_MAX + 1];
struct Media Media;
/***** Trivial cases *****/
if (Name == NULL)
return;
if (!Name[0])
return;
if (Type == Med_YOUTUBE)
/***** Trivial case *****/
if (MedCod <= 0)
return;
/***** Initialize media *****/
Med_MediaConstructor (&Media);
/***** Get media *****/
Media.MedCod = MedCod;
Med_GetMediaDataByCod (&Media);
/***** Step 1. Remove files *****/
if (Media.Type != Med_TYPE_NONE &&
Media.Type != Med_YOUTUBE &&
Media.Name[0])
{
/***** Build path to private directory with the media *****/
snprintf (PathMedPriv,sizeof (PathMedPriv),
"%s/%s/%c%c",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_MEDIA,
Name[0],
Name[1]);
Media.Name[0],
Media.Name[1]);
/***** Remove files *****/
switch (Type)
switch (Media.Type)
{
case Med_JPG:
/***** Remove private JPG file *****/
snprintf (FullPathMediaPriv,sizeof (FullPathMediaPriv),
"%s/%s.%s",
PathMedPriv,Name,Med_Extensions[Med_JPG]);
PathMedPriv,Media.Name,Med_Extensions[Med_JPG]);
unlink (FullPathMediaPriv);
break;
@ -1602,13 +1667,13 @@ void Med_RemoveMediaFiles (const char *Name,Med_Type_t Type)
/***** Remove private GIF file *****/
snprintf (FullPathMediaPriv,sizeof (FullPathMediaPriv),
"%s/%s.%s",
PathMedPriv,Name,Med_Extensions[Med_GIF]);
PathMedPriv,Media.Name,Med_Extensions[Med_GIF]);
unlink (FullPathMediaPriv);
/***** Remove private PNG file *****/
snprintf (FullPathMediaPriv,sizeof (FullPathMediaPriv),
"%s/%s.png",
PathMedPriv,Name);
PathMedPriv,Media.Name);
unlink (FullPathMediaPriv);
break;
@ -1618,22 +1683,30 @@ void Med_RemoveMediaFiles (const char *Name,Med_Type_t Type)
/***** Remove private video file *****/
snprintf (FullPathMediaPriv,sizeof (FullPathMediaPriv),
"%s/%s.%s",
PathMedPriv,Name,Med_Extensions[Type]);
PathMedPriv,Media.Name,Med_Extensions[Media.Type]);
unlink (FullPathMediaPriv);
break;
default:
break;
}
// Public links are removed automatically after a period
}
/***** Step 2. Remove entry for this media from database *****/
DB_QueryDELETE ("can not remove media",
"DELETE FROM media WHERE MedCod=%ld",
MedCod);
/***** Free media *****/
Med_MediaDestructor (&Media);
}
/*****************************************************************************/
/************************ Get media type from string *************************/
/*****************************************************************************/
Med_Type_t Med_GetTypeFromStrInDB (const char *Str)
static Med_Type_t Med_GetTypeFromStrInDB (const char *Str)
{
Med_Type_t Type;
@ -1708,7 +1781,7 @@ static Med_Type_t Med_GetTypeFromExtAndMIME (const char *Extension,
/*************** Get string media type in database from type *****************/
/*****************************************************************************/
const char *Med_GetStringTypeForDB (Med_Type_t Type)
static const char *Med_GetStringTypeForDB (Med_Type_t Type)
{
/***** Check if type is out of valid range *****/
if (Type > (Med_Type_t) (Med_NUM_TYPES - 1))

View File

@ -58,7 +58,7 @@ typedef enum
No file Original file Temporary Definitive Name of the image/video
uploaded uploaded by user processed file processed file stored in database
--------- --------------------------- ------------------ ------------------ ---------------------
Med_STATUS_NONE Med_PROCESSED Med_NAME_STORED_IN_DB
Med_STATUS_NONE Med_PROCESSED Med_MOVED Med_NAME_STORED_IN_DB
--------- --------------------------- ------------------ ------------------ ---------------------
upload-file process file move file insert in database
--------- --------------------------- ------------------ ------------------ ---------------------
@ -82,6 +82,7 @@ typedef enum
{
Med_STATUS_NONE,
Med_PROCESSED,
Med_MOVED,
Med_STORED_IN_DB,
} Med_Status_t;
@ -100,6 +101,7 @@ typedef enum
/***** Struct used to get images/videos from forms *****/
struct Media
{
long MedCod;
Med_Action_t Action;
Med_Status_t Status;
char Name[Med_BYTES_NAME + 1];
@ -135,11 +137,7 @@ void Med_MediaConstructor (struct Media *Media);
void Med_MediaDestructor (struct Media *Media);
void Med_ResetMedia (struct Media *Media);
void Med_GetMediaDataFromRow (const char *Name,
const char *TypeStr,
const char *Title,
const char *URL,
struct Media *Media);
void Med_GetMediaDataByCod (struct Media *Media);
void Med_PutMediaUploader (int NumMediaInForm,const char *ClassInput);
void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media,
@ -148,14 +146,13 @@ void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media,
void Med_SetParamNames (struct ParamUploadMedia *ParamUploadMedia,int NumMediaInForm);
void Med_MoveMediaToDefinitiveDir (struct Media *Media);
void Med_StoreMediaInDB (struct Media *Media);
void Med_ShowMedia (struct Media *Media,
const char *ClassContainer,const char *ClassMedia);
void Med_RemoveMediaFilesFromAllRows (unsigned NumMedia,MYSQL_RES *mysql_res);
void Med_RemoveMediaFilesFromRow (MYSQL_RES *mysql_res);
void Med_RemoveMediaFiles (const char *Name,Med_Type_t Type);
Med_Type_t Med_GetTypeFromStrInDB (const char *Str);
const char *Med_GetStringTypeForDB (Med_Type_t Type);
void Med_RemoveMediaFromAllRows (unsigned NumMedia,MYSQL_RES *mysql_res);
void Med_RemoveMediaFromRow (MYSQL_RES *mysql_res);
void Med_RemoveMedia (long MedCod);
#endif

View File

@ -1282,25 +1282,26 @@ static long Msg_InsertNewMsg (const char *Subject,const char *Content,
long MsgCod;
/***** Check if image is received and processed *****/
Media->MedCod = -1L;
if (Media->Action == Med_ACTION_NEW_MEDIA && // New media
Media->Status == Med_PROCESSED) // The new media received has been processed
{
/* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (Media);
/* Store media in database */
if (Media->Status == Med_MOVED)
Med_StoreMediaInDB (Media); // Set Media->MedCod
}
/***** Insert message subject and content in the database *****/
MsgCod =
DB_QueryINSERTandReturnCode ("can not create message",
"INSERT INTO msg_content"
" (Subject,Content,"
"MediaName,MediaType,MediaTitle,MediaURL)"
" (Subject,Content,MedCod)"
" VALUES"
" ('%s','%s',"
"'%s','%s','%s','%s')",
Subject,Content,
Media->Name,
Med_GetStringTypeForDB (Media->Type),
Media->Title ? Media->Title : "",
Media->URL ? Media->URL : "");
" ('%s','%s',%ld)",
Subject,Content,Media->MedCod);
/***** Insert message in sent messages *****/
DB_QueryINSERT ("can not create message",
@ -1493,10 +1494,8 @@ static void Msg_MoveMsgContentToDeleted (long MsgCod)
/* Insert message content into msg_content_deleted */
DB_QueryINSERT ("can not remove the content of a message",
"INSERT IGNORE INTO msg_content_deleted"
" (MsgCod,Subject,Content,"
"MediaName,MediaType,MediaTitle,MediaURL)"
" SELECT MsgCod,Subject,Content,"
"MediaName,MediaType,MediaTitle,MediaURL"
" (MsgCod,Subject,Content,MedCod)"
" SELECT MsgCod,Subject,Content,MedCod"
" FROM msg_content WHERE MsgCod=%ld",
MsgCod);
@ -2788,10 +2787,7 @@ static void Msg_GetMsgContent (long MsgCod,char Content[Cns_MAX_BYTES_LONG_TEXT
/***** Get content of message from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get the content of a message",
"SELECT Content," // row[0]
"MediaName," // row[1]
"MediaType," // row[2]
"MediaTitle," // row[3]
"MediaURL" // row[4]
"MedCod" // row[1]
" FROM msg_content WHERE MsgCod=%ld",
MsgCod);
@ -2806,8 +2802,9 @@ static void Msg_GetMsgContent (long MsgCod,char Content[Cns_MAX_BYTES_LONG_TEXT
Str_Copy (Content,row[0],
Cns_MAX_BYTES_LONG_TEXT);
/****** Get media data (row[1], row[2], row[3], row[4]) *****/
Med_GetMediaDataFromRow (row[1],row[2],row[3],row[4],Media);
/***** Get media (row[1]) *****/
Media->MedCod = Str_ConvertStrCodToLongCod (row[1]);
Med_GetMediaDataByCod (Media);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);

View File

@ -155,6 +155,11 @@ static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
static unsigned Tst_GetNumAccessesTst (void);
static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res);
static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank,double *TotalScore);
static void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct UsrData *UsrDat,
struct Game *Game,
unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank);
static void Tst_PutFormToEditQstMedia (struct Media *Media,int NumMediaInForm,
const char *ClassContainer,
const char *ClassMedia,
@ -683,8 +688,8 @@ static bool Tst_CheckIfNextTstAllowed (void)
/***** Get date of next allowed access to test from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get last access to test",
"SELECT UNIX_TIMESTAMP(LastAccTst+INTERVAL (NumQstsLastTst*%lu) SECOND)-"
"UNIX_TIMESTAMP(),"
"UNIX_TIMESTAMP(LastAccTst+INTERVAL (NumQstsLastTst*%lu) SECOND)"
"UNIX_TIMESTAMP()," // row[0]
"UNIX_TIMESTAMP(LastAccTst+INTERVAL (NumQstsLastTst*%lu) SECOND)" // row[1]
" FROM crs_usr"
" WHERE CrsCod=%ld AND UsrCod=%ld",
Gbl.Test.Config.MinTimeNxtTstPerQst,
@ -758,7 +763,8 @@ static Tst_Status_t Tst_GetTstStatus (unsigned NumTst)
/***** Get status of test from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get status of test",
"SELECT Status FROM tst_status"
"SELECT Status" // row[0]
" FROM tst_status"
" WHERE SessionId='%s'"
" AND CrsCod=%ld"
" AND NumTst=%u",
@ -795,7 +801,8 @@ static unsigned Tst_GetNumAccessesTst (void)
{
/***** Get number of hits to test from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get number of hits to test",
"SELECT NumAccTst FROM crs_usr"
"SELECT NumAccTst" // row[0]
" FROM crs_usr"
" WHERE CrsCod=%ld AND UsrCod=%ld",
Gbl.CurrentCrs.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
@ -834,6 +841,18 @@ static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res)
MYSQL_ROW row;
double ScoreThisQst; // Not used here
bool AnswerIsNotBlank; // Not used here
/*
row[0] QstCod
row[1] UNIX_TIMESTAMP(EditTime)
row[2] AnsType
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** Write rows *****/
for (NumQst = 0;
@ -872,7 +891,8 @@ static void Tst_ShowTstTagsPresentInATestResult (long TstCod)
/***** Get all tags of questions in this test *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get tags"
" present in a test result",
"SELECT tst_tags.TagTxt FROM"
"SELECT tst_tags.TagTxt" // row[0]
" FROM"
" (SELECT DISTINCT(tst_question_tags.TagCod)"
" FROM tst_question_tags,tst_exam_questions"
" WHERE tst_exam_questions.TstCod=%ld"
@ -939,13 +959,10 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[ 6] MediaName
row[ 7] MediaType
row[ 8] MediaTitle
row[ 9] MediaURL
row[10] NumHits
row[11] NumHitsNotBlank
row[12] Score
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** Get the code of question (row[0]) *****/
@ -994,7 +1011,7 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
/********** Write a row of a test, with one question and its answer **********/
/*****************************************************************************/
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
static void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct UsrData *UsrDat,
struct Game *Game,
unsigned NumQst,long QstCod,MYSQL_ROW row,
@ -1008,13 +1025,10 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[ 6] MediaName
row[ 7] MediaType
row[ 8] MediaTitle
row[ 9] MediaURL
row[10] NumHits
row[11] NumHitsNotBlank
row[12] Score
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** Create test question *****/
@ -1034,16 +1048,19 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
"</td>",
Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
/***** Write stem (row[4]), media data (row[6], row[7], row[8], row[9]),
answers depending on shuffle (row[3]) and feedback (row[5]) *****/
/***** Write stem (row[4]) *****/
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EXA");
Med_GetMediaDataFromRow (row[6],row[7],row[8],row[9],&Gbl.Test.Media);
/***** Get and show media (row[6]) *****/
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
Med_ShowMedia (&Gbl.Test.Media,
"TEST_IMG_SHOW_STEM_CONTAINER",
"TEST_IMG_SHOW_STEM");
/***** Write answers depending on shuffle (row[3]) and feedback (row[5]) *****/
switch (ActionToDoWithQuestions)
{
case Tst_SHOW_TEST_TO_ANSWER:
@ -1639,7 +1656,10 @@ static unsigned long Tst_GetAllTagsFromCurrentCrs (MYSQL_RES **mysql_res)
{
/***** Get available tags from database *****/
return DB_QuerySELECT (mysql_res,"can not get available tags",
"SELECT TagCod,TagTxt,TagHidden FROM tst_tags"
"SELECT TagCod," // row[0]
"TagTxt," // row[1]
"TagHidden" // row[2]
" FROM tst_tags"
" WHERE CrsCod=%ld"
" ORDER BY TagTxt",
Gbl.CurrentCrs.Crs.CrsCod);
@ -1677,6 +1697,11 @@ static void Tst_ShowFormSelTags (unsigned long NumRows,MYSQL_RES *mysql_res,
bool TagHidden = false;
const char *Ptr;
char TagText[Tst_MAX_BYTES_TAG + 1];
/*
row[0] TagCod
row[1] TagTxt
row[2] TagHidden
*/
/***** Label *****/
fprintf (Gbl.F.Out,"<tr>"
@ -1785,6 +1810,11 @@ static void Tst_ShowFormEditTags (void)
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/*
row[0] TagCod
row[1] TagTxt
row[2] TagHidden
*/
if ((TagCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of tag.");
@ -2126,7 +2156,9 @@ bool Tst_CheckIfCourseHaveTestsAndPluggableIsUnknown (void)
/***** Get pluggability of tests for current course from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get configuration of test",
"SELECT Pluggable FROM tst_config WHERE CrsCod=%ld",
"SELECT Pluggable" // row[0]
" FROM tst_config"
" WHERE CrsCod=%ld",
Gbl.CurrentCrs.Crs.CrsCod);
if (NumRows == 0)
@ -2447,18 +2479,15 @@ static unsigned long Tst_GetQuestions (MYSQL_RES **mysql_res)
/* Start query */
snprintf (Query,Tst_MAX_BYTES_QUERY_TEST + 1,
"SELECT tst_questions.QstCod," // row[0]
"UNIX_TIMESTAMP(tst_questions.EditTime) AS F," // row[ 1]
"UNIX_TIMESTAMP(tst_questions.EditTime)," // row[1]
"tst_questions.AnsType," // row[2]
"tst_questions.Shuffle," // row[3]
"tst_questions.Stem," // row[4]
"tst_questions.Feedback," // row[5]
"tst_questions.MediaName," // row[ 6]
"tst_questions.MediaType," // row[ 7]
"tst_questions.MediaTitle," // row[ 8]
"tst_questions.MediaURL," // row[ 9]
"tst_questions.NumHits," // row[10]
"tst_questions.NumHitsNotBlank," // row[11]
"tst_questions.Score" // row[12]
"tst_questions.MedCod," // row[6]
"tst_questions.NumHits," // row[7]
"tst_questions.NumHitsNotBlank," // row[8]
"tst_questions.Score" // row[9]
" FROM tst_questions");
if (!Gbl.Test.Tags.All)
Str_Concat (Query,",tst_question_tags,tst_tags",
@ -2625,13 +2654,10 @@ static unsigned long Tst_GetQuestionsForTest (MYSQL_RES **mysql_res)
"tst_questions.Shuffle," // row[3]
"tst_questions.Stem," // row[4]
"tst_questions.Feedback," // row[5]
"tst_questions.MediaName," // row[ 6]
"tst_questions.MediaType," // row[ 7]
"tst_questions.MediaTitle," // row[ 8]
"tst_questions.MediaURL," // row[ 9]
"tst_questions.NumHits," // row[10]
"tst_questions.NumHitsNotBlank," // row[11]
"tst_questions.Score" // row[12]
"tst_questions.MedCod," // row[6]
"tst_questions.NumHits," // row[7]
"tst_questions.NumHitsNotBlank," // row[8]
"tst_questions.Score" // row[9]
" FROM tst_questions,tst_question_tags,tst_tags"
" WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod NOT IN"
@ -2751,13 +2777,10 @@ bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res)
"Shuffle," // row[3]
"Stem," // row[4]
"Feedback," // row[5]
"MediaName," // row[ 6]
"MediaType," // row[ 7]
"MediaTitle," // row[ 8]
"MediaURL," // row[ 9]
"NumHits," // row[10]
"NumHitsNotBlank," // row[11]
"Score" // row[12]
"MedCod," // row[6]
"NumHits," // row[7]
"NumHitsNotBlank," // row[8]
"Score" // row[9]
" FROM tst_questions"
" WHERE QstCod=%ld",
QstCod) == 1);
@ -2865,13 +2888,10 @@ static void Tst_ListOneOrMoreQuestionsForEdition (unsigned long NumRows,
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[ 6] MediaName
row[ 7] MediaType
row[ 8] MediaTitle
row[ 9] MediaURL
row[10] NumHits
row[11] NumHitsNotBlank
row[12] Score
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** Create test question *****/
Tst_QstConstructor ();
@ -2958,34 +2978,38 @@ static void Tst_ListOneOrMoreQuestionsForEdition (unsigned long NumRows,
}
fprintf (Gbl.F.Out,"</td>");
/* Write stem (row[4]), media data (row[6], row[7], row[8], row[9]),
feedback (row[5]) and answers */
/* Write stem (row[4]) */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EDI");
Med_GetMediaDataFromRow (row[6],row[7],row[8],row[9],&Gbl.Test.Media);
/***** Get and show media (row[6]) *****/
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
Med_ShowMedia (&Gbl.Test.Media,
"TEST_IMG_EDIT_LIST_STEM_CONTAINER",
"TEST_IMG_EDIT_LIST_STEM");
/* Write feedback (row[5]) and answers */
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT");
Tst_WriteAnswersEdit (Gbl.Test.QstCod);
fprintf (Gbl.F.Out,"</td>");
/* Get number of hits
(number of times that the question has been answered,
including blank answers) (row[10]) */
if (sscanf (row[10],"%lu",&NumHitsThisQst) != 1)
including blank answers) (row[7]) */
if (sscanf (row[7],"%lu",&NumHitsThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits to a question.");
/* Get number of hits not blank
(number of times that the question has been answered
with a not blank answer) (row[11]) */
if (sscanf (row[11],"%lu",&NumHitsNotBlankThisQst) != 1)
with a not blank answer) (row[8]) */
if (sscanf (row[8],"%lu",&NumHitsNotBlankThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question.");
/* Get the acumulated score of the question (row[12]) */
/* Get the acumulated score of the question (row[9]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[12],"%lf",&TotalScoreThisQst) != 1)
if (sscanf (row[9],"%lf",&TotalScoreThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong score of a question.");
Str_SetDecimalPointToLocal (); // Return to local system
@ -3119,13 +3143,10 @@ static void Tst_ListOneOrMoreQuestionsForSelection (long GamCod,
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[ 6] MediaName
row[ 7] MediaType
row[ 8] MediaTitle
row[ 9] MediaURL
row[10] NumHits
row[11] NumHitsNotBlank
row[12] Score
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** Create test question *****/
Tst_QstConstructor ();
@ -3193,16 +3214,22 @@ static void Tst_ListOneOrMoreQuestionsForSelection (long GamCod,
fprintf (Gbl.F.Out,"</td>");
/* Write stem (row[4]), media data (row[6], row[7], row[8], row[9]),
feedback (row[5]) and answers */
/* Write stem (row[4]) */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EDI");
Med_GetMediaDataFromRow (row[6],row[7],row[8],row[9],&Gbl.Test.Media);
/***** Get and show media (row[6]) *****/
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
Med_ShowMedia (&Gbl.Test.Media,
"TEST_IMG_EDIT_LIST_STEM_CONTAINER",
"TEST_IMG_EDIT_LIST_STEM");
/* Write feedback (row[5]) */
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT");
/* Write answers */
Tst_WriteAnswersEdit (Gbl.Test.QstCod);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
@ -3255,11 +3282,8 @@ unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle)
"SELECT AnsInd," // row[0]
"Answer," // row[1]
"Feedback," // row[2]
"MediaName," // row[3]
"MediaType," // row[4]
"MediaTitle," // row[5]
"MediaURL," // row[6]
"Correct" // row[7]
"MedCod," // row[3]
"Correct" // row[4]
" FROM tst_answers WHERE QstCod=%ld ORDER BY %s",
QstCod,
Shuffle ? "RAND(NOW())" :
@ -3292,11 +3316,8 @@ static void Tst_WriteAnswersEdit (long QstCod)
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Write the answers *****/
switch (Gbl.Test.AnswerType)
@ -3362,15 +3383,16 @@ static void Tst_WriteAnswersEdit (long QstCod)
Feedback,LengthFeedback,false);
}
/* Get media data (row[3], row[4], row[5], row[6]) */
Med_GetMediaDataFromRow (row[3],row[4],row[5],row[6],
&Gbl.Test.Answer.Options[NumOpt].Media);
/* Get media (row[3]) */
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media);
/* Put an icon that indicates whether the answer is correct or wrong */
/* Put an icon that indicates whether the answer
is correct or wrong (row[4]) */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"BT%u\">",
Gbl.RowEvenOdd);
if (row[7][0] == 'Y')
if (row[4][0] == 'Y')
fprintf (Gbl.F.Out,"<img src=\"%s/check.svg\""
" alt=\"%s\" title=\"%s\""
" class=\"CONTEXT_ICO_16x16\" />",
@ -3467,11 +3489,8 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Write answer depending on type *****/
switch (Gbl.Test.AnswerType)
@ -3585,11 +3604,8 @@ static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Check if number of rows is correct *****/
Tst_CheckIfNumberOfAnswersIsOne ();
@ -3677,11 +3693,8 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,bool Shuffle
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Start table *****/
@ -3719,9 +3732,9 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,bool Shuffle
Gbl.Test.Answer.Options[NumOpt].Text,
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
/***** Get media data (row[3], row[4], row[5], row[6]) *****/
Med_GetMediaDataFromRow (row[3],row[4],row[5],row[6],
&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Get media (row[3]) *****/
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Write selectors and letter of this option *****/
fprintf (Gbl.F.Out,"<tr>"
@ -3803,11 +3816,8 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
@ -3842,12 +3852,12 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
}
/***** Get media data (row[3], row[4], row[5], row[6]) *****/
Med_GetMediaDataFromRow (row[3],row[4],row[5],row[6],
&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Get media (row[3]) *****/
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Assign correctness (row[7]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (row[7][0] == 'Y');
/***** Assign correctness (row[4]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (row[4][0] == 'Y');
}
/***** Get indexes for this question from string *****/
@ -4050,11 +4060,8 @@ static void Tst_WriteChoiceAnsViewGame (struct Game *Game,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Start table *****/
@ -4092,9 +4099,9 @@ static void Tst_WriteChoiceAnsViewGame (struct Game *Game,
Gbl.Test.Answer.Options[NumOpt].Text,
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
/***** Get media data (row[3], row[4], row[5], row[6]) *****/
Med_GetMediaDataFromRow (row[3],row[4],row[5],row[6],
&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Get media (row[3]) *****/
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Write letter of this option *****/
fprintf (Gbl.F.Out,"<tr>"
@ -4168,11 +4175,8 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Get text and correctness of answers for this question from database (one row per answer) *****/
for (NumOpt = 0;
@ -4206,8 +4210,8 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
}
/***** Assign correctness (row[7]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (row[7][0] == 'Y');
/***** Assign correctness (row[4]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (row[4][0] == 'Y');
}
/***** Header with the title of each column *****/
@ -4362,11 +4366,8 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Check if number of rows is correct *****/
Tst_CheckIfNumberOfAnswersIsOne ();
@ -4478,11 +4479,8 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Check if number of rows is correct *****/
if (Gbl.Test.Answer.NumOptions != 2)
@ -5010,7 +5008,11 @@ static void Tst_PutFormEditOneQst (char Stem[Cns_MAX_BYTES_TEXT + 1],
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/*
row[0] TagCod
row[1] TagTxt
row[2] TagHidden
*/
fprintf (Gbl.F.Out,"<option value=\"%s\"",row[1]);
if (!strcasecmp (Gbl.Test.Tags.Txt[NumTag],row[1]))
{
@ -5525,10 +5527,7 @@ static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1],
"Shuffle," // row[1]
"Stem," // row[2]
"Feedback," // row[3]
"MediaName," // row[4]
"MediaType," // row[5]
"MediaTitle," // row[6]
"MediaURL" // row[7]
"MedCod" // row[4]
" FROM tst_questions"
" WHERE QstCod=%ld AND CrsCod=%ld",
Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod);
@ -5551,8 +5550,9 @@ static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1],
Str_Copy (Feedback,row[3],
Cns_MAX_BYTES_TEXT);
/* Get media data (row[4], row[5], row[6], row[7]) */
Med_GetMediaDataFromRow (row[4],row[5],row[6],row[7],&Gbl.Test.Media);
/* Get media (row[4]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[4]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
@ -5577,11 +5577,8 @@ static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1],
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
@ -5623,12 +5620,12 @@ static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1],
Str_Copy (Gbl.Test.Answer.Options[NumOpt].Feedback,row[2],
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
/* Get media data (row[3], row[4], row[5], row[6]) */
Med_GetMediaDataFromRow (row[3],row[4],row[5],row[6],
&Gbl.Test.Answer.Options[NumOpt].Media);
/* Get media (row[3]) */
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media);
/* Get if this option is correct */
Gbl.Test.Answer.Options[NumOpt].Correct = (row[7][0] == 'Y');
/* Get if this option is correct (row[4]) */
Gbl.Test.Answer.Options[NumOpt].Correct = (row[4][0] == 'Y');
break;
default:
break;
@ -5639,7 +5636,7 @@ static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1],
}
/*****************************************************************************/
/***** Get possible image associated with a test question from database ******/
/***** Get possible media associated with a test question from database ******/
/*****************************************************************************/
// NumOpt < 0 ==> image associated to stem
// NumOpt >= 0 ==> image associated to answer
@ -5652,29 +5649,24 @@ static void Tst_GetMediaFromDB (int NumOpt,struct Media *Media)
/***** Query depending on NumOpt *****/
if (NumOpt < 0)
// Get image associated to stem
DB_QuerySELECT (&mysql_res,"can not get image name",
"SELECT MediaName," // row[0]
"MediaType," // row[1]
"MediaTitle," // row[2]
"MediaURL" // row[3]
DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT MedCod" // row[0]
" FROM tst_questions"
" WHERE QstCod=%ld AND CrsCod=%ld",
Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod);
else
// Get image associated to answer
DB_QuerySELECT (&mysql_res,"can not get image name",
"SELECT MediaName," // row[0]
"MediaType," // row[1]
"MediaTitle," // row[2]
"MediaURL" // row[3]
DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT MedCod" // row[0]
" FROM tst_answers"
" WHERE QstCod=%ld AND AnsInd=%u",
Gbl.Test.QstCod,(unsigned) NumOpt);
row = mysql_fetch_row (mysql_res);
/***** Get media data (row[0], row[1], row[2], row[3]) *****/
Med_GetMediaDataFromRow (row[0],row[1],row[2],row[3],Media);
/***** Get media (row[0]) *****/
Media->MedCod = Str_ConvertStrCodToLongCod (row[0]);
Med_GetMediaDataByCod (Media);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -6152,11 +6144,18 @@ static void Tst_MoveMediaToDefinitiveDirectories (void)
and moved to the definitive directory) */
Tst_RemoveMedFileFromStemOfQst (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Test.QstCod);
Gbl.Test.Media.MedCod = -1L;
if (Gbl.Test.Media.Action == Med_ACTION_NEW_MEDIA && // New media
Gbl.Test.Media.Status == Med_PROCESSED) // The new media received has been processed
{
/* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Gbl.Test.Media);
/* Store media in database */
if (Gbl.Test.Media.Status == Med_MOVED)
Med_StoreMediaInDB (&Gbl.Test.Media); // Set Gbl.Test.Media.MedCod
}
/****** Move images associated to answers *****/
if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE ||
Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE)
@ -6171,10 +6170,17 @@ static void Tst_MoveMediaToDefinitiveDirectories (void)
and moved to the definitive directory) */
Tst_RemoveMedFileFromAnsOfQst (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Test.QstCod,NumOpt);
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = -1L;
if (Gbl.Test.Answer.Options[NumOpt].Media.Action == Med_ACTION_NEW_MEDIA && // New media
Gbl.Test.Answer.Options[NumOpt].Media.Status == Med_PROCESSED) // The new media received has been processed
{
/* Move processed media to definitive directory */
Med_MoveMediaToDefinitiveDir (&Gbl.Test.Answer.Options[NumOpt].Media);
/* Store media in database */
if (Gbl.Test.Media.Status == Med_MOVED)
Med_StoreMediaInDB (&Gbl.Test.Answer.Options[NumOpt].Media); // Set Gbl.Test.Answer.Options[NumOpt].Media.MedCod
}
}
}
@ -6506,13 +6512,11 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
DB_QueryINSERTandReturnCode ("can not create question",
"INSERT INTO tst_questions"
" (CrsCod,EditTime,AnsType,Shuffle,"
"Stem,Feedback,"
"MediaName,MediaType,MediaTitle,MediaURL,"
"Stem,Feedback,MedCod,"
"NumHits,Score)"
" VALUES"
" (%ld,NOW(),'%s','%c',"
"'%s','%s',"
"'%s','%s','%s','%s',"
"'%s','%s',%ld,"
"0,0)",
Gbl.CurrentCrs.Crs.CrsCod,
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
@ -6520,14 +6524,7 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
'N',
Gbl.Test.Stem.Text,
Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "",
Gbl.Test.Media.Name,
Med_GetStringTypeForDB (Gbl.Test.Media.Type),
Gbl.Test.Media.Title ? Gbl.Test.Media.Title : "",
Gbl.Test.Media.URL ? Gbl.Test.Media.URL : "");
/* Update media status */
if (Gbl.Test.Media.Type != Med_TYPE_NONE)
Gbl.Test.Media.Status = Med_STORED_IN_DB;
Gbl.Test.Media.MedCod);
}
else // It's an existing question
{
@ -6536,24 +6533,16 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
DB_QueryUPDATE ("can not update question",
"UPDATE tst_questions"
" SET EditTime=NOW(),AnsType='%s',Shuffle='%c',"
"Stem='%s',Feedback='%s',"
"MediaName='%s',MediaType='%s',MediaTitle='%s',MediaURL='%s'"
"Stem='%s',Feedback='%s',MedCod=%ld"
" WHERE QstCod=%ld AND CrsCod=%ld",
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
Gbl.Test.Shuffle ? 'Y' :
'N',
Gbl.Test.Stem.Text,
Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "",
Gbl.Test.Media.Name,
Med_GetStringTypeForDB (Gbl.Test.Media.Type),
Gbl.Test.Media.Title ? Gbl.Test.Media.Title : "",
Gbl.Test.Media.URL ? Gbl.Test.Media.URL : "",
Gbl.Test.Media.MedCod,
Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod);
/* Update media status */
if (Gbl.Test.Media.Type != Med_TYPE_NONE)
Gbl.Test.Media.Status = Med_STORED_IN_DB;
/* Remove answers and tags from this test question */
Tst_RemAnsFromQst ();
Tst_RemTagsFromQst ();
@ -6599,32 +6588,20 @@ static void Tst_InsertTagsIntoDB (void)
static void Tst_InsertAnswersIntoDB (void)
{
char *Query = NULL;
unsigned NumOpt;
unsigned i;
/***** Allocate space for query *****/
if ((Query = (char *) malloc (256 +
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK * 2 +
Med_BYTES_NAME +
Med_MAX_BYTES_TITLE +
Cns_MAX_BYTES_WWW)) == NULL)
Lay_NotEnoughMemoryExit ();
/***** Insert answers in the answers table *****/
switch (Gbl.Test.AnswerType)
{
case Tst_ANS_INT:
DB_QueryINSERT ("can not create answer",
"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,"
"MediaName,MediaType,MediaTitle,MediaURL,Correct)"
" (QstCod,AnsInd,Answer,Feedback,MedCod,Correct)"
" VALUES"
" (%ld,0,%ld,'',"
"'','%s','','','Y')",
" (%ld,0,%ld,'',-1,'Y')",
Gbl.Test.QstCod,
Gbl.Test.Answer.Integer,
Med_GetStringTypeForDB (Med_TYPE_NONE));
Gbl.Test.Answer.Integer);
break;
case Tst_ANS_FLOAT:
Str_SetDecimalPointToUS (); // To print the floating point as a dot
@ -6633,27 +6610,21 @@ static void Tst_InsertAnswersIntoDB (void)
i++)
DB_QueryINSERT ("can not create answer",
"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,"
"MediaName,MediaType,MediaTitle,MediaURL,Correct)"
" (QstCod,AnsInd,Answer,Feedback,MedCod,Correct)"
" VALUES"
" (%ld,%u,'%lg','',"
"'','%s','','','Y')",
" (%ld,%u,'%lg','',-1,'Y')",
Gbl.Test.QstCod,i,
Gbl.Test.Answer.FloatingPoint[i],
Med_GetStringTypeForDB (Med_TYPE_NONE));
Gbl.Test.Answer.FloatingPoint[i]);
Str_SetDecimalPointToLocal (); // Return to local system
break;
case Tst_ANS_TRUE_FALSE:
DB_QueryINSERT ("can not create answer",
"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,"
"MediaName,Mediatype,MediaTitle,MediaURL,Correct)"
" (QstCod,AnsInd,Answer,Feedback,MedCod,Correct)"
" VALUES"
" (%ld,0,'%c','',"
"'','%s','','','Y')",
" (%ld,0,'%c','',-1,'Y')",
Gbl.Test.QstCod,
Gbl.Test.Answer.TF,
Med_GetStringTypeForDB (Med_TYPE_NONE));
Gbl.Test.Answer.TF);
break;
case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE:
@ -6665,18 +6636,13 @@ static void Tst_InsertAnswersIntoDB (void)
{
DB_QueryINSERT ("can not create answer",
"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,"
"MediaName,MediaType,MediaTitle,MediaURL,Correct)"
" (QstCod,AnsInd,Answer,Feedback,MedCod,Correct)"
" VALUES"
" (%ld,%u,'%s','%s',"
"'%s','%s','%s','%s','%c')",
" (%ld,%u,'%s','%s',%ld,'%c')",
Gbl.Test.QstCod,NumOpt,
Gbl.Test.Answer.Options[NumOpt].Text,
Gbl.Test.Answer.Options[NumOpt].Feedback ? Gbl.Test.Answer.Options[NumOpt].Feedback : "",
Gbl.Test.Answer.Options[NumOpt].Media.Name,
Med_GetStringTypeForDB (Gbl.Test.Answer.Options[NumOpt].Media.Type),
Gbl.Test.Answer.Options[NumOpt].Media.Title ? Gbl.Test.Answer.Options[NumOpt].Media.Title : "",
Gbl.Test.Answer.Options[NumOpt].Media.URL ? Gbl.Test.Answer.Options[NumOpt].Media.URL : "",
Gbl.Test.Answer.Options[NumOpt].Media.MedCod,
Gbl.Test.Answer.Options[NumOpt].Correct ? 'Y' :
'N');
@ -6688,9 +6654,6 @@ static void Tst_InsertAnswersIntoDB (void)
default:
break;
}
/***** Free space allocated for query *****/
free ((void *) Query);
}
/*****************************************************************************/
@ -6745,13 +6708,12 @@ static void Tst_RemoveMedFileFromStemOfQst (long CrsCod,long QstCod)
/***** Get names of media files associated to stems of test questions from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get image",
"SELECT MediaName," // row[0]
"MediaType" // row[1]
"SELECT MedCod" // row[0]
" FROM tst_questions"
" WHERE QstCod=%ld AND CrsCod=%ld",
QstCod,CrsCod))
/***** Remove media file *****/
Med_RemoveMediaFilesFromRow (mysql_res);
Med_RemoveMediaFromRow (mysql_res);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -6769,15 +6731,14 @@ static void Tst_RemoveAllMedFilesFromStemOfAllQstsInCrs (long CrsCod)
/***** Get names of images associated to stems of test questions from database *****/
NumMedia =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get images",
"SELECT MediaName," // row[0]
"MediaType" // row[1]
(unsigned) DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT MedCod" // row[0]
" FROM tst_questions"
" WHERE CrsCod=%ld",
CrsCod);
/***** Go over result removing media files *****/
Med_RemoveMediaFilesFromAllRows (NumMedia,mysql_res);
Med_RemoveMediaFromAllRows (NumMedia,mysql_res);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -6793,8 +6754,7 @@ static void Tst_RemoveMedFileFromAnsOfQst (long CrsCod,long QstCod,unsigned AnsI
/***** Get names of media files associated to answers of test questions from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get images",
"SELECT tst_answers.MediaName," // row[0]
"tst_answers.MediaType" // row[1]
"SELECT tst_answers.MedCod" // row[0]
" FROM tst_questions,tst_answers"
" WHERE tst_questions.CrsCod=%ld"// Extra check
" AND tst_questions.QstCod=%ld" // Extra check
@ -6803,7 +6763,7 @@ static void Tst_RemoveMedFileFromAnsOfQst (long CrsCod,long QstCod,unsigned AnsI
" AND tst_answers.AnsInd=%u",
CrsCod,QstCod,QstCod,AnsInd))
/***** Remove media file *****/
Med_RemoveMediaFilesFromRow (mysql_res);
Med_RemoveMediaFromRow (mysql_res);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -6820,9 +6780,8 @@ static void Tst_RemoveAllMedFilesFromAnsOfQst (long CrsCod,long QstCod)
/***** Get names of media files associated to answers of test questions from database *****/
NumMedia =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get images",
"SELECT tst_answers.MediaName," // row[0]
"tst_answers.MediaType" // row[1]
(unsigned) DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT tst_answers.MedCod" // row[0]
" FROM tst_questions,tst_answers"
" WHERE tst_questions.CrsCod=%ld" // Extra check
" AND tst_questions.QstCod=%ld" // Extra check
@ -6831,7 +6790,7 @@ static void Tst_RemoveAllMedFilesFromAnsOfQst (long CrsCod,long QstCod)
CrsCod,QstCod,QstCod);
/***** Go over result removing media files *****/
Med_RemoveMediaFilesFromAllRows (NumMedia,mysql_res);
Med_RemoveMediaFromAllRows (NumMedia,mysql_res);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -6849,16 +6808,15 @@ static void Tst_RemoveAllMedFilesFromAnsOfAllQstsInCrs (long CrsCod)
/***** Get names of media files associated to answers of test questions from database *****/
NumMedia =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get images",
"SELECT tst_answers.MediaName," // row[0]
"tst_answers.MediaType" // row[1]
(unsigned) DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT tst_answers.MedCod" // row[0]
" FROM tst_questions,tst_answers"
" WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod=tst_answers.QstCod",
CrsCod);
/***** Go over result removing media files *****/
Med_RemoveMediaFilesFromAllRows (NumMedia,mysql_res);
Med_RemoveMediaFromAllRows (NumMedia,mysql_res);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -7720,9 +7678,12 @@ static void Tst_ShowTestResults (struct UsrData *UsrDat)
/***** Make database query *****/
NumExams =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get test exams of a user",
"SELECT TstCod,AllowTeachers,"
"UNIX_TIMESTAMP(TstTime),"
"NumQsts,NumQstsNotBlank,Score"
"SELECT TstCod," // row[0]
"AllowTeachers," // row[1]
"UNIX_TIMESTAMP(TstTime)," // row[2]
"NumQsts," // row[3]
"NumQstsNotBlank," // row[4]
"Score" // row[5]
" FROM tst_exams"
" WHERE CrsCod=%ld AND UsrCod=%ld"
" AND TstTime>=FROM_UNIXTIME(%ld)"
@ -8309,13 +8270,10 @@ static void Tst_ShowTestResult (time_t TstTimeUTC)
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[ 6] MediaName
row[ 7] MediaType
row[ 8] MediaTitle
row[ 9] MediaURL
row[10] NumHits
row[11] NumHitsNotBlank
row[12] Score
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** If this question has been edited later than test time
==> don't show question ****/
@ -8382,9 +8340,12 @@ static void Tst_GetTestResultDataByTstCod (long TstCod,time_t *TstTimeUTC,
/***** Make database query *****/
if (DB_QuerySELECT (&mysql_res,"can not get data"
" of a test result of a user",
"SELECT UsrCod,AllowTeachers,"
"UNIX_TIMESTAMP(TstTime),"
"NumQsts,NumQstsNotBlank,Score"
"SELECT UsrCod," // row[0]
"AllowTeachers," // row[1]
"UNIX_TIMESTAMP(TstTime)," // row[2]
"NumQsts," // row[3]
"NumQstsNotBlank," // row[4]
"Score" // row[5]
" FROM tst_exams"
" WHERE TstCod=%ld AND CrsCod=%ld",
TstCod,
@ -8463,7 +8424,9 @@ static void Tst_GetTestResultQuestionsFromDB (long TstCod)
Gbl.Test.NumQsts =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get questions"
" of a test result",
"SELECT QstCod,Indexes,Answers"
"SELECT QstCod," // row[0]
"Indexes," // row[1]
"Answers" // row[2]
" FROM tst_exam_questions"
" WHERE TstCod=%ld ORDER BY QstInd",
TstCod);

View File

@ -143,11 +143,6 @@ void Tst_ShowFormAskTst (void);
void Tst_ShowNewTest (void);
void Tst_AssessTest (void);
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct UsrData *UsrDat,
struct Game *Game,
unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank);
void Tst_WriteQstStem (const char *Stem,const char *ClassStem);
void Tst_WriteQstFeedback (const char *Feedback,const char *ClassFeedback);

View File

@ -200,13 +200,10 @@ void TsI_CreateXML (unsigned long NumRows,MYSQL_RES *mysql_res)
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[ 6] MediaName
row[ 7] MediaType
row[ 8] MediaTitle
row[ 9] MediaURL
row[10] NumHits
row[11] NumHitsNotBlank
row[12] Score
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/* row[0] holds the code of the question */
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
@ -313,12 +310,10 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod)
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MediaName
row[4] MediaType
row[5] MediaTitle
row[6] MediaURL
row[7] Correct
row[3] MedCod
row[4] Correct
*/
/***** Write the answers *****/
switch (Gbl.Test.AnswerType)
{

View File

@ -98,7 +98,7 @@ struct TL_Note
TL_NoteType_t NoteType;
long UsrCod;
long HieCod; // Hierarchy code (institution/centre/degree/course)
long Cod; // Code of file, forum post, notice,...
long Cod; // Code of file, forum post, notice, timeline post...
bool Unavailable; // File, forum post, notice,... unavailable (removed)
time_t DateTimeUTC;
unsigned NumShared; // Number of times (users) this note has been shared
@ -234,8 +234,8 @@ static void TL_UnfavComment (struct TL_Comment *SocCom);
static void TL_RequestRemovalNote (void);
static void TL_PutParamsRemoveNote (void);
static void TL_RemoveNote (void);
static void TL_RemoveImgFileFromPost (long PstCod);
static void TL_RemoveANoteFromDB (struct TL_Note *SocNot);
static void TL_RemoveMediaFromPost (long PstCod);
static void TL_RemoveNoteMediaAndDBEntries (struct TL_Note *SocNot);
static long TL_GetNotCodOfPublication (long PubCod);
static long TL_GetPubCodOfOriginalNote (long NotCod);
@ -243,8 +243,7 @@ static long TL_GetPubCodOfOriginalNote (long NotCod);
static void TL_RequestRemovalComment (void);
static void TL_PutParamsRemoveCommment (void);
static void TL_RemoveComment (void);
static void TL_RemoveImgFileFromComment (long PubCod);
static void TL_RemoveACommentFromDB (struct TL_Comment *SocCom);
static void TL_RemoveCommentMediaAndDBEntries (long PubCod);
static bool TL_CheckIfNoteIsSharedByUsr (long NotCod,long UsrCod);
static bool TL_CheckIfNoteIsFavedByUsr (long NotCod,long UsrCod);
@ -1829,10 +1828,7 @@ static void TL_GetAndWritePost (long PstCod)
NumRows = DB_QuerySELECT (&mysql_res,"can not get the content"
" of a post",
"SELECT Content," // row[0]
"MediaName," // row[1]
"MediaType," // row[2]
"MediaTitle," // row[3]
"MediaURL" // row[4]
"MedCod" // row[1]
" FROM social_posts"
" WHERE PstCod=%ld",
PstCod);
@ -1846,8 +1842,9 @@ static void TL_GetAndWritePost (long PstCod)
Str_Copy (Content,row[0],
Cns_MAX_BYTES_LONG_TEXT);
/****** Get media data (row[1], row[2], row[3], row[4]) *****/
Med_GetMediaDataFromRow (row[1],row[2],row[3],row[4],&Media);
/***** Get media (row[1]) *****/
Media.MedCod = Str_ConvertStrCodToLongCod (row[1]);
Med_GetMediaDataByCod (&Media);
}
else
Content[0] = '\0';
@ -2477,26 +2474,28 @@ static long TL_ReceivePost (void)
Media.Status == Med_PROCESSED) // A media is attached
{
/***** Check if media is received and processed *****/
Media.MedCod = -1L;
if (Media.Action == Med_ACTION_NEW_MEDIA && // New media
Media.Status == Med_PROCESSED) // The new media received has been processed
{
/* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Media);
/* Store media in database */
if (Media.Status == Med_MOVED)
Med_StoreMediaInDB (&Media); // Set Media.MedCod
}
/***** Publish *****/
/* Insert post content in the database */
PstCod =
DB_QueryINSERTandReturnCode ("can not create post",
"INSERT INTO social_posts"
" (Content,"
"MediaName,MediaType,MediaTitle,MediaURL)"
" (Content,MedCod)"
" VALUES"
" ('%s',"
"'%s','%s','%s','%s')",
" ('%s',%ld)",
Content,
Media.Name,
Med_GetStringTypeForDB (Media.Type),
Media.Title ? Media.Title : "",
Media.URL ? Media.URL : "");
Media.MedCod);
/* Insert post in notes */
TL_StoreAndPublishNote (TL_NOTE_POST,PstCod,&SocPub);
@ -2637,10 +2636,7 @@ static void TL_WriteCommentsInNote (const struct TL_Note *SocNot)
"UNIX_TIMESTAMP("
"social_pubs.TimePublish)," // row[3]
"social_comments.Content," // row[4]
"social_comments.MediaName," // row[5]
"social_comments.MediaType," // row[6]
"social_comments.MediaTitle," // row[7]
"social_comments.MediaURL" // row[8]
"social_comments.MedCod" // row[5]
" FROM social_pubs,social_comments"
" WHERE social_pubs.NotCod=%ld"
" AND social_pubs.PubType=%u"
@ -3204,11 +3200,18 @@ static long TL_ReceiveComment (void)
Media.Status == Med_PROCESSED) // A media is attached
{
/***** Check if media is received and processed *****/
Media.MedCod = -1L;
if (Media.Action == Med_ACTION_NEW_MEDIA && // New media
Media.Status == Med_PROCESSED) // The new media received has been processed
{
/* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Media);
/* Store media in database */
if (Media.Status == Med_MOVED)
Med_StoreMediaInDB (&Media); // Set Media.MedCod
}
/***** Publish *****/
/* Insert into publications */
SocPub.NotCod = SocNot.NotCod;
@ -3219,17 +3222,12 @@ static long TL_ReceiveComment (void)
/* Insert comment content in the database */
DB_QueryINSERT ("can not store comment content",
"INSERT INTO social_comments"
" (PubCod,Content,"
"MediaName,MediaType,MediaTitle,MediaURL)"
" (PubCod,Content,MedCod)"
" VALUES"
" (%ld,'%s',"
"'%s','%s','%s','%s')",
" (%ld,'%s',%ld)",
SocPub.PubCod,
Content,
Media.Name,
Med_GetStringTypeForDB (Media.Type),
Media.Title ? Media.Title : "",
Media.URL ? Media.URL : "");
Media.MedCod);
/***** Store notifications about the new comment *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_COMMENT,SocPub.PubCod);
@ -3856,12 +3854,11 @@ static void TL_RemoveNote (void)
ItsMe = Usr_ItsMe (SocNot.UsrCod);
if (ItsMe) // I am the author of this note
{
if (SocNot.NoteType == TL_NOTE_POST)
/***** Remove image file associated to post *****/
TL_RemoveImgFileFromPost (SocNot.Cod);
/***** Delete note from database *****/
TL_RemoveANoteFromDB (&SocNot);
TL_RemoveNoteMediaAndDBEntries (&SocNot);
/***** Reset note *****/
TL_ResetNote (&SocNot);
/***** Message of success *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_TIMELINE_Post_removed);
@ -3875,19 +3872,18 @@ static void TL_RemoveNote (void)
/***************** Remove one file associated to a post **********************/
/*****************************************************************************/
static void TL_RemoveImgFileFromPost (long PstCod)
static void TL_RemoveMediaFromPost (long PstCod)
{
MYSQL_RES *mysql_res;
/***** Get name of image associated to a post from database *****/
/***** Get name of media associated to a post from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get image",
"SELECT MediaName," // row[0]
"MediaType" // row[1]
"SELECT MedCod" // row[0]
" FROM social_posts"
" WHERE PstCod=%ld",
PstCod))
/***** Remove media file *****/
Med_RemoveMediaFilesFromRow (mysql_res);
Med_RemoveMediaFromRow (mysql_res);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -3897,7 +3893,7 @@ static void TL_RemoveImgFileFromPost (long PstCod)
/*********************** Remove a note from database *************************/
/*****************************************************************************/
static void TL_RemoveANoteFromDB (struct TL_Note *SocNot)
static void TL_RemoveNoteMediaAndDBEntries (struct TL_Note *SocNot)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@ -3905,18 +3901,7 @@ static void TL_RemoveANoteFromDB (struct TL_Note *SocNot)
unsigned long NumComments;
unsigned long NumCom;
/***** Mark possible notifications on the publications
of this note as removed *****/
/* Mark notifications of the original note as removed */
PubCod = TL_GetPubCodOfOriginalNote (SocNot->NotCod);
if (PubCod > 0)
{
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_COMMENT,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_FAV ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_SHARE ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_MENTION,PubCod);
}
/***** Remove comments associated to this note *****/
/* Get comments of this note */
NumComments = DB_QuerySELECT (&mysql_res,"can not get comments",
"SELECT PubCod"
@ -3934,43 +3919,50 @@ static void TL_RemoveANoteFromDB (struct TL_Note *SocNot)
row = mysql_fetch_row (mysql_res);
PubCod = Str_ConvertStrCodToLongCod (row[0]);
/* Mark notifications as removed */
if (PubCod > 0)
{
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_COMMENT,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_FAV ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_MENTION,PubCod);
}
/* Remove media associated to comment
and delete comment from database */
TL_RemoveCommentMediaAndDBEntries (PubCod);
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
/***** Remove favs *****/
/* Remove favs for all comments in this note */
DB_QueryDELETE ("can not remove favs for note",
"DELETE FROM social_comments_fav"
" USING social_pubs,social_comments_fav"
" WHERE social_pubs.NotCod=%ld"
" AND social_pubs.PubType=%u"
" AND social_pubs.PubCod=social_comments_fav.PubCod",
SocNot->NotCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
/***** Remove media associated to post *****/
if (SocNot->NoteType == TL_NOTE_POST)
{
TL_RemoveMediaFromPost (SocNot->Cod);
MYSQL_RES *mysql_res;
/* Remove favs for this note */
/* Get name of media associated to a post from database */
if (DB_QuerySELECT (&mysql_res,"can not get image",
"SELECT MedCod" // row[0]
" FROM social_posts"
" WHERE PstCod=%ld",
SocNot->Cod))
/* Remove media */
Med_RemoveMediaFromRow (mysql_res);
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
}
/***** Mark possible notifications on the publications
of this note as removed *****/
/* Mark notifications of the original note as removed */
PubCod = TL_GetPubCodOfOriginalNote (SocNot->NotCod);
if (PubCod > 0)
{
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_FAV ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_SHARE ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_MENTION,PubCod);
}
/***** Remove favs for this note *****/
DB_QueryDELETE ("can not remove favs for note",
"DELETE FROM social_notes_fav"
" WHERE NotCod=%ld",
SocNot->NotCod);
/***** Remove content of the comments of this note *****/
DB_QueryDELETE ("can not remove comments",
"DELETE FROM social_comments"
" USING social_pubs,social_comments"
" WHERE social_pubs.NotCod=%ld"
" AND social_pubs.PubType=%u"
" AND social_pubs.PubCod=social_comments.PubCod",
SocNot->NotCod,(unsigned) TL_PUB_COMMENT_TO_NOTE);
/***** Remove all the publications of this note *****/
DB_QueryDELETE ("can not remove a publication",
"DELETE FROM social_pubs"
@ -3991,9 +3983,6 @@ static void TL_RemoveANoteFromDB (struct TL_Note *SocNot)
"DELETE FROM social_posts"
" WHERE PstCod=%ld",
SocNot->Cod);
/***** Reset note *****/
TL_ResetNote (SocNot);
}
/*****************************************************************************/
@ -4198,11 +4187,12 @@ static void TL_RemoveComment (void)
ItsMe = Usr_ItsMe (SocCom.UsrCod);
if (ItsMe) // I am the author of this comment
{
/***** Remove image file associated to post *****/
TL_RemoveImgFileFromComment (SocCom.PubCod);
/***** Remove media associated to comment
and delete comment from database *****/
TL_RemoveCommentMediaAndDBEntries (SocCom.PubCod);
/***** Delete comment from database *****/
TL_RemoveACommentFromDB (&SocCom);
/***** Reset fields of comment *****/
TL_ResetComment (&SocCom);
/***** Message of success *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_Comment_removed);
@ -4216,49 +4206,42 @@ static void TL_RemoveComment (void)
}
/*****************************************************************************/
/**************** Remove one file associated to a comment ********************/
/*************** Remove comment media and database entries *******************/
/*****************************************************************************/
static void TL_RemoveImgFileFromComment (long PubCod)
static void TL_RemoveCommentMediaAndDBEntries (long PubCod)
{
MYSQL_RES *mysql_res;
/***** Get name of media associated to a post from database *****/
/***** Remove media associated to comment *****/
/* Get name of media associated to a comment from database */
if (DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT MediaName," // row[0]
"MediaType" // row[1]
"SELECT MedCod" // row[0]
" FROM social_comments"
" WHERE PubCod=%ld",
PubCod))
/***** Remove media file *****/
Med_RemoveMediaFilesFromRow (mysql_res);
/* Remove media */
Med_RemoveMediaFromRow (mysql_res);
/***** Free structure that stores the query result *****/
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********************* Remove a comment from database ************************/
/*****************************************************************************/
static void TL_RemoveACommentFromDB (struct TL_Comment *SocCom)
{
/***** Mark possible notifications on this comment as removed *****/
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_COMMENT,SocCom->PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_FAV ,SocCom->PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_MENTION,SocCom->PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_COMMENT,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_FAV ,PubCod);
Ntf_MarkNotifAsRemoved (Ntf_EVENT_TIMELINE_MENTION,PubCod);
/***** Remove favs for this comment *****/
DB_QueryDELETE ("can not remove favs for comment",
"DELETE FROM social_comments_fav"
" WHERE PubCod=%ld",
SocCom->PubCod);
PubCod);
/***** Remove content of this comment *****/
DB_QueryDELETE ("can not remove a comment",
"DELETE FROM social_comments"
" WHERE PubCod=%ld",
SocCom->PubCod);
PubCod);
/***** Remove this comment *****/
DB_QueryDELETE ("can not remove a comment",
@ -4266,12 +4249,9 @@ static void TL_RemoveACommentFromDB (struct TL_Comment *SocCom)
" WHERE PubCod=%ld"
" AND PublisherCod=%ld" // Extra check: I am the author
" AND PubType=%u", // Extra check: it's a comment
SocCom->PubCod,
PubCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
(unsigned) TL_PUB_COMMENT_TO_NOTE);
/***** Reset comment *****/
TL_ResetComment (SocCom);
}
/*****************************************************************************/
@ -4693,10 +4673,7 @@ static void TL_GetDataOfCommByCod (struct TL_Comment *SocCom)
"social_pubs.NotCod," // row[2]
"UNIX_TIMESTAMP(social_pubs.TimePublish)," // row[3]
"social_comments.Content," // row[4]
"social_comments.MediaName," // row[5]
"social_comments.MediaType," // row[6]
"social_comments.MediaTitle," // row[7]
"social_comments.MediaURL" // row[8]
"social_comments.MedCod" // row[5]
" FROM social_pubs,social_comments"
" WHERE social_pubs.PubCod=%ld"
" AND social_pubs.PubType=%u"
@ -4826,10 +4803,7 @@ static void TL_GetDataOfCommentFromRow (MYSQL_ROW row,struct TL_Comment *SocCom)
row[2]: NotCod
row[3]: TimePublish
row[4]: Content
row[5]: MediaName
row[6]: MediaType
row[7]: MediaTitle
row[8]: MediaURL
row[5]: MedCod
*/
/***** Get code of comment (row[0]) *****/
SocCom->PubCod = Str_ConvertStrCodToLongCod (row[0]);
@ -4850,8 +4824,9 @@ static void TL_GetDataOfCommentFromRow (MYSQL_ROW row,struct TL_Comment *SocCom)
/***** Get number of times this comment has been favourited *****/
TL_GetNumTimesACommHasBeenFav (SocCom);
/****** Get media data (row[5], row[6], row[7], row[8]) *****/
Med_GetMediaDataFromRow (row[5],row[6],row[7],row[8],&SocCom->Media);
/***** Get media (row[5]) *****/
SocCom->Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&SocCom->Media);
}
/*****************************************************************************/

View File

@ -3446,13 +3446,10 @@ static int Svc_SendMessageToUsr (long OriginalMsgCod,
NewMsgCod =
DB_QueryINSERTandReturnCode ("can not create message",
"INSERT INTO msg_content"
" (Subject,Content,"
"MediaName,MediaType,MediaTitle,MediaURL)"
" (Subject,Content,MedCod)"
" VALUES"
" ('%s','%s',"
"'','%s','','')",
Subject,Content,
Med_GetStringTypeForDB (Med_TYPE_NONE));
" ('%s','%s',-1)",
Subject,Content);
/* Insert message in sent messages */
DB_QueryINSERT ("can not create message",