html5.php 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603
  1. <?php
  2. /**
  3. * Class that implements ilm_handle, in order to allow manipulation and management of HTML5 iLM
  4. *
  5. * @author Igor Moreira Fe'lix
  6. * @author Patricia Alves Rodrigues
  7. * @author Leo^nidas O. Branda~o
  8. * @version v 1.1 2026/09/03
  9. * @version v 1 2017/17/10
  10. * @package mod_iassign_ilm_handlers
  11. * @copyright iMatica (<a href="http://www.matematica.br">iMath</a>) - Computer Science Dep. of IME-USP (Brazil)
  12. *
  13. * <b>License</b>
  14. * - http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  15. */
  16. global $CFG;
  17. require_once $CFG->dirroot . '/mod/iassign/ilm_handle.php';
  18. class html5 implements ilm_handle {
  19. /// Auxiliary function to check is an directory is empty
  20. public static function is_empty_dir ($dir) {
  21. if (!is_dir($dir))
  22. return FALSE;
  23. $handle = opendir($dir);
  24. while (false !== ($entry = readdir($handle))) {
  25. if ($entry != "." && $entry != "..") {
  26. closedir($handle); // close end return from here
  27. return FALSE;
  28. }
  29. }
  30. closedir($handle); // close end return
  31. return TRUE;
  32. }
  33. /// Produce HTML code to load iLM
  34. // @calledby locallib.php: class ilm_settings: function build_ilm_tags($ilm_id, $options=array()): $retorno=$typec::build_ilm_tags($ilm_id, $options);
  35. public static function build_ilm_tags ($ilm_id, $options = array()) {
  36. global $DB, $OUTPUT;
  37. global $CONF_WWW; //TODO 1 => use iLM under WWW; otherwise use under MoodleData
  38. $html = "";
  39. if (empty($options['Proposition']))
  40. $options['Proposition'] = "";
  41. if (empty($options['addresPOST']))
  42. $options['addresPOST'] = "";
  43. if (empty($options['student_answer']))
  44. $options['student_answer'] = "";
  45. if (empty($options['notSEND']))
  46. $options['notSEND'] = "";
  47. else // Case it is authoring put 'notSEND' (important to iVProgH5 to present authoring tool)
  48. if ($options['type'] == "editor_update")
  49. $options['notSEND'] = "true";
  50. if (empty($options['id_iLM_security'])) // if defined, it is from 'iassign_security'
  51. $options['id_iLM_security'] = "";
  52. $id_iLM_security = $options['id_iLM_security'];
  53. $iassign_ilm = $DB->get_record('iassign_ilm', array('id' => $ilm_id));
  54. if ($iassign_ilm) {
  55. // md_files : filename
  56. $ilm_extension = $iassign_ilm->extension; // use local variavel to efficiency (several use)
  57. if ($ilm_extension) { // avoid problems
  58. $ilm_extension = strtolower($ilm_extension);
  59. }
  60. // Attention: in iAssign 2014 on, all the iLM is located on the Moodle filesystem (usually /var/moodledata/filedir/).
  61. // This means that '$iassign_ilm->file_jar' = '*_files.id'
  62. $file_url = array();
  63. $fs = get_file_storage();
  64. $files_jar = explode(",", $iassign_ilm->file_jar);
  65. $url = $iassign_ilm->file_class; // to HTML5 package, this 'file_class' must have the main HTML file
  66. array_push($file_url, $url);
  67. $lang = substr(current_language(), 0, 2);
  68. if ($options['type'] == "filter") { //leo
  69. $iassign_ilm_width = $options['width']; // or use? $iassign_ilm->width
  70. $iassign_ilm_height = $options['height']; // or use? $iassign_ilm->height
  71. } else { //leo
  72. $iassign_ilm_width = $iassign_ilm->width;
  73. $iassign_ilm_height = $iassign_ilm->height; // or use? $iassign_ilm->height
  74. }
  75. if (!empty($file_url)) { // There is an iLM file
  76. //TODO iLM_HTML5 :: Change to 'object', tag 'applet' was deprecated.
  77. $paramsStr = "?1=1";
  78. $html .= html5::show_ilm_commands();
  79. switch ($options['type']) {
  80. case "view":
  81. $paramsStr .= "&iLM_PARAM_Assignment=" . urlencode($options['Proposition']); //leo
  82. $paramsStr .= "&iLM_PARAM_SendAnswer=true";
  83. //TODO: REVIEW: this code is to insert iLM as HTML5 and to allow general parameter to any iLM
  84. //TODO: For now, 'iassign_ilm_config' is empty... let comment these lines
  85. //n $iassign_ilm_config = $DB->get_records('iassign_ilm_config', array('iassign_ilmid' => $ilm_id));
  86. //n foreach ($iassign_ilm_config as $ilm_config) {
  87. //n if (array_key_exists($ilm_config->param_name, $options)) {
  88. //n $ilm_config->param_value = $options[$ilm_config->param_name];
  89. //n $paramsStr .= "&" . $ilm_config->param_name . "=" . urlencode($ilm_config->param_value);
  90. //n }
  91. //n }
  92. break;
  93. case "filter":
  94. if ($options['toolbar'] == "disable")
  95. $paramsStr .= "&SOH_ADD=ADD";
  96. $paramsStr .= "&iLM_PARAM_AssignmentURL=true";
  97. $paramsStr .= "&iLM_PARAM_Assignment=" . urlencode($options['Proposition']);
  98. $paramsStr .= "&iLM_PARAM_SendAnswer=" . urlencode($options['notSEND']);
  99. $paramsStr .= "&iLM_PARAM_ServerToGetAnswerURL=" . urlencode($ilm_config->param_value);
  100. break; // static function build_ilm_tags($ilm_id, $options=array())
  101. case "activity": // build_ilm_tags
  102. //TODO To generalize to any HTML5 iLM, it is necessary to use 'iLM_PARAM_Assignment' and 'iLM_PARAM_SendAnswer'
  103. //TODO iLM_PARAM_Assignment=Proposition ; iLM_PARAM_SendAnswer=notSEND
  104. $paramsStr .= "&iLM_PARAM_AssignmentURL=true";
  105. // if ($options['special_param'] == 1) { }
  106. $paramsStr .= "&iLM_PARAM_Assignment=" . urlencode($options['Proposition']);
  107. $paramsStr .= "&iLM_PARAM_SendAnswer=" . urlencode($options['notSEND']);
  108. $paramsStr .= "&iLM_PARAM_ServerToGetAnswerURL=" . urlencode($options['addresPOST']);
  109. //TODO iLM_HTML5 :: To extend to any iLM in HTML5
  110. //TODO iLM_HTML5 :: it will allow to load dynamic parameters
  111. //T $iassign_activity_item_configs = $DB->get_records('iassign_statement_config', array('iassign_statementid' => $options['iassign_statement'] ));
  112. //T if ($iassign_activity_item_configs) {
  113. //T foreach ($iassign_activity_item_configs as $iassign_activity_item_config)
  114. //T $paramsStr .= "&" . $iassign_activity_item_config->param_name . "=" . urlencode($iassign_activity_item_config->param_value);
  115. //T }
  116. break;
  117. case "editor_new":
  118. $paramsStr .= "&iLM_PARAM_AssignmentURL=true";
  119. $paramsStr .= "&iLM_PARAM_SendAnswer=" . urlencode($options['notSEND']);
  120. $paramsStr .= "&iLM_PARAM_Authoring=true";
  121. break;
  122. case "editor_update":
  123. $paramsStr .= "&iLM_PARAM_AssignmentURL=true";
  124. $paramsStr .= "&iLM_PARAM_Assignment=" . urlencode($options['Proposition']);
  125. $paramsStr .= "&iLM_PARAM_SendAnswer=" . urlencode($options['notSEND']);
  126. $paramsStr .= "&iLM_PARAM_Authoring=true";
  127. break;
  128. default:
  129. $html .= iassign::warning_message_iassign('error_view_without_actiontype'); // $OUTPUT->notification(get_string('error_view_without_actiontype', 'iassign'), 'notifyproblem'); // The API allows for creation of four types of notification: error, warning, info, and success.
  130. } // switch($options['type'])
  131. $paramsStr .= "&lang=" . $lang; // get the language defined in Moodle
  132. $sty_aux = "overflow-x:hidden !important; overflow-y:hidden !important;";
  133. $parameters = ' style="width: ' . $iassign_ilm_width . 'px; height: ' . $iassign_ilm_height . 'px;' . $sty_aux . '" ';
  134. // $html .= "\n" . '<iframe frameborder="0" seamless="seamless" name="iLM" id="iLM"' . "\n";
  135. $html .= "\n" . '<iframe frameborder="0" name="iLM" id="iLM" scrolling="no"' . "\n";
  136. $html .= ' src="' . $iassign_ilm->file_jar . $iassign_ilm->file_class . $paramsStr . '" ' . $parameters . '>' . "\n";
  137. $html .= "</iframe>\n";
  138. } // if (!empty($file_url))
  139. } // if ($iassign_ilm)
  140. return $html;
  141. } // public static function build_ilm_tags($ilm_id, $options = array())
  142. public static function show_ilm_commands () {
  143. $html = "<script>function full_screen() {
  144. if ('fullscreenEnabled' in document || 'webkitFullscreenEnabled' in document || 'mozFullScreenEnabled' in document || 'msFullscreenEnabled' in document) {
  145. if (document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) {
  146. var element = document.getElementsByName('iLM').item(0);
  147. //requestFullscreen is used to display an element in full screen mode.
  148. if ('requestFullscreen' in element) {
  149. element.requestFullscreen();
  150. }
  151. else if ('webkitRequestFullscreen' in element) {
  152. element.webkitRequestFullscreen();
  153. }
  154. else if ('mozRequestFullScreen' in element) {
  155. element.mozRequestFullScreen();
  156. }
  157. else if ('msRequestFullscreen' in element) {
  158. element.msRequestFullscreen();
  159. }
  160. }
  161. } else {
  162. $('.expand_button').addClass('disabled');
  163. }
  164. }</script>";
  165. $html .= "<div id='fullscreen' style='width: 800px;text-align: right;'><div onClick='full_screen()' style='color: blue; cursor: pointer; display: contents;'>".get_string('full_screen', 'iassign')."</div></div>";
  166. return $html;
  167. } // public static function show_ilm_commands()
  168. //TODO: Remover em favor do 'files_functions.php ! get_from_files(.)'
  169. // Try to get file from {files} using fields 'id', 'file' and 'filesid' in this order
  170. // The current convention is {files}.itemid = {iassign_statement}.id (however previously the others were used)
  171. public static function recover_from_files ($fs, $context_id, $iassign_statement_id, $iassign_statement_file, $iassign_statement_files) {
  172. // {iassign_statement} = table 'iassign_statement'
  173. $answer = [-1,-1]; // indicate error
  174. $files = $fs->get_area_files($context_id, 'mod_iassign', 'exercise', $iassign_statement_id);
  175. //D if ($files) { $msg_aux = ""; foreach ($files as $one_files) if ($one_files!='.') $msg_aux = "{files}=[id=" . $one_files->get_id() . ", itemid=" . $one_files->get_itemid() . "]<br/>"; }
  176. //D echo "ilm_handlers/html5.php: recover_from_files(.): tentou com 'iassign_statement_id'=" . $iassign_statement_id . ": files=" . ($files?"OK":"vazio!") . "<br/>" . $msg_aux . "<br/>";
  177. if (!$files) {
  178. //D echo " * html5.php: falhou com {iassign_statement}: id=" . $iassign_statement_id . " - tente com file=" . $iassign_statement_file . "<br/>\n";
  179. $files = $fs->get_area_files($context_id, 'mod_iassign', 'exercise', $iassign_statement_file);
  180. //D echo "ilm_handlers/html5.php: recover_from_files(.): tentou com 'iassign_statement_file'=" . $iassign_statement_file . ": files=" . ($files?"OK":"vazio!") . "<br/>";
  181. if (!$files) {
  182. //D echo " * html5.php: falhou com {iassign_statement}: file=" . $iassign_statement_file . " - tente com filesid=" . $iassign_statement_filesid . "<br/>\n";
  183. // $files = $fs->get_area_files($context_id, 'mod_iassign', 'exercise', $iassign_statement_filesid);
  184. $files = $fs->get_file_by_id($iassign_statement_filesid);
  185. //D echo "ilm_handlers/html5.php: recover_from_files(.): tentou com 'iassign_statement_filesid'=" . $iassign_statement_filesid . ": files=" . ($files?"OK":"vazio!") . "<br/>";
  186. if (!$files) {
  187. //D echo " * html5.php: falhou com {iassign_statement}: filesid=" . $iassign_statement_fileid . " - estou perdido!<br/>\n";
  188. }
  189. }
  190. }
  191. if ($files) {
  192. //D echo " * html5.php: deu certo com {iassign_statement}: id=" . $iassign_statement_id . ", {files}.id=";
  193. //TODO To be revised? 'files.filename' has '.' is only path (not the file)
  194. foreach ($files as $one_files) {
  195. //D echo $one_files->get_id() . ", ";
  196. if ($one_files->get_filename() != '.') {
  197. $files_id = $one_files->get_id();
  198. $answer[0] = $one_files; // return the {files}
  199. $answer[1] = $one_files->get_id(); // return the {files}.id
  200. break; // found => finish
  201. }
  202. }
  203. //D echo "<br/>\n";
  204. }
  205. return $answer;
  206. }
  207. /// Presents the iLM content (content inside iLM)
  208. // @calledby locallib.php : view_iLM(...)
  209. public static function show_activity_in_ilm ($iassign_statement_activity_item, $student_answer, $enderecoPOST, $view_teacherfileversion) {
  210. global $USER, $CFG, $COURSE, $DB, $OUTPUT;
  211. $special_param1 = $iassign_statement_activity_item->special_param1;
  212. $ilm = $DB->get_record('iassign_ilm', array('id' => $iassign_statement_activity_item->iassign_ilmid));
  213. $context = context_module::instance($USER->cm);
  214. //D if ($USER->id==3) echo "<br/> * html5.php: show_activity_in_ilm(.): {context}.id=" . $context->id . ", iassign_statement_activity_item.id=" . $iassign_statement_activity_item->id . ", view_teacherfileversion=" . $view_teacherfileversion . "<br/>\n";
  215. //TODO Given an activity => find its correspondent file in Moodle data. Bad solution!
  216. //TODO Change the meaning of 'iassign_statement.file' from insertion order to the ID in table 'files'.
  217. //TODO This demands update to each 'iassign_statement', find its corresponding on in 'files', and update 'iassign_statement.file = files.id'
  218. if ($view_teacherfileversion) { // get the exercise in Moodle data (teacher file)
  219. //D if ($USER->id==3) echo " * html5.php: show_activity_in_ilm(.): iassign_statement_activity_item.id=" . $iassign_statement_activity_item->id . ": carrega " . $CFG->dirroot . '/mod/iassign/files_functions.php' . "<br/>\n";
  220. $fileid = "";
  221. $fs = get_file_storage();
  222. //$files = $fs->get_area_files($context->id, 'mod_iassign', 'exercise', $iassign_statement_activity_item->id); // iassign_statement_activity_item = table 'iassign_statement'
  223. // $answer_files = html5::recover_from_files($fs, $context->id, $iassign_statement_activity_item->id, $iassign_statement_activity_item->file, $iassign_statement_activity_item->filesid);
  224. require_once($CFG->dirroot . '/mod/iassign/files_functions.php'); // files_functions.php ! get_from_files(.)
  225. // echo "html5.php: {iassign_statement}.id=" . $iassign_statement_activity_item->id . ", file=" . $iassign_statement_activity_item->file . ", filesid=" . $iassign_statement_activity_item->filesid . "<br/>\n";
  226. $answer_files = NULL;
  227. if ($iassign_statement_activity_item->file!=0 || $iassign_statement_activity_item->filesid!=0) { // problem with restore?
  228. $answer_files = get_from_files(
  229. $iassign_statement_activity_item->id, $iassign_statement_activity_item->file, $iassign_statement_activity_item->filesid,
  230. $fs, $context->id, 'mod_iassign', 'exercise');
  231. if ($answer_files == NULL) { // Error: no {files} were found in this context with these 3 itemid
  232. $answer_files = get_from_files(
  233. $iassign_statement_activity_item->id, $iassign_statement_activity_item->filesid, $iassign_statement_activity_item->filesid,
  234. $fs, $context->id, 'mod_iassign', 'exercise');
  235. }
  236. }
  237. //D if ($USER->id==3) echo " * html5.php: show_activity_in_ilm(.): #answer_files=" . count($answer_files) . "<br/>\n"; //exit;
  238. $one_files = NULL;
  239. $one_files_id = -1;
  240. $one_files_filename = "<vazio>";
  241. if ($answer_files == NULL) { // Error: no {files} were found in this context with these 3 itemid
  242. print "Error: {iassign_statement}.id=" . $iassign_statement_activity_item->id . " associated file not found! file=" .
  243. $iassign_statement_activity_item->file . ", filesid=" . $iassign_statement_activity_item->filesid . "<br/>\n";
  244. }
  245. else {
  246. $one_files = $answer_files[0]; // get $f1_obj from 'files_functions.php!get_from_files(.)'
  247. if (!empty($one_files)) {
  248. $one_files_id = $one_files->get_id(); // write_iLM_security(.) will use this ID to get file content
  249. $one_files_filename = $one_files->get_filename();
  250. }
  251. //D if ($USER->id==3) echo " &nbsp; + {files} : id=" . $one_files_id . ", itemid=" . $one_files->get_itemid() . ", filename=" . $one_files_filename . "<br/>\n"; //leo
  252. }
  253. //D echo " * voltou de 'recover_from_files' com one_files_id=" . $one_files_id . "<br/>\n";
  254. if ($one_files_id == -1) { // 'Something is wrong. Maybe your teacher withdrew this exercise file. Please, inform your teacher.';
  255. //D echo "ERRO: one_files_id=-1<br/>\n";
  256. print iassign::warning_message_iassign('error_exercise_removed') . "<br/>\n"; // I couldn't find the file in table 'files'!
  257. }
  258. } // if ($view_teacherfileversion)
  259. $ilm_name = strtolower($ilm->name);
  260. $extension = iassign_utils::filename_extension($ilm_name);
  261. if ($view_teacherfileversion) { // $view_teacherfileversion==1 => load the exercise ('activity') from the 'moodledata' (id in 'files')
  262. // $content_or_id_from_ilm_security = $this->context->id;
  263. // The content is here: $one_files->get_content(); // since it is teacher get the file contents at once
  264. // however the iLM must requires the content (using ./mod/iassign/ilm_security.php)
  265. $content_or_id_from_ilm_security = $one_files_id; // $iassign_statement_activity_item->file;
  266. }
  267. else { // $view_teacherfileversion==null => load the learner answer from the data base (iassign_submission)
  268. $content_or_id_from_ilm_security = $student_answer;
  269. }
  270. $allow_submission = false; // There is permission to 'submission' button?
  271. // Student already send one answer and the iLM allow to edit the submissiont
  272. // For instance, the Java version of iGeom does not allow editting (because the send answer do not has the target objects)
  273. // However, the iVProg JavaScript version allows editing
  274. // if ($USER->iassignEdit == 1 && $student_answer) { // for now, only iVProg2 and iVProgH5 allows editions of exercise already sent
  275. if ($ilm->editingbehavior == 1 && $student_answer) { // if iLM allow to edit previous solution
  276. $allow_submission = true; // yes!
  277. if ($enderecoPOST!="") {
  278. // In "locallib.php!view_iassign_current()", if due date is excedeed (even with allow test {iassign_statement}.test==1): $enderecoPOST = "";
  279. $write_solution = 1;
  280. $enderecoPOST .= "&write_solution=1"; // complement POST address indicating that the learner could send edited solution
  281. }
  282. }
  283. // Prepare JS to the button "send" to the iAssign addres in $enderecoPOST
  284. // $enderecoPOST is prepared in 'locallib.php:view_iassign_current()'
  285. // with "http://.../mod/iassign/view.php?action=get_answer&iassign_submission_current=ID1&id=ID2&iassign_current=ID3&write_solution=1&userid_iassign=ID4&write_solution=1
  286. // ID1 = {iassign_submission}.id
  287. // ID2 = {course_modules}.id with {course_modules}.instance = {iassign}.id
  288. // ID3 = {iassign_statement}.id
  289. // ID4 = {user}.id
  290. $iassign = "
  291. <script type='text/javascript'>
  292. //<![CDATA[
  293. var strAnswer = '';
  294. var evaluationResult = '';
  295. var comment = '';
  296. function jsAnalyseAnswer () { // this function will call the iLM function 'getEvaluation()'
  297. document.getElementById('spinner-loading').style.visibility = 'visible';
  298. setTimeout(function(){
  299. document.getElementById('spinner-loading').style.visibility = 'hidden';
  300. }, 5000);
  301. // iVProg will call function 'getEvaluationCallback(...)': /var/www/html/.../<iLM_name>/<iLM_version>/<iLM_dir>/js/iassign-integration-functions.js
  302. // - 'getEvaluation()' calls 'js/iassign-integration-functions.js : endTest function(index)' that calls 'getEvaluationCallback(apro/100);'
  303. // iFractions: sumEval = getSummation(); alert('mod/iassign/ilm/ifractions_5/index.html: sumEval = ' + sumEval);
  304. //ATTENTION 2017/11/22 - the use of 'window.frames.iLM' here, results in error 'TypeError: window.frames.iLM.getEvaluation is not a function'
  305. //ATTENTION answerGrade = window.frames.iLM.getEvaluation();
  306. var answerGrade = window.frames[0].getEvaluation(); // with the first frame (can not have another frame!), get the iLM student content
  307. console.log('./iassign/ilm_handlers/html5.php: jsAnalyseAnswer(): getEvaluation() returned value = ' + answerGrade);
  308. // document.getElementsByTagName('frame')[0].src
  309. // here answerGrade will return 'undefined' always
  310. if (answerGrade == 'undefined' || answerGrade == undefined) {
  311. console.log('./iassign/ilm_handlers/html5.php: jsAnalyseAnswer(): Ups! answerGrade undefined!');
  312. return false;
  313. }
  314. strAnswer = window.frames[0].getAnswer(); // get from iLM the student answer
  315. document.formEnvio.iLM_PARAM_ArchiveContent.value = strAnswer;
  316. document.formEnvio.iLM_PARAM_ActivityEvaluation.value = answerGrade;
  317. document.formEnvio.iLM_PARAM_RealGrade.value = answerGrade;
  318. console.log('./iassign/ilm_handlers/html5.php: jsAnalyseAnswer(): iLM_PARAM_RealGrade<-' + answerGrade);
  319. console.log(' * iLM_PARAM_ArchiveContent=' + strAnswer);
  320. console.log('-----');
  321. document.formEnvio.submit();
  322. return true; // success
  323. }
  324. window.flagclick = false;
  325. // ./mod/iassign/ilm/<iLM-name>/js/iassign-integration-functions.js : call this to define the variable 'evaluationResult'
  326. function getEvaluationCallback (evaluation) {
  327. let submissionbehavior = " . $ilm->submissionbehavior . ";
  328. // console.log('getEvaluationCallback(): evaluation=' + evaluation + ', submissionbehavior=' + submissionbehavior);
  329. // console.log('getEvaluationCallback(): enderecoPOST=" . $enderecoPOST . "');
  330. evaluationResult = evaluation;
  331. // Before 2017/11/22: strAnswer = window.frames.iLM.getAnswer();
  332. strAnswer = window.frames[0].getAnswer();
  333. // comment = document.formEnvio.submission_comment.value;
  334. //D alert('getEvaluationCallback(...)' + evaluation + ', strAnswer=' + strAnswer);
  335. //D alert('getEvaluationCallback: enviando evaluationResult=' + evaluation + ', strAnswer=' + strAnswer);
  336. if ((strAnswer==null || strAnswer=='' || strAnswer==-1)) { // undefined // //R && (comment==null || comment=='')
  337. alert('" . get_string('activity_empty', 'iassign') . "'); // 'Activity sent without content.'
  338. return false; // error...
  339. }
  340. else if (submissionbehavior == 1) { // iLM has no submition button, use the form one
  341. document.formEnvio.iLM_PARAM_ArchiveContent.value = strAnswer;
  342. document.formEnvio.iLM_PARAM_ActivityEvaluation.value = evaluationResult;
  343. document.formEnvio.iLM_PARAM_RealGrade.value = evaluation;
  344. //D alert(strAnswer);
  345. document.formEnvio.submit();
  346. return true; // success
  347. }
  348. else if (submissionbehavior == 0) { // iLM has submition button - then, use it to submit answer
  349. var formData = new FormData();
  350. formData.append('iLM_PARAM_ArchiveContent', strAnswer);
  351. formData.append('iLM_PARAM_ActivityEvaluation', evaluationResult);
  352. formData.append('iLM_PARAM_RealGrade', evaluation);
  353. formData.append('iLM_ajax', 1);
  354. var request = new XMLHttpRequest();
  355. request.open('POST', '" . $enderecoPOST . "');
  356. request.onload = function (e) {
  357. if (!window.flagclick) return;
  358. window.flagclick = false;
  359. document.getElementById('spinner-loading').style.visibility = 'hidden';
  360. if (request.readyState === 4) {
  361. if (request.status === 200) {
  362. document.getElementById('check-message-success-submission').style.visibility = 'visible';
  363. setTimeout(function(){
  364. document.getElementById('check-message-success-submission').style.visibility = 'hidden';
  365. }, 3000);
  366. } else {
  367. document.getElementById('error-message-submission').style.visibility = 'visible';
  368. }
  369. } else {
  370. document.getElementById('error-message-submission').style.visibility = 'visible';
  371. }
  372. };
  373. request.send(formData);
  374. }
  375. }
  376. //]]>
  377. </script>\n";
  378. // Security: this avoid the student get a second access to the file content (usually an exercise)
  379. // Data are registered in the table '*_iassign_security' bellow and is erased by function 'view()' above.
  380. // IMPORTANT: the '$end_file' will receive the iLM content URL using the security filter './mod/iassign/ilm_security.php'
  381. // the iLM must request the content using this URL. Data are registered in the table '*_iassign_security'.
  382. // Attention : using iVProgH5 there are lot of " and the use of slashes (as '\"') will imply in iVProgH5 do not read the file!
  383. // do not use: $id_iLM_security = $this->write_iLM_security($iassign_statement_activity_item->id, addslashes($content_or_id_from_ilm_security));
  384. //2017 $id_iLM_security = $this->write_iLM_security($iassign_statement_activity_item->id, $content_or_id_from_ilm_security); // insert in 'iassign_security'
  385. //2017 $this->remove_old_iLM_security_entries($USER->id, $iassign_statement_activity_item->id); // additional security: erase eventually old entries
  386. require_once $CFG->dirroot . '/mod/iassign/ilm_security.php';
  387. $timecreated = time();
  388. $token = md5($timecreated); // iassign_iLM_security->timecreated);
  389. //D if ($USER->id==3) echo " * html5.php: antes de 'write_iLM_security': timecreated=".$timecreated.", iassign_statement_activity_item->id=".$iassign_statement_activity_item->id.", content_or_id_from_ilm_security=".$content_or_id_from_ilm_security."<br/>\n"; //leo
  390. // Additional security to avoid error on "INSERT INTO {iassign_security} (...)"
  391. if (!$content_or_id_from_ilm_security || (is_numeric($content_or_id_from_ilm_security) && !($content_or_id_from_ilm_security>0)))
  392. $content_or_id_from_ilm_security = -1; // to avoid 'write_iLM_security(.)' try to load non existent file
  393. $id_iLM_security = ilm_security::write_iLM_security($USER->id, $timecreated, $iassign_statement_activity_item->id, $content_or_id_from_ilm_security); // insert in 'iassign_security'
  394. // $iassign_iLM_security = $DB->get_record("iassign_security", array("id" => $id_iLM_security));
  395. $end_file = $CFG->wwwroot . '/mod/iassign/ilm_security.php?id=' . $id_iLM_security . '&token=' . $token . '&view=' . $view_teacherfileversion; // need full path...
  396. // $iassign = "..."
  397. $iassign .= "\n<center>\n<form name='formEnvio' id='formEnvio' method='post' action='" . $enderecoPOST . "' enctype='multipart/form-data'>\n";
  398. // Attention: The actual iLM content will be provided by the indirect access in './mod/iassign/ilm_security.php',
  399. // bellow only the 'token' to the content will be shown in URL (by security reason). The iLM must use this URL on
  400. // 'MA_PARAM_Proposition' to request the content.
  401. // Calls static function bellow: parameters are data to store in table '*_iassign_submission'
  402. // In 'locallib.php ! class ilm_settings ! static function build_ilm_tags($ilm_id, $options = array())' that calls 'build_ilm_tags(.)' from here
  403. $iassign .= ilm_settings::build_ilm_tags($ilm->id, array(
  404. "type" => "activity",
  405. "notSEND" => "false",
  406. "addresPOST" => $enderecoPOST,
  407. "Proposition" => $end_file,
  408. "special_param" => $special_param1,
  409. "student_answer" => $student_answer,
  410. "id_iLM_security" => $id_iLM_security,
  411. "iassign_statement" => $iassign_statement_activity_item->id // MOOC 2016
  412. ));
  413. //DEBUG To verify iLM
  414. //D $iassign .= "
  415. //D <script type='text/javascript'>
  416. //D //alert('./mod/iassign/ilm_handlers/html5.php: 1 window.frames[0].getEvaluation()=' + window.frames[0].getEvaluation()); //
  417. //D alert('./mod/iassign/ilm_handlers/html5.php: 1 window.frames[0].getAnswer()=' + window.frames[0].getAnswer()); //
  418. //D </script>\n";
  419. if ($ilm->editingbehavior == 1 || !$student_answer) // the iLM allows editing old submission or has no previous solution send
  420. $allow_submit_button = 1;
  421. else
  422. $allow_submit_button = 0;
  423. //D echo "./iassign/ilm_handlers/html5.php: show_activity_in_ilm(.): ilm->action_buttons=" . $ilm->action_buttons . "<br/>";
  424. //D echo " - iassign_statement_activity_item->type_iassign=" . $iassign_statement_activity_item->type_iassign . ", _GET['action']=" . $_GET['action'] . "<br/>";
  425. // "iassign_statement_activity_item.type_iassign" == 1 => is activity of type "example" - not submit button for submission
  426. // {iassign_ilm}.action_buttons==1 <=> do not use the submition button of the form
  427. if (!isguestuser() && $iassign_statement_activity_item->type_iassign != 1 && $allow_submit_button == 1) {
  428. // ($ilm->editingbehavior == 1 || ($ilm->editingbehavior == 0 && !in_array($_GET['action'], array('viewsubmission', 'view')))))
  429. //D echo " - entrou 1<br/>\n";
  430. $iassign .= " <input type='hidden' name='iLM_PARAM_ArchiveContent' value=''>\n";
  431. $iassign .= " <input type='hidden' name='iLM_PARAM_ActivityEvaluation' value=''>\n";
  432. $iassign .= " <input type='hidden' name='iLM_PARAM_RealGrade' value=''>\n";
  433. // Default: enable button to submit activity - need to avoid "Warning: Undefined variable $disabled_button in..."
  434. $disabled_button = ""; // {iassign_ilm}.action_buttons==1 <=> do not use the submition button of the form
  435. //2023/05/08 Desabilitado para evitar ficar sem o botao!
  436. //2023/05/08 if ($ilm->action_buttons == 1) $disabled_button = "";
  437. //2023/05/08 elseif ($ilm->action_buttons == 0) $disabled_button = " disabled='true' ";
  438. // $iassign .= "<p><textarea rows='2' cols='60' name='submission_comment'></textarea></p>\n";
  439. // Prepare button to send answer (calling the iLM getEvaluation())
  440. // In "locallib.php!view_iassign_current()", if due date is excedeed (even with allow test {iassign_statement}.test==1): $enderecoPOST = "";
  441. // For this reason, if $enderecoPOST == "", do NOT present submission button!
  442. // {iassign_statement}.preventlate==0 <=> do NOT allow submission after due date
  443. if ($enderecoPOST && $enderecoPOST!="&write_solution=1" && $enderecoPOST!="&write_solution=0") {
  444. // There is a valid address - caution with $iassign_statement_activity_item->preventlate==1 <=> allow submission after due date
  445. $iassign .= "<center>\n<!-- load button -->\n" .
  446. " <br> <br> <button " . $disabled_button . " class='btn btn-primary' type=button value='" . get_string('submit_iassign', 'iassign') . "' " .
  447. " onClick = 'window.flagclick = true; window.jsAnalyseAnswer();' title='" . get_string('message_submit_iassign', 'iassign') . "'>" .
  448. get_string('submit_iassign', 'iassign') . "</button> <i id='check-message-success-submission' class='fa fa-check' aria-hidden='true' " .
  449. " style='position: absolute; color: green; font-size: 2.0rem; margin-left: 1rem; visibility: hidden;'><span style='font-size: 1.0rem;'>" .
  450. get_string('get_answer', 'iassign') . "</span></i><i id='error-message-submission' class='fa fa-times' aria-hidden='true' " .
  451. " style='position: absolute; color: red; font-size: 2.0rem; margin-left: 1rem; visibility: hidden;'><span style='font-size: 1.0rem;'>" .
  452. get_string('error_insert_submissions', 'iassign') . "</span></i>\n" . " <div class='spinner-border' style='position: absolute; margin-left: 1rem; visibility: hidden;' " .
  453. " id='spinner-loading' role='status'><span class='sr-only'>Loading...</span>\n </div> </center>\n";
  454. }
  455. } // if (!isguestuser() && $iassign_statement_activity_item->type_iassign != 1 && $allow_submit_button == 1)
  456. elseif ($ilm->editingbehavior == 0 && $student_answer) { // already send some answer
  457. // Button to redo the activity
  458. //D echo " - entrou 2<br/>\n";
  459. $iassign .= "<center><br><a href=\"view.php?action=repeat&id=" . $_GET['id'] . "&iassign_current=" . $_GET['iassign_current'] . "\"> \n" .
  460. " <button type='button' class='btn btn-success' value='" . get_string('repeat', 'iassign') . "'>" . get_string('repeat', 'iassign') . "</button></a></center>\n";
  461. }
  462. //D else echo " - NAO entrou <br/>\n";
  463. $iassign .= "</form></center>\n\n";
  464. return $iassign;
  465. } // public static function show_activity_in_ilm($iassign_statement_activity_item, $student_answer, $enderecoPOST, $view_teacherfileversion)
  466. /// Presents iLM information
  467. public static function view_ilm ($ilmid, $from) {
  468. global $DB;
  469. $url = new moodle_url('/admin/settings.php', array('section' => 'modsettingiassign'));
  470. $iassign_ilm = $DB->get_record('iassign_ilm', array('id' => $ilmid));
  471. $str = "";
  472. $str .= '<table id="outlinetable" cellpadding="5" width="100%" >' . "\n";
  473. $str .= '<tr>';
  474. $str .= '<td colspan=3 align=right>';
  475. if ($from != 'admin') {
  476. $str .= '<input type=button value="' . get_string('return', 'iassign') . '" onclick="javascript:window.location = \'' . $_SERVER['HTTP_REFERER'] . '\';">' . "\n";
  477. }
  478. $str .= '<input type=button value="' . get_string('close', 'iassign') . '" onclick="javascript:window.close();">';
  479. $str .= '</td>' . "\n";
  480. $str .= '</tr>' . "\n";
  481. if ($iassign_ilm) {
  482. $iassign_statement_activity_item = $DB->get_records('iassign_statement', array("iassign_ilmid" => $iassign_ilm->id));
  483. if ($iassign_statement_activity_item) {
  484. $total = count($iassign_statement_activity_item);
  485. } else {
  486. $total = 0;
  487. }
  488. if ($from == 'admin') {
  489. $str .= '<tr><td colspan=2>' . "\n";
  490. $str .= '<table width="100%" class="generaltable boxaligncenter" >' . "\n";
  491. $str .= '<tr>' . "\n";
  492. $str .= '<td class=\'cell c0 actvity\' ><strong>' . get_string('activities', 'iassign') . ':</strong>&nbsp;' . $total . '</td>' . "\n";
  493. $str .= '<td><strong>' . get_string('url_ilm', 'iassign') . '</strong>&nbsp;<a href="' . $iassign_ilm->url . '">' . $iassign_ilm->url . '</a></td>' . "\n";
  494. $str .= '</tr>' . "\n";
  495. $str .= '<tr><td colspan=2><strong>' . get_string('description', 'iassign') . ':</strong>&nbsp;' . iassign_language::get_description_lang(current_language(), $iassign_ilm->description) . '</td></tr>' . "\n";
  496. $str .= '<tr><td width="50%"><strong>' . get_string('type_ilm', 'iassign') . ':</strong>&nbsp;' . $iassign_ilm->type . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>' . get_string('extension', 'iassign') . ':</strong>&nbsp;' . $iassign_ilm->extension . '</td>' . "\n";
  497. $str .= '<td width="50%"><strong>' . get_string('width', 'iassign') . ':</strong>&nbsp;' . $iassign_ilm->width;
  498. $str .= '&nbsp;&nbsp;<strong>' . get_string('height', 'iassign') . ':</strong>&nbsp;' . $iassign_ilm->height . '</td></tr>' . "\n";
  499. $date_jar = $iassign_ilm->file_jar;
  500. $str .= '<tr><td><strong>' . get_string('file_jar', 'iassign') . ':</strong>&nbsp;' . $date_jar . '</td>' . "\n";
  501. $str .= '<td ><strong>' . get_string('file_class', 'iassign') . ':</strong>&nbsp;' . $iassign_ilm->file_class . '</td></tr>' . "\n";
  502. if ($iassign_ilm->evaluate == 1) {
  503. $evaluate = get_string('yes', 'iassign');
  504. } else {
  505. $evaluate = get_string('no', 'iassign');
  506. }
  507. $str .= '<tr><td width="50%"><strong>' . get_string('evaluate', 'iassign') . ':</strong>&nbsp;' . $evaluate . '</td>' . "\n";
  508. if ($iassign_ilm->enable == 1) {
  509. $enable = get_string('yes', 'iassign');
  510. } else {
  511. $enable = get_string('no', 'iassign');
  512. }
  513. $str .= '<td width="50%"><strong>' . get_string('enable', 'iassign') . ':</strong>&nbsp;' . $enable . '</td></tr>' . "\n";
  514. $str .= '<tr>' . "\n";
  515. $str .= '<td width="50%"><strong>' . get_string('file_created', 'iassign') . ':</strong>&nbsp;' . userdate($iassign_ilm->timecreated) . '</td>' . "\n";
  516. $str .= '<td width="50%"><strong>' . get_string('file_modified', 'iassign') . ':</strong>&nbsp;' . userdate($iassign_ilm->timemodified) . '</td>' . "\n";
  517. $str .= '</tr>' . "\n";
  518. $user_ilm = $DB->get_record('user', array('id' => $iassign_ilm->author));
  519. if ($user_ilm) {
  520. $str .= '<tr>' . "\n";
  521. $str .= '<td colspan=2><strong>' . get_string('author', 'iassign') . ':</strong>&nbsp;' . $user_ilm->firstname . '&nbsp;' . $user_ilm->lastname . '</td>' . "\n";
  522. $str .= '</tr>' . "\n";
  523. }
  524. $str .= '</table>' . "\n";
  525. $str .= '</td></tr>' . "\n";
  526. }
  527. if (!empty($iassign_ilm->file_jar)) {
  528. //TODO: REVIEW: to be used for parameters of "applet" from DB
  529. $options = array("type" => "view"); //MOOC2014: start
  530. $str .= '<tr class=\'cell c0 actvity\'><td colspan=3 align=center bgcolor="#F5F5F5">' . "\n";
  531. // Second parameter null since 'iassign_security' are not define yet
  532. $str .= ilm_settings::build_ilm_tags($iassign_ilm->id, $options);
  533. //TODO: REVIEW: missing code to manage parameters
  534. //MOOC2014: tem este codigo!
  535. } else {
  536. $str .= '<tr class=\'cell c0 actvity\'>' . "\n";
  537. $str .= '<td colspan=2 align=center>' . get_string('null_file', 'iassign') . '</td>' . "\n";
  538. $str .= '<td align=center><a href="' . $url . '</a></td>' . "\n";
  539. $str .= '</tr>' . "\n";
  540. }
  541. $str .= '</td></tr>' . "\n";
  542. }
  543. $str .= '</table>' . "\n";
  544. return $str;
  545. } // public static function view_ilm($ilmid, $from)
  546. /// Make a copy or produce a new version of an iLM (using a ZIP package)
  547. // Interface: Administration > plugins > iAssign : after select the iLM and the option 'Add new iLM version'
  548. // @see settings_ilm.php: $action == 'new_version'
  549. // @calledby locallib.php!copy_new_version_ilm($param): with $action=='new_version' or $action=='copy'
  550. public static function copy_new_version_ilm ($param, $files_extract) {
  551. global $DB, $CFG;
  552. $iassign_ilm = new stdClass();
  553. $iassign_ilm->name = $param->name;
  554. $iassign_ilm->version = $param->version;
  555. $iassign_ilm->file_jar = null;
  556. //D echo "html5.php!copy_new_version_ilm(.): <br/>"; // . $type_ipz_zip . "<br/>";
  557. //D // echo "param="; print_r($param);
  558. //D echo "Construir 'application_xml'<br/>";
  559. // Since we are using the same code that process IPZ package (that uses tags from "ilm-application.xml"), lets build it!
  560. $application_xml = new stdClass(); // build object with fields equivalent to those in "ilm-application.xml" from IPZ importer
  561. foreach ($param as $field => $value) {
  562. $application_xml->$field = $value;
  563. //D echo $field . "=" . $value . "; ";
  564. }
  565. //D $application_xml = @simplexml_load_file($CFG->dataroot . '/temp/' . 'ilm-application.xml', null, LIBXML_NOCDATA); // get XML fields
  566. //D echo "<br/>file_jar=" . $file_jar . "<br/>";
  567. $paramcopy_zip = "copy";
  568. if ($param->action == "new_version")
  569. $paramcopy_zip = "zip";
  570. // It creates directory and iLM files on it, will return the iLM path (after iAssign dir.): ./ilm/...
  571. $dir_and_file_jar = self::save_ilm_by_xml($paramcopy_zip, $application_xml, $files_extract);
  572. $ilm_final_directory = $dir_and_file_jar[0]; // {iassign_ilm}.file_jar is the first element (not used here)
  573. $file_jar = $dir_and_file_jar[1]; // {iassign_ilm}.file_jar is the second element (if null then occorred error, do not insert in {iassign_ilm})
  574. //D echo "file_jar=" . $file_jar . "<br/>";
  575. if ($file_jar == null) { // 'save_ilm_by_xml(...)' detected a problem (perhaps no write permission)
  576. //D echo "Erro! file_jar==null<br/>"; exit;
  577. return false;
  578. }
  579. $file_jar = str_replace("./", "", $file_jar);
  580. if ($file_jar[strlen($file_jar)-1]!=DIRECTORY_SEPARATOR)
  581. $file_jar .= DIRECTORY_SEPARATOR; // add final separator "/"
  582. //D echo "file_jar=" . $file_jar . "<br/>";
  583. //D exit; // to debug, stop here - before insert in {iassign_ilm} table
  584. // From a single text in default language => generate multi-language
  585. //R $description = json_decode($param->description_lang);
  586. //R $description->{$param->set_lang} = $param->description;
  587. $description_json_lang = $param->description_lang;
  588. $newentry = new stdClass();
  589. $newentry->name = $param->name;
  590. $newentry->version = $param->version;
  591. $newentry->type = 'HTML5';
  592. $newentry->url = $param->url;
  593. $newentry->description = $description_json_lang; //R strip_tags(json_encode($description));
  594. $newentry->extension = strtolower($param->extension);
  595. $newentry->file_jar = $file_jar;
  596. $newentry->file_class = $param->file_class;
  597. $newentry->width = $param->width;
  598. $newentry->height = $param->height;
  599. $newentry->enable = 0;
  600. $newentry->timemodified = $param->timemodified;
  601. $newentry->timecreated = $param->timecreated;
  602. $newentry->evaluate = $param->evaluate;
  603. $newentry->author = $param->author;
  604. $newentry->parent = $param->parent;
  605. $newentry->id = $DB->insert_record("iassign_ilm", $newentry);
  606. // log event --------------------------------------------------------------------------------------
  607. iassign_log::add_log('copy_iassign_ilm', 'name: ' . $param->name . ' ' . $param->version, 0, $newentry->id);
  608. // log event --------------------------------------------------------------------------------------
  609. } // public static function copy_new_version_ilm($param, $files_extract)
  610. /// Export the iLM to the IPZ package
  611. // @calledby locallib.php : export_ilm($ilm_id) : require_once 'ilm_handlers/' . $typec . '.php'; $typec::export_ilm($ilm_id);
  612. public static function export_ilm ($ilm_id) {
  613. global $DB, $CFG;
  614. $iassign_ilm = $DB->get_record('iassign_ilm', array('id' => $ilm_id));
  615. $iassign_ilm_configs = $DB->get_records('iassign_ilm_config', array('iassign_ilmid' => $ilm_id)); //MOOC 2016
  616. //if (!$iassign_ilm_configs) return;
  617. $files_jar = $iassign_ilm->file_jar;
  618. $zip_filename = $CFG->dataroot . '/temp/ilm-' . iassign_utils::format_pathname($iassign_ilm->name . '-v' . $iassign_ilm->version) . '_' . date("Ymd-Hi") . '.ipz';
  619. $zip = new zip_archive;
  620. $zip->open($zip_filename);
  621. $rootdir = $CFG->dirroot . '/mod/iassign/' . $files_jar;
  622. $first_folder = str_replace($CFG->dirroot . '/mod/iassign/ilm/', "", $rootdir);
  623. $zip->add_directory($first_folder);
  624. $allfiles = self::list_directory($rootdir);
  625. $i = 0;
  626. foreach ($allfiles as $file) {
  627. $mini = str_replace($CFG->dirroot . '/mod/iassign/ilm/', "", $file);
  628. $mini = str_replace('//', "/", $mini);
  629. if (is_dir($file)) {
  630. $zip->add_directory($mini);
  631. } else {
  632. $zip->add_file_from_pathname($mini, $file);
  633. }
  634. }
  635. $folder = str_replace('ilm/', "", $files_jar);
  636. $application_descriptor = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
  637. $application_descriptor .= '<application xmlns="http://line.ime.usp.br/application/1.5">' . "\n"; //TODO: o que colocar aqui???
  638. $application_descriptor .= ' <name>' . $iassign_ilm->name . '</name>' . "\n";
  639. $application_descriptor .= ' <url>' . $iassign_ilm->url . '</url>' . "\n";
  640. $application_descriptor .= ' <version>' . $iassign_ilm->version . '</version>' . "\n";
  641. $application_descriptor .= ' <type>' . $iassign_ilm->type . '</type>' . "\n";
  642. $application_descriptor .= ' <description>' . html_entity_decode(str_replace(array('<p>', '</p>'), array('', ''), $iassign_ilm->description)) . '</description>' . "\n";
  643. $application_descriptor .= ' <extension>' . $iassign_ilm->extension . '</extension>' . "\n";
  644. $application_descriptor .= ' <file_jar>' . $folder . '</file_jar>' . "\n";
  645. $application_descriptor .= ' <file_class>' . $iassign_ilm->file_class . '</file_class>' . "\n";
  646. $application_descriptor .= ' <width>' . $iassign_ilm->width . '</width>' . "\n";
  647. $application_descriptor .= ' <height>' . $iassign_ilm->height . '</height>' . "\n";
  648. $application_descriptor .= ' <evaluate>' . $iassign_ilm->evaluate . '</evaluate>' . "\n";
  649. $application_descriptor .= ' <reevaluate>' . $iassign_ilm->reevaluate . '</reevaluate>' . "\n";
  650. $application_descriptor .= ' <editingbehavior>' . $iassign_ilm->editingbehavior . '</editingbehavior>' . "\n";
  651. $application_descriptor .= ' <submissionbehavior>' . $iassign_ilm->submissionbehavior . '</submissionbehavior>' . "\n"; // 0 => iLM has no submition button, use the form one
  652. $application_descriptor .= ' <action_buttons>' . $iassign_ilm->action_buttons . '</action_buttons>' . "\n"; // {iassign_ilm}.ction_buttons==1 <=> do not use the submition button of the form
  653. if ($iassign_ilm_configs) { //MOOC 2016
  654. $application_descriptor .= ' <params>' . "\n";
  655. foreach ($iassign_ilm_configs as $iassign_ilm_config) {
  656. $application_descriptor .= ' <param>' . "\n";
  657. $application_descriptor .= ' <type>' . $iassign_ilm_config->param_type . '</type>' . "\n";
  658. $application_descriptor .= ' <name>' . $iassign_ilm_config->param_name . '</name>' . "\n";
  659. $application_descriptor .= ' <value>' . $iassign_ilm_config->param_value . '</value>' . "\n";
  660. $application_descriptor .= ' <description>' . htmlentities(str_replace("\n", "", $iassign_ilm_config->description)) . '</description>' . "\n";
  661. $application_descriptor .= ' <visible>' . $iassign_ilm_config->visible . '</visible>' . "\n";
  662. $application_descriptor .= ' </param>' . "\n";
  663. }
  664. $application_descriptor .= ' </params>' . "\n";
  665. } //MOOC 2016
  666. $application_descriptor .= '</application>' . "\n";
  667. $zip->add_file_from_string('ilm-application.xml', $application_descriptor);
  668. $zip->close();
  669. header("Pragma: public");
  670. header("Expires: 0");
  671. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  672. header("Cache-Control: private", false);
  673. header("Content-Type: application/zip");
  674. header("Content-Disposition: attachment; filename=\"" . basename($zip_filename) . "\";");
  675. header("Content-Transfer-Encoding: binary");
  676. header("Content-Length: " . (filesize($zip_filename)));
  677. set_time_limit(0);
  678. readfile($zip_filename) || die("File not found.");
  679. unlink($zip_filename);
  680. exit;
  681. } // public static function export_ilm($ilm_id)
  682. /// Function for list the directory where iLM is allocated.
  683. // @param type $dir
  684. // @return type
  685. static function list_directory ($dir) {
  686. $ds = DIRECTORY_SEPARATOR; // to use short name of directory separator (on Linux is "/")
  687. $files = array();
  688. $cont = 0;
  689. $ffs = scandir($dir);
  690. unset($ffs[array_search('.', $ffs, true)]);
  691. unset($ffs[array_search('..', $ffs, true)]);
  692. if (count($ffs) < 1) {
  693. return;
  694. }
  695. foreach ($ffs as $ff) {
  696. $files[$cont] = $dir . $ds . $ff;
  697. $cont++;
  698. if (is_dir($dir . $ds . $ff)) {
  699. $temp = self::list_directory($dir . $ds . $ff);
  700. foreach ($temp as $t) {
  701. $files[$cont] = $t;
  702. $cont++;
  703. }
  704. }
  705. }
  706. return $files;
  707. }
  708. /// Function to really remove files from the iLM remove from interface to remove iLM)
  709. // @calledy locallib.php!delete_ilm($ilm_id) : $return_ilm_parent_id = $typec::delete_ilm($ilm_id);
  710. // @param int $ilm_id is the iLM ID ({iassign_ilm}.id)
  711. // @return int Return ID of parent iLM ({iassign_ilm}.id)
  712. public static function delete_ilm ($ilm_id) {
  713. global $DB, $CFG, $OUTPUT;
  714. echo "ilm_handlers/html5.php!delete_ilm(.): remove www do " . $ilm_id. "<br/>\n"; //2025/04/11 leo
  715. $ds = DIRECTORY_SEPARATOR; // to use short name of directory separator (on Linux is "/")
  716. $iassign_ilm = $DB->get_record('iassign_ilm', array('id' => $ilm_id));
  717. //D echo "ilm_handlers/html5.php!delete_ilm(.): ilm_id=" . $ilm_id . ", file_jar=" . $iassign_ilm->file_jar . "<br/>\n"; //exit; //2025/04/11 leo
  718. // In case iLM has error in its path (perhaps during its creation or by misunderstanding edition)
  719. if (!file_exists($iassign_ilm->file_jar)) {
  720. //D echo "ilm_handlers/html5.php!delete_ilm(.): " . $iassign_ilm->file_jar . " nao existe, tenta completar<br/>\n"; //exit; //2025/04/11 leo
  721. // iLM directory under which the new version will be created
  722. $ilm_base_directory = "ilm" . $ds . $iassign_ilm->name; // ./mod/iassign/ilm/<iLM name>
  723. $ilm_directory_version = $ilm_base_directory . $ds . $iassign_ilm->version; // ./mod/iassign/ilm/<iLM name>/<iLM version>
  724. $iassign_ilm->file_jar = $ilm_directory_version;
  725. //D
  726. echo "ilm_handlers/html5.php!delete_ilm(.): completado para: " . $iassign_ilm->file_jar . "<br/>\n"; //exit; //2025/04/11 leo
  727. }
  728. // Prepare the path of directory to be removed
  729. $path_w = rtrim($iassign_ilm->file_jar, $ds); // remove white space and "/" from the end of the string
  730. $folder_to_remove = $path_w; // substr($path_w, 0, strrpos($path_w, '/') + 1); - ja tinha removido "/" final, com "rtrim(.)"
  731. echo "ilm_handlers/html5.php!delete_ilm(.): path_w="; print_r($path_w); echo "<br/> - folder_to_remove=" . $folder_to_remove . "<br/>\n"; //exit; //2025/04/11 leo
  732. // ilm_handlers/html5.php!delete_ilm(.): path_w=ilm/iHanoi/1.0.20240815
  733. // - folder_to_remove=ilm/iHanoi/
  734. // Check if the iLM directory is writable
  735. if (!is_writable($iassign_ilm->file_jar)) {
  736. //D echo "ilm_handlers/html5.php!delete_ilm(.): ilm_id=" . $ilm_id . ", ops, file_jar=" . $iassign_ilm->file_jar . " nao permite escrita<br/>\n"; //exit; //2025/04/11 leo
  737. return null;
  738. }
  739. self::delete_dir("www", $folder_to_remove); // from WWW of Moodle
  740. $ilm_folder = "ilm" . $ds . $iassign_ilm->name . $ds;
  741. $k = 0;
  742. // Verify if iLM parent directory is empty, if yes, remove it
  743. foreach (glob($ilm_folder . "*", GLOB_ONLYDIR) as $dir) {
  744. $k ++;
  745. break; // it is enough 1 (implies not empty, implies do not remove "ilm/<iLM name>")
  746. }
  747. if ($k == 0) { // parent directory is empty => this is the last iLM version, so also remove the it root ./ilm/<iLM name>
  748. echo "ilm_handlers/html5.php!delete_ilm(.): if k==0, ilm_id=" . $ilm_id . ", k=" . $k . ", delete_dir(" . $ilm_folder . ")<br/>\n"; //exit; //2025/04/11 leo
  749. self::delete_dir("www", $ilm_folder); // from WWW of Moodle
  750. }
  751. else echo "ilm_handlers/html5.php!delete_ilm(.): else k==0, ilm_id=" . $ilm_id . ", k=" . $k . ", delete_dir(" . $ilm_folder . ")<br/>\n"; //exit; //2025/04/11 leo
  752. $DB->delete_records("iassign_ilm", array('id' => $ilm_id));
  753. $DB->delete_records("iassign_ilm_config", array('iassign_ilmid' => $ilm_id)); //MOOC 2016
  754. // log event --------------------------------------------------------------------------------------
  755. iassign_log::add_log('delete_iassign_ilm', 'name: ' . $iassign_ilm->name . ' ' . $iassign_ilm->version, 0, $iassign_ilm->id);
  756. // log event --------------------------------------------------------------------------------------
  757. return $iassign_ilm->parent;
  758. } // public static function delete_ilm($ilm_id)
  759. /// Receive the updated data from an iLM to process it
  760. // @calledby locallib.php: static function edit_ilm($param,$itemid): $typec::edit_ilm($param,$itemid,$files_extract,$contextuser);
  761. public static function edit_ilm ($param, $itemid, $files_extract, $contextuser) {
  762. global $DB, $CFG;
  763. $ds = DIRECTORY_SEPARATOR; // to use short name of directory separator (on Linux is "/")
  764. $iassign_ilm = new stdClass();
  765. $iassign_ilm->name = $param->name;
  766. $iassign_ilm->version = $param->version;
  767. $iassign_ilm->file_jar = $param->file_jar;
  768. $file_jar = null;
  769. if (!is_null($files_extract)) { // if there is a new iLM (from IPZ pachage)
  770. $dir_and_file_jar = self::save_ilm_by_xml("edit", null, $files_extract);
  771. $ilm_final_directory = $dir_and_file_jar[0]; // {iassign_ilm}.file_jar is the first element (not used here)
  772. $file_jar = $dir_and_file_jar[1]; // {iassign_ilm}.file_jar is the second element
  773. if ($file_jar == null) {
  774. return false;
  775. }
  776. $file_jar = str_replace("." . $ds, "", $file_jar) . $ds; // "./"
  777. }
  778. if (is_null($file_jar)) {
  779. // there is not definition to 'file_jar' in the IPZ packege, use eventually something entered by the form
  780. $file_jar = $param->file_jar;
  781. }
  782. $description = json_decode($param->description_lang);
  783. $description->{$param->set_lang} = $param->description;
  784. $updentry = new stdClass();
  785. $updentry->id = $param->id;
  786. $updentry->version = $param->version;
  787. $updentry->url = $param->url;
  788. // $updentry->description = json_encode($description); //R strip_tags(json_encode($description)); // will replace any special character by tags
  789. // $updentry->description = html_entity_decode((String)$param->description_lang); - the same as above
  790. $updentry->description = json_encode($description, JSON_UNESCAPED_UNICODE); // encode using UTF8
  791. $updentry->extension = strtolower($param->extension);
  792. if (!is_null($file_jar)) {
  793. $updentry->file_jar = $file_jar;
  794. }
  795. $updentry->file_class = $param->file_class;
  796. $updentry->width = $param->width;
  797. $updentry->height = $param->height;
  798. $updentry->enable = $param->enable;
  799. $updentry->timemodified = $param->timemodified;
  800. $updentry->evaluate = $param->evaluate;
  801. $updentry->reevaluate = $param->reevaluate; // reevaluate = 1 => allows to the teacher calls method to re-evaluate (does it in batch, to all students)
  802. $updentry->editingbehavior = $param->editingbehavior; // editingbehavior = 1 => iLM auto-evaluation remains working over a solution sent by the student (iGeom does not work, iVProg does)
  803. $updentry->submissionbehavior = $param->submissionbehavior; // 0 => iLM has no submition button, use the form one; 1 => it has, use it
  804. //D echo "./ilm_handlers/html5.php: edit_ilm(...): file_jar=$file_jar, file_class=" . $updentry->file_class . "<br/>"; //D exit;
  805. $DB->update_record("iassign_ilm", $updentry);
  806. // log event --------------------------------------------------------------------------------------
  807. iassign_log::add_log('update_iassign_ilm', 'name: ' . $param->name . ' ' . $param->version, 0, $param->id);
  808. // log event --------------------------------------------------------------------------------------
  809. } // public static function edit_ilm($param, $itemid, $files_extract, $contextuser)
  810. //2023/05/30
  811. // Removi funcao NAO mais usada: static function new_file_ilm ($itemid, $fs, $contextuser, $contextsystem, $files_ilm)
  812. // Tambem removi homonima de './iassign/locallib.php': static function new_file_ilm ($itemid, $iassign_ilm)
  813. // Para : /home/leo/projetos/iMA/lms/itarefa/novo/removidos/locallib_html_2023_05_30.php
  814. // Help 'new_ilm(.)' to recover {iassign_ilm}.name with no more than 20 characters
  815. public static function get_xml_name ($app_xml) {
  816. if (!isset($app_xml)) return NULL;
  817. $name = (String) $app_xml->name;
  818. if (isset($name)) {
  819. $itens = explode(":", $name); // try "iVProg: something"
  820. $name = str_replace(" ", "_", $itens[0]); // avoid blanks in iLM name (to ./mod/iassign/ilm/<iLM name>)
  821. if (strlen($name)>20) {
  822. $name = substr($name, 0, 20); // {iassign}.name is char(20)
  823. }
  824. }
  825. return $name;
  826. }
  827. /// Add a new iLM using form (and ZIP package)
  828. // Admin user: arrive here trhough admin interface to manage "Plugins | Activity modules" then choosing "Add iLM".
  829. // The admin must fill a form (with all iLM meta-data) and load a ZIP package, then 'save_ilm_by_xml(.)'
  830. // will create the directory ./mod/iassign/ilm/<iLM name>/<iLM version>/<base_name>
  831. // and using files and meta-data in 'ilm-application.xml' will insert iLM data into {iassign_ilm} table
  832. // Before reach here, it came from 'locallib.php!new_ilm($itemid)' that is called by 'settings_ilm.php'
  833. // Admin user in iLM manager interface (iassign/settings_ilm.php) clicks on the button "Add iLM".
  834. // After this, "iassign/settings_ilm.php" calls "locallib.php!new_ilm($itemid)" that
  835. // calls this function (to insert new iLM in database and in proper directory)
  836. // @calledby ./mod/iassign/locallib.php!new_ilm($itemid): $retorno = $typec::new_ilm($itemid, $files_extract, $iassign_ilm_instance, $contextuser, $fs);
  837. public static function new_ilm ($itemid, $files_extract, $iassign_ilm_instance, $contextuser, $fs) {
  838. global $DB, $CFG, $USER, $OUTPUT;
  839. $description_str = $iassign_ilm_instance->description; // to {iassign_ilm}.description
  840. // If necessary truncate (String)$application_xml->name, since {iassign_ilm}.name has at most 20 characters!
  841. //TODO: also can use 'iassign_utils::filename_from_iLM_name($iassign_ilm_instance->name, false);'
  842. $ilm_trunc_name = html5::get_xml_name($iassign_ilm_instance); // send all data, standardizer 'get_xml_name($app_xml)' will get the field 'name'
  843. $array_ilm = array("name" => $ilm_trunc_name, "version" => $iassign_ilm_instance->version, "type" => $iassign_ilm_instance->type);
  844. $iassign_ilm = $DB->get_record('iassign_ilm', $array_ilm);
  845. $auxm = ": " . $ilm_trunc_name . ", " . $iassign_ilm_instance->version . ", " . $iassign_ilm_instance->type;
  846. //D //xxxxxxxxxxxxxxxxxxx remover
  847. //D $msg = " * new_ilm(.): files_extract: <br/>";
  848. //D foreach ($files_extract as $key => $value) $msg .= " - diretorio = " . $diretorio . " (" . $key . "," . $value . ")<br/>\n";
  849. //D echo $msg;
  850. //D if ($iassign_ilm) echo "Entrara 1<br/>";
  851. //D else echo "Entrara 2<br/>";
  852. //D exit;
  853. if ($iassign_ilm) { // there is such iLM (same name, version and type!)
  854. foreach ($files_extract as $key => $value) {
  855. $rootfolder = $CFG->dataroot . '/temp/' . $key;
  856. self::delete_dir("data", $rootfolder); // from Moodle data
  857. break;
  858. }
  859. print($OUTPUT->notification(get_string('error_import_ilm_version', 'iassign') . $auxm, 'notifyproblem')); // There is another iLM with the same version!
  860. return false;
  861. }
  862. else { // if ($iassign_ilm)
  863. //D $msg = " * new_ilm(.): files_extract: <br/>";
  864. //D foreach ($files_extract as $key => $value) $msg .= " - diretorio = " . $diretorio . " (" . $key . "," . $value . ")<br/>\n";
  865. //D echo $msg; exit;
  866. // It creates directory and iLM files on it, will return the iLM path (after iAssign dir.): ./ilm/...
  867. $dir_and_file_jar = self::save_ilm_by_xml("zip", $iassign_ilm_instance, $files_extract);
  868. $ilm_final_directory = $dir_and_file_jar[0]; // {iassign_ilm}.file_jar is the first element (not used here)
  869. $file_jar = $dir_and_file_jar[1]; // {iassign_ilm}.file_jar is the second element
  870. if ($file_jar == null) {
  871. return false;
  872. }
  873. //2022/05/13
  874. //D echo "/var/www/html/saw2021_2/mod/iassign/ilm_handlers/html5.php: file_jar=" . $file_jar . "<br/>\n";
  875. $file_jar = str_replace("./", "", $file_jar);
  876. //D echo "/var/www/html/saw2021_2/mod/iassign/ilm_handlers/html5.php: file_jar=" . $file_jar . "<br/>\n";
  877. if (empty($file_jar)) {
  878. $msg_error = get_string('error_add_ilm', 'iassign') . "<br/>In new_ilm: file_jar empty, files_extract=" . $files_extract . "<br/>\n";
  879. print_error($msg_error);
  880. //xx print_error('error_add_ilm', 'iassign');
  881. //print("New file = " . file_jar . "<br/>");
  882. }
  883. else { // if (empty($file_jar))
  884. //TODO {iassign_ilm}.name has at most 20 characters!
  885. // $ilm_trunc_name = (String) $iassign_ilm_instance->name;
  886. $iassign_ilm = $DB->get_record('iassign_ilm', array("parent" => 0, "name" => $ilm_trunc_name));
  887. if (!$iassign_ilm) {
  888. $iassign_ilm = new stdClass(); //MOOC 2016
  889. $iassign_ilm->id = 0;
  890. }
  891. $newentry = new stdClass();
  892. $newentry->name = $ilm_trunc_name; // html5::get_xml_name($iassign_ilm_instance); // be sure {iassign_ilm}.name is up to char(20)
  893. $newentry->version = (String) $iassign_ilm_instance->version;
  894. $newentry->type = (String) $iassign_ilm_instance->type;
  895. $newentry->url = (String) $iassign_ilm_instance->url;
  896. $newentry->description = strip_tags($description_str);
  897. $newentry->extension = strtolower((String) $iassign_ilm_instance->extension);
  898. $newentry->file_jar = $file_jar . "/"; //DEBUG need to use DIRECTORY_SEPARATOR (instead "/")?
  899. $newentry->file_class = (String) $iassign_ilm_instance->file_class;
  900. $newentry->width = (String) $iassign_ilm_instance->width;
  901. $newentry->height = (String) $iassign_ilm_instance->height;
  902. $newentry->enable = 0;
  903. $newentry->timemodified = time();
  904. $newentry->author = $USER->id;
  905. $newentry->timecreated = time();
  906. $newentry->evaluate = (String) $iassign_ilm_instance->evaluate;
  907. $newentry->reevaluate = (String) $iassign_ilm_instance->reevaluate;
  908. $newentry->parent = $iassign_ilm->id;
  909. $newentry->editingbehavior = (String) $iassign_ilm_instance->editingbehavior;
  910. $newentry->submissionbehavior = (String) $iassign_ilm_instance->submissionbehavior; // 0 => iLM has no submition button, use the form one; 1 => it has, use it
  911. $newentry->action_buttons = (String) $iassign_ilm_instance->action_buttons; // {iassign_ilm}.action_buttons==1 <=> do not use the submition button of the form
  912. $newentry->id = $DB->insert_record("iassign_ilm", $newentry); //leo voltar
  913. // log event --------------------------------------------------------------------------------------
  914. iassign_log::add_log('add_iassign_ilm', 'name: ' . $newentry->name . ' ' . $newentry->version, 0, $newentry->id); //2023/05/08 //leo voltar
  915. // log event --------------------------------------------------------------------------------------
  916. if ($iassign_ilm_instance->params->param) {
  917. foreach ($iassign_ilm_instance->params->param as $value) {
  918. $newentry = new stdClass();
  919. $newentry->iassign_ilmid = $iassign_ilmid;
  920. $newentry->param_type = (String) $value->type;
  921. $newentry->param_name = (String) $value->name;
  922. $newentry->param_value = (String) $value->value;
  923. $newentry->description = html_entity_decode((String) $value->description);
  924. $newentry->visible = (String) $value->visible;
  925. $newentry->id = $DB->insert_record("iassign_ilm", $newentry); //2023/05/08 //leo voltar
  926. if (!$newentry->id) {
  927. print_error('error_add_param', 'iassign');
  928. }
  929. }
  930. } // if ($iassign_ilm_instance->params->param)
  931. } // else // if (empty($file_jar))
  932. } // else // if ($iassign_ilm)
  933. $resp = $fs->delete_area_files($contextuser->id, 'user', 'draft', $itemid);
  934. //exit; //xxxxxxxxxxxxxxxxxxx remover
  935. return true;
  936. } // public static function new_ilm($itemid, $files_extract, $iassign_ilm_instance, $contextuser, $fs)
  937. // Adjust the cases in which 'ilm-application.xml' presents 'file_jar' starting with './' and does not have '/' in its final
  938. // @return $file_jar cleaned and with '/' final
  939. public static function adjust_File_jar ($file_jar) {
  940. $file_jar = trim($file_jar); // strip whitespace (or other characters) from the beginning and end of a string
  941. $file_jar = str_replace("./", "", $file_jar); // do not use tag 'file_jar' from 'ilm-application.xml', use actual directory name
  942. $size_file_jar = strlen($file_jar);
  943. if ($size_file_jar>0) {
  944. if ($file_jar[0] == '/') {
  945. $file_jar = substr($file_jar, 1, $size_file_jar-1); // erase initial '/'
  946. $size_file_jar--;
  947. }
  948. if ($file_jar[$size_file_jar-1] != "/") // does not end with "/" => insert it
  949. $file_jar .= '/'; // add final '/'
  950. }
  951. return $file_jar;
  952. }
  953. /// Import a iLM from IPZ package
  954. // Admin user: arrive here trhough admin interface to manage "Plugins | Activity modules" then choosing "Import iLM".
  955. // The admin must load the IPZ package, then 'save_ilm_by_xml(.)' will create the directory ./mod/iassign/ilm/<iLM name>/<iLM version>/<base_name>
  956. // and using files and meta-data in 'ilm-application.xml' will insert iLM data into {iassign_ilm} table
  957. // @calledby locallib.php!import_ilm($itemid)
  958. public static function import_ilm ($itemid, $files_extract, $application_xml, $contextuser, $fs) {
  959. global $DB, $CFG, $USER, $OUTPUT;
  960. $ds = DIRECTORY_SEPARATOR; // to use short name of directory separator (on Linux is "/")
  961. $description_str = str_replace(array('<description>', '</description>'), array('', ''), $application_xml->description->asXML());
  962. //D- echo "html5.php!import_ilm(...): application_xml=|"; print_r($application_xml); echo "|<br/>\n"; //exit;
  963. //TODO {iassign_ilm}.name has at most 20 characters!
  964. $iassign_ilm = $DB->get_record('iassign_ilm', array("name" => (String)$application_xml->name, "version" => (String)$application_xml->version));
  965. if ($iassign_ilm) { // There is (at least) one iLM with this 'name' and this 'version'
  966. foreach ($files_extract as $key0 => $value0) {
  967. //D- echo " self::delete_dir - " . $key0 . " , " . $value0. "<br/>\n";
  968. $rootfolder = $CFG->dataroot . $ds . 'temp' . $ds . $key0;
  969. self::delete_dir("data", $rootfolder); // from Moodle data
  970. break;
  971. }
  972. unlink($CFG->dataroot . $ds . 'temp' . $ds . "ilm-application.xml"); // also remove the "ilm-application.xml" file
  973. print($OUTPUT->notification(get_string('error_import_ilm_version', 'iassign'), 'notifyproblem'));
  974. }
  975. else {
  976. // This explode IPZ package coping all of its file/directories to ./mod/iassign/ilm/<iLM name>/<iLM version>/<base_name>
  977. // The <base_name> will be deduced from IPZ package, it must be the directory name containing files, i.e.
  978. // the directory at the same level of 'ilm-application.xml' descriptor file.
  979. // ATENTION: the tag 'file_jar' must coincide <base_name>, i.e. descriptor must have "<file_jar>base_name</file_jar>"
  980. $dir_and_file_jar = self::save_ilm_by_xml("ipz", $application_xml, $files_extract); // really creates iLM directory under ilm/<iLM name>/<iLM version>/<file_jar>
  981. $ilm_final_directory = $dir_and_file_jar[0]; // {iassign_ilm}.file_jar is the first element (not used here)
  982. $file_jar = $dir_and_file_jar[1]; // {iassign_ilm}.file_jar is the second element
  983. echo "dir_and_file_jar : ilm_final_directory="; print_r($ilm_final_directory); echo "<br/>file_jar="; print_r($file_jar); echo "<br/>"; //exit;
  984. if (!is_dir($file_jar)) { // If the admin does not includes "ilm/<iLM name>" add it to the $file_jar (since this path is necessary)
  985. // $items = explode("/", $ilm_final_directory); // get [<iLM name>, <iLM version>]
  986. // $iLMname = $items[0];
  987. $file_jar = "ilm" . $ds . $ilm_final_directory . $ds . $file_jar;
  988. echo " - completado file_jar=" . $file_jar. "<br/>\n"; //2025/04/11 leo
  989. }
  990. // ilm_final_directory=iHanoi/1.0.20240815, file_jar=ihanoi/
  991. if ($file_jar == null) {
  992. exit; // this allow to keep the error message into the interface
  993. // return false;
  994. }
  995. // If necessary truncate (String)$application_xml->name, since {iassign_ilm}.name has at most 20 characters!
  996. $ilm_xml_name = html5::get_xml_name($application_xml);
  997. // Adjust the cases in which 'ilm-application.xml' presents 'file_jar' starting with './' and does not have '/' in its final
  998. // $file_jar = html5::adjust_File_jar($file_jar); // do not use tag 'file_jar' from 'ilm-application.xml', use actual directory name
  999. if (empty($file_jar)) {
  1000. $msg_error = get_string('error_add_ilm', 'iassign') . "<br/>In import_ilm: file_jar empty, files_extract=" . $files_extract . "<br/>\n";
  1001. print_error($msg_error); //xx print_error('error_add_ilm', 'iassign'); //D print("Import file = " . file_jar . "<br/>");
  1002. }
  1003. else { // else if (empty($file_jar))
  1004. // Seach for iLM with this name $ilm_xml_name, considering only those with "type == 'HTML5'" (avoid to return similar Java iLM)
  1005. $iassign_ilm = $DB->get_record('iassign_ilm', array("parent" => 0, "name" => $ilm_xml_name, "type" => "HTML5"));
  1006. echo "apos get_record: iassign_ilm="; print_r($iassign_ilm); echo "<br/>"; //2026/09/03 leo
  1007. //TODO: NAO esta' removendo o diretorio?! //2026/09/03 leo
  1008. if (!$iassign_ilm) { // New iLM (it does not have any parent)
  1009. $iassign_ilm = new stdClass();
  1010. $iassign_ilm->id = 0;
  1011. }
  1012. //D- echo " - html5.php!import_ilm(.): ilm_xml_name=" . $ilm_xml_name . ", parent = iassign_ilm->id = " . $iassign_ilm->id . "<br/>\n"; //xxxxxxxxxx //2023/05/08 //leo remover
  1013. $newentry = new stdClass();
  1014. $newentry->name = $ilm_xml_name;
  1015. $newentry->version = (String) $application_xml->version;
  1016. $newentry->type = (String) $application_xml->type;
  1017. $newentry->url = (String) $application_xml->url;
  1018. $newentry->description = strip_tags($description_str);
  1019. $newentry->extension = strtolower((String) $application_xml->extension);
  1020. $newentry->file_jar = $file_jar; // it must ends with '/' - see 'adjust_File_jar(.)'
  1021. $newentry->file_class = (String) $application_xml->file_class;
  1022. $newentry->width = (String) $application_xml->width;
  1023. $newentry->height = (String) $application_xml->height;
  1024. $newentry->enable = 0;
  1025. $newentry->timemodified = time();
  1026. $newentry->author = $USER->id;
  1027. $newentry->timecreated = time();
  1028. $newentry->evaluate = (String) $application_xml->evaluate;
  1029. $newentry->reevaluate = (String) $application_xml->reevaluate;
  1030. $newentry->editingbehavior = (String) $application_xml->editingbehavior;
  1031. $newentry->submissionbehavior = (String) $application_xml->submissionbehavior; // 0 => iLM has no submition button, use the form one; 1 => it has, use it
  1032. $newentry->action_buttons = (String) $application_xml->action_buttons; // {iassign_ilm}.action_buttons==1 <=> do not use the submition button of the form
  1033. $newentry->parent = $iassign_ilm->id;
  1034. $iassign_ilmid = $DB->insert_record("iassign_ilm", $newentry); // insert in {iassign_ilm} table
  1035. if ($application_xml->params->param) {
  1036. foreach ($application_xml->params->param as $value) {
  1037. $newentry = new stdClass();
  1038. $newentry->iassign_ilmid = $iassign_ilmid;
  1039. $newentry->param_type = (String) $value->type;
  1040. $newentry->param_name = (String) $value->name;
  1041. $newentry->param_value = (String) $value->value;
  1042. $newentry->description = html_entity_decode((String) $value->description);
  1043. $newentry->visible = (String) $value->visible;
  1044. $newentry->id = $DB->insert_record("iassign_ilm", $newentry);
  1045. if (!$newentry->id) {
  1046. print_error('error_add_param', 'iassign');
  1047. }
  1048. }
  1049. } // if ($application_xml->params->param)
  1050. } // else if (empty($file_jar))
  1051. print $OUTPUT->notification(get_string('ok_import_ilm_version', 'iassign'), 'notifysuccess'); // The iLM was successfully imported!
  1052. }
  1053. $fs->delete_area_files($contextuser->id, 'user', 'draft', $itemid);
  1054. //D- echo " - import_ilm(.): newentry ="; print_r($newentry); echo "<br/>\n"; //xxxxxxxxxx //2023/05/08 //leo remover
  1055. } // public static function import_ilm($itemid, $files_extract, $application_xml, $contextuser, $fs)
  1056. /// Function for register iLM from XML descriptor (the 'ilm-application.xml' file in IPZ package)
  1057. // It creates the correspondent directory (the insertion in {iassin_ilm} table is under 'import_ilm(.)' responsability)
  1058. // @see : self::copy_new_version_ilm($param,$files_extract); edit_ilm($param,$itemid,$files_extract,$contextuser); new_ilm($itemid,$files_extract,$application_xml,$contextuser,$fs); import_ilm($itemid,$files_extract,$application_xml,$contextuser,$fs);
  1059. // @calledby : self::new_ilm($itemid,$files_extract,$application_xml,$contextuser,$fs) : $file_jar = self::save_ilm_by_xml($application_xml, $files_extract);
  1060. // @param string $str_from Define the event origin ("copy", "edit", "zip" or "ipz")
  1061. // @param array $application_xml Data of XML descriptor (with all {iassign_ilm} field and something more)
  1062. // @param array $files_extract Filenames of extract files
  1063. // @return string with the iLM path (since ./ilm/...)
  1064. static function save_ilm_by_xml ($str_from, $application_xml, $files_extract) {
  1065. global $CFG, $USER, $OUTPUT;
  1066. $ds = DIRECTORY_SEPARATOR; // to short name (to directory separator, on Linux "/")
  1067. $source = "";
  1068. $temp_directory = "";
  1069. //D echo "html5.php!save_ilm_by_xml(.): " .$str_from . "<br/>";
  1070. $html_header = "";
  1071. // ./lib/outputrenderers.php: public function notification($message, $type = null, $closebutton = true)
  1072. $html_header_end = "</html></body>"; // in case of erro, to close HTML format window frame (to be used with '$OUTPUT->notification(.)"
  1073. // Check if the iLM directory is writable: ./mod/iassign/ilm
  1074. if (!is_writable("ilm")) { // is writable the directory "/moodle/mod/iassign/ilm/"?
  1075. // Error: There are no permission to modify files in iLM directory. Please, you need to verify iLM directory permissions (Moodle admin prerogative)!
  1076. $err_msg = $html_header . get_string('error_folder_permission_denied', 'iassign') . "<br/>\n";
  1077. $err_msg .= get_string('error_folder_permission_dir', 'iassign') . " ./mod/iassign/ilm"; // Directory:
  1078. print $OUTPUT->header() . $OUTPUT->heading(get_string('error_folder_permission_create', 'iassign')); // "iLM creation error: directory without permission"
  1079. print $OUTPUT->notification($err_msg, 'notifyproblem') . $html_header_end;
  1080. exit; // ensure do not follow processing...
  1081. }
  1082. // The filter 'filename_from_iLM_name(...)' is essential to clear the name for directory from the iLM original name,
  1083. // it is used to define the field {iassign_ilm}.name has at most 20 characters!
  1084. // ./mod/iassign/locallib.php!(class iassign_utils) filename_from_iLM_name($ilm_name,$is_lowercase=true): remove special char; find initial name
  1085. $application_file_name = iassign_utils::filename_from_iLM_name($application_xml->name, false); //TODO: also can use html5::get_xml_name($application_xml);
  1086. //D //2025/04/09 echo "html5.php!save_ilm_by_xml(.): application_file_name=" . $application_file_name . ", str_from=" . $str_from . "<br/>"; //exit;
  1087. if ($str_from == "ipz") { // come from "ilm-application.xml" (IPZ)
  1088. // From XML arrives only one directory (iLM base), we must complete the path to create iLM directory under WWW
  1089. // Apply the same filter to avoid special character in the internal directory name {iassign_ilm}.file_jar
  1090. // We need to produze {iassign_ilm}.file_jar with a complete path (e.g., to iFraction: "ilm/iFractions/3.1.0/ifractions/")
  1091. $file_jar = iassign_utils::filename_from_iLM_name($application_xml->file_jar, false); // in "locallib.php": static function filename_from_iLM_name($ilm_name, $is_lowercase = true)
  1092. // iLM directory under which the new version will be created: the final directory will also have the suffix given by $file_jar
  1093. $ilm_base_directory = "ilm" . $ds . $application_file_name; // ./mod/iassign/ilm/<iLM name>
  1094. $ilm_directory_version = $ilm_base_directory . $ds . $application_xml->version; // ./mod/iassign/ilm/<iLM name>/<iLM version>
  1095. if ($CFG->debugdisplay) { // debug messages is turned on
  1096. print "ilm_handlers/html5.php!save_ilm_by_xml(.): file_jar=" . $file_jar . ", ilm_base_directory=" . $ilm_base_directory . ", version=" . $application_xml->version . "<br/>\n"; //DEBUG
  1097. }
  1098. // Final directory of the new iLM: in ./mod/iassign/ilm/
  1099. // $ilm_final_directory = "ilm" . $ds . $application_file_name . $ds . $application_xml->version; // ilm/<iLM name>/<iLM version>
  1100. // $ilm_final_directory .= $ds . $file_jar; // ilm/<iLM name>/<iLM version>/<base_name>/
  1101. //2025/04/09 echo "html5.php!save_ilm_by_xml(.): file_jar=" . $file_jar . "<br/>"; //
  1102. $ilm_final_directory = $file_jar; // ilm/<iLM name>/<iLM version>/<base_name>/
  1103. //2025/04/09 static function save_ilm_by_xml($str_from, $application_xml, $files_extract)
  1104. $sizedir = strlen($ilm_final_directory);
  1105. if ($sizedir>0 && $ilm_final_directory[$sizedir-1] == $ds) // remove last "/"
  1106. $ilm_final_directory = substr($ilm_final_directory, 0, $sizedir-1);
  1107. }
  1108. else { // come from form (ZIP) or "ilm-application.xml" (IPZ)
  1109. //2025/04/09 echo "html5.php!save_ilm_by_xml(.): opa, NAO esperava chegar nesse ponto!<br/>"; //exit;
  1110. $file_jar = $application_xml->file_jar;
  1111. $ilm_base_directory = "ilm" . $ds . $application_file_name; // ./mod/iassign/ilm/<iLM name>
  1112. $ilm_directory_version = $ilm_base_directory . $ds . $application_xml->version; // ilm/<iLM name>/<iLM version>
  1113. // Final directory of the new iLM: in ./mod/iassign/ilm/
  1114. // $ilm_final_directory = $ilm_directory_version . $ds . $application_xml->version; // ilm/<iLM name>/<iLM version>
  1115. $ilm_final_directory = $ilm_directory_version . $ds . $application_file_name; // ilm/<iLM name>/<iLM version>/<base_name>/
  1116. //D echo "file_jar=" . $file_jar . ", ilm_directory=" . $ilm_base_directory . ", ilm_directory_version=" . $ilm_directory_version . "<br/>";
  1117. //D echo "ilm_final_directory=" . $ilm_final_directory . "<br/>";
  1118. }
  1119. //D echo "save_ilm_by_xml(.): file_jar=" . $file_jar . ", ilm_directory=" . $ilm_base_directory . ", ilm_directory_version=" . $ilm_directory_version . "<br/>"; //exit;
  1120. // Moodle use "temp/" directory in MoodleData area to keep the IPZ package sent
  1121. $source_in_moodledata = null; // to get the directory on the IPZ file (on MoodleData)
  1122. $source_in_moodledata_root = $CFG->dataroot . $ds . "temp"; // to get the "ilm-application.xml" file (to remotion at the end)
  1123. // Package files been sending is under MoodleData: MoodleData/temp/<entry>
  1124. // Find the initial directory to be used as {iassign_ilm}.file_jar: looking at each <entry> em IPZ package
  1125. // ATTENTION: the ZIP or IPZ package must have all of its files inside a single directory, to be recovery bellow
  1126. $countDir = 0; // must be a single
  1127. $error = 0; // if finished with positive implies error
  1128. $actual_file_jar = ""; // base directory with all iLM files - ideally must be equals to above $application_file_name
  1129. $second_file_jar = ""; // if was detect more than one directory at the root level of package
  1130. $temp_files = array(); // if package has not a single directory this will help to remove all the wrong files
  1131. $temp_dir = array(); // if package has not a single directory this will help to remove all the wrong directories
  1132. foreach ($files_extract as $key1 => $value1) {
  1133. $file_name = $CFG->dataroot . $ds . "temp" . $ds . $key1; // look at MoodleData/temp/<entry>
  1134. if (is_dir($file_name)) { // Is it a directory? (stop with the first directory)
  1135. if ($source_in_moodledata == null) { // not yet defined, use the first directory
  1136. $items = explode($ds, $key1);
  1137. if (count($items)>0) {
  1138. $actual_file_jar = $items[0];
  1139. $source_in_moodledata = $CFG->dataroot . $ds . "temp" . $ds . $items[0]; // to avoid the first be a sub-directory...
  1140. $countDir++;
  1141. }
  1142. else {
  1143. $actual_file_jar = $key1;
  1144. $source_in_moodledata = $file_name; // to avoid the first be a sub-directory...
  1145. }
  1146. $temp_dir[] = $source_in_moodledata; // if package has not a single directory this will help to remove all the wrong directories
  1147. }
  1148. else { // already defined "initial" file in $source_in_moodledata
  1149. $items = explode($ds, $key1);
  1150. $newdir = $items[0]; // eventually is sub-directory of $source_in_moodledata (which is allowed)
  1151. $newdir_complete = $CFG->dataroot . $ds . "temp" . $ds . $newdir;
  1152. if (!in_array($newdir_complete, $temp_dir)) // new dir to the list of directories to be remove
  1153. $temp_dir[] = $newdir_complete; // if package has not a single directory this will help to remove all the wrong directories
  1154. if ($newdir != $actual_file_jar) { // ups, other main directory!
  1155. $countDir++;
  1156. $second_file_jar = $newdir;
  1157. $error = 1; // more than one directory inside package: $newdir, $actual_file_jar
  1158. }
  1159. }
  1160. } // if (is_dir($file_name))
  1161. else { // is file
  1162. $items = explode($ds, $key1); // eventually is sub-directory of $source_in_moodledata (which is allowed)
  1163. if (count($items)>1) // it is allowed (files under the root level directory)
  1164. continue;
  1165. $filename = $items[0]; // get the first
  1166. $temp_files[] = $CFG->dataroot . $ds . "temp" . $ds . $filename; // if package has not a single directory this will help to remove all the wrong files
  1167. if ($filename != "ilm-application.xml") {
  1168. $error = 2; // error, all files (but 'ilm-application.xml') must be under a single directory!
  1169. //D $items = explode($ds, $key1); echo " +++ key1=" . $key1 . " count=" . count($items) . "<br/>"; if (count($items)==1)
  1170. }
  1171. }
  1172. } // foreach
  1173. if ($error>0) {
  1174. if ($CFG->debugdisplay) { // debug messages is turned on
  1175. print "ilm_handlers/html5.php!save_ilm_by_xml(.): Error more files at the root level?<br/> - actual_file_jar=" . $actual_file_jar . ", second_file_jar=" . $second_file_jar . "<br/>temp_dir=\n"; //DEBUG
  1176. print_r($temp_dir); print "<br/>";
  1177. }
  1178. $param = new stdClass(); $param->dir1 = $actual_file_jar; $param->dir2 = $second_file_jar;
  1179. $msg1 = get_string('error_zip_ipz_single_directory', 'iassign'); // Error! The ZIP or IPZ package must have all of its files inside a single directory.
  1180. $msg2 = get_string('error_zip_ipz_more_directories', 'iassign', $param); // Was found at least two sub-directories inside the package: "{$a}" and "{$b}"
  1181. $msg3 = get_string('error_zip_ipz_file_in_pack', 'iassign'); // Was found at least one file (other than "ilm-application.xml") at the root level of the package:
  1182. $err_msg = $html_header . $msg1 . "<br/>\n";
  1183. if ($error == 1) {
  1184. $err_msg .= $msg2; // "Was found at least two sub-directories inside the package: {$actual_file_jar} and {$key1}
  1185. }
  1186. else { // other file than 'ilm-application.xml' inside the package at root level
  1187. $err_msg .= $msg3 . ' ' . $key1; // Was found at least one file (other than 'ilm-application.xml') at the root level of the package:
  1188. }
  1189. foreach ($temp_files as $one_file) { // $temp_files // if package has not a single directory this will help to remove all the wrong files
  1190. //D echo $one_file . "<br/>";
  1191. unlink($one_file); // $source_in_moodledata_root . $ds . $one_file
  1192. }
  1193. foreach ($temp_dir as $one_dir) { // $temp_files // if package has not a single directory this will help to remove all the wrong directories
  1194. //D echo $one_dir . "<br/>";
  1195. self::delete_dir("data", $one_dir); // try to remove source directories from MoodleData - $source_in_moodledata_root . $ds . $one_dir
  1196. }
  1197. self::delete_dir("data", $CFG->dataroot . $ds . "temp" . $ds . "filestorage"); // remove auxiliary Moodle directory (created during the process)
  1198. print $OUTPUT->header() . $OUTPUT->heading(get_string('error_zip_ipz', 'iassign')); // "iLM creation error: fail in package ZIP or IPZ
  1199. print $OUTPUT->notification($err_msg, 'notifyproblem') . $html_header_end;
  1200. exit; // ensure do not follow processing...
  1201. }
  1202. //D echo "html5.php!save_ilm_by_xml(.): (1) ilm_directory=" . $ilm_base_directory . "<br/>"; // html5.php!save_ilm_by_xml(.): (1) ilm_directory=ilm/iHanoi
  1203. // Check if iLM root directory already exists
  1204. if (!file_exists($ilm_base_directory)) { // If the root iLM directory does exist, create "./mod/iassign/ilm/<LM name>"
  1205. //D echo "html5.php!save_ilm_by_xml(.): (2) ilm_directory=" . $ilm_base_directory . "<br/>";
  1206. if (!is_writable("ilm")) { // can be created "./mod/iassign/ilm/<iLM name>" in "./mod/iassign/ilm/"?
  1207. //D echo "html5.php!save_ilm_by_xml(.): (3) is_writable(ilm)<br/>";
  1208. // Error: There are no permission to modify files in iLM directory. Please, you need to verify iLM directory permissions (Moodle admin prerogative)!
  1209. $err_msg = $html_header . get_string('error_folder_permission_denied', 'iassign') . "<br/>\n";
  1210. $err_msg .= get_string('error_folder_permission_ilmdir', 'iassign') . " " . $ilm_base_directory; // iLM directory:
  1211. print $OUTPUT->header() . $OUTPUT->heading(get_string('error_folder_permission_create', 'iassign')); // "iLM creation error: directory without permission"
  1212. print $OUTPUT->notification($err_msg, 'notifyproblem') . $html_header_end;
  1213. exit; // ensure do not follow processing...
  1214. }
  1215. mkdir($ilm_base_directory, 0755, true); // create directory - 755 = (111)(101)(101) = rwxr-xr-x
  1216. if (!file_exists($ilm_base_directory . $ds . "index.html")) // if does not already exist "index.html" create an empty one
  1217. touch($ilm_base_directory . $ds . "index.html");
  1218. //D echo "html5.php!save_ilm_by_xml(.): (4) mkdir " . $ilm_base_directory . "<br/>";
  1219. }
  1220. // Check if does note already exists the directory to this iLM version
  1221. if (!file_exists($ilm_directory_version)) {
  1222. if (!is_writable($ilm_base_directory)) { // ./mod/iassign/ilm/<iLM name>: can not create ./mod/iassign/ilm/<iLM name>/<iLM version>
  1223. $err_msg = $html_header . get_string('error_folder_permission_denied', 'iassign') . "<br/>\n"; // Error: There are no permission to modify files in iLM directory. Please,...
  1224. $err_msg .= get_string('error_folder_permission_ilmver', 'iassign') . " " . $ilm_directory_version; // "iLM version directory: "
  1225. print $OUTPUT->header() . $OUTPUT->heading(get_string('error_folder_permission_create', 'iassign')); // "iLM creation error: directory without permission"
  1226. print $OUTPUT->notification($err_msg, 'notifyproblem') . $html_header_end;
  1227. return [$ilm_directory_version, null]; // null will indicate to 'import_ilm(.)' an error (avoid to write in table {iassign_ilm})
  1228. exit; // ensure do not follow processing...
  1229. }
  1230. mkdir($ilm_directory_version, 0755, true);
  1231. if (!file_exists($ilm_directory_version . $ds . "index.html")) // if does not already exist "index.html" create an empty one
  1232. touch($ilm_directory_version . $ds . "index.html");
  1233. }
  1234. else { // the iLM directory and version already exists
  1235. // $ilm_trunc_name, $iassign_ilm_instance
  1236. $auxm = "<br/>" . get_string('error_import_ilm_version_type', 'iassign'). ": " .
  1237. $application_xml->name . ", " . // {iassign_ilm}.name
  1238. $application_xml->version . ", " . // {iassign_ilm}.version
  1239. "html5"; // {iassign_ilm}.type
  1240. //D echo "save_ilm_by_xml(.): Erro! Diretorio '" . $ilm_directory_version . "' ja existe!<br/>(name,version,type)=" . $auxm;
  1241. $temp_directory = "." . $ds . $ilm_directory_version;
  1242. $err_msg = $html_header . get_string('error_import_ilm_version', 'iassign') . $auxm . "<br/>\n"; // ERROR: this iLM version is already installed
  1243. $err_msg .= get_string('error_folder_permission_ilmver', 'iassign') . " " . $ilm_directory_version; // "iLM version directory: "
  1244. if (!$OUTPUT->has_started())
  1245. print $OUTPUT->header();
  1246. print $OUTPUT->heading(get_string('error_import_ilm_version_exist', 'iassign')); // "There is already a iLM with this name and version"
  1247. print $OUTPUT->notification($err_msg, 'notifyproblem') . $html_header_end;
  1248. exit; // Better stop here! Otherwise the message in 'copy_new_version_ilm(.)' will use empty field "file_jar"
  1249. // return [$temp_directory, null]; // null will indicate to 'import_ilm(.)' an error (avoid to write in table {iassign_ilm})
  1250. }
  1251. // Write from MoodleData to the final directory (in the WWW area): './mod/iassign/ilm/'
  1252. $rec_dir_md = new RecursiveDirectoryIterator($source_in_moodledata, RecursiveDirectoryIterator::SKIP_DOTS);
  1253. $iterator = new RecursiveIteratorIterator($rec_dir_md, RecursiveIteratorIterator::SELF_FIRST);
  1254. $wwwpath = getcwd(); // usually "/var/www/html/moodle/mod/iassign" considering "http://localhost/moodle/mod/iassign"
  1255. $ilm_complete_path_base = $wwwpath . $ds . $ilm_final_directory; // base iLM directory: /mod/iassign/ihanoi
  1256. if ($CFG->debugdisplay) { // debug messages is turned on
  1257. print "ilm_handlers/html5.php!save_ilm_by_xml(.): wwwpath=" . $wwwpath . ", ilm_complete_path_base=" . $ilm_complete_path_base . "<br/>\n"; //DEBUG
  1258. // ilm_handlers/html5.php!save_ilm_by_xml(.): wwwpath=/var/www/html/saw_limpo/mod/iassign, ilm_base=/var/www/html/saw_limpo/mod/iassign/ihanoi
  1259. }
  1260. // Here, above: $application_file_name = iassign_utils::filename_from_iLM_name($application_xml->name, false); //TODO: also can use html5::get_xml_name($application_xml);
  1261. $ilm_final_directory = $application_file_name; // base iLM directory: iHanoi
  1262. // In case iLM has error in its path (perhaps during its creation or by misunderstanding edition)
  1263. if (!file_exists($ilm_complete_path_base)) { // perhaps reach here from IPZ with 'file_jar' with a single name (e.g. file_jar='ihanoi/')
  1264. if ($CFG->debugdisplay) { // debug messages is turned on
  1265. print "ilm_handlers/html5.php!save_ilm_by_xml(.): " . $ilm_complete_path_base . " does not exist! Try to complete<br/>\n"; //DEBUG
  1266. }
  1267. $ilm_complete_path_base = $wwwpath . $ds . "/ilm/" . $application_file_name;
  1268. $ilm_complete_path_base = $wwwpath . $ds . "ilm" . $ds . $application_file_name; // use $ds to "/" on Linux or inverted barr in Win...
  1269. if ($CFG->debugdisplay) { // debug messages is turned on
  1270. print "ilm_handlers/html5.php!save_ilm_by_xml(.): completed path base=" . $ilm_complete_path_base . "<br/>\n"; //DEBUG
  1271. }
  1272. }
  1273. //D echo "html5.php!save_ilm_by_xml(.): (5) wwwpath=" . $wwwpath . ", mkdir ilm_complete_path_base=" . $ilm_complete_path_base . "<br/>"; // html5.php!save_ilm_by_xml(.): (5) wwwpath=/var/www/html/saw_limpo/mod/iassign, mkdir ilm_base=/var/www/html/saw_limpo/mod/iassign//ilm/iHanoi
  1274. //D mkdir ilm_base=/var/www/html/saw_limpo/mod/iassign//ilm/iHanoi
  1275. if (!is_dir($ilm_complete_path_base)) { // create base directory: ./mod/iassign/ilm/<iLM name>
  1276. mkdir($ilm_complete_path_base, 0755, true);
  1277. touch($ilm_complete_path_base . $ds . "index.html"); // if does not appear any other "index"...
  1278. }
  1279. $ilm_path_version_filejar = $ilm_complete_path_base . $ds . $application_xml->version . $ds . $file_jar; // ./mod/iassign/ilm/<iLM name>/<iLM version>
  1280. $ilm_final_directory = $ilm_final_directory . $ds . $application_xml->version; // now base iLM directory: <iLM name>/<version>
  1281. if (!is_dir($ilm_path_version_filejar)) { // create base directory
  1282. //D echo "html5.php!save_ilm_by_xml(.): (6) mkdir ilm_path_version_filejar=" . $ilm_path_version_filejar . "<br/>";
  1283. mkdir($ilm_path_version_filejar, 0755, true); // create directory version: ./mod/iassign/ilm/<iLM name>/<iLM version>
  1284. touch($ilm_path_version_filejar . $ds . "index.html"); // if does not appear any other "index"...
  1285. }
  1286. $err_msg = "";
  1287. //D echo "html5.php: copiar<br/>";
  1288. //D foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source_in_moodledata, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item
  1289. foreach ($iterator as $item) {
  1290. $directory_name = $ilm_path_version_filejar . $ds . $iterator->getSubPathName(); // = $wwwpath . $ds . $ilm_final_directory . $ds . $iterator->getSubPathName();
  1291. if ($item->isDir()) {
  1292. mkdir($directory_name, 0755); // explicitly create with permission 0755 (others only can read and execute)
  1293. //D echo " + mkdir(" . $directory_name . ", 0755)<br/>";
  1294. touch($directory_name . $ds . "index.html"); // it creates empty "index" to avoid users to see all files directly
  1295. }
  1296. else {
  1297. //D echo "html5.php!save_ilm_by_xml(.): (6) copy item para directory_name=" . $directory_name . "<br/>";
  1298. if (!copy($item, $directory_name)) //aqui
  1299. $err_msg .= "Error copy " . $item . " to " . $directory_name . "<br/>\n";
  1300. else { // Change permission: everything for owner, read and execute for others
  1301. chmod($directory_name, 0755); // (0)(111)(101)(101)
  1302. //D echo " + chmod(" . $directory_name . ", 0755)<br/>";
  1303. }
  1304. }
  1305. }
  1306. //D if ($err_msg!="") echo " + Erros:<br/>" . $err_msg;
  1307. self::delete_dir("data", $source_in_moodledata); // remove source file in the MoodleData
  1308. unlink($source_in_moodledata_root . $ds . "ilm-application.xml"); // also remove the "ilm-application.xml" file
  1309. rmdir($source_in_moodledata); // now remove the directory
  1310. //D echo "html5.php!save_ilm_by_xml(.): (7) devolva ilm_final_directory/file_jar, sendo: ilm_final_directory=" . $ilm_final_directory . ", file_jar=" . $file_jar . "<br/>";
  1311. //D // html5.php!save_ilm_by_xml(.): (7) devolva ilm_final_directory/file_jar, sendo: ilm_final_directory=iHanoi, file_jar=ihanoi/
  1312. // return [$ilm_final_directory . $ds, $file_jar];
  1313. return [$ilm_final_directory, $file_jar]; // [<iLM name>, <internal path>]
  1314. } // static function save_ilm_by_xml($str_from, $application_xml, $files_extract)
  1315. /// Function for delete directory where the iLM is allocated.
  1316. // Remove iLM directories under WWW and temporary files of MoodleData (MoodleData/temp/)
  1317. // @calledby save_ilm_by_xml(.): self::delete_dir($source_in_moodledata); // remove source file in the MoodleData
  1318. // @calledby self::delete_dir($source_in_moodledata); // remove source file in the MoodleData
  1319. // @calledby some more
  1320. // @param string $dirPath
  1321. // @throws InvalidArgumentException
  1322. public static function delete_dir ($www_or_data, $dirPath) {
  1323. global $CFG;
  1324. $ds = DIRECTORY_SEPARATOR; // to short name (to directory separator, on Linux "/")
  1325. var_dump(debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); //2025/04/11 leo
  1326. echo "ilm_handlers/html5.php!delete_dir(.): www_or_data=" . $www_or_data . ", original dirPath=" . $dirPath . "<br/>\n"; //2025/04/11 leo
  1327. $dh = opendir($dirPath);
  1328. if (!$dh) {
  1329. echo "ilm_handlers/html5.php!delete_dir(.): dirPath=" . $dirPath . " NAO e' diretorio, esqueca!<br/>\n"; //2025/04/11 leo
  1330. // Error...
  1331. return false;
  1332. }
  1333. // To use 'unlink(.)' needs complete path:
  1334. if ($www_or_data == "www") { // came from here delete_ilm(.), then add path prefix
  1335. $dirPathC = $CFG->dirroot . DIRECTORY_SEPARATOR . "mod" . DIRECTORY_SEPARATOR . "iassign" . DIRECTORY_SEPARATOR . $dirPath;
  1336. if (is_dir($dirPathC)) { // came here with an incomplete path, complete it
  1337. $dirPath = $dirPathC;
  1338. echo "ilm_handlers/html5.php!delete_dir(.): novo dirPath=" . $dirPath . "<br/>\n"; //2025/04/11 leo
  1339. }
  1340. }
  1341. while (($file_name = readdir($dh)) !== false) {
  1342. if (!$file_name || $file_name == ".." || $file_name == ".")
  1343. continue; // ignore empty or subdirectories
  1344. if ($dirPath[strlen($dirPath) - 1] != $ds) // avoid append when it already has final "/" (ou "\")
  1345. $file_name = $dirPath . DIRECTORY_SEPARATOR . $file_name;
  1346. else
  1347. $file_name = $dirPath . $file_name;
  1348. if (is_dir($file_name)) { // recursivelly remove
  1349. self::delete_dir($www_or_data, $file_name);
  1350. $result = rmdir($file_name); // after removed its files, remove the directory
  1351. if ($CFG->debugdisplay) { // debug messages is turned on
  1352. if ($result) print "html5.php!delete_dir(.): after removed its files, remove the directory, file_name=" . $file_name . " successfully removed with 'unlink(file_name)'!<br/>";
  1353. else print "html5.php!delete_dir(.): after removed its files, remove the directory, file_name=" . $file_name . ", occurred an ERROR with 'unlink(file_name)'!<br/>";
  1354. }
  1355. }
  1356. else {
  1357. // ilm_handlers/html5.php!save_ilm_by_xml(.): www_or_data=www, original dirPath=ilm/iHanoi/
  1358. // ilm_handlers/html5.php!save_ilm_by_xml(.): novo dirPath=/var/www/html/saw_limpo/mod/iassign/ilm/iHanoi/
  1359. // ilm_handlers/html5.php!save_ilm_by_xml(.): www_or_data=www, original dirPath=/var/www/html/saw_limpo/mod/iassign/ilm/iHanoi/1.0.20200803
  1360. // ilm_handlers/html5.php!save_ilm_by_xml(.): novo dirPath=/var/www/html/saw_limpo/mod/iassign//var/www/html/saw_limpo/mod/iassign/ilm/iHanoi/1.0.20200803
  1361. //
  1362. // /var/www/html/saw_limpo/mod/iassign//var/www/html/saw_limpo/mod/iassign/ilm/iHanoi/1.0.20200803/index.html
  1363. if (!is_dir($file_name) || self::is_empty_dir($file_name)) { // Not directory or is empty directory, then remove it
  1364. $result = unlink($file_name); // remove this file
  1365. //x $result = unlink($file_nameC); // remove this file
  1366. if ($CFG->debugdisplay) { // debug messages is turned on
  1367. // dirPath = ilm/iHanoi/1.0.20230525/ihanoi
  1368. // file_name = ilm/iHanoi/1.0.20230525/ihanoi/index_ihanoi.html
  1369. if ($result) print "html5.php!delete_dir(.): in dirPath=" . $dirPath . ", file_name=" . $file_name . " successfully removed with 'unlink(file_name)'!<br/>";
  1370. else print "html5.php!delete_dir(.): in dirPath=" . $dirPath . ", occurred an ERROR to remove " . $file_name . " with 'unlink(file_name)'!<br/>";
  1371. }
  1372. }
  1373. else echo "ilm_handlers/html5.php!delete_dir(.): file_name=" . $file_name . ", NAO e' diretorio limpo, esqueca<br/>\n";
  1374. }
  1375. } // while (($file_name = readdir($dh)) !== false)
  1376. closedir($dh);
  1377. if (is_dir($dirPath)) {
  1378. if (self::is_empty_dir($file_name)) { // If there is another iLM under this name, do not even try to remove!
  1379. $result = rmdir($dirPath); //TODO Warning: rmdir(/var/data/moodle_data_saw/temp/ivprog-html/js/semantic/): Directory not empty in /var/www/html/saw/...
  1380. // Esta sobrando diretorio no Moodle data! /var/data/saw_limpo/temp/ihanoi/img/*
  1381. //x $result = rmdir($dirPathC);
  1382. if ($CFG->debugdisplay) { // debug messages is turned on
  1383. if ($result) print "html5.php!delete_dir(.): in dirPath=" . $dirPath . " successfully removed with 'unlink(dirPath)'!<br/>\n";
  1384. else print "html5.php!delete_dir(.): occurred an ERROR to remove " . $dirPath . " with 'unlink(dirPath)'!<br/>dirPath=" . $dirPath . "<br/>\n";
  1385. }
  1386. }
  1387. } // if (is_dir($dirPath))
  1388. // if (error) {
  1389. // print($OUTPUT->notification(get_string('error_file_jar_exists', 'iassign'), 'notifyproblem')); // just warning the user
  1390. // //D echo "./mod/iassign/ilm_handlers/html5.php: delete_dir(" . $dirPath . "): " . $error_msg . "<br/>\n";
  1391. // $error_msg = get_string('error_file_jar_exists', 'iassign') . "<br/>\nThere was no directory " . $dirPath . " to be removed";
  1392. // print($OUTPUT->notification($error_msg, 'notifyproblem')); // just warning the user"
  1393. // If the directory does not exist, simply ignore it!
  1394. // }
  1395. } // public static function delete_dir($www_or_data, $dirPath)
  1396. } // class html5 implements ilm_handle
  1397. ?>