Browse Source

Adding nanogong question type in exercises see BT#3593

Julio Montoya 13 years ago
parent
commit
528cfd47c2

+ 21 - 0
main/css/base.css

@@ -4303,3 +4303,24 @@ a:active{
     margin-right: auto;
     width: 120px;
 }
+
+/* Nanogong - exercise player*/
+
+.nanogong_player_container {
+	width:370px;
+	margin: 0 auto;
+	
+}
+
+.nanogong_player {    
+    float:left;
+}
+
+.action_player {
+    float:right;
+    width:120px;	
+}
+
+.audio_preview_container {
+    margin-left: 50px;	
+}

+ 7 - 0
main/exercice/answer_admin.inc.php

@@ -85,6 +85,13 @@ if($modifyIn)
         $free_comment=$comment;
         $weighting=unserialize($weighting);
 
+	}
+	elseif($answerType == ORAL_EXPRESSION )
+	{
+		$reponse=unserialize($reponse);
+		$comment=unserialize($comment);
+		$free_comment=$comment;
+		$weighting=unserialize($weighting);
 	}
 	elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER || $answerType == HOT_SPOT_DELINEATION)
     {

+ 67 - 2
main/exercice/exercise.class.php

@@ -1867,9 +1867,33 @@ class Exercise {
 		if ($debug) error_log('$answerType : '.$answerType);
 
 
-		if ($answerType == FREE_ANSWER) {
+		if ($answerType == FREE_ANSWER || $answerType == ORAL_EXPRESSION) {
 			$nbrAnswers = 1;
 		}
+		
+		$nano = null;
+		
+		if ($answerType == ORAL_EXPRESSION) {
+			require_once api_get_path(LIBRARY_PATH).'nanogong.lib.php';
+			$exe_info = get_exercise_results_by_attempt($exeId);
+			$exe_info = $exe_info[$exeId];		
+				
+			$params = array();
+			$params['course_id'] 	= api_get_course_int_id();
+			$params['session_id'] 	= api_get_session_id();
+			$params['user_id'] 		= isset($exe_info['exe_user_id'])? $exe_info['exe_user_id'] : api_get_user_id();			
+			$params['exercise_id']  = isset($exe_info['exe_exo_id'])? $exe_info['exe_exo_id'] : $this->id;
+			$params['question_id'] 	= $questionId;
+			$params['exe_id'] 		= isset($exe_info['exe_id']) ? $exe_info['exe_id'] : $exeId;
+						
+			$nano = new Nanogong($params);
+			
+			//probably this attempt came in an exercise all question by page			
+			if ($feedback_type == 0) {
+				$nano->replace_with_real_exe($exeId);
+			}			
+		}
+		
 		$user_answer = '';
 
 		// Get answer list for matching
@@ -2012,7 +2036,6 @@ class Exercise {
 							$real_answers[$answerId] = false;
 						}
 					}
-
 					break;
 				case MULTIPLE_ANSWER_COMBINATION:
 					if ($from_database) {
@@ -2218,6 +2241,31 @@ class Exercise {
 						}
 					}
 					break;
+				case ORAL_EXPRESSION :
+					if ($from_database) {
+						$query  = "SELECT answer, marks FROM ".$TBL_TRACK_ATTEMPT." WHERE exe_id = '".$exeId."' AND question_id= '".$questionId."'";
+						$resq   = Database::query($query);
+						$choice = Database::result($resq,0,'answer');
+						$choice = str_replace('\r\n', '', $choice);
+						$choice = stripslashes($choice);
+						$questionScore = Database::result($resq,0,"marks");
+						if ($questionScore==-1) {
+							$totalScore+=0;
+						} else {
+							$totalScore+=$questionScore;
+						}
+						$arrques[] = $questionName;
+						$arrans[]  = $choice;
+					} else {
+						$studentChoice = $choice;
+						if ($studentChoice) {
+							//Fixing negative puntation see #2193
+							$questionScore = 0;
+							$totalScore += 0;
+						}
+					}
+					break;						
+					
 					// for matching
 				case MATCHING :
 					if ($from_database) {
@@ -2384,6 +2432,13 @@ class Exercise {
 							if($origin != 'learnpath') {
 								ExerciseShowFunctions::display_free_answer($choice,0,0);
 							}
+						} elseif($answerType == ORAL_EXPRESSION) {
+							// to store the details of open questions in an array to be used in mail
+							$arrques[] = $questionName;
+							$arrans[]  = $choice;
+							if($origin != 'learnpath') {								
+								ExerciseShowFunctions::display_oral_expression_answer($choice, 0, 0, $nano);
+							}
 						} elseif($answerType == HOT_SPOT) {
 							if ($origin != 'learnpath') {
 								ExerciseShowFunctions::display_hotspot_answer($answerId, $answer, $studentChoice, $answerComment);
@@ -2593,6 +2648,12 @@ class Exercise {
                             </tr>
                             </table>';
 							break;
+						case ORAL_EXPRESSION:
+							echo '<tr>
+		                            <td valign="top">'.ExerciseShowFunctions::display_oral_expression_answer($choice, $exeId, $questionId, $nano).'</td>
+		                            </tr>
+		                            </table>';
+							break;
 						case HOT_SPOT:
 							ExerciseShowFunctions::display_hotspot_answer($answerId, $answer, $studentChoice, $answerComment);
 							break;
@@ -2999,6 +3060,10 @@ class Exercise {
 			} elseif ($answerType == FREE_ANSWER) {
 				$answer = $choice;
 				exercise_attempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
+			} elseif ($answerType == ORAL_EXPRESSION) {
+				$answer = $choice;				
+				exercise_attempt($questionScore, $answer, $quesId, $exeId, 0, $this->id, $nano);			
+				
 			} elseif ($answerType == UNIQUE_ANSWER || $answerType == UNIQUE_ANSWER_NO_OPTION) {
 				$answer = $choice;
 				exercise_attempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);

+ 37 - 1
main/exercice/exercise.lib.php

@@ -143,7 +143,43 @@ function showQuestion($questionId, $only_questions = false, $origin = false, $cu
             $s .= '<tr><td colspan="3">';
             $s .= $oFCKeditor->CreateHtml();
             $s .= '</td></tr>';
-		}  
+		} elseif ($answerType == ORAL_EXPRESSION) {
+			//Add nanog
+			if (api_get_setting('enable_nanogong') == 'true') {				
+				
+				require_once api_get_path(LIBRARY_PATH).'nanogong.lib.php';
+				
+				//@todo pass this as a parameter
+				global $exercise_stat_info, $exerciseId,$exe_id;
+				
+				if (!empty($exercise_stat_info)) {
+					$params = array(					
+						'exercise_id' 	=> $exercise_stat_info['exe_exo_id'],
+						'exe_id' 		=> $exercise_stat_info['exe_id'],
+						'question_id'   => $questionId
+					);				
+				} else {
+					$params = array(
+						'exercise_id' 	=> $exerciseId,
+						'exe_id' 		=> 'temp_exe',
+						'question_id'   => $questionId
+					);
+				}
+				
+				$nano = new Nanogong($params);
+				echo $nano->show_button();				
+			}
+			
+			$oFCKeditor = new FCKeditor("choice[".$questionId."]") ;			
+			$oFCKeditor->ToolbarSet = 'TestFreeAnswer';
+			$oFCKeditor->Width  = '100%';
+			$oFCKeditor->Height = '150';
+			$oFCKeditor->ToolbarStartExpanded = false;			
+			$oFCKeditor->Value	= '' ;
+			$s .= '<tr><td colspan="3">';
+			$s .= $oFCKeditor->CreateHtml();
+			$s .= '</td></tr>';
+		} 
     
 		// Now navigate through the possible answers, using the max number of
 		// answers for the question as a limiter

+ 7 - 2
main/exercice/exercise_show.php

@@ -318,6 +318,11 @@ foreach ($questionList as $questionId) {
         $question_result = $objExercise->manage_answer($id, $questionId, $choice,'exercise_show', array(), false, true, $show_results, $objExercise->selectPropagateNeg());            
         $questionScore   = $question_result['score'];
         $totalScore     += $question_result['score'];
+	} elseif ($answerType == ORAL_EXPRESSION) {
+		$answer = $str;
+		$question_result = $objExercise->manage_answer($id, $questionId, $choice,'exercise_show', array(), false, true, $show_results, $objExercise->selectPropagateNeg());
+		$questionScore   = $question_result['score'];
+		$totalScore     += $question_result['score'];
 	} elseif ($answerType == MATCHING) {            
         $question_result = $objExercise->manage_answer($id, $questionId, $choice,'exercise_show', array(), false, true, $show_results, $objExercise->selectPropagateNeg());            
         $questionScore   = $question_result['score'];
@@ -500,7 +505,7 @@ foreach ($questionList as $questionId) {
 			<br />
 			<a href="javascript://" onclick="showfck('<?php echo $name; ?>','<?php echo $marksname; ?>');">
 			<?php
-			if ($answerType == FREE_ANSWER) {
+			if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION))) {
 				echo get_lang('EditCommentsAndMarks');
 			} else {
 				if ($action=='edit') {
@@ -543,7 +548,7 @@ foreach ($questionList as $questionId) {
 		}
 		
 		if ($is_allowedToEdit) {
-			if ($answerType == FREE_ANSWER) {
+			if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION))) {
 				$marksname = "marksName".$questionId;
 				?>
 				<div id="<?php echo $marksname; ?>" style="display:none">

+ 1 - 0
main/exercice/export/qti/qti_classes.php

@@ -36,6 +36,7 @@ define('FIB',				3);
 define('MATCHING',			4);
 define('FREE_ANSWER', 		5);
 define('HOTSPOT',			6);
+define('ORAL_EXPRESSION', 		13);
 /**
  *
  * @package chamilo.exercise

+ 1 - 0
main/exercice/export/qti2/qti2_classes.php

@@ -20,6 +20,7 @@ define('FIB',				3);
 define('MATCHING',			4);
 define('FREE_ANSWER', 		5);
 define('HOTSPOT',			6);
+define('ORAL_EXPRESSION', 		13);
 
 if (!function_exists('mime_content_type')) {
 	require_once api_get_path(LIBRARY_PATH).'document.lib.php';

+ 1 - 0
main/exercice/export/qti2/qti2_export.php

@@ -21,6 +21,7 @@ define(MATCHING,		4);
 define(FREE_ANSWER,     5);
 define(HOT_SPOT, 		6);
 define(HOT_SPOT_ORDER, 	7);
+define('ORAL_EXPRESSION', 		13);
 /**
  * An IMS/QTI item. It corresponds to a single question.
  * This class allows export from Claroline to IMS/QTI2.0 XML format of a single question.

+ 1 - 0
main/exercice/export/scorm/scorm_classes.php

@@ -36,6 +36,7 @@ define('HOTSPOT',			6);
 define('HOT_SPOT_ORDER', 	7);
 define('HOT_SPOT_DELINEATION', 		8);
 define('MULTIPLE_ANSWER_COMBINATION', 	9);
+define('ORAL_EXPRESSION', 		13);
 
 
 /**

+ 1 - 0
main/exercice/export/scorm/scorm_export.php

@@ -21,6 +21,7 @@ define(MATCHING,		4);
 define(FREE_ANSWER,     5);
 define(HOT_SPOT, 		6);
 define(HOT_SPOT_ORDER, 	7);
+define('ORAL_EXPRESSION', 		13);
 /**
  * A SCORM item. It corresponds to a single question.
  * This class allows export from Dokeos SCORM 1.2 format of a single question.

+ 1 - 0
main/exercice/mark_free_answer.php

@@ -30,6 +30,7 @@ define('FILL_IN_BLANKS',	3);
 define('MATCHING',		4);
 define('FREE_ANSWER', 5);
 define('MULTIPLE_ANSWER_COMBINATION', 9);
+define('ORAL_EXPRESSION', 		13);
 
 //debug param. 0: no display - 1: debug display
 $debug=0;

+ 75 - 0
main/exercice/oral_expression.class.php

@@ -0,0 +1,75 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+*	File containing the FreeAnswer class.
+*	This class allows to instantiate an object of type FREE_ANSWER,
+*	extending the class question
+*	@package chamilo.exercise
+* 	@author Eric Marguin
+* 	@version $Id: admin.php 10680 2007-01-11 21:26:23Z pcool $
+*/
+/**
+ * Code
+ */
+if(!class_exists('OralExpression')):
+/**
+ * @package chamilo.exercise
+ */
+class OralExpression extends Question {
+
+	static $typePicture = 'audio_question.png';
+	static $explanationLangVar = 'OralExpression';
+
+	/**
+	 * Constructor
+	 */
+	function OralExpression(){
+		parent::question();
+		$this -> type = ORAL_EXPRESSION;
+		$this -> isContent = $this-> getIsContent();
+	}
+
+	/**
+	 * function which redifines Question::createAnswersForm
+	 * @param the formvalidator instance
+	 */
+	function createAnswersForm ($form) {
+		$form -> addElement('text','weighting',get_lang('Weighting'),'size="5"');
+		global $text, $class;
+		// setting the save button here and not in the question class.php
+		$form->addElement('style_submit_button','submitQuestion',$text, 'class="'.$class.'"');
+		if (!empty($this->id)) {
+			$form -> setDefaults(array('weighting' => float_format($this->weighting, 1)));
+		} else {
+			if ($this -> isContent == 1) {
+				$form -> setDefaults(array('weighting' => '10'));
+			}
+		}
+	}
+
+	/**
+	 * abstract function which creates the form to create / edit the answers of the question
+	 * @param the formvalidator instance
+	 */
+	function processAnswersCreation($form) {
+		$this -> weighting = $form -> getSubmitValue('weighting');
+		$this->save();
+	}
+	
+	function return_header($feedback_type, $counter = null) {
+	    parent::return_header($feedback_type, $counter);
+	    $header = '<table width="100%" border="0" cellspacing="3" cellpadding="3">
+			<tr>
+			<td>&nbsp;</td>
+			</tr>
+			<tr>
+			<td><i>'.get_lang("Answer").'</i> </td>
+			</tr>
+			<tr>
+			<td>&nbsp;</td>
+			</tr>';				
+        return $header;	  
+	}
+	
+}
+endif;

+ 58 - 47
main/exercice/question.class.php

@@ -26,6 +26,7 @@ define('MULTIPLE_ANSWER_COMBINATION', 	9);
 define('UNIQUE_ANSWER_NO_OPTION',       10);
 define('MULTIPLE_ANSWER_TRUE_FALSE',    11);
 define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE',    12);
+define('ORAL_EXPRESSION', 		13);
 
 if (!class_exists('Category')) include_once("testcategory.class.php");	// hub 12-10-2011
 
@@ -61,13 +62,13 @@ abstract class Question
                                 FILL_IN_BLANKS => 				array('fill_blanks.class.php' , 	'FillBlanks'),
                                 MATCHING => 					array('matching.class.php' , 		'Matching'),
                                 FREE_ANSWER => 					array('freeanswer.class.php' , 		'FreeAnswer'),
+                                ORAL_EXPRESSION => 				array('oral_expression.class.php' , 'OralExpression'),
                                 HOT_SPOT => 					array('hotspot.class.php' , 		'HotSpot'),
                                 HOT_SPOT_DELINEATION =>         array('hotspot.class.php' , 'HotspotDelineation'),
                                 MULTIPLE_ANSWER_COMBINATION =>	array('multiple_answer_combination.class.php' , 'MultipleAnswerCombination'),
                                 UNIQUE_ANSWER_NO_OPTION =>      array('unique_answer_no_option.class.php' ,   'UniqueAnswerNoOption'),
                                 MULTIPLE_ANSWER_TRUE_FALSE =>   array('multiple_answer_true_false.class.php' , 'MultipleAnswerTrueFalse'),
-                                MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE =>   array('multiple_answer_combination_true_false.class.php' , 'MultipleAnswerCombinationTrueFalse'),
-                            
+                                MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE =>   array('multiple_answer_combination_true_false.class.php' , 'MultipleAnswerCombinationTrueFalse')                            
 							);
 
 	/**
@@ -115,7 +116,6 @@ abstract class Question
         
         $course_id = $course_info['real_id'];
 
-		$TBL_EXERCICES         = Database::get_course_table(TABLE_QUIZ_TEST);
 		$TBL_QUESTIONS         = Database::get_course_table(TABLE_QUIZ_QUESTION);
 		$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
         
@@ -127,29 +127,31 @@ abstract class Question
 		if ($object = Database::fetch_object($result)) {
 			
 			$objQuestion 				= Question::getInstance($object->type);
+            if (!empty($objQuestion)) {
 			
-			$objQuestion->id			= $id;
-			$objQuestion->question		= $object->question;
-			$objQuestion->description	= $object->description;
-			$objQuestion->weighting		= $object->ponderation;
-			$objQuestion->position		= $object->position;
-			$objQuestion->type			= $object->type;
-			$objQuestion->picture		= $object->picture;
-			$objQuestion->level			= (int) $object->level;
-            $objQuestion->extra         = $object->extra;
-            $objQuestion->course        = $course_info;
-            $objQuestion->category	    = Testcategory::getCategoryForQuestion($id);	// hub 12-10-2011
-                    
-			$sql = "SELECT exercice_id FROM $TBL_EXERCICE_QUESTION WHERE c_id = $course_id AND question_id = $id";
-			$result_exercise_list = Database::query($sql);
-
-			// fills the array with the exercises which this question is in
-			if ($result_exercise_list) {
-				while ($obj = Database::fetch_object($result_exercise_list)) {
-					$objQuestion->exerciseList[] = $obj->exercice_id;
-				}
-			}
-			return $objQuestion;
+                $objQuestion->id			= $id;
+                $objQuestion->question		= $object->question;
+                $objQuestion->description	= $object->description;
+                $objQuestion->weighting		= $object->ponderation;
+                $objQuestion->position		= $object->position;
+                $objQuestion->type			= $object->type;
+                $objQuestion->picture		= $object->picture;
+                $objQuestion->level			= (int) $object->level;
+                $objQuestion->extra         = $object->extra;
+                $objQuestion->course        = $course_info;
+                $objQuestion->category	    = Testcategory::getCategoryForQuestion($id);	// hub 12-10-2011
+
+                $sql = "SELECT exercice_id FROM $TBL_EXERCICE_QUESTION WHERE c_id = $course_id AND question_id = $id";
+                $result_exercise_list = Database::query($sql);
+
+                // fills the array with the exercises which this question is in
+                if ($result_exercise_list) {
+                    while ($obj = Database::fetch_object($result_exercise_list)) {
+                        $objQuestion->exerciseList[] = $obj->exercice_id;
+                    }
+                }
+                return $objQuestion;
+            }
 		}
 		// question not found
 		return false;
@@ -1039,23 +1041,39 @@ abstract class Question
 		$this->exportPicture($new_question_id, $course_info);
 		return $new_question_id;
 	}
+    function get_question_type($type) {
+        if ($type == ORAL_EXPRESSION && api_get_setting('enable_nanogong') != 'true') {
+            return null;
+        }        
+        return self::$questionTypes[$type];
+    }
+    
+    function get_question_type_list() {
+        if (api_get_setting('enable_nanogong') != 'true') {
+            self::$questionTypes[ORAL_EXPRESSION] = null;
+            unset(self::$questionTypes[ORAL_EXPRESSION]);
+        }   
+        return self::$questionTypes;
+    }
 
 	/**
 	 * Returns an instance of the class corresponding to the type
 	 * @param integer $type the type of the question
 	 * @return an instance of a Question subclass (or of Questionc class by default)
 	 */
-	static function getInstance ($type) {
-		if (!is_null($type)) {
-			list($file_name,$class_name) = self::$questionTypes[$type];
-			include_once($file_name);
-			if (class_exists($class_name)) {
-				return new $class_name();
-			} else {
-				echo 'Can\'t instanciate class '.$class_name.' of type '.$type;
-				return null;
-			}
+	static function getInstance($type) {
+		if (!is_null($type)) {            
+			list($file_name, $class_name) = self::get_question_type($type);
+            if (!empty($file_name)) {
+                include_once $file_name;
+                if (class_exists($class_name)) {
+                    return new $class_name();
+                } else {
+                    echo 'Can\'t instanciate class '.$class_name.' of type '.$type;                   
+                }
+            }
 		}
+        return null;
 	}
 
 	/**
@@ -1254,7 +1272,7 @@ abstract class Question
         $course_id = api_get_course_int_id();
         
 		// 1. by default we show all the question types
-		$question_type_custom_list = self::$questionTypes;
+		$question_type_custom_list = self::get_question_type_list();
 
 		if (!isset($feedbacktype)) $feedbacktype=0;
 		if ($feedbacktype==1) {
@@ -1320,14 +1338,6 @@ abstract class Question
 		echo '</div></li>';
 		echo '</ul>';
 	}
-
-	static function get_types_information(){
-		return self::$questionTypes;
-	}
-
-	static function updateId() {
-		return self::$questionTypes;
-	}
     
     static function saveQuestionOption($question_id, $name, $course_id, $position = 0) {
         $TBL_EXERCICE_QUESTION_OPTION    = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);   
@@ -1419,9 +1429,10 @@ abstract class Question
      *
     */
     public function get_type_icon_html() {
-    	$type = $this->selectType();
-    	$tabQuestionList = Question::get_types_information(); // [0]=file to include [1]=type name
-    	require_once($tabQuestionList[$type][0]);
+    	$type            = $this->selectType();        
+    	$tabQuestionList = Question::get_question_type_list(); // [0]=file to include [1]=type name
+        
+    	require_once $tabQuestionList[$type][0];
 			eval('$img = '.$tabQuestionList[$type][1].'::$typePicture;');
 			eval('$explanation = get_lang('.$tabQuestionList[$type][1].'::$explanationLangVar);');
 			return array($img, $explanation);

+ 1 - 1
main/exercice/question_admin.inc.php

@@ -54,7 +54,7 @@ if(is_object($objQuestion)) {
 		$type = $_REQUEST['answerType'];
 	}
 
-	$types_information = $objQuestion->get_types_information();
+	$types_information = $objQuestion->get_question_type_list();
 	$form_title_extra = get_lang($types_information[$type][1]);
 
 	// form title

+ 7 - 4
main/exercice/question_create.php

@@ -69,8 +69,8 @@ $form->addRule('question_type_hidden', get_lang('InvalidQuestionType'), 'validqu
 
 if ($form->validate()) {
 	$values = $form->exportValues();
-
-	foreach (Question::$questionTypes as $question_type_id => $question_type_class_and_name) {
+    $question_list = Question::get_question_type_list();
+	foreach ($question_list as $question_type_id => $question_type_class_and_name) {
 		if (get_lang($question_type_class_and_name[1]) == $values['question_type_hidden']) {
 			$answer_type = $question_type_id;
 		}
@@ -125,8 +125,10 @@ $pictures_question_types[9] = 'mcmac.gif';
 $pictures_question_types[10] = 'mcuao.gif';
 $pictures_question_types[11] = 'mcmao.gif';
 $pictures_question_types[12] = 'mcmaco.gif';
+$pictures_question_types[13] = 'audio_question.png';
+$question_list = Question::get_question_type_list();
 
-foreach (Question::$questionTypes as $key=>$value) {
+foreach ($question_list as $key=>$value) {
 	if ($key != HOT_SPOT_DELINEATION ) { // DELINEATION hide
 		?>
 		ddlObj1.addItem('<table width="100%"><tr><td style="width: 37px;" valign="top"><?php Display::display_icon($pictures_question_types[$key],addslashes(get_lang($value[1])),array('height'=>'40px;', 'style' => 'vertical-align:top; cursor:hand;')); ?></td><td><span class="thistext" style="cursor:hand"><?php echo addslashes(get_lang($value[1])); ?></span><br/><sub><?php /*echo addslashes(get_lang($value[1].'Comment'));*/ ?></sub></td></tr></table>','');
@@ -137,7 +139,8 @@ foreach (Question::$questionTypes as $key=>$value) {
 </script>
 <?php
 function check_question_type($parameter) {
-	foreach (Question::$questionTypes as $key=>$value) {
+    $question_list = Question::get_question_type_list();    
+	foreach ($question_list as $key=>$value) {
 		$valid_question_types[] = get_lang($value[1]);
 		//$valid_question_types[] = trim($value[1]);
 	}

+ 0 - 1
main/exercice/question_list_admin.inc.php

@@ -203,7 +203,6 @@ if (!$inATest) {
 				
 				// Question type
 				
-				$tabQuestionList = Question::get_types_information();
 				list($typeImg, $typeExpl) = $objQuestionTmp->get_type_icon_html();
 				$questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array('style'=>$styleType));
 				

+ 18 - 6
main/exercice/question_pool.php

@@ -374,7 +374,8 @@ echo Display::form_row(get_lang('Difficulty'), $select_difficulty_html);
  
 // Answer type
  
-$question_list = Question::get_types_information();
+$question_list = Question::get_question_type_list();
+
 $new_question_list = array();
 $new_question_list['-1']  = get_lang('All');
 $objExercise = new Exercise();
@@ -617,8 +618,16 @@ $data = array();
 
 foreach ($main_question_list as $tabQuestion) {
 	$row = array();
+    
+    //This function checks if the question can be read
+    $question_type = get_question_type_for_question($selected_course, $tabQuestion['id']);
+    
+    if (empty($question_type)) {
+        continue;
+    }
+    
 	$row[] = get_a_tag_for_question($questionTagA, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], $tabQuestion['question']);
-	$row[] = get_question_type_for_question($selected_course, $tabQuestion['id']);
+	$row[] = $question_type;
 	$row[] = get_question_categorie_for_question($selected_course, $tabQuestion['id']);
 	$row[] = $tabQuestion['level'];
 	$row[] = get_action_icon_for_question($actionIcon1, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], 
@@ -763,10 +772,13 @@ function get_action_icon_for_question($in_action, $from_exercice, $in_questionid
 // return the icon for the question type
 // hubert.borderiou 13-10-2011
 function get_question_type_for_question($in_selectedcourse, $in_questionid) {
-	$myObjQuestion = Question::read($in_questionid, $in_selectedcourse);
-	list($typeImg, $typeExpl) = $myObjQuestion->get_type_icon_html();
-	$questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array());
-	unset($myObjQuestion);
+	$myObjQuestion = Question::read($in_questionid, $in_selectedcourse);    
+    $questionType = null;
+    if (!empty($myObjQuestion)) {        
+        list($typeImg, $typeExpl) = $myObjQuestion->get_type_icon_html();
+        $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array());
+        unset($myObjQuestion);
+    }
 	return $questionType;
 }
 

BIN
main/img/audio_question.png


BIN
main/img/icons/32/audio_question.png


+ 2 - 0
main/inc/lib/add_course.lib.inc.php

@@ -147,6 +147,8 @@ function prepare_course_repository($course_repository, $course_code) {
     mkdir(api_get_path(SYS_COURSE_PATH).$course_repository . '/work', $perm);
     mkdir(api_get_path(SYS_COURSE_PATH).$course_repository . '/upload/announcements', $perm);
     mkdir(api_get_path(SYS_COURSE_PATH).$course_repository . '/upload/announcements/images', $perm);
+    //Oral expression question type
+    mkdir(api_get_path(SYS_COURSE_PATH).$course_repository . '/exercises', $perm);
 
     // Create .htaccess in the dropbox directory.
     $fp = fopen(api_get_path(SYS_COURSE_PATH).$course_repository . '/dropbox/.htaccess', 'w');

+ 10 - 4
main/inc/lib/events.lib.inc.php

@@ -448,7 +448,7 @@ function create_event_exercice($exo_id) {
  * @param	integer	Position
  * @return	boolean	Result of the insert query
  */
-function exercise_attempt($score, $answer, $quesId, $exeId, $j, $exercise_id = 0) {	
+function exercise_attempt($score, $answer, $quesId, $exeId, $j, $exercise_id = 0, $nano = null) {	
     require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.lib.php';
 	$score 	= Database::escape_string($score);
 	$answer = Database::escape_string($answer);
@@ -472,9 +472,14 @@ function exercise_attempt($score, $answer, $quesId, $exeId, $j, $exercise_id = 0
 	} else {
 		// anonymous
 		$user_id = api_get_anonymous_id();
+	}		
+	$file = '';
+	
+	if (isset($nano)) {	
+		$file = basename($nano->load_filename_if_exists(false));
 	}
     
-	$sql = "INSERT INTO $TBL_TRACK_ATTEMPT (exe_id, user_id, question_id, answer, marks, course_code, session_id, position, tms )
+	$sql = "INSERT INTO $TBL_TRACK_ATTEMPT (exe_id, user_id, question_id, answer, marks, course_code, session_id, position, tms, filename)
 			  VALUES (
 			  ".$exeId.",
 			  ".$user_id.",
@@ -484,8 +489,9 @@ function exercise_attempt($score, $answer, $quesId, $exeId, $j, $exercise_id = 0
 			   '".api_get_course_id()."',
 			   '".api_get_session_id()."',
 			   '".$j."',
-			   '".$reallyNow."'
-			  )";
+			   '".$reallyNow."',
+			   '".$file."'
+			)";		
     //error_log($sql);
 	if (!empty($quesId) && !empty($exeId) && !empty($user_id)) {
 		$res = Database::query($sql);		

+ 36 - 0
main/inc/lib/exercise_show_functions.lib.php

@@ -87,6 +87,42 @@ class ExerciseShowFunctions {
 			echo '</tr>';
         }
 	}
+	
+	function display_oral_expression_answer($answer,$id,$questionId, $nano = null) {
+		global $feedback_type;
+		
+		if (isset($nano)) {
+			echo $nano->show_audio_file();
+		}
+		
+		if (empty($id)) {
+		
+			echo '<tr>';
+			echo Display::tag('td',nl2br(Security::remove_XSS($answer,COURSEMANAGERLOWSECURITY)), array('width'=>'55%'));
+			echo '</tr>';
+			if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
+				echo '<tr>';
+				echo Display::tag('td',get_lang('notCorrectedYet'), array('width'=>'45%'));
+				echo '</tr>';
+			} else {
+				echo '<tr><td>&nbsp;</td></tr>';
+			}
+		} else {
+			echo '<tr>';
+			echo '<td>';
+			if (!empty($answer)) {
+				echo nl2br(Security::remove_XSS($answer,COURSEMANAGERLOWSECURITY));
+			}
+			echo '</td>';
+				
+			if(!api_is_allowed_to_edit(null,true) && $feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
+				echo '<td>';
+				$comm = get_comments($id,$questionId);
+				echo '</td>';
+			}
+			echo '</tr>';
+		}
+	}
 
 	/**
 	 * Displays the answer to a hotspot question

+ 656 - 0
main/inc/lib/nanogong.lib.php

@@ -0,0 +1,656 @@
+<?php  
+/* For licensing terms, see /license.txt */
+
+/*
+ * 
+ * Files are saved in the path:
+ * 
+ *  courses/XXX/exercises/(session_id)/(exercise_id)/(question_id)/(user_id)/
+ *
+ * The file name is composed with 
+ * 
+ * (course_id)/(session_id)/(user_id)/(exercise_id)/(question_id)/(exe_id).wav|mp3|ogg
+ *
+ *
+ */
+class Nanogong {
+	
+	var $filename;
+	var $store_filename;
+	var $store_path;
+	var $params;
+	var $can_edit = false;
+	
+	/* Files allowed to upload */
+	var $available_extensions = array('mp3', 'wav', 'ogg');
+	
+	public function __construct($params = array()) {
+		$this->set_parameters($params);
+	}
+	
+	function create_user_folder() {
+				
+		//COURSE123/exercises/session_id/exercise_id/question_id/user_id
+		if (empty($this->store_path)) {
+			return false;
+		}
+        
+        //@todo use an array to create folders
+		$folders_to_create = array();
+        
+        //Trying to create the courses/COURSE123/exercises/ dir just in case
+        if (!is_dir($this->store_path)) {
+			mkdir($this->store_path);
+		}		
+			
+		if (!is_dir($this->store_path.$this->session_id)) {
+			mkdir($this->store_path.$this->session_id);
+		}
+		
+		if (!empty($this->exercise_id) && !is_dir($this->store_path.$this->session_id.'/'.$this->exercise_id)) {
+			mkdir($this->store_path.$this->session_id.'/'.$this->exercise_id);
+		}
+		
+		if (!empty($this->question_id) && !is_dir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id)) {
+			mkdir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id);
+		}
+		
+		if (!empty($this->user_id) && !is_dir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id.'/'.$this->user_id)) {
+			mkdir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id.'/'.$this->user_id);
+		}
+	}
+	
+	/**
+	 * Setting parameters: course id, session id, etc
+	 * @param	array	
+	 */
+	function set_parameters($params = array()) {
+		
+		//Setting course id
+		if (isset($params['course_id'])) {
+			$this->course_id = intval($params['course_id']);
+		} else {
+			$this->course_id = $params['course_id'] = api_get_course_int_id();
+		}
+		
+		//Setting course info
+		if (isset($this->course_id)) {
+			$this->course_info = api_get_course_info_by_id($this->course_id);
+		}
+		
+		//Setting session id
+		if (isset($params['session_id'])) {
+			$this->session_id = intval($params['session_id']);
+		} else {
+			$this->session_id = $params['session_id'] = api_get_session_id();
+		}
+		
+		//Setting user ids
+		if (isset($params['user_id'])) {
+			$this->user_id = intval($params['user_id']);
+		} else {
+			$this->user_id = $params['user_id'] = api_get_user_id();
+		}
+		
+		//Setting user ids
+		if (isset($params['exercise_id'])) {
+			$this->exercise_id = intval($params['exercise_id']);
+		} else {
+			$this->exercise_id = 0;
+		}
+		
+		//Setting user ids
+		if (isset($params['question_id'])) {
+			$this->question_id = intval($params['question_id']);
+		} else {
+			$this->question_id = 0;
+		}
+				
+		$this->can_edit  = false;
+		
+		if (api_is_allowed_to_edit()) {
+			$this->can_edit = true;			
+		} else {
+			if ($this->user_id ==  api_get_user_id()) {
+				$this->can_edit = true;
+			}
+		}
+		
+		//Settings the params array
+		$this->params 			= $params;
+				
+		$this->store_path 		= api_get_path(SYS_COURSE_PATH).$this->course_info['path'].'/exercises/';
+		
+		$this->create_user_folder();	
+				
+		$this->store_path 		= $this->store_path.implode('/', array($this->session_id, $this->exercise_id, $this->question_id, $this->user_id)).'/';
+		$this->filename 		= $this->generate_filename();
+		$this->store_filename 	= $this->store_path.$this->filename;
+	}
+	
+	/**
+	 * Generates the filename with the next format:
+	 * (course_id)/(session_id)/(user_id)/(exercise_id)/(question_id)/(exe_id)
+	 *
+	 * @return string
+	 */
+	function generate_filename() {
+		if (!empty($this->params)) {
+			//filename
+			//course_id/session_id/user_id/exercise_id/question_id/exe_id
+			$filename_array = array($this->params['course_id'], $this->params['session_id'], $this->params['user_id'], $this->params['exercise_id'], $this->params['question_id'], $this->params['exe_id']);			
+			return implode('-', $filename_array);
+		} else {
+			return api_get_unique_id();
+		}
+	}
+	
+	/**
+	 * Delete audio file
+	 * @return number
+	 */
+	function delete_files() {
+		$delete_found = 0;
+		if ($this->can_edit) {			
+			$file = $this->load_filename_if_exists();			
+			
+			$path_info = pathinfo($file);			
+			foreach($this->available_extensions as $extension) {
+				$file_to_delete = $path_info['dirname'].'/'.$path_info['filename'].'.'.$extension;
+				if (is_file($file_to_delete)) {
+					unlink($file_to_delete);
+					$delete_found = 1;
+				}
+			}		
+		}
+		return $delete_found;
+	}
+	
+	/**
+	 * 
+	 * Tricky stuff to deal with the feedback = 0 in exercises (all question per page)
+	 * @param unknown_type $exe_id
+	 */
+	function replace_with_real_exe($exe_id) {
+		$filename = null;
+		//@ugly fix
+		foreach($this->available_extensions as $extension) {			
+			$items = explode('-', $this->filename);
+			$items[5] = 'temp_exe';
+			$filename = implode('-', $items);			
+			if (is_file($this->store_path.$filename.'.'.$extension)) {				 
+				$old_name = $this->store_path.$filename.'.'.$extension;				
+				$items = explode('-', $this->filename);
+				$items[5] = $exe_id;
+				$filename = $filename = implode('-', $items);
+				$new_name = $this->store_path.$filename.'.'.$extension;
+				//var_dump($old_name, $new_name);
+				rename($old_name, $new_name);				
+				break;
+			}		
+		}
+	}
+	
+	function load_filename_if_exists($load_from_database = false) {
+		$filename = null;
+		//@ugly fix
+		foreach($this->available_extensions as $extension) {			
+			if (is_file($this->store_path.$this->filename.'.'.$extension)) {				
+				$filename = $this->filename.'.'.$extension;
+				break;				
+			}
+		}		
+		
+		//temp_exe		
+		if ($load_from_database) {
+		
+			//Load the real filename just if exists
+			if (isset($this->params['exe_id']) && isset($this->params['user_id']) && isset($this->params['question_id']) && isset($this->params['session_id']) && isset($this->params['course_id'])) {
+				$attempt_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
+				$sql = "SELECT filename FROM $attempt_table
+								WHERE 	exe_id 		= ".$this->params['exe_id']." AND
+										user_id 	= ".$this->params['user_id']." AND 	
+										question_id = ".$this->params['question_id']." AND
+										session_id 	= ".$this->params['session_id']." AND 
+										course_code = '".$this->course_info['code']."' LIMIT 1";
+				$result = Database::query($sql);
+				$result = Database::fetch_row($result,'ASSOC');
+									
+				if (isset($result) && isset($result[0]) && !empty($result[0])) {
+					$filename = $result[0];				
+				}
+			}
+		}
+		
+		if (is_file($this->store_path.$filename)) {
+			return $this->store_path.$filename;
+		}
+		return null;
+	}
+	
+	/**
+	 * 
+	 * Get the URL of the file
+	 * path courses/XXX/exercises/(session_id)/(exercise_id)/(question_id)/(user_id)/
+	 * 
+	 * @return string
+	 */
+	function get_public_url($force_download = 0) {
+		$params = $this->get_params(true);
+		$url = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=get_file&download='.$force_download.'&'.$params;
+		
+		$params = $this->get_params();
+		
+		$filename = basename($this->load_filename_if_exists());
+		
+		$url = api_get_path(WEB_COURSE_PATH).$this->course_info['code'].'/exercises/'.
+		$params['session_id'].'/'.$params['exercise_id'].'/'.$params['question_id'].'/'.$params['user_id'].'/'.$filename;		
+		return $url;
+	}
+	
+	/**
+	 * Uploads the nanogong wav file 
+	 */	
+	public function upload_file($is_nano = false) {
+		require_once api_get_path(LIBRARY_PATH).'fileDisplay.lib.php';
+		require_once api_get_path(LIBRARY_PATH).'document.lib.php';
+		require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
+				
+		if (!empty($_FILES)) {		
+			$upload_ok = process_uploaded_file($_FILES['file'], false);			
+			
+			if (!is_uploaded_file($_FILES['file']['tmp_name'])) {
+				return 0;
+			}
+					
+			if ($upload_ok) {
+				// Check if there is enough space to save the file
+				if (!DocumentManager::enough_space($_FILES['file']['size'], DocumentManager::get_course_quota())) {
+					return 0;				
+				}		
+				
+				//first we delete everything before uploading the file
+				$this->delete_files();
+								
+				//Reload the filename variable
+				$file_name = add_ext_on_mime($_FILES['file']['name'], $_FILES['file']['type']);				
+				$file_name = strtolower($file_name);
+				$file_info = pathinfo($file_name);				
+				
+				if ($is_nano == true) {
+					$file_info['extension'] = 'wav';					
+				}
+				
+				$file_name = $this->filename.'.'.$file_info['extension'];
+			
+				if (in_array($file_info['extension'], $this->available_extensions)) {				
+					if (move_uploaded_file($_FILES['file']['tmp_name'], $this->store_path.$file_name)) {
+						$this->store_filename = $this->store_path.$file_name;						
+						//error_log('saved');
+						return 1;
+					}
+				}
+			}			
+		}
+		return 0;
+	}
+	
+	/**
+	 * Show the audio file + a button to download
+	 *
+	 */
+	public function show_audio_file($show_delete_button = false) {
+		$html = '&nbsp;&nbsp;';
+		$file_path = $this->load_filename_if_exists();
+		
+		if (!empty($file_path)) {
+			$url = $this->get_public_url(true);
+			$actions = Display::url(Display::return_icon('save.png', get_lang('Download'), array(), 22), $url, array('target'=>'_blank'));
+			$download_button = Display::url(get_lang('Download'), $url, array('class' =>'a_button gray medium'));
+			
+			if ($show_delete_button) {				
+				$actions .= ' '.Display::url(Display::return_icon('delete.png', get_lang('Delete'), array(), 22), "#", array('onclick'=>'delete_file();'));
+			}
+							
+			$basename = basename($file_path);
+			$path_info = pathinfo($basename);
+			
+			if ($path_info['extension'] == 'wav') {
+				
+				$html .= '<script>
+				$(document).ready( function() {
+					var java_enabled = navigator.javaEnabled();
+											
+					if (java_enabled) {				
+						$("#nanogong_warning").hide();
+						$("#nanogong_player_id").show();
+					} else {
+						$("#nanogong_warning").show();
+						$("#nanogong_player_id").hide();
+					}
+				});
+				</script>';
+												
+				$html .= '<div id="nanogong_player_id" class="nanogong_player_container">';
+					$html .= '<div class="action_player">'.$actions.'</div>';				
+					$html .= '<div class="nanogong_player">';	
+						$html .= '<applet id="nanogong_player" archive="'.api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar" code="gong.NanoGong" width="250" height="40" ALIGN="middle">';
+						
+						$html .= '<param name="ShowRecordButton" value="false" />'; // default true
+						$html .= '<param name="ShowSaveButton" value="false" />'; //you can save in local computer | (default true)
+						//echo '<param name="ShowSpeedButton" value="false" />'; // default true
+						//echo '<param name="ShowAudioLevel" value="false" />'; //  it displays the audiometer | (default true)
+						$html .= '<param name="ShowTime" value="true" />'; // default false
+						$html .= '<param name="Color" value="#FFFFFF" />';
+						//echo '<param name="StartTime" value="10.5" />';
+						//echo '<param name="EndTime" value="65" />';
+						$html .= '<param name="AudioFormat" value="ImaADPCM" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
+						//$html .= '<param name="AudioFormat" value="Speex" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
+						
+						//Quality for ImaADPCM (low 8000, medium 11025, normal 22050, hight 44100) OR Quality for Speex (low 8000, medium 16000, normal 32000, hight 44100) | (default 44100)						
+						//echo '<param name="SamplingRate" value="32000" />';
+						//echo '<param name="MaxDuration" value="60" />';
+						$html .=  '<param name="SoundFileURL" value="'.$url.'" />';//load a file |(default "")
+						$html .= '</applet>';						
+					$html .= '</div>';
+				$html .= '</div>';
+						
+				$html .= '<div id="nanogong_warning">'.Display::return_message(get_lang('BrowserNotSupportNanogongListen'),'warning').$download_button.'</div>';
+				
+				
+			} elseif(in_array($path_info['extension'],array('mp3', 'ogg','wav'))) {
+				$js_path 		= api_get_path(WEB_LIBRARY_PATH).'javascript/';
+				
+				$html .= '<link rel="stylesheet" href="'.$js_path.'jquery-jplayer/skins/blue/jplayer.blue.monday.css" type="text/css">';
+				$html .= '<script type="text/javascript" src="'.$js_path.'jquery-jplayer/jquery.jplayer.min.js"></script>';
+				
+				$html .= '<div class="nanogong_player"></div>';
+				$html .= '<br /><div class="action_player">'.$actions.'</div><br /><br /><br />';
+				
+				$jquery .= ' $("#audio_preview").jPlayer({
+                                ready: function() {                    
+                                    $(this).jPlayer("setMedia", {                                        
+                                        '.$path_info['extension'].' : "'.$url.'"                                                                                  
+                                    });
+                                },                            
+                                swfPath: "'.$js_path.'jquery-jplayer",                                
+                                supplied: "mp3, ogg, oga, wav",
+		                        solution: "flash, html",  // Do not change this setting otherwise
+		                        width:0,
+		                        height:0,
+                            });';
+				
+				$html .= '<script type="text/javascript">
+				$(document).ready( function() {        
+				    //Experimental changes to preview mp3, ogg files        
+				     '.$jquery.'                 
+				});
+				</script>';
+				
+				//@todo fix this
+				$html .= '
+						<div id="audio_preview" class="jp-jplayer"></div>
+							<div class="jp-audio audio_preview_container">
+								<div class="jp-type-single">
+									<div id="jp_interface_1" class="jp-interface">
+										<ul class="jp-controls">
+											<li><a href="#" class="jp-play" tabindex="1">play</a></li>
+											<li><a href="#" class="jp-pause" tabindex="1">pause</a></li>
+											<li><a href="#" class="jp-stop" tabindex="1">stop</a></li>
+											<li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
+											<li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>
+										</ul>
+										<div class="jp-progress">
+											<div class="jp-seek-bar">
+												<div class="jp-play-bar"></div>
+											</div>
+										</div>
+										<div class="jp-volume-bar">
+											<div class="jp-volume-bar-value"></div>
+										</div>
+										<div class="jp-current-time"></div>
+										<div class="jp-duration"></div>
+									</div>					
+									<div id="jp_playlist_1" class="jp-playlist">					
+									</div>
+								</div>
+							</div>
+							<br />';				
+			}
+			return $html;
+		}	
+	}
+	
+	
+	/*
+	var filename = document.getElementById("audio_title").value+".wav";
+	var filename = filename.replace(/\s/g, "_");//replace spaces by _
+	var filename = encodeURIComponent(filename);
+	var filepath="'.urlencode($filepath).'";
+	var dir="'.urlencode($dir).'";
+	var course_code="'.urlencode($course_code).'";
+	var urlnanogong="'.$url.'?filename="+filename+"&filepath="+filepath+"&dir="+dir+"&course_code="+course_code;
+	*/
+	
+	/**
+	 * Returns the nanogong javascript code
+	 * @return string
+	 */
+	function return_js() {
+		$params = $this->get_params(true);
+		$url = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=save_file&'.$params.'&is_nano=1';
+		$url_load_file = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=show_audio&'.$params;
+		
+		$url_delete = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=delete&'.$params;
+		
+		$js =  '<script language="javascript">
+
+			//lang vars
+			
+			var lang_no_applet				= "'.get_lang('NanogongNoApplet').'";
+			var lang_record_before_save		= "'.get_lang('NanogongRecordBeforeSave').'";
+			var lang_give_a_title			= "'.get_lang('NanogongGiveTitle').'";
+			var lang_failed_to_submit		= "'.get_lang('NanogongFailledToSubmit').'";
+			var lang_submitted				= "'.get_lang('NanogongSubmitted').'";
+			var lang_deleted				= "'.get_lang('Deleted').'";
+
+			var is_nano = 0;
+			
+			function check_gong() {
+				//var record = document.getElementById("nanogong");
+				var recorder;
+				
+				var java_enabled = navigator.javaEnabled()
+				return java_enabled;				
+			}
+		
+			$(document).ready( function() {	
+				$("#no_nanogong_div").hide();
+				$("#nanogong_div").hide();
+				
+				var check_js = check_gong();
+				
+				if (check_js == true) {
+					$("#nanogong_div").show();
+					$("#no_nanogong_div").hide();
+					is_nano = 1;
+					$(".nanogong_player").show(); 
+				} else {
+					$("#no_nanogong_div").show();
+					$("#nanogong_div").hide();
+					$(".nanogong_player").hide();
+				}
+					
+				//show always the mp3/ogg upload form (for dev purposes)
+				
+				//$("#no_nanogong_div").show();
+				//$("#nanogong_div").hide();					
+			});
+			
+			function delete_file() {
+				$.ajax({
+					url: "'.$url_delete.'",
+					success:function(data) {
+						$("#status_warning").hide();
+						$("#status_ok").hide();
+			
+						$("#messages").html(data);
+						$("#messages").show();
+						$("#preview").hide();	
+					}
+				});
+			}
+			
+			function upload_file() {
+				$("#form_nanogong_simple").submit();
+			}			
+			
+			function send_voice() {
+				$("#status_warning").hide();
+				$("#status_ok").hide();
+				$("#messages").hide();
+				
+				var check_js = check_gong();
+			
+				//check
+				
+				if (!check_js) {
+					$("#status_warning").html(lang_no_applet);
+					$("#status_warning").show();
+					return false;
+				}
+				
+				var recorder = document.getElementById("nanogong");
+				
+				if (!recorder || !check_js) {
+					//alert(lang_no_applet)
+					$("#status_warning").html(lang_no_applet);
+					$("#status_warning").show();
+					return false;
+				}
+				
+				var duration = parseInt(recorder.sendGongRequest("GetMediaDuration", "audio")) || 0;
+				
+				if (duration <= 0) {
+					$("#status_warning").html(lang_record_before_save);
+					$("#status_warning").show();
+					return false;				
+				}		
+				
+				var applet = document.getElementById("nanogong");
+				
+				var ret = applet.sendGongRequest("PostToForm", "'.$url.'", "file", "", "temp"); // PostToForm, postURL, inputname, cookie, filename
+				
+				if (ret == 1)  {				
+					$("#status_ok").html(lang_submitted);
+					$("#status_ok").show();					
+					$.ajax({
+						url:"'.$url_load_file.'&is_nano="+is_nano,
+						success: function(data){													
+							$("#preview").html(data);
+							$("#preview").show();					
+						}					
+					});					
+				} else {
+					//alert(lang_submitted+"\n"+ret);
+					$("#status_warning").html(lang_failed_to_submit);
+					$("#status_warning").show();
+				}
+				return false;
+			}
+			</script>';
+		return $js;
+	}
+	
+	/**
+	 * Returns the HTML form to upload a nano file or upload a file	 
+	 */
+	function return_form($message = null) {
+	
+		$params = $this->get_params(true);
+		$url = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=save_file&'.$params;
+			
+		//check browser support and load form
+		$array_browser = api_browser_support('check_browser');
+	
+		$preview_file = $this->show_audio_file(true, true);
+		$preview_file = Display::div($preview_file, array('id' => 'preview', 'style' => 'text-align:center;'));
+	
+		$html .= '<center>';
+	
+		//Use normal upload file
+		$html .= Display::return_icon('microphone.png', get_lang('PressRecordButton'),'','128');
+		$html .='<br />';
+	
+		$html .= '<div id="no_nanogong_div">';
+		$html .= Display::return_message(get_lang('BrowserNotSupportNanogongSend'), 'warning');
+	
+		$html .= '<form id="form_nanogong_simple" action="'.$url.'" name="form_nanogong" method="POST" enctype="multipart/form-data">';
+		$html .= '<input type="file" name="file">';
+		$html .= '<a href="#" class="a_button white medium"  onclick="upload_file()" />'.get_lang('UploadFile').'</a>';
+		$html .= '</form></div>';	
+	
+		$html .= '<div id="nanogong_div">';
+	
+		$html .= '<applet id="nanogong" archive="'.api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar" code="gong.NanoGong" width="250" height="40" align="middle">';
+		//echo '<param name="ShowRecordButton" value="false" />'; // default true
+		// echo '<param name="ShowSaveButton" value="false" />'; //you can save in local computer | (default true)
+		//echo '<param name="ShowSpeedButton" value="false" />'; // default true
+		//echo '<param name="ShowAudioLevel" value="false" />'; //  it displays the audiometer | (default true)
+		$html .= '<param name="ShowTime" value="true" />'; // default false
+		$html .= '<param name="Color" value="#FFFFFF" />'; // default #FFFFFF
+		//echo '<param name="StartTime" value="10.5" />';
+		//echo '<param name="EndTime" value="65" />';
+		$html .= '<param name="AudioFormat" value="ImaADPCM" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
+		//$html .= '<param name="AudioFormat" value="Speex" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
+	
+		//echo '<param name="SamplingRate" value="32000" />';//Quality for ImaADPCM (low 8000, medium 11025, normal 22050, hight 44100) OR Quality for Speex (low 8000, medium 16000, normal 32000, hight 44100) | (default 44100)
+		//echo '<param name="MaxDuration" value="60" />';
+		//echo '<param name="SoundFileURL" value="http://somewhere.com/mysoundfile.wav" />';//load a file |(default "")
+		$html .= '</applet>';
+	
+		$html .= '<br /><br /><br /><form name="form_nanogong_advanced">';
+		$html .= '<input type="hidden" name="is_nano" value="1">';
+		$html .= '<a href="#" class="a_button white medium"  onclick="send_voice()" />'.get_lang('SendRecord').'</a>';
+		$html .= '</form></div>';	
+	
+		$html .= '</center>';
+		
+		$html .= '<div style="display:none" id="status_ok" class="confirmation-message"></div><div style="display:none" id="status_warning" class="warning-message"></div>';
+		
+		$html .= '<div id="messages">'.$message.'</div>';		
+		
+		$html .= $preview_file;
+			
+		
+		return $html;
+	}
+	
+	function get_params($return_as_query = false) {
+		if (empty($this->params)) {
+			return false;
+		}		
+		if ($return_as_query) {
+			return http_build_query($this->params);
+		}
+		return $this->params;		
+	}
+	
+	function get_param_value($attribute) {
+		if (isset($this->params[$attribute])) {
+			return $this->params[$attribute];
+		}
+	}
+	
+	/**
+	 * Show a button to load the form
+	 * @return string
+	 */
+	function show_button() {		
+		$params_string = $this->get_params(true);		
+		$html .= '<br />'.Display::url(get_lang('RecordAnswer'),api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=show_form&'.$params_string.'&TB_iframe=true&height=350&width=500', 
+						array('class'=>'a_button white thickbox'));
+		$html .= '<br /><br />'.Display::return_message(get_lang('UseTheMessageBelowToAddSomeComments'));				
+		return $html;
+	}	
+}