oral_expression.class.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class OralExpression
  5. * This class allows to instantiate an object of type FREE_ANSWER,
  6. * extending the class question.
  7. *
  8. * @author Eric Marguin
  9. *
  10. * @package chamilo.exercise
  11. */
  12. class OralExpression extends Question
  13. {
  14. public static $typePicture = 'audio_question.png';
  15. public static $explanationLangVar = 'OralExpression';
  16. public $available_extensions = ['wav', 'ogg'];
  17. private $sessionId;
  18. private $userId;
  19. private $exerciseId;
  20. private $exeId;
  21. private $storePath;
  22. private $fileName;
  23. private $filePath;
  24. /**
  25. * Constructor.
  26. */
  27. public function __construct()
  28. {
  29. parent::__construct();
  30. $this->type = ORAL_EXPRESSION;
  31. $this->isContent = $this->getIsContent();
  32. }
  33. /**
  34. * {@inheritdoc}
  35. */
  36. public function createAnswersForm($form)
  37. {
  38. $form->addText(
  39. 'weighting',
  40. get_lang('Weighting'),
  41. ['class' => 'span1']
  42. );
  43. global $text;
  44. // setting the save button here and not in the question class.php
  45. $form->addButtonSave($text, 'submitQuestion');
  46. if (!empty($this->id)) {
  47. $form->setDefaults(['weighting' => float_format($this->weighting, 1)]);
  48. } else {
  49. if ($this->isContent == 1) {
  50. $form->setDefaults(['weighting' => '10']);
  51. }
  52. }
  53. }
  54. /**
  55. * {@inheritdoc}
  56. */
  57. public function processAnswersCreation($form, $exercise)
  58. {
  59. $this->weighting = $form->getSubmitValue('weighting');
  60. $this->save($exercise);
  61. }
  62. /**
  63. * {@inheritdoc}
  64. */
  65. public function return_header(Exercise $exercise, $counter = null, $score = [])
  66. {
  67. $score['revised'] = $this->isQuestionWaitingReview($score);
  68. $header = parent::return_header($exercise, $counter, $score);
  69. $header .= '<table class="'.$this->question_table_class.'">
  70. <tr>
  71. <th>'.get_lang("Answer").'</th>
  72. </tr>';
  73. return $header;
  74. }
  75. /**
  76. * initialize the attributes to generate the file path.
  77. *
  78. * @param $sessionId integer
  79. * @param $userId integer
  80. * @param $exerciseId integer
  81. * @param $exeId integer
  82. */
  83. public function initFile($sessionId, $userId, $exerciseId, $exeId)
  84. {
  85. $this->sessionId = intval($sessionId);
  86. $this->userId = intval($userId);
  87. $this->exerciseId = 0;
  88. $this->exeId = intval($exeId);
  89. if (!empty($exerciseId)) {
  90. $this->exerciseId = intval($exerciseId);
  91. }
  92. $this->storePath = $this->generateDirectory();
  93. $this->fileName = $this->generateFileName();
  94. $this->filePath = $this->storePath.$this->fileName;
  95. }
  96. /**
  97. * Return the HTML code to show the RecordRTC/Wami recorder.
  98. *
  99. * @return string
  100. */
  101. public function returnRecorder()
  102. {
  103. $directory = '/..'.$this->generateRelativeDirectory();
  104. $recordAudioView = new Template(
  105. '',
  106. false,
  107. false,
  108. false,
  109. false,
  110. false,
  111. false
  112. );
  113. $recordAudioView->assign('directory', $directory);
  114. $recordAudioView->assign('user_id', $this->userId);
  115. $recordAudioView->assign('file_name', $this->fileName);
  116. $recordAudioView->assign('question_id', $this->id);
  117. $template = $recordAudioView->get_template('exercise/oral_expression.tpl');
  118. return $recordAudioView->fetch($template);
  119. }
  120. /**
  121. * Get the absolute file path. Return null if the file doesn't exists.
  122. *
  123. * @param bool $loadFromDatabase
  124. *
  125. * @return string
  126. */
  127. public function getAbsoluteFilePath($loadFromDatabase = false)
  128. {
  129. $fileName = $this->fileName;
  130. if ($loadFromDatabase) {
  131. $em = Database::getManager();
  132. //Load the real filename just if exists
  133. if (isset($this->exeId, $this->userId, $this->id, $this->sessionId, $this->course['real_id'])) {
  134. $result = $em
  135. ->getRepository('ChamiloCoreBundle:TrackEAttempt')
  136. ->findOneBy([
  137. 'exeId' => $this->exeId,
  138. 'userId' => $this->userId,
  139. 'questionId' => $this->id,
  140. 'sessionId' => $this->sessionId,
  141. 'cId' => $this->course['real_id'],
  142. ]);
  143. if (!$result) {
  144. return '';
  145. }
  146. $fileName = $result->getFilename();
  147. if (empty($fileName)) {
  148. return '';
  149. }
  150. return $this->storePath.$result->getFilename();
  151. }
  152. }
  153. foreach ($this->available_extensions as $extension) {
  154. $audioFile = $this->storePath.$fileName;
  155. $file = "$audioFile.$extension";
  156. if (is_file($file)) {
  157. return $file;
  158. }
  159. // Function handle_uploaded_document() adds the session and group id by default.
  160. $file = "$audioFile"."__".$this->sessionId."__0.$extension";
  161. if (is_file($file)) {
  162. return $file;
  163. }
  164. continue;
  165. }
  166. return '';
  167. }
  168. /**
  169. * Get the URL for the audio file. Return null if the file doesn't exists.
  170. *
  171. * @param bool $loadFromDatabase
  172. *
  173. * @return string
  174. */
  175. public function getFileUrl($loadFromDatabase = false)
  176. {
  177. $filePath = $this->getAbsoluteFilePath($loadFromDatabase);
  178. if (empty($filePath)) {
  179. return null;
  180. }
  181. return str_replace(
  182. api_get_path(SYS_COURSE_PATH),
  183. api_get_path(WEB_COURSE_PATH),
  184. $filePath
  185. );
  186. }
  187. /**
  188. * Tricky stuff to deal with the feedback = 0 in exercises (all question per page).
  189. *
  190. * @param $exe_id integer
  191. */
  192. public function replaceWithRealExe($exe_id)
  193. {
  194. $filename = null;
  195. //ugly fix
  196. foreach ($this->available_extensions as $extension) {
  197. $items = explode('-', $this->fileName);
  198. $items[5] = 'temp_exe';
  199. $filename = implode('-', $items);
  200. if (is_file($this->storePath.$filename.'.'.$extension)) {
  201. $old_name = $this->storePath.$filename.'.'.$extension;
  202. $items = explode('-', $this->fileName);
  203. $items[5] = $exe_id;
  204. $filename = $filename = implode('-', $items);
  205. $new_name = $this->storePath.$filename.'.'.$extension;
  206. rename($old_name, $new_name);
  207. break;
  208. }
  209. }
  210. }
  211. /**
  212. * Generate the necessary directory for audios. If them not exists, are created.
  213. *
  214. * @return string
  215. */
  216. private function generateDirectory()
  217. {
  218. $this->storePath = api_get_path(SYS_COURSE_PATH).$this->course['path'].'/exercises/';
  219. if (!is_dir($this->storePath)) {
  220. mkdir($this->storePath);
  221. }
  222. if (!is_dir($this->storePath.$this->sessionId)) {
  223. mkdir($this->storePath.$this->sessionId);
  224. }
  225. if (!empty($this->exerciseId) && !is_dir($this->storePath.$this->sessionId.'/'.$this->exerciseId)) {
  226. mkdir($this->storePath.$this->sessionId.'/'.$this->exerciseId);
  227. }
  228. if (!empty($this->id) && !is_dir($this->storePath.$this->sessionId.'/'.$this->exerciseId.'/'.$this->id)) {
  229. mkdir($this->storePath.$this->sessionId.'/'.$this->exerciseId.'/'.$this->id);
  230. }
  231. if (!empty($this->userId) &&
  232. !is_dir($this->storePath.$this->sessionId.'/'.$this->exerciseId.'/'.$this->id.'/'.$this->userId)
  233. ) {
  234. mkdir($this->storePath.$this->sessionId.'/'.$this->exerciseId.'/'.$this->id.'/'.$this->userId);
  235. }
  236. $params = [
  237. $this->sessionId,
  238. $this->exerciseId,
  239. $this->id,
  240. $this->userId,
  241. ];
  242. $this->storePath .= implode('/', $params).'/';
  243. return $this->storePath;
  244. }
  245. /**
  246. * Generate the file name.
  247. *
  248. * @return string
  249. */
  250. private function generateFileName()
  251. {
  252. return implode(
  253. '-',
  254. [
  255. $this->course['real_id'],
  256. $this->sessionId,
  257. $this->userId,
  258. $this->exerciseId,
  259. $this->id,
  260. $this->exeId,
  261. ]
  262. );
  263. }
  264. /**
  265. * Generate a relative directory path.
  266. *
  267. * @return string
  268. */
  269. private function generateRelativeDirectory()
  270. {
  271. $params = [
  272. $this->sessionId,
  273. $this->exerciseId,
  274. $this->id,
  275. $this->userId,
  276. ];
  277. $path = implode('/', $params);
  278. $directory = '/exercises/'.$path.'/';
  279. return $directory;
  280. }
  281. }