Skip to content
Snippets Groups Projects
course_competency.php 17.21 KiB
<?php 

require_once('../../config.php');

global $USER, $COURSE;

$courseid = required_param('courseid', PARAM_INT);
$studentid = required_param('studentid', PARAM_INT);
$competencyid = required_param('competencyid', PARAM_INT);

$url = new moodle_url('/blocks/competency_iena/course_competency.php', array('courseid' => $courseid, 'studentid' => $studentid, 'competencyid' => $competencyid));
$PAGE->set_url($url);

require_login($courseid, false, NULL);

$PAGE->set_pagelayout('course');
$PAGE->set_title(get_string('title_plugin', 'block_competency_iena'));
$PAGE->set_heading($OUTPUT->heading($COURSE->fullname, 2, 'headingblock header outline'));
$PAGE->requires->js("/blocks/competency_iena/js/datalist-polyfill.min.js");
$PAGE->requires->js("/blocks/competency_iena/js/stud-x-cpts.js");
$PAGE->requires->js("/blocks/competency_iena/js/cpt-x-studs.js");
$PAGE->requires->js("/blocks/competency_iena/js/cpt-stud-course.js");

/* <<< GESTION DROITS D'ACCÈS >>> */

$context = context_course::instance($courseid);

/* Check if studentid is a course participant */
$is_enrolled = is_enrolled($context, $studentid, '', true);

/* Check if the user is teacher */
$is_teacher = false; 
if (has_capability('moodle/course:update', $context, $USER->id)) {
	$is_teacher = true;
}

/* Redirect student if he try accèss another student data */
if ( $is_teacher === false && $studentid != $USER->id ) {
	$link = $CFG->wwwroot . '/blocks/competency_iena/course_competency.php?courseid=' . $courseid . '&studentid=' . $USER->id . '&competencyid=' . $competencyid;
	header("Location: {$link}");
	exit;
}

echo $OUTPUT->header();


/* <<< REVIEW DATA >>> */

$sql_rev = "SELECT * FROM {competency_usercomp} 
WHERE userid = ? AND competencyid = ? AND status = ?";
$reviews_data = $DB->get_records_sql($sql_rev, [$studentid, $competencyid, 1]);
$review_asked = count($reviews_data) > 0 ? true : false;


/* <<< POST >>> */

/* POST EVALUATION */

if ( isset($_POST['grade']) ) {
	$note = $_POST['note'];
	\core_competency\api::grade_competency_in_course($courseid, $studentid, $competencyid, $_POST['grade'], $note);
	if ( $review_asked ) {
		\core_competency\api::user_competency_start_review($studentid, $competencyid);
		\core_competency\api::user_competency_stop_review($studentid, $competencyid);
		/* Refresh review data */
		$reviews_data = $DB->get_records_sql($sql_rev, [$studentid, $competencyid, 1]);
		$review_asked = count($reviews_data) > 0 ? true : false;
	}
}
/* POST REVIEW */

if ( isset($_POST['review']) ) {
	if ( $_POST['review'] == 'request' ) {
		\core_competency\api::user_competency_request_review($studentid, $competencyid);
	} elseif ( $_POST['review'] == 'cancel' ) {
		\core_competency\api::user_competency_cancel_review_request($studentid, $competencyid);
	}
	/* Refresh review data */
	$reviews_data = $DB->get_records_sql($sql_rev, [$studentid, $competencyid, 1]);
	$review_asked = count($reviews_data) > 0 ? true : false;
}


/* <<< HELPERS >>> */

function _html($el, $str, $class = "") {
	$class = " class='" . $class . "'";
	echo "<" . $el . $class . ">" . $str . "</" . $el . ">";
}

function _modal_builder($id, $title, $body) {
	return "<div class='modal fade' id='{$id}' tabindex='-1' role='dialog' aria-labelledby='exampleModalScrollableTitle' aria-hidden='true'><div class='modal-dialog modal-dialog-scrollable' role='document'><div class='modal-content'><div class='modal-header'><h5 class='modal-title' id='exampleModalScrollableTitle'>{$title}</h5><button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button></div><div class='modal-body'>{$body}</div></div></div></div>";
}


/* <<< GESTION ERREUR ACCÈS >>> */

if ( $is_enrolled === false ) {
	_html("p", "L'étudiant demandé n'est pas inscrit dans ce cours.", "alert alert-warning");
}


/* <<< DATA >>> */

/* Student USER object */
$student = user_get_users_by_id([$studentid])[$studentid];

/* All students */
/* Only if is teacher because it's to load stud list to switch : teacher feature */
$students = NULL;
if ( $is_teacher ) {
	$students = get_enrolled_users($context);
}

/* Course modules linked to this competency */
$cm_ids = \core_competency\api::list_course_modules_using_competency($competencyid, $courseid);

/* Competency */
$u_c_cpt = \core_competency\api::get_user_competency_in_course($courseid, $studentid, $competencyid);
$cpt = new \core_competency\competency($competencyid);
$cpt_scale = $cpt->get_scale()->scale_items;
$eval = "-"; /* current eval string */
if ( $u_c_cpt->get('grade') != null ) {
	$eval = $cpt_scale[$u_c_cpt->get('grade') - 1];
}
$proficiency = $u_c_cpt->get('proficiency') == 1 ? "Oui" : "Non";
$proficiency_class = $u_c_cpt->get('proficiency') == 1 ? "success" : "secondary";

/* All course competencies */
$course_cpts = \core_competency\course_competency::list_competencies($COURSE->id);


/* <<< PAGE >>> */

// echo "<pre>";
// var_dump($_POST);
// echo "</pre>";

/* STUDENT NAME */

_html("h2", $student->firstname . " " . $student->lastname, "h3' style='margin-bottom: 0.3rem;'");

/* SWITCH STUDENT FORM */

if ( $is_teacher && $students != NULL && count($students) != 0 ) {
	echo "<form action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php' id='change_stud_form' class='form-inline m-b-1'>";
	echo "<input type='text' hidden name='courseid' value='{$courseid}'>";
	echo "<input type='text' hidden name='competencyid' value='{$competencyid}'>";
	echo "<span hidden id='studentid'>{$studentid}</span>";
	/*echo "<label class='m-y-1 m-r-1' for='studentid_sel' style='color: black;'>Etudiant</label>";*/
	echo "<input type='text' name='studentid' id='studentid_sel' value='' list='student_list' class='form-control' style='font-size: .7rem; line-height: 1;'>";
	echo "<datalist id='student_list' title='Select student'>";
	foreach ($students as $stud) {
		echo "<option value='{$stud->firstname} {$stud->lastname} ({$stud->id})' data-value='{$stud->id}'>{$stud->firstname} {$stud->lastname} ({$stud->id})</option>";
	}
	echo "</datalist>";
	echo "<div><button class='btn btn-secondary' id='prevStud' style='font-size: .8rem;line-height: 1.09; margin-left: 0.5rem;'>Précédent</button>";
	echo "<button class='btn btn-secondary' id='nextStud' style='font-size: .8rem;line-height: 1.09; margin-left: 0.5rem;'>Suivant</button></div>";
	echo "</form>";
}

/* INFO ABOUT COMPETENCIES, FRAMEWORK AND CURRENT GRADE */

_html('h2', $cpt->get('shortname'), "h3' style='margin-bottom: 0.3rem;'");

/* COMPETENCY TREE PATH */

/* Competency tree parents path from current to framework */
$cptid = $competencyid;
$parent_cpts = array();
while ($cptid > 0) {
	$tmp_cpt = new \core_competency\competency($cptid);
	array_unshift($parent_cpts, ['id' => $tmp_cpt->get('id'), 'shortname' => $tmp_cpt->get('shortname'), 'description' => $tmp_cpt->get('description')]);
	$cptid = $tmp_cpt->get('parentid');
}
/* Framework infos */
$cpt_path_link = "<a href='#' data-toggle='modal' data-target='#modalref'>{$cpt->get_framework()->get('shortname')}</a>" . _modal_builder('modalref', $cpt->get_framework()->get('shortname'), $cpt->get_framework()->get('description'));
/* Each competency info */
foreach ($parent_cpts as $parent_cpt) {
	$cpt_path_link .= " / <a href='#' data-toggle='modal' data-target='#modal{$parent_cpt['id']}'>{$parent_cpt['shortname']}</a>" . _modal_builder("modal{$parent_cpt['id']}", $parent_cpt['shortname'], $parent_cpt['description']);
}
echo "<div style='margin-bottom: 0.7rem;'>" . $cpt_path_link . "</div>";

/* SWITCH COMPETENCY FORM */

echo "<form action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php' id='change_cpt_form' class='form-inline m-b-1'>";
echo "<input type='text' hidden name='courseid' value='{$courseid}'>";
echo "<input type='text' hidden name='studentid' value='{$studentid}'>";
echo "<span hidden id='competencyid'>{$competencyid}</span>";
/*echo "<label class='m-r-1' for='competencyid_sel' style=''>Changer de compétence</label>";*/
echo "<input type='text' name='competencyid' id='competencyid_sel' value='' list='competency_list' class='form-control' style='font-size: .7rem; line-height: 1;'>";
echo "<datalist id='competency_list' title='Select competency'>";
foreach ($course_cpts as $course_cpt) {
	echo "<option value='{$course_cpt->get('shortname')} ({$course_cpt->get('id')})' data-value='{$course_cpt->get('id')}'>{$course_cpt->get('shortname')} ({$course_cpt->get('id')})</option>";
}
echo "</datalist>";
echo "<button class='btn btn-secondary' id='prevCpt' style='font-size: .8rem;line-height: 1.09; margin-left: 0.5rem;'>Précédent</button>";
echo "<button class='btn btn-secondary' id='nextCpt' style='font-size: .8rem;line-height: 1.09; margin-left: 0.5rem;'>Suivant</button>";
echo "</form>";
/* END switch competency form */

/* EVALUATION INFOS AND ACTIONS */

echo "<div class='row'>";
/* Proficiency info */
echo "<div class='col-12 col-lg-3'>";
echo "<div class='alert alert-{$proficiency_class}'>";
echo "<h3 class='h4'>Validé</h3>";
echo "<p class='m-b-0 btn p-l-0' style='cursor: text;'>{$proficiency}</p>";
echo "</div>";
echo "</div>";
/* Grade info */
echo "<div class='col-12 col-lg-3'>";
echo "<div class='alert alert-{$proficiency_class}'>";
echo "<h3 class='h4'>Évaluation</h3>";
echo "<p class='m-b-0 btn p-l-0' style='cursor: text;'>{$eval}</p>";
echo "</div>";
echo "</div>";
/* Review and grade ASK and ACTION */
$review_class = $review_asked ? "info" : "secondary";
$review_msg = $review_asked ? "Évaluation demandée" : "Aucune évaluation demandée";
echo "<div class='col-12 col-lg-6'>";
echo "<div class='alert alert-{$review_class}'>";
echo "<h3 class='h4'>{$review_msg}</h3>";
if ( $review_asked ) {
	/* Request review and cancel buttons */
	if ( $USER->id == $studentid ) {
		/* Student cancel his own review */
		echo "<form method='post' action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$competencyid}' style='display: inline; margin-right: 1rem;'>";
		echo "<input hidden style='display: none;' type='text' name='review' value='cancel'>";
		echo "<button type='submit' class='btn btn-secondary'>Annuler la demande</button>";
		echo "</form>";
	}
} else {
	if ( $USER->id == $studentid ) {
		/* Student ask review */
		echo "<form method='post' action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$competencyid}' style='display: inline; margin-right: 1rem;'>";
		echo "<input hidden style='display: none;' type='text' name='review' value='request'>";
		echo "<button type='submit' class='btn btn-primary'>Demande d'évaluation</button>";
		echo "</form>";
	}
}
if ( $is_teacher ) {
	/* Evaluation button and modal */
	echo "<a href='#' data-toggle='modal' data-target='#modaleval' class='btn btn-primary'>Évaluer</a>";
	$eval_modale_echo = "";
	$eval_modale_echo .= "<form method='post' action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$competencyid}'><div class='form-group'><div class='form-group'><label>Évaluation</label><select name='grade' class='form-control'>";
	foreach ($cpt_scale as $key => $item) {
		$grade = $key + 1;
		$selected = "";
		if ( $item == $eval ) {
			$selected = " selected";
		}
		$eval_modale_echo .= "<option value='{$grade}'{$selected}>{$item}</option>";
	}
	$eval_modale_echo .= "</select></div><div class='form-group'><textarea name='note' class='form-control' placeholder=\"Commentaire d'évaluation\"></textarea></div><button type='submit' class='btn btn-primary'>Évaluer</button></form></div>";
	echo _modal_builder("modaleval", "Évaluation", $eval_modale_echo);
}
echo "</div>"; /* END review and grade ASK and ACTION - col */
echo "</div>"; /* END review and grade ASK and ACTION - alert */
echo "</div>"; /* END evaluation info and actions row */

/* GRADES AND EVIDENCES HISTORY CHART AND LIST */

/* Utilisation des renderer du /admin/tool/lp/class/output pour obtenir toutes les données d'historique construites et organisées */
/* /admin/tool/lp/user_competency.php?id= */ 

$tool_lp_renderer = $PAGE->get_renderer('tool_lp');

$user_competency = \core_competency\api::get_user_competency($studentid, $competencyid);
$user_cpt_all_data = new \tool_lp\output\user_competency_summary($user_competency);
$user_cpt_all_data = $user_cpt_all_data->export_for_template($tool_lp_renderer);
$all_evidences = $user_cpt_all_data->evidence;

if ( count($all_evidences) != 0 ) {

	$user_cpt_course_data = new \tool_lp\output\user_competency_summary_in_course($studentid, $competencyid, $courseid);
	$user_cpt_course_data = $user_cpt_course_data->export_for_template($tool_lp_renderer);
	$course_evidences = $user_cpt_course_data->usercompetencysummary->evidence;
	$course_evidences_ids = array();
	foreach ($course_evidences as $course_evidence) {
		$course_evidences_ids[] = $course_evidence->id;
	}

	/* CHART EVALUATION HISTORY */

	$labels = array();
	$series_data_all = array();
	$series_data_course = array();
	$series_data_other = array();
	foreach ($all_evidences as $key => $ev) {
		if ( isset($ev->grade) ) {
			$labels[] = userdate($ev->timemodified, "%d/%m/%y");
			$series_data_all[] = $ev->grade;
			if ( in_array($ev->id, $course_evidences_ids) ) {
				$series_data_course[] = $ev->grade;
				$series_data_other[] = 0;
			} else {
				$series_data_course[] = 0;
				$series_data_other[] = $ev->grade;
			}
		}
	}

	echo "<div class='alert alert-secondary'>";
	/* $chart = new core\chart_line(); */
	$chart = new core\chart_bar();
	$chart->get_yaxis(0, true)->set_labels(["", "Non compétent", "Compétent"]);
	$series_all = new core\chart_series("Complet", array_reverse($series_data_all));
	$series_course = new core\chart_series('Dans ce cours', array_reverse($series_data_course));
	$series_other = new core\chart_series('Hors de ce cours', array_reverse($series_data_other));
	// $chart->add_series($series_all);
	$chart->add_series($series_course);
	$chart->add_series($series_other);
	$chart->set_labels(array_reverse($labels));
	echo $OUTPUT->render($chart);
	echo "</div>";

	/* LIST COMPLETE HISTORY (evaluation and other evidences) */

	echo "<div class='row'>";
	echo "<div class='col-12'>";
	echo "<h2 class='h3'>Historique</h2><ul class='nav nav-tabs' id='hist-tabs'>
	<li class='nav-item'>
	<a class='nav-link active' href='#' id='all_history_tab'>Complet</a>
	</li>
	<li class='nav-item'>
	<a class='nav-link' href='#' id='course_history_tab'>Dans ce cours</a>
	</li>
	<li class='nav-item'>
	<a class='nav-link' href='#' id='other_history_tab'>Hors de ce cours</a>
	</li>
	</ul>";
	echo "<ul class='list-group' style='max-height: 40vh; overflow: scroll;'>";
	foreach ($all_evidences as $key => $ev) {
		/* mark difference between this course evidences in html for JS filter with tabs */
		if ( in_array($ev->id, $course_evidences_ids) ) {
			$is_course_evidence = " data-evidenceorigin='course'";
		} else {
			$is_course_evidence = " data-evidenceorigin='other'";
		}
		if ( $ev->action === "0" ) {
			$grade_make_proficient = ' list-group-item-light';
		} else { 
			/* proficient or not depending of rating in scale (set in framework by creator) */
			$scale_rules = json_decode($user_cpt_all_data->competency->scaleconfiguration);
			foreach ($scale_rules as $scale_rule) {
				if ( isset($scale_rule->proficient) && $scale_rule->id == $ev->grade && $scale_rule->proficient == 1 ) {
					$grade_make_proficient = ' list-group-item-success';
				} else {
					$grade_make_proficient = '';
				}
			}
		}
		$date = date("d/m/y – H:i", $ev->timemodified);
		echo "<li class='list-group-item{$grade_make_proficient}'{$is_course_evidence}>
		<div class='d-flex w-100 justify-content-between'>";
		if ( isset($ev->gradename) ) {
			echo "<h5 class='mb-1' style='font-weight: 600;'>$ev->gradename ({$ev->id})</h5>";
		}
		echo "<small>{$date}</small>
		</div>
		<p class='mb-1 font-weight-light'><em>{$ev->description}</em></p>";
		if ( isset($ev->note) && $ev->note != "" ) {
			echo "<p class='mb-1' style='font-weight: 500;'>{$ev->note}</p>";
		}
		if ( isset($ev->actionuser) ) {
			echo "<small>Évalué par : <a target='_blank' href='{$ev->actionuser->profileurl}'>{$ev->actionuser->fullname}</a></small>";
		}
		echo "</li>";
	}
	echo "</ul>";
	echo "</div>"; /* evidences list col */
	echo "</div>"; /* evidences list row */

} /* END IF count all evidences (course and outside) == 0 */

echo "<pre>";
// print_r($all_evidences);
echo "</pre>";

/* 

TODO : 

Remonter ces données en haut et commenter les données préalablement récupérées d'une autre manière devenues superflues avec celles-ci. Ca réduira l'impact du chargement de la page. Et ça sera plus propre et plus concis. Quand-même garder les éléments en commentaire au cas où les exporteurs sautent dans les prochaines versions de MOODLE. 

*/

/* LINKED MODULES */

_html("h3", "Lié à cette compétence");
if ( count($cm_ids) !== 0 ) {
	$modinfo = get_fast_modinfo($courseid);
	echo "<div class='list-group'>";
	foreach ($cm_ids as $cm_id) {
		echo "<a href='{$modinfo->cms[$cm_id]->url->out()}' target='_blank' class='list-group-item list-group-item-action'><img src='$CFG->wwwroot/theme/image.php/boost/{$modinfo->cms[$cm_id]->modname}/1/icon>' style='height: 1.3rem;'><span class='align-middle'> {$modinfo->cms[$cm_id]->name}</span></a>";
	}
	echo "</div>";
} else {
	_html("p", "Aucune ressource ou activité n'est liée à cette compétence dans ce cours. ", "alert alert-secondary");
}


echo $OUTPUT->footer();

?>