-
DELARUELLE Myriam authoredDELARUELLE Myriam authored
suivi_unit.php 20.41 KiB
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
*
* @package format_iena
* @copyright 2018 Softia/Université lorraine
* @author vrignaud camille / Thomas Fradet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_OUTPUT_BUFFERING', true);
require_once('../../../config.php');
//require_once('view/view_param_indicateur.php');
require_once('entity/course_format_iena_section_ressources.php');
require_once('entity/course_format_iena_sections.php');
require_once('entity/course_format_iena_groups.php');
require_once($CFG->dirroot.'/course/modlib.php');
use core_completion\cm_completion_details;
$PAGE->requires->css('/course/format/iena/styles.css');
global $COURSE, $DB, $USER, $PAGE;
function init_page($course) {
global $PAGE;
// Defines the id of the course with a get parameter.
// Getting DB information (*) of the course.
$PAGE->set_title($course->fullname);
$PAGE->set_heading($course->fullname . " – " .get_string('table_progress', 'format_iena'));
$PAGE->set_pagelayout('incourse');
// Cache le menu dans le header.
$coursenode = $PAGE->navbar->add(get_string('table_progress', 'format_iena'),
null, navigation_node::TYPE_CONTAINER, null, 'suiviena');
$coursenode->make_active();
$coursenode->force_open();
}
function get_groups($context, $activegroupids, $groups) {
global $USER, $COURSE;
// Groupe du GET provenant du sélecteur de la page du cours
// ou premier groupe de l'utilisateur, ou groupe 0 (tous les groupes).
$groupsall = new StdClass();
// TODO à supprimer si pas utilisé dans le JS (mettre dans la clause IF pour éviter un appel inutile si le GET existe).
$currentusergroupsids = groups_get_user_groups($COURSE->id, $USER->id)[0];
$currentusergroups = [];
$othergroups = [];
// Groupes du cours avec id, nom et liste des id utilisateur de tous les
// membres (3 clefs d'un tableau de groupes : id, name, member).
$activegroupname = "";
foreach ($groups as $group) {
// Récupération des groupes dont fait partie l'utilisateur
if (in_array($group->id, $currentusergroupsids)) {
$currentusergroups[] = $group;
} else {
$othergroups[] = $group;
}
}
$groupsall->othergroups = $othergroups;
$groupsall->current_user_groups = $currentusergroups;
return $groupsall;
}
// Formate l'achèvement d'activités pour le tableau de suivi. Pour chaque étudiant, on aura
// dans le bon ordre la liste des modules et le completionstate.
function format_progress($progress, $modules, $groups, $search=false, $activegroupids=0, $activesectionid=0) {
global $CFG, $COURSE;
$students = array();
foreach ($progress as $proginfo) {
$progressstudent = new StdClass();
$progressstudent->firstname = $proginfo->firstname;
$progressstudent->lastname = $proginfo->lastname;
$progressstudent->id = $proginfo->id;
$progressstudent->email = $proginfo->email;
$progressstudent->progress = array();
$progressstudent->report_link = $CFG->wwwroot . "/report/outline/user.php?id=" .
$progressstudent->id . "&course=" . $COURSE->id . "&mode=outline";
$progressstudent->message_link = $CFG->wwwroot . "/message/index.php?id=" . $progressstudent->id;
$progressstudent->groups = "";
$progressstudent->groupsid=array();
if (!$search) {
foreach ($groups as $group) {
if (in_array($progressstudent->id, $group->members)) {
if(empty( $progressstudent->groups)){
$progressstudent->groups .= $group->name . "";
}
else{
$progressstudent->groups .= ", " .$group->name . " ";
}
array_push( $progressstudent->groupsid, $group->id);
}
}
}
else{
$progressstudent->groups= $proginfo->groups;
$progressstudent->groupsid= $proginfo->groupsid;
}
foreach ($modules as $key => $module) {
$moduleprogress = new StdClass();
if (!isset($proginfo->progress[$module->id])) {
$moduleprogress->completionstate = '0';
} else {
$moduleprogress->completionstate = $proginfo->progress[$module->id]->completionstate;
}
$moduleprogress->namemodule = $module->name;
$moduleprogress->idmodule = $module->id;
$progressstudent->progress[$key] = $moduleprogress;
}
//error_log(print_r($progressstudent, true));
$students[] = $progressstudent;
}
return $students;
}
function get_activities($completion, $activesectionid) {
$activities = $completion->get_activities();
$modules = [];
foreach ($activities as $activity) {
$module = new StdClass();
$module->id = $activity->id;
$module->name = $activity->name;
$displayname = format_string($activity->name, true, array('context' => $activity->context));
$module->displayname = strlen($displayname) > 50 ? mb_substr($displayname, 0, 49, 'UTF-8').'…' : $displayname;
$module->section = $activity->section;
if($activity->get_url()){
$module->link=$activity->get_url()->out();
}
$modules[] = $module;
if ($activity->section == $activesectionid || $activesectionid == 0 ) {
$module->visible = true;
} else {
$module->visible = false;
}
}
return $modules;
}
function get_sections($activesectionid) {
global $COURSE;
// Liste des sections du cours.
$modinfo = get_fast_modinfo($COURSE->id);
$sectionsinfoall = $modinfo->get_section_info_all();
$sections = [];
foreach ($sectionsinfoall as $key => $sectioninfo) {
$section = new StdClass();
$section->id = $sectioninfo->id;
$section->name = $sectioninfo->name === null || $sectioninfo->name === '' ? 'Section ' . $key : $sectioninfo->name;
if ($section->id == $activesectionid) {
$section->selected = "selected";
}
$sections[] = $section;
}
return $sections;
}
function set_filters($data, $filters, $symbols, $sections, $currentusergroups, $othergroups, $activesectionid) {
if (isset($_GET['filter'])) {
$filtercomplete = $_GET['filter'];
$symbols[mb_substr($filtercomplete, 0, 1, 'UTF-8')]->selected = "selected";
$filters[mb_substr($filtercomplete, 1, null, 'UTF-8')]->selected = "selected";
} else {
$filters["0"]->selected = "selected";
$symbols["≥"]->selected = "selected";
}
$data['filters'] = array_values($filters);
$data['symbols'] = array_values($symbols);
$data["sections"] = $sections;
//Ici on récupère les groupes "autres" auxquels je n'appartiens pas
//$data["groups"] = array_values($groups);
$data["othergroups"]=$othergroups;
$data['current_user_groups'] = $currentusergroups;
$data['default_group'] = 'selected';
$data['data'] = array();
$data['data']["sections"] = $sections;
//$data['data']["groups"] = array_values($groups);
$data['data']['current_user_groups'] = $currentusergroups;
$data['data']['active_section_id'] = $activesectionid;
return $data;
}
//
function set_links($data, $modules,$listoptions) {
global $COURSE, $USER, $CFG;
$countmodules = count($modules);
//$data["students"] = format_progress($progress, $modules, $groups, $activegroupsids, $activesectionid);
//$countstudents = count($data["students"]);
if ($countstudents > 0 && $countmodules > 0) {
$data['count_results'] = $countstudents;
}
if (has_capability('course/iena:suivi_edit', $context = context_course::instance($COURSE->id), $USER->id)) {
$data['link_bulkcompletion'] = $CFG->wwwroot . "/course/bulkcompletion.php?id=" . $COURSE->id;
}
$data['link_classicview'] = $CFG->wwwroot . "/report/progress/index.php?course=" . $COURSE->id;
$data['link_editview']=$CFG->wwwroot . "/course/format/iena/suivi_edit.php?courseid=" . $COURSE->id;
if($listoptions->listoptions['display_groups']["value"]){
$data["display_groups"]=1;
}
if($listoptions->listoptions['display_details']["value"]){
$data["display_details"]=1;
}
//$data['data'] = json_encode($data);
return $data;
}
function get_progress_students($modules, $progress, $groups, $activegroupsids, $activesectionid, $courseid, $cache, $completion){
//Si le progrès de chacun des groupes existe déjà en cache on va les charger, sinon on les récupère dans la BDD et on les stocke
$arrayprogress=array();
for($i=0; $i<count($activegroupsids); $i++){
if($cache->get($courseid."-".$activegroupsids[$i]) !== false){
error_log("on est passé dans le cache");
$progress=$cache->get($courseid."-".$activegroupsids[$i]);
}
else{
//On récupère le progrès des étudiants qui font partie des groupes activegroupsids
$progressrequest = $completion->get_progress_all(
'',
array(),
$activegroupsids[$i],
'u.lastname ASC, u.firstname ASC',
'',
'',
$context
);
//On active le cache seulement s'il y a plus de x étudiants
if($countstudents<1500){
error_log("on set le cache");
$cache->set($courseid."-".$activegroupsids[$i], $progressrequest);
}
$progress=$progressrequest;
}
$arrayprogress=(object) array_unique(array_merge((array) $arrayprogress, (array) $progress), SORT_REGULAR);
}
return format_progress($arrayprogress, $modules, $groups, false, $activegroupsids, $activesectionid);
}
function get_progress_student($identifier, $completion, $modules){
global $DB;
global $COURSE;
$countmethod=0;
$users=array();
//Essayer de faire des switch case avec counttries
$arrayparams=array();
$explodedname=explode(" ", $identifier);
$sql="SELECT DISTINCT u.id, u.firstname, u.lastname, u.email, u.idnumber
FROM {user} u
JOIN {user_enrolments} ue ON ue.userid = u.id
JOIN {enrol} e ON e.id = ue.enrolid
JOIN {role_assignments} ra ON ra.userid = u.id
JOIN {context} ct ON ct.id = ra.contextid AND ct.contextlevel = 50
JOIN {course} c ON c.id = ct.instanceid AND e.courseid = c.id
JOIN {role} r ON r.id = ra.roleid AND r.shortname = 'student'
WHERE e.status = 0 AND u.suspended = 0 AND u.deleted = 0 AND c.id= ?";
$arrayparams[]=$COURSE->id;
if(count($explodedname)>1){
$sql.=" AND (u.lastname LIKE ? AND u.firstname LIKE ?) OR (u.lastname LIKE ? AND u.firstname LIKE ?)";
array_push($arrayparams, $explodedname[0], $explodedname[1], $explodedname[1], $explodedname[0]);
}
else{
$sql.=" AND u.lastname LIKE ? OR u.idnumber = ?";
array_push($arrayparams, "".$identifier."%", $identifier);
}
$users=array_values($DB->get_records_sql($sql, $arrayparams));
if(count($users)>0){
$completion_student=array();
$where = array();
$where_params = array();
//regarder get_in_or_equal
for($i=0; $i<count($users);$i++){
// foreach($users as $user){
$where = $DB->sql_equal('u.id', ':idstudent', false, false);
$where_params['idstudent'] = $users[$i]->id.'%';
$completion_student=array_values($completion->get_progress_all($where, $where_params));
$usergroup=groups_get_all_groups($COURSE->id, $users[$i]->id);
$completion_student[0]->groups="";
$completion_student[0]->groupsid=array();
foreach($usergroup as $group){
$completion_student[0]->groups.=$group->name;
$completion_student[0]->groupsid[]=$group->id;
}
$arrayprogress=(object) array_unique(array_merge((array) $arrayprogress, (array) $completion_student), SORT_REGULAR);
}
return format_progress($arrayprogress, $modules, false, true);
}
else{
//On a pas trouvé d'utilisateur
return array("error"=>"Pas d'utilisateurs trouvés");
}
}
$filters = [
"0" => (object)[
"value" => "0",
"name" => "0",
],
"25" => (object)[
"value" => "25",
"name" => "25%",
],
"50" => (object)[
"value" => "50",
"name" => "50%",
],
"75" => (object)[
"value" => "75",
"name" => "75%",
],
"100" => (object)[
"value" => "100",
"name" => "100%",
]
];
$symbols = [
"=" => (object)[
"value" => "=",
"name" => "=",
],
"<" => (object)[
"value" => "<",
"name" => "<",
],
">" => (object)[
"value" => ">",
"name" => ">",
],
"≤" => (object)[
"value" => "≤",
"name" => "≤",
],
"≥" => (object)[
"value" => "≥",
"name" => "≥",
]
];
//On s'occupe des options ici
$cache = cache::make('format_iena', 'students');
$courseid = required_param('courseid', PARAM_INT);
// Define the url of the view.
$url = new moodle_url('/course/format/iena/suivi_unit.php', array('courseid' => $courseid));
$PAGE->set_url($url);
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
require_login($course);
require_once($CFG->libdir . '/completionlib.php');
$completion = new completion_info($course);
$context = context_course::instance($COURSE->id);
//On récupère les options du tableau de suivi : affichage du groupe, modale détails....
$listoptions=new \format_iena\output\course_format_iena_table_option();
$listoptions->setCourseid($courseid);
$listoptions->get_request_options();
if (!has_capability('course/iena:suivi', $context = context_course::instance($courseid), $USER->id)) {
$link = $CFG->wwwroot . '/course/view.php?id=' . $courseid;
header("Location: {$link}");
exit;
}
$countstudents=count_enrolled_users($context);
//Si on a sélectionné des groupes dans les filtres
if (isset($_POST['groupsid'])) {
$activegroupsids = $_POST['groupsid'];
} else {
if($countstudents>1500){
$activegroupsids = array();
}
else{
$activegroupsids = array(0);
}
}
$activesectionid = 0;
// Section du get acquise depuis le clic sur l'indicateur dans la page du cours,
// section depuis laquelle on a cliqué sur le bouton pour voir le suivi.
if (isset($_GET['sectionid'])) {
$activesectionid = $_GET['sectionid'];
}
// On récupère les ids des membres parce que dans l'excel on veut savoir qui appartient à quel groupe.
$renderer = $PAGE->get_renderer('format_iena');
//Si on cherche les détails d'une activité
if (isset($_POST['action']) && $_POST['action'] == "details") {
require_once($CFG->libdir . '/gradelib.php');
$data = [];
$idetu=$_POST['idetudiant'];
$idmodule=$_POST['idmodule'];
$modinfo = get_fast_modinfo($COURSE->id, $idetu);
$cm = $modinfo->get_cm($idmodule);
//Utile ?
$completioninfo = new \completion_info($COURSE);
$completiondetails = new cm_completion_details($completioninfo, $cm, $idetu);
$activitydates = \core\activity_dates::get_dates_for_module($cm, $idetu);
$activityinfo = new \core_course\output\activity_information($cm, $completiondetails, $activitydates);
$activityhtml=$renderer->render_activity_information($activityinfo);
$gradesobject=array();
try{
$gradesobject=grade_get_grades($COURSE->id, 'mod', $cm->modname, $cm->instance, $idetu);
}
catch(Exception $e){
error_log($e);
}
$lastgrade=array();
if(!empty($gradesobject) && !empty($gradesobject->items)){
$lastgradeobject=end($gradesobject->items[0]->grades);
if($lastgradeobject){
$lastgrade["lastgrade"]=$lastgradeobject->str_long_grade;
$lastgrade["datelastgrade"]=$lastgradeobject->dategraded;
}
if(isset($gradesobject->items[0]->gradepass)){
$lastgrade["passgrade"]=number_format($gradesobject->items[0]->gradepass, 2, ',', '');
}
/*$lastgrade["passgrade"]=$gradesobject->items[0]->gradepass ? number_format($gradesobject->items[0]->gradepass, 2, ',', '') : null;*/
}
//en cas d'achèvement manuel on créé les petites pastilles vertes ou grises (terminé ou à faire)
//
$data =array();
$data['url']=strval($cm->url);
$data['completion']=strval($cm->completion);
$data["grades"]=$lastgrade;
$data["customcompletion"]=$cm->customdata;
$data["completioninfos"]=$activityhtml;
//Récupère le pourcentage de complétion total
$data["completionstate"]=$completiondetails->get_overall_completion();
$data["completiondetails"] = $completiondetails;
$data["activityname"]=$cm->name;
echo json_encode($data);
}
else if(isset($_POST['action']) && $_POST['action'] == 'search_student' && isset($_POST['search_input'])){
$data=[];
$sanitized=filter_var($_POST['search_input'], FILTER_SANITIZE_STRING);
$modules = get_activities($completion, $activesectionid);
$data["modules"]=$modules;
$data["students"]=get_progress_student($sanitized, $completion, $modules);
//$data = set_links($data, $modules, $listoptions);
echo json_encode($data);
}
// If a post is sent trought the page --> Si on change les filtres (de groupes), le template est appelé en JS
else if (isset($_POST['action']) && !empty($_POST['action'])) {
$groups = groups_get_all_groups($COURSE->id, 0, 0, 'g.*', true);
$data = [];
$modules = get_activities($completion, $activesectionid);
$data["students"]=get_progress_students($modules, $arrayprogress, $groups, $activegroupsids, $activesectionid, $courseid, $cache, $completion);
$data["modules"]=$modules;
$data["countstudents"]=$countstudents;
$data["groups"]=$activegroupsids;
$data["courseid"]=$courseid;
//$data = set_links($data, $modules, $listoptions);
echo json_encode($data);
}
else {
init_page($course, $PAGE);
echo $OUTPUT->header();
//$progress=$cache->get($activegroupids);
$groups = groups_get_all_groups($COURSE->id, 0, 0, 'g.*', true);
$data = [];
//Si la complétion du cours n'est pas activée on redirige l'enseignant vers l'interface pour l'activer
if(!$COURSE->enablecompletion){
$data["completion_enabled"]=0;
$data["link_enable"]= "<a href='".$CFG->wwwroot . '/course/edit.php?id=' . $courseid."'>sur ce lien</a>";
}
else{
$data["completion_enabled"]=1;
$currentusergroups = [];
$activegroupname = "";
$modules = get_activities($completion, $activesectionid);
//Répartit les groupes en "mes groupes" et "les groupes dont je ne fais pas partie"
$groupsall = get_groups($context, $activegroupsids, $groups);
if (isset($groupsall->current_user_groups) && !empty($groupsall->current_user_groups)) {
$currentusergroups = $groupsall->current_user_groups;
}
//$groups = $groupsall->groups;
$sections = get_sections($activesectionid);
//$data["countstudents"]=$countstudents;
$data = set_links($data, $modules, $listoptions);
$data = set_filters($data, $filters, $symbols, $sections, $groupsall->current_user_groups, $groupsall->othergroups, $activesectionid);
$data["groups"]=$activegroupsids;
if (isset($_GET["msg_success"])) {
$msg = $_GET["msg_success"];
$data["msg_success"] = $msg;
}
}
$renderer->display_completion($data);
echo $OUTPUT->footer();
}