special_param1==1) $lTA=true;' to call '$ilm->view_iLM(...lTA)'
*
* - v 4.9 2017/03/13
* + Great number of changes to allow the use o iVProgH5 (e.g. function changed: from 'applet_ilm' to 'build_ilm_tags')
*
* - v 4.8 2016/05/12
* + Function add_to_log() is deprecated it was then rewritten to the new events API
* + Resolved: the field "description" table "iassign_ilm" was being filled with the codes in HTML when importing magnet package and
* due to this the language field was not being displayed because in place of the quotes was recorded in the & quot field.
* ("$description_str = htmlentities(str_replace(array('',''), array('',''), $application_xml->description->asXML()));"
* replaced by
* "description_str = str_replace(array('',''), array('',''), $application_xml->description->asXML());")
* - v 4.7 2016/02/17
* + Moodle 3.X: now iAssign is working fine under version 3.X (iassign/version.php: '$module->' changed to '$plugin->'; iassign/locallib.php: 'format_text(...)' replaced 'filter_text(...)')
* + Improved: now is possible to see the iGeom menus in preview (from iAssign Repository) - it depends on the version 1.3 of iAssign filter!
* + Improved: new names for 'form.input.MA_POST_Archive' and 'form.input.MA_POST_Value', now: 'iLM_PARAM_ArchiveContent' and 'iLM_PARAM_ActivityEvaluation'
* + BUG fixed: now it is fine the "online" edition of activities (in iAssign Repository) - inserted 'iLM_PARAM_Authoring' (iLM 2) and 'MA_POST_ArchiveTeacher' (iLM 1)
* + BUG fixed: it is possible to change the name of any file in iAssign Repository - problems was in 'optional_param(...)', 'PARAM_TEXT' replaced 'PARAM_ALPHANUMEXT'
* + BUG fixed: it is possible to duplicate any file in iAssign Repository - problems also in 'optional_param(...)', 'PARAM_TEXT' replaced 'PARAM_ALPHANUMEXT'
* + BUG fixed: now is possible to edit an iAssign activity with no new object been created (in iGeom: turn an example in exercise)
*
* --------------- (code bellow was used at our MOOC 2014)
* - v 4.6 2014/02/25
* + Fix bugs in filter function for open applets.
* - v 4.5 2014/02/24
* + Fix bugs in params.
* + Insert new param type.
* - v 4.4 2014/01/24
* + Allow select type of params.
* + Insert the use of applet params specific for activities.
* - v 4.3 2014/01/23
* + Insert function for move activities for other iLM (ilm_settings::confirm_move_iassign, ilm_settings::move_iassign).
* - v 4.2 2016/02/13
* + Fixed API usage to work fine under Moodle 3.X: ilm_editor_new()
* --------------- (above code used at our MOOC 2014)
*
* - v 4.1 2013/12/13
* + Insert log in iAssign actions.
* + Allow use the language in iLM description (ilm_settings::new_file_ilm, ilm_settings::new_ilm, ilm_settings::edit_ilm, ilm_settings::copy_new_version_ilm, ilm_settings::add_edit_copy_ilm, iassign_language::get_description_lang, iassign_language::get_all_lang).
* + Insert class for Log actions in system.
* - v 4.0 2013/10/31
* + Insert support of export iLM in zip packages (ilm_settings::export_ilm).
* + Insert support of import iLM from zip packages (ilm_settings::import_ilm).
* + Fix bugs in message alert in iassign title and remove message alert of the description by cache error.
* - v 3.9 2013/10/25
* + Insert support of upgrade iLM.
* + Insert support for more than one extension in iLM.
* + Fix bugs in verion control.
* - v 3.8 2013/09/19
* + Get data of general fields in iassign statement table (iassign::add_edit_iassign).
* - v 3.7 2013/09/12
* + Change tag APPLET in all functions of module (ilm::view_iLM, ilm_manager::ilm_editor_new, ilm_manager::ilm_editor_update).
* + Insert tool for manage aditional params for iLM (ilm_settings::add_edit_copy_param, ilm_settings::visible_param, ilm_settings::add_param, ilm_settings::edit_param, ilm_settings::copy_param, ilm_settings::delete_param).
* - v 3.6 2013/09/05
* + Insert function ilm_settings::applet_ilm for create APPLET html tag.
* + Insert function ilm_settings::applet_filetime for get modified date of iLM file.
* + Change tag APPLET in function ilm_settings::view_ilm.
* - v 3.5 2013/08/26
* + Fix bug in download package iassign without answers (iassign::report).
* - v 3.4 2013/08/23
* + Fix bug in export package iassign.
* - v 3.3 2013/08/22
* + Insert functions for export users answer in iassign (iassign::export_file_answer, iassign::export_package_answer, iassign::view_iassign_current, iassign::report).
* + Insert function for rename iassign file (ilm_manager::rename_file_ilm, ilm_manager::view_files_ilm).
* - v 3.2 2013/08/21
* + Change title link with message for get file for donwload file (ilm_manager::view_files_ilm).
* + Change functions for import files for ilm_manager.php.
* + Create static utils class for functions system utils (iassign_utils::format_filename, iassign_utils::version_filename).
* - v 3.1 2013/08/15
* + Change return file selected (ilm_manager::add_ilm).
* + Insert functions for import files, export files and remove selected files (ilm_manager::view_files_ilm, ilm_manager::import_files_ilm, ilm_manager::export_files_ilm, ilm_manager::delete_selected_ilm).
* - v 3.0 2013/08/02
* + Insert link for view informations of iLMs in teacher view, same screen of admin view but wiht some features hide (ilm_settings::list_ilm, ilm_settings::view_ilm, iassign::view_iassigns).
* - v 2.9 2013/08/01
* + Fix bugs in functions ilm_settings::new_file_ilm, ilm_settings::copy_new_version_ilm, ilm_settings::add_edit_copy_ilm.
* - v 2.8 2013/07/25
* + Insert the activity name in header of view (activity::view_dates).
* + Set function default iLM in view iLMs versions (ilm_settings::default_ilm and ilm_settings::confirm_default_ilm).
* - v 2.7 2013/07/24
* + Create link previous and next for student view in one activity (activity::view_dates).
* + Fix bugs for view error in iLM not on DB in function iassign::view_iassign_current.
* - v 2.6 2013/07/23
* + Fix bugs for view files in function ilm_manager::view_files_ilm.
* + Fix bugs for comment on teacher view in function iassign::view_iassign_current.
* - v 2.5 2013/07/12
* + Change iLM settings for accept versions (ilm_settings::new_file_ilm, ilm_settings::new_ilm, ilm_settings::edit_ilm, ilm_settings::copy_new_version_ilm).
* + Insert new informations in iLMs table: created date, modified date, author, version, modified date of JAR (ilm_settings::view_ilm).
* + Added support for PHP 7.0 Constructors and fallback for previous Moodle Versions (<3.1) (@contributor Ma'rcio Passos)
*
* @author Patricia Alves Rodrigues
* @author Leo^nidas de Oliveira Branda~o
* @contributor Igor Moreira Fe'lix (2018-)
* @contributor Ma'rcio de Lima Passos (2014)
* @version v 4.9.9 2023/04/20
* @version v 4.9.2 2019/03/13
* @version v 4.8 2016/05/12
* @package mod_iassign_lib
* @since 2010/09/27
* @copyright iMath (http://www.matematica.br) and LInE (http://line.ime.usp.br) - Computer Science Dep. of IME-USP (Brazil)
*
* License
* - http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
//TODO Review: eliminate iLM JAR under MoodleData? It is necessary to HTML5 packages (like iVProgH5), anyway
//TODO Whenever under HTTPS, verify if MoodleData is working, if it is not, please use iLM JAR under WWW setting $CONF_WWW = 1
//TODO (under HTTPS could fail 'pluginfile', like 'https://saw.atp.usp.br/pluginfile.php/1/mod_iassign/ilm/182563135/iassign/ilm/igeom/5920/iGeom.jar"'
$CONF_WWW = 1; //TODO get iLM (JAR) from WWW, avoiding MoodleData
/// Standard base class for all iAssign
// Basic class to iAssign block of activities
class iassign {
var $cm;
var $course;
var $iassign;
var $striassign;
var $striassigns;
var $context;
var $activity;
var $iassign_up;
var $iassign_down;
var $action;
var $iassign_submission_current;
var $userid_iassign;
var $allowPostButton;
var $write_solution;
var $view_iassign;
var $coursecontext, $return; // if missing, PHP8 launch warning bellow
// Attention with PHP8: Deprecated: Creation of dynamic property iassign::X is deprecated in /var/www/html/saw/mod/iassign/locallib.php on line Y
// 3.1 update PHP 7.0 compatibility for all moodle versions
//D public function iassign($iassign, $cm, $course) { self::__construct($iassign, $cm, $course); }
/// Constructor for the base iassign class
// @calledby ./mod/iassign/view.php : $iassigninstance = new iassign($iassign, $cm, $course)
// @calledby ./mod/iassign/grade.php : $iassigninstance = new iassign($iassign, $cm, $course);
// @calledby ./mod/iassign/renderer.php : return $this->render(new iassign_files($context, $itemid, $filearea));
function __construct ($iassign, $cm, $course) {
global $COURSE, $CFG, $USER, $DB;
$botton = optional_param('botton', NULL, PARAM_TEXT);
$this->userid_iassign = optional_param('userid_iassign', 0, PARAM_INT);
if (!is_null($botton))
$USER->iassignEdit = $botton;
// The Moodle function 'optional_param(...)' allow to filter GET parameters over a click that launches, e.g., './mod/iassign/view.php&userid_iassign=6'
// If "$var1 = optional_param('userid_iassign', 'NOT', PARAM_TEXT);", $var1 will be set to 6 (if 'userid_iassign' is not present, $var1 will be set to 'NOT'
$this->iassign_up = optional_param('iassign_up', 0, PARAM_INT); // if parameter 'iassign_up' does not exists or it is not integer => use 0 as "default"
$this->iassign_down = optional_param('iassign_down', 0, PARAM_INT);
$this->iassign_submission_current = optional_param('iassign_submission_current', 0, PARAM_INT);
$this->write_solution = optional_param('write_solution', 0, PARAM_INT);
$this->action = optional_param('action', NULL, PARAM_TEXT);
$this->cm = $cm;
$this->context = context_module::instance($this->cm->id);
if (!has_capability('mod/iassign:evaluateiassign', $this->context, $USER->id))
$this->userid_iassign = $USER->id;
if ($course) {
$this->course = $course;
}
else if ($this->cm->course == $COURSE->id) {
$this->course = $COURSE;
}
else if (!$this->course = $DB->get_record('course', array('id' => $this->cm->course))) {
print_error('invalidid', 'iassign');
}
$this->coursecontext = context_course::instance($this->course->id);
if ($iassign) {
$this->iassign = $iassign;
}
else if (!$this->iassign = $DB->get_record('iassign', array('id' => $this->cm->instance))) {
print_error('invalidid', 'iassign');
}
$USER->context = context_module::instance($this->cm->id);
$USER->cm = $this->cm->id;
$this->iassign->cmidnumber = $this->cm->idnumber; // compatibility with modedit ia obj
$this->iassign->courseid = $this->course->id; // compatibility with modedit ia obj
$this->context = context_module::instance($this->cm->id);
$this->striassign = get_string('modulename', 'iassign');
$this->striassigns = get_string('modulenameplural', 'iassign');
$this->return = $CFG->wwwroot . "/mod/iassign/view.php?id=" . $this->cm->id;
$this->allowPostButton = 0; // hide submit button
$this->view_iassign = optional_param('action', false, PARAM_BOOL);
$this->activity = new activity(optional_param('iassign_current', NULL, PARAM_TEXT)); // this is the activity inside iAssign block (content file)
$this->view();
} // function __construct($iassign, $cm, $course)
//DEBUG To be used in debug process
//DEBUG Present the calling stack
function generateCallTrace () { //DEBUG
$e = new Exception();
$trace = explode("\n", $e->getTraceAsString());
// reverse array to make steps line up chronologically
$trace = array_reverse($trace);
array_shift($trace); // remove {main}
array_pop($trace); // remove call to this method
$length = count($trace);
$result = array();
for ($i = 0; $i < $length; $i++) {
$result[] = ($i + 1) . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering
}
return "\t" . implode("\n\t", $result);
}
//DEBUG "code_to_write_file_through_javascript_calling"
function code_to_write_file_through_javascript_calling () {
// Copy this code in any point to debug JavaScript calling
// Used to write data in /mod/iassign/ilm_debug/
// Usefull when view() is called through JavaScript
//leo REMOVER! xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// function write_comment_submission(): 5610/9739
// if (!empty($submission_comment) && (strcmp($str1, $str2) != 0)) // there is comment and it is different from "previous"
require_once("ilm_debug/escreva.php");
$jj = 0; for ($ii=0; $ii<100000; $ii++) $jj += 1; //retardo para diferencia $timestamp de "view.php" e de "locallib.php"
$userid = $USER->id;
$data = date('Y_m_d_h_s');
$timestamp = time(); // timestamp
if (!isset($iassign_submission_current)) $iassign_submission_current = $_GET["iassign_submission_current"]; // http://localhost/saw/mod/iassign/view.php?action=viewsubmission&id=26981&iassign_submission_current=35665&userid_iassign=10823&iassign_current=6848&view_iassign=1&row=6&column=2
if (!isset($iassign_current)) $iassign_current = $_GET["iassign_current"]; // iassign_current
if (!isset($id)) $id = $_GET["id"]; // id => course_modules.id : course_modules.instance = iassign.id
// http://localhost/saw/mod/iassign/view.php?action=viewsubmission&id=26981&iassign_submission_current=35665&userid_iassign=10823&iassign_current=6848&view_iassign=1&row=6&column=2
// course_modules : id , course , module , instance = 6981 , 519 , 9 , 1787
$texto = " userid=" . $userid . ", data=" . $data . ", timestamp=" . $timestamp . "\n id=" . $id . ", iassign_submission_current=" . $iassign_submission_current . ", iassign_current=" . $iassign_current . "\n";
$texto .= " this->action = " . (isset($this->action) ? $this->action : "<>") . "\n";
$contexto = $this->generateCallTrace(); // debug_backtrace()
//$resp = writeContent("", "", "comentario_write_comment_submission_leo.txt", $texto);
$resp = writeContent("", "", "comentario_locallib_view.txt", $contexto . "\n" . $texto);
//leo REMOVER! xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//PHP8.4 Warning: Undefined variable $id_submission in /var/www/html/saw/mod/iassign/locallib.php on line 276
//PHP8.4 Warning: Undefined variable $sum_comment in /var/www/html/saw/mod/iassign/locallib.php on line 276
//PHP8.4 Warning: Undefined variable $submission_comment in /var/www/html/saw/mod/iassign/locallib.php on line 276
}
/// Show iAssign by using the security filter (temporary data on '*_iassign_security')
// This method provides the page to view each iLM with any interactive activity
// @calledby view.php : $iassigninstance->view($id); that instantiate 'iassign' (constructor above)
function view () { // This is an standard function for each iAssign instance (to not use parameters, it is ignored)
global $USER, $DB, $OUTPUT;
// $iassign_statementid = $this->iassign->iassign_statementid;
if ($this->activity!=null && $this->activity->get_activity()!=null && isset($this->activity->get_activity()->id))
$iassign_statementid = $this->activity->get_activity()->id;
else
$iassign_statementid = "";
// '$this' has : iassign Object = cm ; course ; iassign ; striassign ; striassigns ; context ; activity ; iassign_up ; iassign_down ; action ; ... ; coursecontext ; return
// If this user has no capability to View 'iassign': stop here
require_capability('mod/iassign:view', $this->context); // /lib/accesslib.php: if (!has_capability($capability, $context, $userid, $doanything))
// /lib/accesslib.php [873/5177]: function require_capability($capability, context $context, $userid = null, $doanything = true, $errormessage = 'nopermissions', $stringfile = '')
// /lib/accesslib.php [432/5177]: function has_capability($capability, context $context, $user = null, $doanything = true) {
//DEBUG To debug JavaScript calling, copy here the code in code_to_write_file_through_javascript_calling()
// Use code to write data in /mod/iassign/ilm_debug/
// Usefull when view() is called through JavaScript
// Put here the code "code_to_write_file_through_javascript_calling"
// Trigger module view event - in lib/classes/event/base.php!create(array $data = null)
$event = \mod_iassign\event\course_module_viewed::create(array(
'objectid' => $this->iassign->id,
'context' => $this->context
));
$event->add_record_snapshot('course', $this->course);
$event->trigger();
if ($this->action) { // when student do/redo activity or teacher see student solution
$this->action(); // calls '$this->view_iLM();'
}
else {
print $OUTPUT->header();
$this->view_iassigns(); // show the iLM with the content
print $OUTPUT->footer();
}
// Security: delete all records with an error loading iLM - 'iassign_security : id iassign_statementid userid file timecreated view'
//D $DB->delete_records("iassign_security", array("userid" => $USER->id, "view" => 1));
//D $iassign_iLM_security = $DB->get_record("iassign_security", array("iassign_statementid" => $iassign_statementid));
//D foreach ($iassign_iLM_security as $item) { echo $iassign_iLM_security->id . " ; " . $iassign_iLM_security->iassign_statementid . " ; " . $iassign_iLM_security->userid . " ; " . $iassign_iLM_security->timecreated . " ; " . $iassign_iLM_security->view . " ; " . $iassign_iLM_security->file . " \n" }
$DB->delete_records("iassign_security", array("userid" => $USER->id, "iassign_statementid" => $iassign_statementid));
//D $iassign_iLM_security = $DB->get_record("iassign_security", array("iassign_statementid" => $iassign_statementid));
//D if ($iassign_iLM_security) foreach ($iassign_iLM_security as $item) { echo $iassign_iLM_security->id . " ; " . $iassign_iLM_security->iassign_statementid . " ; " . $iassign_iLM_security->userid . " ; " . $iassign_iLM_security->timecreated . " ; " . $iassign_iLM_security->view . " ; " . $iassign_iLM_security->file . " \n" }
//D else echo "Apagou! ";
die();
} // function view()
/// Execute the action from Moodle (move, make visible, register the exercise (teacher) or its answer (learner)...)
function action () {
global $USER;
// action:
// up - move up activity (mover atividade para cima)
// down - move down activity (mover atividade para baixo)
// visible - view/hide activity (exibir/ocultar atividade)
// delete - delete activity (excluir atividade)
// deleteyes - confirms exclusion of activity (confirm the activity exclusion)
// deleteno - does not erase activity (do not erase activity)
// add - add activity (adicionar atividade)
// edit - edit activity (modificar atividade)
// Role 'teacher': reach this point if the user has role 'teacher' above
$action_iassign = array(
'newcomment' => '$this->add_comment();',
'view' => '$this->view_iassign_current();',
'get_answer' => '$this->get_answer();',
'repeat' => '$this->view_iassign_current();',
'overwrite' => '$this->get_answer();',
'stats_student' => '$this->stats_students();',
'download_answer' => '$this->export_file_answer();',
'download_all_answer' => '$this->export_package_answer();',
'notifications' => '$this->view_notifications();');
// Role 'nonediting-teacher': reach this point if the user has role 'nonediting-teacher'
$action_iassign_limit = array( // user with no capacity 'mod/iassign:editiassign' (e.g. 'nonediting-teacher')
'view' => '$this->view_iassign_current();',
'newcomment' => '$this->add_comment();', // this is necessary to allow "noneditingteacher" to send "new comment" in the student submission
'viewsubmission' => '$this->view_iassign_current();',
'edit_status' => '$this->edit_status();',
'edit_grade' => '$this->edit_grade();',
'stats_student' => '$this->stats_students();', // this is necessary to allow "noneditingteacher" to see iAssign survey
'export_csv' => '$this->export_csv();',
'report' => '$this->report();',
'print' => '$this->report();',
'stats' => '$this->stats();',
'printstats' => '$this->stats();');
$restricted = array('firstdown' => '$this->activity->move_iassign("firstdown", $this->iassign_down, $this->return);',
'up' => '$this->activity->move_iassign("up", $this->iassign_up, $this->return);',
'down' => '$this->activity->move_iassign("down", $this->iassign_down, $this->return);',
'visible' => '$this->activity->visible_iassign($this->return);',
'delete' => '$this->activity->delete($this->return);',
'deleteno' => '$this->return_home_course("confirm_not_delete_iassign");',
'deleteyes' => '$this->activity->deleteyes($this->return, $this);',
'add' => '$this->add_edit_iassign();',
'edit' => '$this->add_edit_iassign();',
'get_answer' => '$this->get_answer();',
'duplicate_activity' => '$this->duplicate_activity();',
'move_activity' => '$this->move_activity();',
'auto_evaluate' => '$this->auto_evaluate();',
'all_submissions' => '$this->all_submissions();',
'delete_submissions' => '$this->delete_submissions();',
'download_submissions' => '$this->download_submissions();',
'open_individual_submission' => '$this->open_individual_submission();',
'get_individual_submission' => '$this->get_individual_submission();',
'get_student_submission' => '$this->get_student_submission();',
'get_teacher_exercise' => '$this->get_teacher_exercise();',
'post_auto_eval_result' => '$this->post_auto_eval_result();',
'import_activity' => '$this->import_activity();',
'import_activity_confirm' => '$this->import_activity_confirm();'
);
$action_iassign_restricted = array_merge($restricted, $action_iassign_limit, $action_iassign);
$action = $this->action;
$array_teacher = array("edit", "delete", "visible", "firstdown", "up", "down", "duplicate_activity");
if (in_array($action, $array_teacher) && !has_capability('mod/iassign:editiassign', $this->context, $USER->id)) { //TODO block when editing (probably block must be in "add_edit_iassign()"
// Invalid access!!! Perhaps the message 'invalidsection'='Invalid section.' is more explainable?
// Capabilities 'mod/iassign:editiassign' and 'mod/iassign:editiassign' are similar, the first one is more permissive
// allowing 'teacher' (the second starts with 'editingteacher').
// redirect(new moodle_url('/admin/index.php'));
print_error('accessdenied', 'admin', $CFG->wwwroot . "/" . $CFG->admin); // ./lang/en/admin.php: "Access denied"
exit; // additional security...
// $this->userid_iassign = $USER->id;
}
// On depends the user's capability: precedence to edit power ('editiassign'); after to analyse ('evaluateiassign'); otherwise only view (any other).
if (has_capability('mod/iassign:editiassign', $this->context, $USER->id)) {
// When teacher is seeing student solution. By 'viewsubmission' goes to the function 'view_iassign_current()'
eval($action_iassign_restricted[$this->action]); // Now load 'view_iassign_current()' with 'viewsubmission' or 'new_iassign($param)' by '$this->add_edit_iassign()'
}
elseif (has_capability('mod/iassign:evaluateiassign', $this->context, $USER->id)) {
//D echo "locallib.php: this->action=" . $this->action . " action_iassign_limit[]="; print_r($action_iassign_limit); echo " ";
if (isset($action_iassign_limit[$this->action]))
eval($action_iassign_limit[$this->action]); // if the permission 'stats_student' is missing in $action_iassign_limit = array(...) this helps
}
else { // Student reaches this point
// When student do/redo activity: do => action = "view"; redo => action = "repeat"
// Arrive here with: "get_answer"; "view"
if (isset($action_iassign[$this->action])) // avoid error if non capable user try direct acess
eval($action_iassign[$this->action]); // Now load 'view_iassign_current()' with 'view'
}
} // function action()
//2022: ---------------------------------------------------------------------------------------------------------------------------------
//2022: Recuperacao {files} {iassign_statement}
//2022/02 see_all_files_context($context, $DB)
/// Temporary: fix 'iassign_statement.filesid' and 'files.itemid' (iassign_statement.filesid <- files.id; files.itemid <- iassign_statement.id)
// First version of iAssign used a random value to associate 'files.itemid' with 'iassign_statement.file'
// @calledby locallib.php ! get_update_files($context_id, $component, $filearea, $iassign_statement)
static function update_iassign_statement_files ($iassign_statement_id, $context_id, $component, $filearea, $files_itemid) {
global $DB; //2022: echo "update_iassign_statement_files: ";//D2022
// $files = $DB->get_records("files", array("component" => "mod_iassign", "filearea" => "exercise", "contextid" => $context_id, "itemid" => $files_itemid)); // contextid=1390 ; itemid=400 ;
// $sql_query = "SELECT * FROM {files} WHERE component='mod_iassign' AND filearea='exercise' AND contextid=" . $context_id . " AND filename<>'.' AND itemid=" . $files_itemid;
$sql_query = "SELECT * FROM {files} WHERE component='mod_iassign' AND filearea='exercise' AND contextid=" . $context_id . " AND itemid=" . $files_itemid;
$elem_in_files = $DB->get_records_sql($sql_query);
if (!$elem_in_files) {
print "Vazio! "; //TODO: se mantiver, internacionalizar!
return NULL;
}
// if (count($elem_in_files)>1) { echo "Problema! Mais de um arquivo! "; return NULL; }
//2022: echo "#files=" . count($elem_in_files) . ": "; // print_r($elem_in_files); echo " ";//D2022
foreach ($elem_in_files as $element_file) { // since ID is greater than 0, only "$file1 = $elem_in_files[0]" will not work!
if ($element_file->filename != '.') { // If not '.' is the actual file
$file1 = $element_file; // this '$file1' has the 'hashcontent' of the real file content, then it will be used to update 'iassign_statement.filesid' <- 'files.id'
}
// Update 'files.itemid' with 'iassign_statement.id'
$newentry = new stdClass();
$newentry->id = $element_file->id; $newentry->itemid = $iassign_statement_id;
//2022: if (!$DB->update_record('files', $newentry)) print_error('error_update', 'iassign');
}
// Update 'iassign_statement.filesid' with 'files.id'
$newentry = new stdClass();
$newentry->id = $iassign_statement_id; $newentry->filesid = $file1->id;
//2022: if (!$DB->update_record('iassign_statement', $newentry)) print_error('error_update', 'iassign');
} // static function update_iassign_statement_files($iassign_statement_id, $context_id, $component, $filearea, $files_itemid)
//TODO
//TODO Remover funcao 'get_update_files(.)' em favor do 'files_functions.php!update_iassignstatement_files(.)' ???????????
//TODO
/// Get file from table 'files', if 'files.itemid != iassign_statement.id' then update 'files.itemid' with 'iassign_statement.id'
// Usually 'context.instanceid' is 'course_modules.id' and 'course_modules.instance = iassign.id'
// However since iAssign is a "block of actual activities" from "iassign_statement", we store in 'files.itemid' the 'iassign_statement.id'
// @calledby function add_edit_iassign(): if ($this->action == 'edit'): to edit iAssign activity with "$files_list = iassign::get_update_files(...)" [2721/9504]
static function get_update_files ($context_id, $component, $filearea, $iassign_statement, $fs) {
// $fs is the reference to all files in Moodle data
//leo //REMOVE
echo "
get_update_files: iassign_statement: " . $context_id . ", " . $component . ", " . $filearea . ", " .
"id=" . $iassign_statement->id . ", file=" . $iassign_statement->file . ", filesid=" . $iassign_statement->filesid .
", iassign_ilmid =" . $iassign_statement->iassign_ilmid . ",name=" . $iassign_statement->name . " \n";//D2022
$msgAux = "";
$must_update_files_itemid = 0; // if changed to 1 => must update {files}.itemid; depois muda para $iassign_statement->filesid
// To consider old versions with improper association 'files.itemid': try 'iassign_statement.id' (correct one), 'iassign_statement.file' and 'iassign_statement.filesid'
// Correct association: {files}->itemid = $iassign_statement->id and {files}->id=$iassign_statement->fileid;
$files = $fs->get_area_files($context_id, $component, $filearea, $iassign_statement->id); // try: 'iassign_statement.id'
if (!$files) { // Could not find with 'iassign_statement.id'
$msgAux .= "- Nao com 'iassign_statement.id' \n";
$must_update_files_itemid = 1; // {files}.itemid must receive {iassign_statement}.id
$files = $fs->get_area_files($context_id, $component, $filearea, $iassign_statement->file); // try with 'iassign_statement.file'
if (!$files) { // Could not find with 'iassign_statement.file'
$msgAux .= "- Nao com 'iassign_statement.file' \n";
$files = $fs->get_area_files($context_id, $component, $filearea, $iassign_statement->filesid); // try with 'iassign_statement.filesid'
if (!$files) { // Could not find with 'iassign_statement.file'
print "ERROR {files} not found: " . $msgAux; //D2022
return NULL;
}
else { $must_update_files_itemid = $iassign_statement->filesid; echo "OK 3, nao com 'id', nem com 'file', mas pegou com 'iassign_statement.filesid'=" . $iassign_statement->filesid . " \n"; }
}
else { $must_update_files_itemid = $iassign_statement->file; echo "OK 2, nao com 'id', pegou com 'iassign_statement.file'=" . $iassign_statement->file . " \n"; }
}
else echo "OK 1, pegou com 'iassign_statement.id'=" . $iassign_statement->id . " \n";//D2022
if ($must_update_files_itemid!=0) {
$res_update = iassign::update_iassign_statement_files($iassign_statement->id, $context_id, $component, $filearea, $must_update_files_itemid);
}
foreach ($files as $file) { if ($file->get_filename() != '.') break; }
//$files_itemid = $file->get_itemid(); // /var/www/html/saw2021_1/lib/filestorage/stored_file.php: devolve 'files.itemid'
//$files_id = $file->get_id(); // file_record
echo "files[.]: id=" . $files_id . ", itemid=" . $files_itemid . " \n"; //D2022
return $file;
} // function get_update_files($context_id, $component, $filearea, $iassign_statement)
//2022: Recuperacao {files} {iassign_statement}
//2022: ---------------------------------------------------------------------------------------------------------------------------------
/// This method prints the student submission to a specific exercise
function get_student_submission () {
global $DB;
$student = optional_param('iassign_student', NULL, PARAM_TEXT);
$exercise = optional_param('iassign_exercise', NULL, PARAM_TEXT);
if (!$student || !$exercise) exit;
$iassign_submission = $DB->get_record("iassign_submission", array("iassign_statementid" => $exercise, "userid" => $student));
if ($iassign_submission)
print($iassign_submission->answer);
die();
}
/// This method prints the teacher exercise
// @calledby AJAX trhough "function action()" that calls "function auto_evaluate()"
function get_teacher_exercise () {
global $DB, $COURSE;
$ilmid = optional_param('iassign_exercise', NULL, PARAM_INT);
$iassign_statement = $DB->get_record("iassign_statement", array("id" => $ilmid));
$fs = get_file_storage(); // Get reference to all files in Moodle data
//2021/12: $files = $fs->get_area_files(context_module::instance($this->cm->id)->id, 'mod_iassign', 'exercise', $iassign_statement->filesid);
//TODO 2022: trocar "$iassign_statement->id" por "$iassign_statement->file"???
// ./lib/filestorage/file_storage.php: public function get_area_files($contextid, $component, $filearea, $itemid = false,...)
$files = $fs->get_area_files(context_module::instance($this->cm->id)->id, 'mod_iassign', 'exercise', $iassign_statement->id); // use itemid=$iassign_statement->id
if (!$files) { // try with 'iassign_statement->filesid'
$files = $fs->get_area_files(context_module::instance($this->cm->id)->id, 'mod_iassign', 'exercise', $iassign_statement->filesid);
}
foreach ($files as $file) {
if ($file->get_filename() != ".") {
print($file->get_content());
}
}
die();
}
/// This method receives the data from auto_eval event
/// @see auto_evaluate()
function post_auto_eval_result () {
global $COURSE, $CFG, $USER, $DB;
if (!has_capability('mod/iassign:runautoevaluate', $USER->context, $USER->id))
exit;
//$exercise="+exercises[actual_exercise]+"&student="+students[actual_student]+"&grade="+(grade * actual_value),
$exercise = optional_param('iassign_exercise', -1, PARAM_INT);
$student = optional_param('student', -1, PARAM_INT);
$grade = optional_param('grade', 0, PARAM_FLOAT);
// 1: Recuperar a nota atual:
$actual = $DB->get_record('iassign_submission', array('iassign_statementid' => $exercise, 'userid' => $student));
// 2: Atualizar a tabela:
$update_entry = new stdClass();
$update_entry->id = $actual->id;
$update_entry->previous_grade = $actual->grade;
$update_entry->grade = $grade;
// Update the iassign_submission
$DB->update_record("iassign_submission", $update_entry);
}
/// Function to help download all_submissions files
function download_submissions_help ($list) {
global $DB, $CFG, $OUTPUT;
// Get list of iLMs
$ilm_list = $DB->get_records("iassign_ilm");
// Get list of enrolled students:
$params_temp = array('shortname' => 'student');
$role = $DB->get_record_sql("SELECT s.id, s.shortname FROM {role} s WHERE s.shortname = :shortname", $params_temp);
$context = context_course::instance($this->course->id);
$params_temp = array('contextid' => $context->id, 'roleid' => $role->id);
$students_list = $DB->get_records_sql(
"SELECT s.userid, a.firstname, a.lastname FROM {role_assignments} s, {user} a WHERE s.contextid = :contextid AND s.userid = a.id AND s.roleid = :roleid ORDER BY a.firstname ASC,a.lastname ASC", $params_temp);
$json_obj = new stdclass();
$json_obj->submissions = [];
$csvfields = [];
$csvfields[] = 'submissionid';
$csvfields[] = 'file';
$csvfields[] = 'filesize';
$csvfields[] = 'timestamp';
$csvfields[] = 'humandate';
$csvfields[] = 'grade';
$csvfields[] = 'userid';
$csvfields[] = 'exerciseid';
$json_obj->submissions[] = $csvfields;
$exercise_dir = [];
$exercises_list = [];
foreach ($list as $item) {
if (!in_array($item->iassign_statementid, $exercise_dir)) {
$temp = $DB->get_record("iassign_statement", array("id" => $item->iassign_statementid));
$exercises_list[] = $temp;
$exercise_dir[] = $temp->id;
}
}
$student_dir = [];
$students_list = [];
foreach ($list as $item) {
if (!in_array($item->userid, $student_dir)) {
$temp = $DB->get_record("user", array("id" => $item->userid));
$students_list[] = $temp;
$student_dir[] = $temp->id;
}
}
//2021 $directory = $CFG->dataroot . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR;
//TODO: tem que criar moodledata/temp/iassign_files
// Create $CFG->dataroot/temp/iassign_files
$tempfilespath = $CFG->dataroot . DIRECTORY_SEPARATOR . 'temp';
if (!file_exists($tempfilespath)) {
mkdir($tempfilespath, 0777, true);
}
$iassignfilespath = $tempfilespath . DIRECTORY_SEPARATOR . 'iassign_files';
if (!file_exists($iassignfilespath)) {
mkdir($iassignfilespath, 0777, true);
}
$directory = $CFG->dataroot . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . 'iassign_files' . DIRECTORY_SEPARATOR;
if (!file_exists($directory)) {
// print 'Não foi possível criar o diretório para preparar o arquivo com as submissões. Possivelmente o caminho está bloqueado para escrita.';
print 'It was not possible to create the directory to receive the students submission files. Possibly the path has no write permission.';
exit;
}
$zip_filename = $directory . 'package_iassign_' . time() . '.zip';
$zip = new zip_archive(); // create ZIP
if (!$zip->open($zip_filename)) {
// print 'Não foi possível criar o arquivo zip com as submissões dos alunos, pois o diretório no servidor está bloqueado para escrita: ' . $directory;
print 'It was not possible to create the ZIP file with the students submission files. Possibly the server directory has no write permission: ' . $directory;
exit;
}
foreach ($exercises_list as $exercise) {
$dir_ex = iassign_utils::format_filename($exercise->name);
$zip->add_directory($dir_ex);
$extension_ilm = '';
foreach ($ilm_list as $ilm) {
if ($exercise->iassign_ilmid == $ilm->id) {
$extension_ilm = $ilm->extension;
break;
}
}
foreach ($students_list as $student) {
$individual_dir =
$dir_ex . DIRECTORY_SEPARATOR .
iassign_utils::format_filename($student->firstname . ' ' . $student->lastname);
$zip->add_directory($individual_dir);
$i = 1;
foreach ($list as $item) {
if ($item->userid == $student->id && $item->iassign_statementid == $exercise->id) {
$date = new DateTime();
$date->setTimestamp($item->timecreated);
$new_file = $individual_dir . DIRECTORY_SEPARATOR . iassign_utils::format_filename('submission_' . ($i++) . '_' . date_format($date, 'Y-m-d_H-i-s')) . '.' . $extension_ilm;
$zip->add_file_from_string($new_file, $item->answer);
$temp_json = [];
$temp_json[] = intval($item->id);
$temp_json[] = $new_file;
$temp_json[] = strlen($new_file);
$temp_json[] = intval($item->timecreated);
$temp_json[] = date_format($date, 'Y-m-d H-i-s');
$temp_json[] = doubleval($item->grade);
$temp_json[] = intval($item->userid);
$temp_json[] = intval($exercise->id);
$json_obj->submissions[] = $temp_json;
}
}
}
}
$csv_str = "";
foreach ($json_obj->submissions as $sub) {
$csv_str .= $this->csvstr($sub) . "\n";
}
$zip->add_file_from_string('index.csv', $csv_str);
$zip->close();
iassign_utils::download_file($zip_filename);
exit;
}
function csvstr (array $fields) : string {
$f = fopen('php://memory', 'r+');
if (fputcsv($f, $fields) === false) {
return false;
}
rewind($f);
$csv_line = stream_get_contents($f);
return rtrim($csv_line);
}
/// Download submissions from table iassign_allsubmissions
function download_submissions () {
global $COURSE, $CFG, $USER, $DB, $OUTPUT, $PAGE;
if (!has_capability('mod/iassign:runautoevaluate', $this->context, $USER->id))
exit;
$type = optional_param('type', NULL, PARAM_TEXT);
$item = optional_param('item', NULL, PARAM_TEXT);
$exercise = optional_param('exercise', NULL, PARAM_TEXT);
$iassign_id = optional_param('iassign', NULL, PARAM_TEXT);
$sub_list = [];
if ($type == 'individual') {
$sub_list[] = $DB->get_record(
'iassign_allsubmissions', array('id' => $item));
} elseif ($type == 'student') {
$sub_list = $DB->get_records(
'iassign_allsubmissions', array('userid' => $item, 'iassign_statementid' => $exercise));
} elseif ($type == 'exercise') {
$sub_list = $DB->get_records(
'iassign_allsubmissions', array('iassign_statementid' => $item));
} elseif ($type == 'block') {
$exercises_in_block = $DB->get_records(
'iassign_statement', array('iassignid' => $iassign_id));
foreach ($exercises_in_block as $exercise) {
$temp = $DB->get_records(
'iassign_allsubmissions', array('iassign_statementid' => $exercise->id));
$sub_list = array_merge($sub_list, $temp);
}
}
$this->download_submissions_help($sub_list);
}
/// Delete submissions in table iassign_allsubmissions
function delete_submissions () {
global $COURSE, $CFG, $USER, $DB, $OUTPUT, $PAGE;
if (!has_capability('mod/iassign:runautoevaluate', $this->context, $USER->id))
exit;
$type = optional_param('type', NULL, PARAM_TEXT);
$item = optional_param('item', NULL, PARAM_TEXT);
$exercise = optional_param('exercise', NULL, PARAM_TEXT);
if ($type == 'individual') {
$DB->delete_records('iassign_allsubmissions', array('id' => $item));
} elseif ($type == 'student') {
$DB->delete_records('iassign_allsubmissions', array('userid' => $item, 'iassign_statementid' => $exercise));
} elseif ($type == 'exercise') {
$DB->delete_records('iassign_allsubmissions', array('iassign_statementid' => $item));
}
}
function get_individual_submission () {
global $DB, $USER;
if (!has_capability('mod/iassign:runautoevaluate', $this->context, $USER->id))
exit;
$submissionid = optional_param('submissionid', NULL, PARAM_TEXT);
$submission = $DB->get_record("iassign_allsubmissions", array("id" => $submissionid));
print $submission->answer;
}
/// Open individual submission
function open_individual_submission () {
global $DB, $USER, $CFG;
if (!has_capability('mod/iassign:runautoevaluate', $this->context, $USER->id))
exit;
$submissionid = optional_param('item', NULL, PARAM_TEXT);
$id = $this->cm->id;
$param_aux = "id=" . $id . "&userid_iassign=" . $USER->id;
$url = "" . $CFG->wwwroot . "/mod/iassign/view.php?action=get_individual_submission&" . $param_aux . "&submissionid=" . $submissionid;
$atual_submission = $DB->get_record('iassign_allsubmissions', array('id' => $submissionid));
$atual_statement = $DB->get_record("iassign_statement", array("id" => $atual_submission->iassign_statementid));
$all_submissions = $DB->get_records('iassign_allsubmissions', array('iassign_statementid' => $atual_submission->iassign_statementid, 'userid' => $atual_submission->userid));
$user = $DB->get_record('user', array('id' => $atual_submission->userid));
$previous = null;
$next = null;
$i = 0;
$found = false;
foreach($all_submissions as $individual) {
if (!$found && $individual->id != $submissionid) {
$previous = $individual;
}
if ($found) {
$next = $individual;
break;
}
if ($individual->id === $submissionid) {
$found = true;
}
$i++;
}
print '
'; // "
print '
' . chr(13); // ' end of JavaScript code
// Get list of exercises in the instance:
$iassignid = optional_param('iassignid', NULL, PARAM_TEXT);
$exercises_list = $DB->get_records("iassign_statement", array("iassignid" => $iassignid));
print '
\n";
// Who has to receive?
$teachers = get_users_by_capability($this->context, 'mod/iassign:evaluateiassign');
$userfrom = \core_user::get_noreply_user();
if (has_capability('mod/iassign:evaluateiassign', $this->context, $USER->id)) { // a teacher has sent the comment:
// other teachers receive also: (excepts the sender)
foreach ($teachers as $teacher) {
if ($teacher->id != $USER->id) {
email_to_user(
$teacher,
$USER->firstname . " " . $USER->lastname . " (via " . $SITE->shortname . ")",
$subject,
"",
$text,
'',
'',
false,
$userfrom->email,
get_string('comment_not_answer_this', 'iassign') // 'Do not answer this message'
);
$message = new \core\message\message();
$message->component = 'mod_iassign';
$message->name = 'message';
$message->userfrom = core_user::get_noreply_user();
$message->userto = $teacher;
$message->subject = $subject;
$message->fullmessage = $text;
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = $text;
$message->smallmessage = $subject;
$message->notification = 1;
$message->contexturl = $url_submissao . '#comments';
$message->contexturlname = $this->activity->get_activity()->name;
$messageid = message_send($message);
}
} // foreach ($teachers as $teacher)
// and student:
$student = $DB->get_record('user', array('id' => $student_id));
$formated_text = str_replace("viewsubmission", "view", $text);
email_to_user(
$student,
$USER->firstname . " " . $USER->lastname . " (via " . $SITE->shortname . ")",
$subject,
"",
$formated_text,
'',
'',
false,
$userfrom->email,
get_string('comment_not_answer_this', 'iassign') // 'Do not answer this message'
);
$url_student = new moodle_url('/mod/iassign/view.php',
array(
'id' => $this->cm->id,
'action' => 'view',
'iassign_current' => $this->activity->get_activity()->id));
$message = new \core\message\message();
$message->component = 'mod_iassign';
$message->name = 'message';
$message->userfrom = core_user::get_noreply_user();
$message->userto = $student;
$message->subject = $subject;
$message->fullmessage = $formated_text;
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = $formated_text;
$message->smallmessage = $subject;
$message->notification = 1;
$message->contexturl = $url_student . '#comments';
$message->contexturlname = $this->activity->get_activity()->name;
$messageid = message_send($message);
} // if (has_capability('mod/iassign:evaluateiassign', $this->context, $USER->id))
else { // a student has sent the comment:
foreach ($teachers as $teacher) {
email_to_user(
$teacher,
$USER->firstname . " " . $USER->lastname . " (via " . $SITE->shortname . ")",
$subject,
"",
$text,
'',
'',
false,
$userfrom->email,
get_string('comment_not_answer_this', 'iassign') // 'Do not answer this message'
);
$message = new \core\message\message();
$message->component = 'mod_iassign';
$message->name = 'message';
$message->userfrom = core_user::get_noreply_user();
$message->userto = $teacher;
$message->subject = $subject;
$message->fullmessage = $text;
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = $text;
$message->smallmessage = $subject;
$message->notification = 1;
$message->contexturl = $url_submissao . '#comments';
$message->contexturlname = $this->activity->get_activity()->name;
$messageid = message_send($message);
} // foreach ($teachers as $teacher)
}
} // function send_alert_new_comment($comment, $student_id = -1)
/// This method gets the content from the iLM and register it
// It could be the "exercise template" (teacher) or an answer (student)
// If student answer: the answer must be registered in table {iassign_submission} (perhaps also in {submission_comment}, {iassign_allsubmissions})
// In 2022/10/05 was fixed to allow the registration of new solutions send by the student (even when the grade is reduced)
function get_answer () {
global $USER, $CFG, $DB, $OUTPUT;
$id = $this->cm->id;
$submission_comment = optional_param('submission_comment', NULL, PARAM_TEXT);
$submission_ajax = optional_param('iLM_ajax', NULL, PARAM_TEXT);
if ($submission_ajax == 1) ob_start(); // submission through JavaScript => do not present echoes
$comment = false;
if ($submission_comment)
$comment = $this->write_comment_submission();
// receives data of iLM using the current activity
$iassign_ilm = $DB->get_record("iassign_ilm", array("id" => $this->activity->get_activity()->iassign_ilmid)); // has automatic evaluation?
$iassign = $DB->get_record("iassign", array("id" => $this->activity->get_activity()->iassignid)); // activity
// Receives data of submission of current activity: the field 'activity' of class 'activity' has all fields of {iassign_statement}
$iassign_submission = $DB->get_record("iassign_submission", array("iassign_statementid" => $this->activity->get_activity()->id, "userid" => $this->userid_iassign)); // data about student solution
// receives post and get
$iLM_PARAM_ActivityEvaluation = optional_param('iLM_PARAM_ActivityEvaluation', 0, PARAM_INT); // 1 - activity evaluated as correct ; 0 - activity evaluated as incorrect
$iLM_PARAM_RealGrade = optional_param('iLM_PARAM_RealGrade', 0, PARAM_FLOAT); // the grade send by the iLM automatic evaluator (if it has one): a value between 0 and 1
//2016/02/16: IMPORTANTE trocar formatador para "nao formatado", pois esta destruindo o conteudo do arquivo
$iLM_PARAM_ArchiveContent = optional_param('iLM_PARAM_ArchiveContent', NULL, PARAM_RAW); // answer file (ATTENTION: do not change format, use RAW in order to ensure the correct content)
$MA_POST_Info = optional_param('MA_POST_Info', NULL, PARAM_FORMAT);
$MA_POST_SystemData = optional_param('MA_POST_SystemData', NULL, PARAM_FORMAT);
//TODO: With $return_get_answer == 1 implies that the new submission will over-write the old one, even with a smaller grade
//TODO: To be implemented: we can use JS functions 'overwrite()' and 'nooverwrite()' (bellow) to the student to choose over-write or not
// $return_get_answer = optional_param('return_get_answer', 0, PARAM_INT);
$return_get_answer = optional_param('return_get_answer', 1, PARAM_INT); // if 1 then register new submission even if the grade is reduced from 1.0 to any lower value
$msg = '';
// If the activity is defined to store all submissions
if ($this->activity->get_activity()->store_all_submissions == 1) {
$activity_scale = $this->activity->get_activity()->grade; // get {iassign_statement}.grade (to be used to weighted the student grade from [0,1])
$newentry = new stdClass();
$newentry->iassign_statementid = $this->activity->get_activity()->id;
$newentry->userid = $this->userid_iassign;
$newentry->timecreated = time();
//2023/05/25 $newentry->grade = round($iLM_PARAM_RealGrade, 2);
$newentry->grade = round($iLM_PARAM_RealGrade * $activity_scale, 2); // iLM must return through 'getEvaluation()' a value between 0 and 1
$newentry->answer = $iLM_PARAM_ArchiveContent;
$DB->insert_record("iassign_allsubmissions", $newentry);
}
// Feedback
// Activity status: 0 => not post 1; => post; 2 => evaluated as incorrect; 3 => evaluated as correct
$str_action = "view"; // repeat
if (strtolower($iassign_ilm->name) == "igeom") {
}
$title = get_string('evaluate_iassign', 'iassign');
print $OUTPUT->header();
print $OUTPUT->box_start();
// Action = { view ; repeat ; viewsubmission }
// * 'view' => it is impossible to re-send answer (this is correct with iGeom because its model to ensure security - do not allow the learner's access to the "answer model")
// * 'repeat' => student explicitly requested to redo the activiy or enter in the last submission under iLM other then iGeom
// * 'viewsubmission' => teacher/non editing teacher seeing the learner's activity
$return = $CFG->wwwroot . "/mod/iassign/view.php?action=view&id=" . $id . "&iassign_submission_current=" . $this->iassign_submission_current . "&userid_iassign=" . $this->userid_iassign . "&iassign_current=" . $this->activity->get_activity()->id;
$return_last = " " . iassign_icons::insert('return_home') . ' ' . get_string('return_iassign', 'iassign') . "\n";
$link_return = " " . iassign_icons::insert('home') . ' ' . get_string('activities_page', 'iassign') . "\n";
print "
\n";
if ($iLM_PARAM_ArchiveContent == - 1 || empty($iLM_PARAM_ArchiveContent)) { // if ($iLM_PARAM_ActivityEvaluation == -1)
//TODO Does it need review?
$this->write_solution = 0; // necessary in order to take note in Moodle 'grade' system
// empty_answer_post = No solution was posted.
if ($comment)
print '
' . "\n";
}
else { // if ($iLM_PARAM_ArchiveContent == - 1 || empty($iLM_PARAM_ArchiveContent))
$this->write_solution = 1; // indicate that this answer must overwrite the old one
if ($iassign_ilm->evaluate == 1 && $this->activity->get_activity()->automatic_evaluate == 1) { // iLM with automatic evaluator
//TODO Do compare with previous soluction to prevent update to one answer with a smaller grade?
// The student grade must be a value between 0 and 1: 0 => complete wrong ; 1 => 100% correct!
if (intval($iLM_PARAM_ActivityEvaluation) == 1) {
// if (true) { // after 2022/10/04: accept any new submission (overwrite, even when the grade is reduced!)
// intval($iLM_PARAM_ActivityEvaluation) == 1 => correct answer!!
//TODO Perhaps, must we use 'write_solution=0'?
// $this->write_solution = 1; // indicate that this answer must overwrite the old one
$status = 3;
$grade_student = $iLM_PARAM_RealGrade; // evaluated as correct solution submitted is assigned the note pattern of activity
$msg = '
";
print $OUTPUT->box_end();
} else {
print $OUTPUT->box_start();
print "
";
$param_aux = "action=overwrite&iassign_submission_current=" . $iassign_submission->id . "&id=" . $id . "&iassign_current=" . $this->activity->get_activity()->id . "&write_solution=" . $this->write_solution . "&userid_iassign=" . $USER->id;
$get_answer_overwrite = $CFG->wwwroot . "/mod/iassign/view.php?" . $param_aux;
print "\n";
print $OUTPUT->box_end();
}
}
} // if ($this->write_solution == 1)
print $OUTPUT->footer();
if ($submission_ajax == 1) {
ob_end_clean();
print 'OK';
}
die();
} // function get_answer()
/// Export in file the answer of student.
function export_file_answer () {
global $DB;
$iassign_submission_id = optional_param('iassign_submission_id', NULL, PARAM_INT);
$iassign_submission = $DB->get_record("iassign_submission", array("id" => $iassign_submission_id));
$iassign_statement = $DB->get_record("iassign_statement", array("id" => $iassign_submission->iassign_statementid));
$name = iassign_utils::format_filename(strip_tags($iassign_statement->name));
$iassign_ilm = $DB->get_record("iassign_ilm", array("id" => $iassign_statement->iassign_ilmid));
$extensions = explode(",", $iassign_ilm->extension);
$iassign_user = $DB->get_record("user", array("id" => $iassign_submission->userid));
$username = iassign_utils::format_filename($iassign_user->firstname . ' ' . $iassign_user->lastname);
$name_answer = $username . '-' . $name . '-' . userdate($iassign_submission->timemodified, '%Y%m%d-%H%M') . '.' . $extensions[0];
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: document/unknown");
header("Content-Disposition: attachment; filename=\"" . $name_answer . "\";");
set_time_limit(0);
print($iassign_submission->answer);
exit;
} // function export_file_answer()
/// Prepare data to static exportation (with course name, iAsssing block name, and exercises names
// @calledby $this->export_package_answer()
//TODO Precisa terminar! //TODO_HTML
function htmlcode_2_export ($course_fullname, $course_id, $iassign_block_id, $iassign_block_name, $array_iassign_name, $array_iassign_id, $userid, $username) {
$str_html = "
" . get_string('pluginname', 'iassign') . "\n"; // 'iAssign: interactive Learning Activities'
$str_html .= "
\n";
$tam = sizeof($array_iassign_name);
for ($ii=0; $ii<$tam; $ii++) {
//TODO_HTML completar construir HTML com titulo do exercicio e talvez legar com HTML para abri-lo com o iMA
}
$str_html .= "
\n";
return $str_html;
}
/// Export an package (zip) with all answer of students
// @calledby $this->action()
function export_package_answer () {
global $DB, $CFG, $OUTPUT, $USER;
$iassign_id = optional_param('iassign_id', NULL, PARAM_INT); // ID of iAssign block of activities
if (!$iassign_id) // allow direct access through http?://.../moodle/mod/iassign/view.php?action=download_all_answer&id=CMID&iassignid=IASSIGNID
$iassign_id = optional_param('iassignid', NULL, PARAM_INT);
$iassign = $DB->get_record("iassign", array("id" => $iassign_id)); // all data from this block of iAssign activities (table '*_iassign')
$iassign_block_name = iassign_utils::format_filename($iassign->name);
$userid = optional_param('userid', NULL, PARAM_INT);
$package_all_students = false;
if (!$userid) { // allow direct access through http?://.../moodle/mod/iassign/view.php?action=download_all_answer&id=CMID&iassignid=IASSIGNID
if (has_capability('mod/iassign:evaluateiassign', $USER->context, $USER->id)) { // Teacher (or above) access, so can export all users answers
$userid = $USER->id;
$package_all_students = true;
}
}
$iassign_user = $DB->get_record("user", array("id" => $userid));
$username = ""; // if all student use empty name
if (!$package_all_students) {
if (isset($iassign_user->firstname)) {
$firstname = strtolower($iassign_user->firstname);
$sep_aux = "_";
}
if (isset($iassign_user->lastname)) {
$lastname = strtolower($iassign_user->lastname);
$sep_aux = "_";
}
$username = iassign_utils::format_filename($firstname . $sep_aux . $lastname) . '_'; // user information
}
$current_date = date('Y_m_d_H');
$directory = $CFG->dataroot . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR; // /var//temp/files/
// If temporary directory under Moodle data does not exists => create it
if (!is_dir($directory)) {
mkdir($directory, 0755, true); // permissions: drwxr-xr-x
// created directory with permissions to be seen by everyone
}
$zip_filename = $directory . 'package_iassign_' . $username . strtolower($iassign_block_name) . '_' . $current_date . '.zip';
if (!is_writable($directory)) { // send a highlighted message!
print_error('error_answer_export_dir', 'iassign'); // Error: the target directory has no permission! Please, send this message to the Moodle admin!
exit; // just in case
}
//D echo "locallib.php!export_package_answer(): iassign_id=" . $iassign_id . ", iassign_block_name=" . $iassign_block_name . ", userid=" . $userid . ", directory=" . $directory;
//D echo " - zip_filename=" . $zip_filename . " ";
//D echo " "; exit;
$zip = new zip_archive(); // create ZIP
$zip->open($zip_filename); // open ZIP using the temporary file/directory
$iassign_statements = $DB->get_records("iassign_statement", array("iassignid" => $iassign_id));
//TODO $vet_exerc_title = array(); //TODO to be used with 'htmlcode_2_export(...)' - missing: build the HTML and directories linking files
$vet_student_filename = array();
$vet_student_content = array();
foreach ($iassign_statements as $iassign_statement) {
$activity_name = iassign_utils::format_filename(strip_tags($iassign_statement->name));
$iassign_ilm = $DB->get_record("iassign_ilm", array("id" => $iassign_statement->iassign_ilmid));
//TODO_HTML $vet_exerc_title[] = $iassign_statement->name;
$extensions = explode(",", $iassign_ilm->extension);
if ($package_all_students)
$array_iassign_submissions = $DB->get_records("iassign_submission", array("iassign_statementid" => $iassign_statement->id)); // get ALL students
else {
$iassign_submission = $DB->get_record("iassign_submission", array("iassign_statementid" => $iassign_statement->id, "userid" => $userid));
$array_iassign_submissions = array($iassign_submission); // only one student (but put in array to uniform treatment
}
foreach ($array_iassign_submissions as $iassign_submission) { // to all students
if ($iassign_submission) { // student has submission to this activity
$appendix_student_filename = "";
if ($package_all_students)
$appendix_student_filename = "userid_" . $iassign_submission->userid . "_"; // use the student ID
$timemodified = '-' . userdate($iassign_submission->timemodified, '%Y_%m_%d_%H_%M');
$student_content = $iassign_submission->answer;
$student_filename = $appendix_student_filename . iassign_utils::format_filename(strtolower($activity_name)) . $timemodified . '.' . $extensions[0];
$resp = $zip->add_file_from_string($student_filename, $student_content); // add file to ZIP
//$resp = $zip->add_file_from_string($path_dir . $one_file, $destination . $ds . $one_file); //2 Esta versao funciona!
if ($resp) {
$vet_student_filename[] = $student_filename;
$vet_student_content[] = $student_content;
}
else { // send a highlighted message!
print_error('error_answer_export_file', 'iassign'); // Error: fail to insert content to the file
exit; // just in case
}
}
} // foreach ($array_iassign_submissions as $iassign_submission) // to all students
} // foreach ($iassign_statements as $iassign_statement)
$zip->close(); // close the ZIP file
if (count($vet_student_filename)>0) {
$vet_result = iassign_utils::register_temporary_file($zip_filename, $vet_student_filename, $vet_student_content);
$result_tf = $vet_result[0];
$filenameZip = $vet_result[1]->filename;
}
iassign_utils::download_file($zip_filename); // download the ZIP file
exit;
} // function export_package_answer()
/// Editing status of interactive activities
function edit_status () {
global $USER, $DB, $OUTPUT;
$newentry = new stdClass();
$newentry->id = $this->iassign_submission_current;
$newentry->status = optional_param('return_status', 0, PARAM_INT);
$iassign_submission = $DB->get_record('iassign_submission', array('id' => $this->iassign_submission_current));
if ($iassign_submission->status != 0 && $newentry->status == 0)
$newentry->status = $iassign_submission->status;
$newentry->teacher = $USER->id;
if (!$DB->update_record('iassign_submission', $newentry))
print_error('error_update', 'iassign');
else {
// Trigger module viewed event.
$event = \mod_iassign\event\submission_updated::create(array(
'objectid' => $this->iassign->id,
'context' => $this->context
));
$event->add_record_snapshot('course', $this->course);
$event->trigger();
$this->action = 'viewsubmission';
$this->view_iassign_current();
} // if (!$DB->update_record('iassign_submission', $newentry))
} // function edit_status()
/// Editing grade of interactive activities
function edit_grade () {
global $USER, $DB, $OUTPUT;
$newgrade = optional_param('return_grade', 0, PARAM_INT);
if ($newgrade && $newgrade >= 0) {
$newentry = new stdClass();
$newentry->id = $this->iassign_submission_current;
$newentry->grade = optional_param('return_grade', 0, PARAM_INT);
$newentry->teacher = $USER->id;
if (!$DB->update_record('iassign_submission', $newentry))
print_error('error_update', 'iassign');
else {
// Trigger module viewed event.
$event = \mod_iassign\event\submission_updated::create(array(
'objectid' => $this->iassign->id,
'context' => $this->context
));
$event->add_record_snapshot('course', $this->course);
$event->trigger();
}
} // if ($newgrade >= 0)
$this->action = 'viewsubmission';
$this->view_iassign_current();
} // function edit_grade()
/// Add or Edit interactive activities
// Get here when editing form and and submitted form data
// To each activity, we have an associated file in Moodle Data (registered in {files}) with: {files}.itemid := {iassign_statement}.id and {iassign_statement}.filesid := {files}.id
// Given a {iassign_statement}.id it is possible to recover its associated {files} using this (e.g. {iassign_statement}.id=10):
// SELECT cm.course, cm.id, cm.instance, c.instanceid, c.id AS contextid, f.id AS files_id, f.itemid, f.author, f.timecreated, f.filename,
// ia.id AS iaid, ias.file, ia.name AS ianame, ias.file AS iasfile, ias.id AS iasid, ias.name AS iasname, ias.timecreated
// FROM {modules} AS m, {course_modules} AS cm, {context} AS c, {files} AS f, {iassign} AS ia, {iassign_statement} AS ias
// WHERE m.name='iassign' AND m.id=cm.module AND cm.id = c.instanceid AND cm.instance = ia.id AND c.id=f.contextid AND f.component='mod_iassign'
// AND ia.id=ias.iassignid AND (f.itemid=ias.file OR f.itemid=ias.id) AND ias.id=10
// @calledby $this->action(): with "'add' => '$this->add_edit_iassign();'," or "'edit' => '$this->add_edit_iassign();',"
function add_edit_iassign () {
global $USER, $CFG, $COURSE, $DB, $OUTPUT;
require_once('iassign_form.php');
$id = $this->cm->id; // All iAssign statement => iassign_statement.iassignid
$iassignid = $this->iassign->id;
$param = new stdClass(); // parameters to build data to the form - see bellow "$mform = new mod_iassign_form(...); $mform->set_data($param);
$param->action = $this->action; // hidden
$param->id = $id; // hidden
$param->special_param1 = 0; // 'special_param1 == 1' => script of iGeom
// Trick to pass value to the Moodle form that is loaded bellow (with "$mform = new mod_iassign_form(null,...)")
// the last 2 are used in "iassign_form.php!definition()"
//x $COURSE->cm = $id; // "$id = $COURSE->cm;" but not used...
$COURSE->iassignid = $iassignid; // "$iassigns = $DB->get_records('iassign_statement', array('iassignid' => $COURSE->iassignid));"
$COURSE->iassign_file_id = NULL; // "if (!is_null($COURSE->iassign_file_id))"
// Associated {files} are registered with contextid from {context}.contextlevel = CONTEXT_MODULE
// ./lib/accesslib.php : CONTEXT_MODULE = 70 (CONTEXT_COURSE = 50)
$context = context_module::instance($this->cm->id); // use context from this course
$component = 'mod_iassign'; // to {files}
$filearea = 'exercise';
//x TODO remove this after a while (2023/04/19) - here $this->iassign_current is empty and $COURSE->iassign_id is never used!
if (!empty($this->iassign_current)) $COURSE->iassign_id = $this->iassign_current;
else $COURSE->iassign_id = 0;
$total_of_activities = 0; // get the total number of activities in this iAssign block
if ($this->action == 'add') {
$iassign_data = $DB->get_record("iassign", array('id' => $iassignid));
$params_temp = array('iassignid' => $iassignid);
$query_str = "SELECT s.id, s.name, s.dependency FROM {iassign_statement} s WHERE s.iassignid = :iassignid ORDER BY s.position ASC";
$iassign_statement = $DB->get_records_sql($query_str, $params_temp); //
$total_of_activities = count($iassign_statement);
$param->iassignid = $iassignid;
$param->name = "";
$param->oldname = "";
$param->type_iassign = 3;
$param->proposition = "";
$author = $USER; //x $DB->get_record("user", array("id" => $USER->id)); --- useless since we already have {user} info.!!!
$param->author_name = $author->firstname . ' ' . $author->lastname . ' (' . $author->id . ')';
$param->author_modified_name = $author->firstname . ' ' . $author->lastname . ' (' . $author->id . ')';
$param->author = $param->author_name;
$param->author_modified = $param->author_modified_name;
$COURSE->iassign_list = array();
$param->iassign_list = array();
if ($iassign_statement) {
foreach ($iassign_statement as $iassign) {
$iassignid = $iassign->id;
$param->iassign_list[$iassignid] = 0;
$COURSE->iassign_list[$iassignid] = new stdClass();
$COURSE->iassign_list[$iassignid]->id = $iassignid;
$COURSE->iassign_list[$iassignid]->name = $iassign->name;
$COURSE->iassign_list[$iassignid]->enable = 1;
} // foreach ($iassign_statement as $iassign)
}
$param->iassign_ilmid = 0;
$param->file = 0;
$param->fileid = 0; // to receive {files}.id
$param->fileold = 0;
$param->filename = "";
$param->grade = $iassign_data->grade;
$param->timemodified = time();
$param->timecreated = time();
$param->timeavailable = $iassign_data->timeavailable;
$param->timedue = $iassign_data->timedue;
$param->preventlate = $iassign_data->preventlate;
$param->test = $iassign_data->test;
$param->special_param1 = 0;
$param->visible = 1;
$param->max_experiment = $iassign_data->max_experiment;
$param->dependency = 0;
$param->automatic_evaluate = 1;
$param->show_answer = 1;
} // if ($this->action == 'add')
elseif ($this->action == 'edit') {
// First form load
// The update is effectively registered in {iassign_statement} and {files} bellow,
// in the second "elseif ($this->action == 'edit')": $iassignid = $this->activity->update_iassign($result);
$COURSE->iassign_list = array();
$this_activity = $this->activity->get_activity();
if ($this_activity != null) { // first enter here: fill form data
$iassign_statement_current = $this_activity; // $DB->get_record("iassign_statement", array("id" => $this_activity->id));
$param->iassign_id = $iassign_statement_current->id; // oculto
$param->iassignid = $iassign_statement_current->iassignid; // oculto
$param->name = $iassign_statement_current->name;
$param->oldname = $iassign_statement_current->name;
$param->type_iassign = $iassign_statement_current->type_iassign;
$param->store_all_submissions = $iassign_statement_current->store_all_submissions;
$param->proposition = array('text' => $iassign_statement_current->proposition, ''); //'format' => $instance->introformat
$param->author_name = $iassign_statement_current->author_name; // hidden field
$param->author = $iassign_statement_current->author_name;
$author = $USER; //x $DB->get_record("user", array('id' => $USER->id)); --- useless since we already have {user} info.!!!
$param->author_modified_name = $author->firstname . ' ' . $author->lastname . ' (' . $author->id . ')';
$param->author_modified = $param->author_modified_name;
$dependency = explode(';', $iassign_statement_current->dependency);
$param->iassign_list = array();
// Select all other iAssign activities inside this block with dependency
$str_query = "SELECT * FROM {iassign_statement} WHERE iassignid = '" . $iassignid . "' AND id!='" . $iassign_statement_current->id . "' AND dependency!=0";
$iassign_statement_dependency = $DB->get_records_sql($str_query);
$array_dependency = array();
$subdependency = "";
$sub_subdependency = "";
// Dependents on this exercise
if ($iassign_statement_dependency) {
$subdependency .= $this->search_dependency($iassign_statement_current->id, $iassign_statement_dependency);
// to whom this exercise depends
foreach ($subdependency as $tmp)
$sub_subdependency .= $this->search_sub_dependency($tmp);
$list_dependency = $subdependency . $sub_subdependency;
$array_dependency = explode(";", $list_dependency);
}
// Get all other activities in the same iAssigment block:
$str_query = "SELECT id, name FROM {iassign_statement} WHERE iassignid = '" . $iassignid . "' AND id!='" . $iassign_statement_current->id . "' ORDER BY position ASC";
$all_others_iassign_statement = $DB->get_records_sql($str_query);
$total_of_activities = count($all_others_iassign_statement) + 1;
$inter = array();
if ($all_others_iassign_statement) {
foreach ($all_others_iassign_statement as $iassign)
if (in_array($iassign->id, $dependency))
$inter[] = $iassign->id;
}
if ($all_others_iassign_statement) {
foreach ($all_others_iassign_statement as $iassign) {
$iassignid = $iassign->id;
$COURSE->iassign_list[$iassignid] = new stdClass();
$COURSE->iassign_list[$iassignid]->name = $iassign->name;
$COURSE->iassign_list[$iassignid]->id = $iassignid;
if (in_array($iassignid, $dependency))
$param->iassign_list[$iassignid] = 1;
else
$param->iassign_list[$iassignid] = 0;
if (in_array($iassignid, $array_dependency))
$COURSE->iassign_list[$iassignid]->enable = 0;
else
$COURSE->iassign_list[$iassignid]->enable = 1;
} // foreach ($all_others_iassign_statement as $iassign)
} // if ($all_others_iassign_statement)
$param->iassign_ilmid = $iassign_statement_current->iassign_ilmid; // define iLM ID to be used to define 'select' on 'iassign_form.php'
$param->fileold = 0;
$param->filesid = 0;
$param->file = $iassign_statement_current->file; // old version of {iassign_statement}/{files} association
$param->filesid = 0; // new version of {iassign_statement}/{files} association: {iassign_statement}.filesid := {files}.id and {files}.itemid := {iassign_statement}.id
$param->filename = '';
$param->grade = $iassign_statement_current->grade;
$param->timecreated = $iassign_statement_current->timecreated; // hidden
$param->timeavailable = $iassign_statement_current->timeavailable;
$param->timedue = $iassign_statement_current->timedue;
$param->preventlate = $iassign_statement_current->preventlate;
$param->test = $iassign_statement_current->test;
$param->special_param1 = $iassign_statement_current->special_param1; // 'special_param1 == 1' => script of iGeom
$param->position = $iassign_statement_current->position; // hidden
$param->visible = $iassign_statement_current->visible;
$param->max_experiment = $iassign_statement_current->max_experiment;
$param->automatic_evaluate = $iassign_statement_current->automatic_evaluate;
$param->show_answer = $iassign_statement_current->show_answer;
// Association {iassign_statement} with {files}
// Attention to the {files}.contextid and {files}.itemid used: "{files}.itemid" must be "{iassign_statement}.id" (and {iassign_statement}.filesid={files}.id)
// Old version used: {iassign_statement}.files = {files}.itemid with a randam value...
// ./lib/filestorage/file_storage.php: public function get_area_files($contextid, $component, $filearea, $itemid = false,...)
$fs = get_file_storage(); // Get reference to all files in Moodle data
//2021/12 $files_list = $fs->get_area_files($context->id, $component, $filearea, $iassign_statement_current->filesid);
//2022/02 $files_list = $fs->get_area_files($context->id, $component, $filearea, $iassign_statement_current->id); // em alguns "_files.id" tem 'file' NAO 'id'
$iassign_statement_id = $iassign_statement_current->id;
$iassign_statement_file = $iassign_statement_current->file;
$iassign_statement_filesid = $iassign_statement_current->filesid;
//D if ($USER->id == 3) // Here: function add_edit_iassign() : elseif ($this->action == 'edit') : if ($this_activity != null)
//D echo "
locallib.php: add_edit_iassign(): user.id=3: {ia}.id=" . $iassign_statement_id . ", contextid=" . $context->id . " \n"; //leo
// Get the element associated to {iassign_statement} in {files} using 'files_functions.php!get_from_files($ia_id, $ia_file, $ia_filesid, $fs, $contextid, $component, $filearea)'
require_once('files_functions.php'); // Get auxiliary functions to manage {iassign_statement}/{files}
$answer_array = get_from_files($iassign_statement_id, $iassign_statement_file, $iassign_statement_filesid, $fs, $context->id, $component, $filearea);
// if $f2_obj!=NULL but $f2_obj==NULL, then probably $f1_obj was recovered by 'files_functions.php!get_from_filesAll(.)' in the previous edition
if ($answer_array==NULL) {
if ($USER->id == 3) { //D Debug study - only {user}.id==3 sees it
echo " x locallib.php!add_edit_iassign(.): ERRO! {iassign_statement}.id=" . $iassign_statement_id . ", contextid=" . $context->id . " NAO esta' com {files} associado! \n"; //D
echo "Error: answer_array==NULL "; //D
echo "invalidid = " . get_string('invalidid', 'iassign') . " \n"; //D
// {files} : id contenthash pathnamehash contextid component filearea itemid filepath filename userid filesize mimetype status source author license timecreated
}
// Try to recover file in the same context with the smallest Levenstein distance from the activity name:
// levenshtein($str1,$str2) is the minimal number of characters you have to replace, insert or delete to transform $str1 into $str2
$ia_name = $iassign_statement_current->name;
$mindist_levenshtein = strlen($ia_name);
$mindist_component = '';
$answer_array = get_from_filesAll($fs, $context->id, 'exercise', $filearea); // $component='exercise'
if ($USER->id == 3) { //D Debug study - only {user}.id==3 sees it
if (is_null($answer_array) || !is_array($answer_array)) $count_arr = 0; //D
else $count_arr = count($answer_array); //D
}
foreach ($answer_array as $one_files)
if ($one_files->filename!='.') {
$dist_levenshtein = levenshtein($one_files->filename,$ia_name);
if ($dist_levenshtein <= $mindist_levenshtein) { // smaller distance (get always the last one - more recent one)
$mindist_levenshtein = $dist_levenshtein;
$mindist_component = 'exercise';
$f1_obj = $one_files;
}
} // if ($one_files->filename!='.')
$answer_array = get_from_filesAll($fs, $context->id, 'activity', $filearea); // $component='activity'
foreach ($answer_array as $one_files)
if ($one_files->filename!='.') {
$dist_levenshtein = levenshtein($one_files->filename,$ia_name);
if ($dist_levenshtein <= $mindist_levenshtein) { // smaller distance (get always the last one - more recent one)
$mindist_levenshtein = $dist_levenshtein;
$mindist_component = 'activity';
$f1_obj = $one_files;
}
} // if ($one_files->filename!='.')
// Now get as a 'file_storage' object (not a generic one returned fron $DB->get_records('files',...)
//./lib/filestorage/file_storage.php: public function get_file_instance(stdClass $filerecord)
if ($f1_obj != NULL) {
$f1_obj = $fs->get_file_instance($f1_obj);
}
$f2_obj = NULL;
//D print_error('invalidid', 'iassign'); // $string['invalidid'] = 'Invalid ID';
//D exit; // do not need 'print_error(.)' will stop execution
}
else { //DEBUG if ($answer_array==NULL)
//DEBUG evitar mensagens de depuracao no caso de erro de 'files_functions.php!get_from_files(.)' devolver vazio
$f1_obj = $answer_array[0]; // regular 'filename'
$f2_obj = $answer_array[1]; // directory (filename == '.')
} //DEBUG REMOVER if ($answer_array==NULL)
$ia_obj = $iassign_statement_current;
// 2022/10/07 Keep this until next iAssign version update
// ATTENTION: Some iAssign activity could have only one entry in {files} => came from duplication (using the same Moodle Data file)
// TODO: every duplication of activity must generate a new copy of actual file in Moodle Data
//TOD: Quem nao esta' duplicando {files}: "duplicar" ou "backup"?
// Ver: /home/leo/projetos/iMA/lms/itarefa/novo/files_iassign_statement/sobre_recuperacao_ia_files.txt
// It must have: {files}->id=$iassign_statement_current->file
if ($f1_obj != NULL) {
// ---------------------------------------------------------------------------------------------------------------------------------
// Try to recover association {iassign_statement}/{files}
// It uses "files_functions.php ! update_iassignstatement_files(...)" to (eventually) reconstruct relation
$result = update_iassignstatement_files($DB, $ia_obj->id, $f1_obj->get_id(), $ia_obj, $f1_obj, $f2_obj, $context); // ./files_functions.php
if (!$result) print "Could not change {iassign_statement}.filesid=" . $ia_obj->id . " or {files}.itemid=" . $f1_obj->itemid . " ";
// $files_list = iassign::get_update_files($context->id, $component, $filearea, $iassign_statement_current, $fs); //2022: tentativa de recupearar arquivos se perdido
if ($f1_obj->get_filename() != '.') { // additional security: ensure the first {files} has real "filename"
$param->filename = $f1_obj->get_filename();
$param->file = $f1_obj->get_id();
$param->fileold = $f1_obj->get_id();
$COURSE->iassign_file_id = $f1_obj->get_id(); // necessary to "iassign_form.php" (loaded bellow with "$mform = new mod_iassign_form(...)")
}
} // if ($f1_obj != NULL)
//TODO //MOOC2014 -- get special parameters?
//D $iassign_ilm_configs = $DB->get_records('iassign_statement_config', array('iassign_statementid' => $iassign_statement_current->id));
//D if ($iassign_ilm_configs) {
//D foreach ($iassign_ilm_configs as $iassign_ilm_config)
//D $param->{'param_'.$iassign_ilm_config->iassign_ilm_configid} = $iassign_ilm_config->param_value;
//D } //MOOC2014 --
} // if ($this_activity != null)
} // elseif ($this->action == 'edit')
//D Get all iActivity in the iAssign block with id = $this->iassign->id ($this->iassign has data from the form)
//D It could be used to define dependency of the current activity (considering those list $iassign_list)
//D $iassign_list = $DB->get_records_list('iassign_statement', 'iassignid', array($this->iassign->id), 'position ASC'); //2022: not used any more
//D echo "locallib.php: add_edit_iassign(): this->iassign->id=" . $this->iassign->id . " ";
//D foreach ($iassign_list as $item) echo " - id=" . $item->id . ", name=" . $item->name . ", iassignid=" . $item->iassignid . ", type_iassign=" . $item->type_iassign . " ";
//D if ($iassign_list) { $end_list = array_pop($iassign_list); $param->position = $end_list->position + 1; } else $param->position = 1;
$param->position = $total_of_activities; // $total_of_activities = count($all_others_iassign_statement) + 1;
// Create form and associate its data that will be finally processed by 'locallib.php!update_iassign($param)'
// If {iassign_ilm}.enable == 0, then iLM remains undefined (does not appear in iLM selection)
// 'mform1' is used in: ./mod/iassign/iassign_form.php, ./mod/iassign/settings_form.php
// new mod_iassign_form(...) in ./mod/iassign/iassign_form.php extends /lib/formslib.php:
// ./lib/formslib.php: __construct($action=null, $customdata=null, $method='post', $target='', $attributes=null, $editable=true, $ajaxformdata=null)
if (isset($param->iassign_ilmid)) {
// array is additional atributes to 'form'
// 'special_param1 == 1' => script of iGeom :
\n";
//1 $only_one_send_button = 1; // avoid put comment frame again (bellow)
//1 }
$output .= $OUTPUT->box_end();
print $output;
} // if ($this->view_iassign)
print $OUTPUT->box_end(); // Box 5 to 'proposition' - close
} // if ($this->view_iassign)
} // elseif (has_capability('mod/iassign:submitiassign', $USER->context, $USER->id))
else
if (isguestuser()) { // else of elseif (has_capability('mod/iassign:submitiassign', $USER->context, $USER->id))
print($OUTPUT->notification(get_string('no_permission_iassign', 'iassign'), 'notifyproblem'));
print '
' . "\n";
// Prepare the list of all {iassign_statement} in this iAssign block {iassign}: number; due date; exercise statement ({iassign_statement}.name)
$i = 1; // to exercises 'students_submissions[]'
$students_submissions = array(); // array indexed by student index with all submissions (to all activities)
$array_type_iassign = array(); // array with all exercises and tests: $array_type_iassign[$i]==true => type_iassign=3
$stylebutton = "background: none; -webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);-moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75); min-width: 3.5rem;";
foreach ($iassign_list as $one_iassign_statement) { // for all exercise in this block, print its information: number; due date; exercise statement
$test_exercise = "";
// Get all submissions to this activity (all students)
$iassign_submission = $DB->get_records("iassign_submission", array("iassign_statementid" => $one_iassign_statement->id));
if (($iassign_submission) && $one_iassign_statement->type_iassign < 3) { // Activity type not any more 'exercise' (however has submission)
// Since 2025/06/27 we also presents type_iassign=2 (tests), so this message dos not make sense any more
// $test_exercise = " (" . get_string('iassign_exercise', 'iassign') . ")"; // 'Activity has been exercise'
}
if ($one_iassign_statement->type_iassign > 1) { // 3: is 'exercise' => has evaluation grade
$students_submissions[$i] = new stdClass();
$students_submissions[$i]->name = $one_iassign_statement->name;
$students_submissions[$i]->id = $i;
$students_submissions[$i]->iassignid = $one_iassign_statement->id;
$students_submissions[$i]->timedue = $one_iassign_statement->timedue;
if ($one_iassign_statement->type_iassign == 3) { // 3: is 'exercise' => has evaluation grade
$students_submissions[$i]->grade = $one_iassign_statement->grade;
$array_type_iassign[$i] = true; // $array_type_iassign[$i]==true => type_iassign=3
$msg_grade = "max grade=" . $one_iassign_statement->grade;
}
else {
$array_type_iassign[$i] = false; // $array_type_iassign[$i]==false => type_iassign=2, is test
$msg_grade = "test has no grade";
}
$students_submissions[$i]->total_answers = 0; // initialize the total of answers to this activity
print '
' . "\n";
$context = context_course::instance($this->course->id);
if ($num_exerc > 1) {
// $role = $DB->get_record_sql("SELECT s.id, s.shortname FROM {$CFG->prefix}role s WHERE s.shortname = 'student'");
$params_temp = array('shortname' => 'student');
$role = $DB->get_record_sql("SELECT s.id, s.shortname FROM {role} s WHERE s.shortname = :shortname", $params_temp);
// $students = $DB->get_records_sql("SELECT s.userid, a.firstname, a.lastname FROM {$CFG->prefix}role_assignments s, {$CFG->prefix}user a WHERE s.contextid = '$context->id' AND s.userid = a.id AND s.roleid = '$role->id' ORDER BY a.firstname ASC,a.lastname ASC");
$params_temp = array('contextid' => $context->id, 'roleid' => $role->id);
$students = $DB->get_records_sql(
"SELECT s.userid, a.firstname, a.lastname FROM {role_assignments} s, {user} a " .
" WHERE s.contextid = :contextid AND s.userid = a.id AND s.roleid = :roleid " .
" ORDER BY a.firstname ASC,a.lastname ASC", $params_temp);
print '
' . get_string('students', 'iassign') . '
' . "\n";
$width = 85/$num_exerc; // width to each column
for ($j=1; $j<$num_exerc; $j++) { // all exercises on this block: initialize the counter of correct answers
$sum_iassign_correct[$j] = 0;
print '
' . $students_submissions[$j]->id . '
' . "\n";
//
}
print '
' . get_string('functions', 'iassign') . '
';
$sum_iassign = $j - 1;
print '
' . "\n";
$total = 0;
$sum_student = 0;
$comment = iassign_icons::insert('comment_read');
$sum_comment = 0;
$sum_correct_iassign = array(); //NOT used
$sum_correct_student = array(); //NOT used
$USER->matrix_iassign = array();
if ($students) {
$total_students = 0;
foreach ($students as $tmp) { // count students
$users_array[$total_students] = $tmp;
$total_students++;
}
print "" . get_string('report_total_students', 'iassign') . ": " . $total_students . " "; // 'Total of students in class'
for ($student_index=0; $student_index<$total_students; $student_index++) { // for all students
print '
\n"; // 'Total of submissions'
for ($ii = 1; $ii < $num_exerc; $ii++) {
print "
" . $students_submissions[$ii]->total_answers . "
";
}
print "
\n";
} // if ($students)
} // if ($num_exerc>1)
else {
print_string('no_activity', 'iassign');
}
print "
\n";
print '
' . get_string('ps_experiment', 'iassign') . "
\n"; // the number of atemps is...
print '
' . get_string('ps_comment', 'iassign') . "
\n"; // the total number of messages is...
if ($this->action != 'print')
print $OUTPUT->footer();
die();
} // function report()
/// Display graphics of performance
// Used by teacher's interface: Reports | Graphics
function stats () {
global $USER, $CFG, $DB, $OUTPUT;
$id = $this->cm->id;
$iassign_statement_list = $DB->get_records_list('iassign_statement', 'iassignid', array('iassignid' => $this->iassign->id), "position ASC");
if ($this->action != 'printstats')
$title = get_string('graphic', 'iassign');
$num = array();
$ii = 1;
$total_iassign_statement = 0; // total of exercises in this iAssign block
foreach ($iassign_statement_list as $one_iassign_statement) {
//REMOVE: useless here: $iassign_submission = $DB->get_records("iassign_submission", array("iassign_statementid" => $one_iassign_statement->id));
if ($one_iassign_statement->type_iassign == 3) { // {iassign_statement}.type_iassign == 3 <=> is exercise
$total_iassign_statement++; // one more exercise
$sum_iassign_correct[$ii] = 0;
$num[$ii] = new stdClass();
$num[$ii]->name = $one_iassign_statement->name;
$num[$ii]->id = $ii; // register index by {iassign_statement}.id
$num[$ii]->iassignid = $one_iassign_statement->id; // {iassign_submission}.id xxxxxxxxxxxxx remover!!!
$num[$ii]->iassign_statementid = $one_iassign_statement->id; // {iassign_submission}.iassign_statementid = {iassign_statement}.id
$ii++;
} // if ($one_iassign_statement->type_iassign == 3)
} // foreach ($iassign_statement_list as $one_iassign_statement)
$context = context_course::instance($this->course->id);
if ($total_iassign_statement > 0) { // it has any exercise?
// $role = $DB->get_record_sql("SELECT s.id, s.shortname FROM {$CFG->prefix}role s WHERE s.shortname = 'student'");
$params_temp = array('shortname' => 'student');
$role = $DB->get_record_sql(
"SELECT s.id, s.shortname FROM {role} s " .
" WHERE s.shortname = :shortname", $params_temp);
// $students = $DB->get_records_sql("SELECT s.userid, a.firstname, a.lastname FROM {$CFG->prefix}role_assignments s, {$CFG->prefix}user a WHERE s.contextid = '$context->id' AND s.userid = a.id AND s.roleid = '$role->id' ORDER BY a.firstname ASC,a.lastname ASC");
$params_temp = array('contextid' => $context->id, 'roleid' => $role->id);
$students = $DB->get_records_sql(
"SELECT s.userid, a.firstname, a.lastname FROM {role_assignments} s, {user} a " .
" WHERE s.contextid = :contextid AND s.userid = a.id AND s.roleid = :roleid " .
" ORDER BY a.firstname ASC,a.lastname ASC", $params_temp);
$j = 0;
$total = 0;
$total_students_class = 0; // will receive the total of students in class
$aux_total_students_class = 0; // will count students in class, to define '$total_students_class'
$sum_correct_iassign = array();
$sum_correct_student = array();
$sum_experiment = array();
$total_at_least_one_submission = array(); // array to register the total number of exercises with at least one submission (per exercicse)
for ($jj = 1; $jj <= $total_iassign_statement; $jj++) {
$sum_experiment[$jj] = 0;
$total_at_least_one_submission[$jj] = 0;
}
if ($students) { // $students has {role_assignments}.userid, {user}.firstname, {user}.lastname
foreach ($students as $one_user) { // For each student
$aux_total_students_class++;
$name = $one_user->firstname . ' ' . $one_user->lastname;
// rows
$count_student_correct_answer = 0;
for ($jj = 1; $jj <= $total_iassign_statement; $jj++) { // {iassign_submission}.iassign_statementid = {iassign_statement}.id
$student_submissions = $DB->get_record("iassign_submission", array('iassign_statementid' => $num[$jj]->iassignid, 'userid' => $one_user->userid)); // data about student solution
if ($student_submissions) {
if ($student_submissions->status == 3) {
$sum_iassign_correct[$jj]++;
$count_student_correct_answer++;
} // if ($student_submissions->status == 3)
// Sum the total number of "experiment" (if set, all of them is registerede in {iassign_allsubmissions})
// {iassign_submission}.experiment is the number of time student "click" in the evaluation button of the iLM
$total_experiment = $student_submissions->experiment;
$sum_experiment[$jj] += $student_submissions->experiment; // to be used in 'Total Attempts' and 'Average attempts'
$total_at_least_one_submission[$jj]++; // one more student with submission to this exercise - used in 'Average attempts'
}
} // for ($jj=1; $jj<$total_iassign_statement; $jj++)
$total = $total + $count_student_correct_answer;
$sum_correct_student[$aux_total_students_class] = new stdClass();
$sum_correct_student[$aux_total_students_class]->name = $name;
$sum_correct_student[$aux_total_students_class]->sum = $count_student_correct_answer; // total of correct exercises of this student
} // foreach ($students as $one_user)
$total_students_class = $aux_total_students_class;
}
for ($ii = 1; $ii < $total_iassign_statement; $ii++) {
if (is_null($sum_iassign_correct[$ii])) {
$sum_iassign_correct[$ii] = 0;
}
$sum_correct_iassign[$ii] = new stdClass();
$sum_correct_iassign[$ii]->sum = $sum_iassign_correct[$ii];
$sum_correct_iassign[$ii]->name = $num[$ii]->name;
$sum_correct_iassign[$ii]->experiment = $sum_experiment[$ii]; // {iassign_submission}.experiment : total
} // for ($ii = 1; $ii < $total_iassign_statement; $ii++)
} // if ($total_iassign_statement > 1)
print $OUTPUT->header();
$this->print_main_menu();
if ($this->action != 'printstats') {
$title = get_string('graphic', 'iassign');
$link_report = "" . iassign_icons::insert('view_report') . ' ' . get_string('report', 'iassign') . "";
$link_print_stats = "" . iassign_icons::insert('print') . ' ' . get_string('print', 'iassign') . "";
print '
\n";
} // if ($this->action != 'printstats')
die();
} // function stats()
/// Display a survey (an a graphic) of the student situation
// The survey is to the current student
function stats_students () {
global $USER, $CFG, $DB, $OUTPUT;
$id = $this->cm->id;
$sql_str = "SELECT * FROM {iassign_statement} s WHERE s.iassignid = '{$this->iassign->id}' AND s.type_iassign=3 ORDER BY s.position";
//D echo "
locallib.php!stats_students(): this->iassign->id=" . $this->iassign->id . " " . $sql_str . " "; //exit;
$iassign_statement_list = $DB->get_records_sql($sql_str); // get all the iActivities in this block
$title = get_string('results', 'iassign');
$sum_correct = 0;
$sum_incorrect = 0;
$sum_post = 0;
$sum_nopost = 0;
$sum_iassign_st = count($iassign_statement_list);
$bar_nopost = "";
$bar_correct = "";
$bar_incorrect = "";
$bar_post = "";
$text_nopost = "";
$text_correct = "";
$text_incorrect = "";
foreach ($iassign_statement_list as $iassign_statement_activity_item) { // get all the submissions to each iActivity considering the current user
$iassign_submission = $DB->get_record("iassign_submission", array('iassign_statementid' => $iassign_statement_activity_item->id, 'userid' => $USER->id)); // data about student solution
if ($iassign_submission) {
if ($iassign_submission->status == 3)
$sum_correct++;
elseif ($iassign_submission->status == 2)
$sum_incorrect++;
elseif ($iassign_submission->status == 1)
$sum_post++;
elseif ($iassign_submission->status == 0 || !$iassign_submission)
$sum_nopost++;
} // if ($iassign_submission)
} // foreach ($iassign_statement_list as $iassign_statement_activity_item)
if ($sum_iassign_st > 0) {
$percent_correct = ($sum_correct / $sum_iassign_st) * 100; //Attention: final grade
$text_correct = number_format($percent_correct, 1) . '%';
}
if ($sum_correct > 0) {
for ($i = 1; $i < $percent_correct * 2; $i++)
$bar_correct .= iassign_icons::insert('hbar_green');
$bar_correct .= iassign_icons::insert('hbar_green_r');
} // if ($sum_correct > 0)
if ($sum_iassign_st > 0) {
$percent_incorrect = ($sum_incorrect / $sum_iassign_st) * 100;
$text_incorrect = number_format($percent_incorrect, 1) . '%';
}
if ($sum_incorrect > 0) {
for ($i = 1; $i < $percent_incorrect * 2; $i++)
$bar_incorrect .= iassign_icons::insert('hbar_red');
$bar_incorrect .= iassign_icons::insert('hbar_red_r');
} // if ($sum_incorrect > 0)
if ($sum_iassign_st > 0) {
$percent_post = ($sum_post / $sum_iassign_st) * 100;
$text_post = number_format($percent_post, 1) . '%';
}
if ($sum_post > 0) {
for ($i = 1; $i < $percent_post * 2; $i++)
$bar_post .= iassign_icons::insert('hbar_blue');
$bar_post .= iassign_icons::insert('hbar_blue_r');
} // if ($sum_post > 0)
if ($sum_iassign_st > 0) {
$percent_nopost = ($sum_nopost / $sum_iassign_st) * 100;
$text_nopost = number_format($percent_nopost, 1) . '%';
}
if ($sum_nopost > 0) {
for ($i = 1; $i < $percent_nopost * 2; $i++)
$bar_nopost .= iassign_icons::insert('hbar_orange');
$bar_nopost .= iassign_icons::insert('hbar_orange_r');
} // if ($sum_nopost > 0)
print $OUTPUT->header();
//2021/12 $link_return = " " . iassign_icons::insert('home') . get_string('activities_page', 'iassign') . "";
//2021/12 print '
";
print $OUTPUT->footer();
die();
} // function stats_students()
function get_total_notifications () {
global $DB, $USER, $COURSE;
$total_messages = 0;
if (has_capability('mod/iassign:editiassign', $this->context, $USER->id)) {
$params = array('userid' => $USER->id, 'course' => $COURSE->id, 'receiver' => '1');
$total_messages = $DB->get_record_sql("SELECT COUNT(*) AS total FROM {iassign_submission_comment} AS c, {iassign_submission} AS s, {iassign_statement} AS st, {iassign} AS ias "
. " WHERE c.return_status=0 AND c.receiver=:receiver AND c.iassign_submissionid=s.id AND s.iassign_statementid=st.id AND st.iassignid=ias.id AND ias.course=:course", $params);
}
else {
$params = array('userid' => $USER->id, 'course' => $COURSE->id, 'receiver' => '2');
$total_messages = $DB->get_record_sql("SELECT COUNT(*) AS total FROM {iassign_submission_comment} AS c, {iassign_submission} AS s, {iassign_statement} AS st, {iassign} AS ias "
. " WHERE c.return_status=0 AND c.receiver=:receiver AND c.iassign_submissionid=s.id AND s.userid=:userid AND s.iassign_statementid=st.id AND st.iassignid=ias.id AND ias.course=:course", $params);
}
return $total_messages->total;
}
function get_iassign_statement_messages () {
global $DB, $USER, $COURSE;
if (has_capability('mod/iassign:editiassign', $this->context, $USER->id)) {
$params = array('userid' => $USER->id, 'course' => $COURSE->id, 'receiver' => '1');
$totais = array();
$messages = $DB->get_records_sql("SELECT c.id AS commentid, st.id AS stid, s.userid AS user, ias.id AS iasid, s.id AS subid, st.name AS stname, ias.name AS iasname FROM {iassign_submission_comment} AS c, {iassign_submission} AS s, {iassign_statement} AS st, {iassign} AS ias "
. " WHERE c.return_status=0 AND c.receiver=:receiver AND c.iassign_submissionid=s.id AND s.iassign_statementid=st.id AND st.iassignid=ias.id AND ias.course=:course", $params);
foreach($messages as $item) {
if (isset($totais[$item->subid])) {
$totais[$item->subid]->total++;
}
else {
$totais[$item->subid] = new stdclass();
$item->total = 1;
$totais[$item->subid] = $item;
}
}
return $totais;
}
else {
$params = array('userid' => $USER->id, 'course' => $COURSE->id, 'receiver' => '2');
$totais = array();
$messages = $DB->get_records_sql("SELECT c.id as commentid, s.id AS subid, st.id AS stid, ias.id AS iasid, s.userid AS userid, st.name AS stname, ias.name AS iasname FROM {iassign_submission_comment} AS c, {iassign_submission} AS s, {iassign_statement} AS st, {iassign} AS ias "
. " WHERE c.return_status=0 AND c.receiver=:receiver AND c.iassign_submissionid=s.id AND s.userid=:userid AND s.iassign_statementid=st.id AND st.iassignid=ias.id AND ias.course=:course", $params);
foreach ($messages as $item) {
if (isset($totais[$item->subid])) {
$totais[$item->subid]->total++;
}
else {
$totais[$item->subid] = new stdclass();
$item->total = 1;
$totais[$item->subid] = $item;
}
}
return $totais;
}
}
// It shows to the teacher all iAssign notifications (all new students' comments)
function view_notifications_teachers () {
global $OUTPUT, $USER, $DB;
$messages = $this->get_iassign_statement_messages();
print '
';
// 1. list all messages received in the current block:
$actual_block = $this->iassign->id;
$id = $this->cm->id;
$total_include = 0;
$activities_actual_block = array();
if ($messages) {
foreach ($messages as $item)
if ($item->iasid == $actual_block)
if (!in_array($item->stid, $activities_actual_block))
array_push($activities_actual_block, $item->stid);
}
if ($activities_actual_block) {
foreach ($activities_actual_block as $activity_id) {
$printed = false;
foreach ($messages as $item) {
if ($item->stid == $activity_id) {
if (!$printed) {
$student_url = "view.php?id=$id&userid_iassign=$USER->id&action=view&iassign_current=$item->stid";
$link_student = "" . $item->stname . "";
print '
';
// 2. List all the messages received from another blocks:
$iassign_ids = array();
if ($messages) {
foreach ($messages as $item)
if (!in_array($item->iasid, $iassign_ids) && $item->iasid != $actual_block)
array_push($iassign_ids, $item->iasid);
}
foreach ($iassign_ids as $id_iassign) {
$printed = false;
foreach ($messages as $item) {
if ($item->iasid == $id_iassign) {
if (!$printed) {
$printed = true;
print ' ' . $item->iasname . " \n";
print '
\n";
} // for ($j=0; $j<$total_of_activities; $j++)
//D echo "locallib.php: show_iassign(): ";
//EXTRA: This for is to correct error in ordem inside the block, to detect (and fix it) 'iassign_statement.position' errors
$vector_final_order = array(); // get the final order to be used to correct existent one
for ($j=0; $j<$total_of_activities; $j++) { // List all iAssign activity inside this block
//D echo $j . ": id=" . $iassign_array[$j]->id . ", position=" . $iassign_array[$j]->position . " ";
if ($iassign_array[$j]->position!=($j+1)) {
activity::move_change_activity_position($DB, $iassign_array[$j]->id, $iassign_array[$j]->id, $j+1, $j+1);
}
}
print "