public function OpignoModuleController::userResult in Opigno module 3.x
Same name and namespace in other branches
- 8 src/Controller/OpignoModuleController.php \Drupal\opigno_module\Controller\OpignoModuleController::userResult()
Returns user result.
1 string reference to 'OpignoModuleController::userResult'
File
- src/
Controller/ OpignoModuleController.php, line 753
Class
- OpignoModuleController
- Class OpignoModuleController.
Namespace
Drupal\opigno_module\ControllerCode
public function userResult(OpignoModuleInterface $opigno_module, UserModuleStatus $user_module_status = NULL) {
$content = [];
$user_answers = $user_module_status
->getAnswers();
$question_number = 0;
$module_activities = $opigno_module
->getModuleActivities();
$score = $user_module_status
->getScore();
$moduleHandler = \Drupal::service('module_handler');
$lp_id = $user_module_status
->get('learning_path')->target_id;
OpignoGroupContext::setGroupId($lp_id);
// Load more activities for 'skills module' with switched on option 'use all suitable activities from Opigno system'.
if ($moduleHandler
->moduleExists('opigno_skills_system') && $opigno_module
->getSkillsActive()) {
$target_skill = $opigno_module
->getTargetSkill();
$term_storage = \Drupal::entityTypeManager()
->getStorage('taxonomy_term');
$skills_tree = array_reverse($term_storage
->loadTree('skills', $target_skill));
$current_skills = [];
if ($opigno_module
->getModuleSkillsGlobal()) {
foreach ($skills_tree as $skill) {
$current_skills[] = $skill->tid;
}
$module_activities += $opigno_module
->getSuitableActivities($current_skills);
}
}
foreach ($user_answers as $answer) {
$question_number++;
$answer_activity = $answer
->getActivity();
if (!$answer_activity) {
continue;
}
$content[] = [
'#theme' => 'opigno_user_result_item',
'#opigno_answer' => $answer,
'#opigno_answer_activity' => $answer_activity,
'#question_number' => $question_number,
'#answer_max_score' => isset($module_activities[$answer_activity
->id()], $module_activities[$answer_activity
->id()]->max_score) ? $module_activities[$answer_activity
->id()]->max_score : 10,
];
}
$user = $this
->currentUser();
$uid = $user
->id();
$gid = OpignoGroupContext::getCurrentGroupId();
if (!empty($gid)) {
$group = Group::load($gid);
$latest_cert_date = LPStatus::getTrainingStartDate($group, $uid);
$steps = LearningPathContent::getAllStepsOnlyModules($gid, $uid, FALSE, NULL, $latest_cert_date);
if (!empty($_SESSION['step_required_conditions_failed'])) {
// If guided option set, required conditions exist and didn't met.
unset($_SESSION['step_required_conditions_failed']);
$content_type_manager = \Drupal::service('opigno_group_manager.content_types.manager');
$step_info = opigno_learning_path_get_module_step($gid, $uid, $opigno_module, $latest_cert_date);
$content = [];
$content[] = [
'#type' => 'html_tag',
'#tag' => 'h1',
'#value' => $this
->t('Next'),
];
if (!empty($step_info)) {
$course_entity = OpignoGroupManagedContent::load($step_info['cid']);
$course_content_type = $content_type_manager
->createInstance($course_entity
->getGroupContentTypeId());
$current_step_url = $course_content_type
->getStartContentUrl($course_entity
->getEntityId(), $gid);
$content[] = [
'#type' => 'markup',
'#markup' => $this
->t('<p>You should first met required conditions for the step "%step" before going further. <a href=":link">Try again.</a></p>', [
':link' => $current_step_url
->toString(),
'%step' => $opigno_module
->getName(),
]),
];
}
return $content;
}
// Find current step.
$current_step_key = array_search($opigno_module
->id(), array_column($steps, 'id'));
$current_step = isset($current_step_key) ? $steps[$current_step_key] : NULL;
// Remove the live meeting and instructor-led training steps.
$steps = array_filter($steps, function ($step) {
return !in_array($step['typology'], [
'Meeting',
'ILT',
]);
});
// Get training guided navigation option.
$freeNavigation = !OpignoGroupManagerController::getGuidedNavigation($group);
if ($current_step !== NULL) {
$last_step = end($steps);
$is_last = $last_step['cid'] === $current_step['cid'];
$current_step['current attempt score'] = $score;
$start_time = (int) $user_module_status
->get('started')
->getValue()[0]['value'];
$end_time = (int) $user_module_status
->get('finished')
->getValue()[0]['value'];
$time = $end_time > $start_time ? $end_time - $start_time : 0;
$current_step['current attempt time'] = $time;
if (isset($current_step['parent'])) {
$current_step['parent']['current attempt time'] = $time;
}
// Send notification about manual evaluation.
$module_id = $opigno_module
->id();
$is_evaluated = $user_module_status
->get('evaluated')
->getValue()[0]['value'];
if (!$is_evaluated) {
$status_id = $user_module_status
->id();
$message = $this
->t('Module "@module" need manual evaluating.', [
'@module' => $current_step['name'],
]);
$url = Url::fromRoute('opigno_module.module_result_form', [
'opigno_module' => $module_id,
'user_module_status' => $status_id,
])
->toString();
// Get user managers.
$members = $group
->getMembers('learning_path-user_manager');
$members_entities = array_map(function ($member) {
return $member
->getUser();
}, $members);
// Get admins.
$admins = opigno_module_get_users_by_role('administrator');
// Get array of all users who must receive notification.
$users = array_merge($members_entities, $admins);
foreach ($users as $user) {
opigno_set_message($user
->id(), $message, $url);
}
}
$skip_links = \Drupal::request()->query
->get('skip-links');
if (!$skip_links) {
if ($score >= $current_step['required score']) {
$message = $this
->t('Successfully completed module "@module" in "@name"', [
'@module' => $current_step['name'],
'@name' => $group
->label(),
]);
$url = Url::fromRoute('entity.group.canonical', [
'group' => $group
->id(),
])
->toString();
opigno_set_message($uid, $message, $url);
if ($is_last) {
$message = $this
->t('Congratulations! You successfully finished the training "@name"', [
'@name' => $group
->label(),
]);
$url = Url::fromRoute('entity.group.canonical', [
'group' => $group
->id(),
])
->toString();
opigno_set_message($uid, $message, $url);
}
}
// Training attempt update/finish.
// Get mandatory steps.
$mandatory_steps = array_filter($steps, function ($step) {
return $step['mandatory'];
});
// Steps queue mapping.
$steps_cids_mapping = array_map(function ($step) {
return $step['cid'];
}, $steps);
// Check if there are more mandatory steps.
// Get last mandatory step key.
$last_mandatory_step = end($mandatory_steps);
$last_mandatory_step_key = array_search($last_mandatory_step["cid"], $steps_cids_mapping);
// Get current step key.
$current_step_key = array_search($current_step["cid"], $steps_cids_mapping);
if ($current_step_key < $last_mandatory_step_key) {
// There are more mandatory steps.
$lp_status = 'in progress';
$finished = 0;
}
else {
// No more mandatory steps.
// Calculate training attempt status.
$training_is_passed = opigno_learning_path_is_passed($group, $uid, TRUE);
if ($training_is_passed) {
$lp_status = 'passed';
}
else {
$lp_status = 'failed';
}
$finished = !empty($end_time) ? $end_time : time();
}
// Get training unfinished attempt.
$attempt_lp = $opigno_module
->getTrainingActiveAttempt($this
->currentUser(), $group);
if ($attempt_lp) {
// Update training unfinished attempt.
$attempt_lp
->setStatus($lp_status);
$attempt_lp
->setFinished($finished);
if ($lp_status == 'passed') {
// Save training current attempt score.
$training_score = opigno_learning_path_get_score($group
->id(), $uid, TRUE);
$attempt_lp
->setScore($training_score);
}
$attempt_lp
->save();
// Save passed training certificate expire date if set expiration.
if ($lp_status == 'passed' && LPStatus::isCertificateExpireSet($group)) {
$expiration_period = LPStatus::getCertificateExpirationPeriod($group);
if ($expiration_period) {
// Latest certificate timestamp - existing or new.
$started = $attempt_lp
->getStarted();
if ($started) {
$latest_cert_date = $started;
}
if (!LPStatus::isCertificateExpired($group, $uid)) {
if ($existing_cert_date = LPStatus::getLatestCertificateTimestamp($gid, $uid)) {
$latest_cert_date = $existing_cert_date;
}
}
$latest_cert_date = !empty($latest_cert_date) ? $latest_cert_date : $start_time;
// Calculate expiration timestamp.
$suffix = $expiration_period > 1 ? 's' : '';
$offset = '+' . $expiration_period . ' month' . $suffix;
$expiration_timestamp = strtotime($offset, $finished);
// Set expiration data.
LPStatus::setCertificateExpireTimestamp($gid, $uid, $latest_cert_date, $expiration_timestamp);
}
}
}
// Training achievements.
if (function_exists('opigno_learning_path_save_step_achievements')) {
// Save current step parent achievements.
$parent_id = isset($current_step['parent']) ? opigno_learning_path_save_step_achievements($gid, $uid, $current_step['parent']) : 0;
// Save current step achievements.
opigno_learning_path_save_step_achievements($gid, $uid, $current_step, $parent_id);
}
if (function_exists('opigno_learning_path_save_achievements')) {
// Save training achievements.
opigno_learning_path_save_achievements($gid, $uid);
}
// Modules notifications and badges.
if ($current_step['typology'] == 'Module' && $opigno_module->badge_active->value) {
$badge_notification = '';
$save_badge = FALSE;
// Badge notification for finished state.
if ($opigno_module->badge_criteria->value == 'finished') {
$badge_notification = $opigno_module->badge_name->value;
$save_badge = TRUE;
}
// Badge notification for successful finished state.
if ($opigno_module->badge_criteria->value == 'success' && $score >= $current_step['required score']) {
$badge_notification = $opigno_module->badge_name->value;
$save_badge = TRUE;
}
if (!empty($save_badge)) {
// Save badge.
try {
OpignoModuleBadges::opignoModuleSaveBadge($uid, $gid, $current_step['typology'], $current_step['id']);
} catch (\Exception $e) {
$this
->messenger()
->addMessage($e
->getMessage(), 'error');
}
}
if ($badge_notification) {
$message = $this
->t('You earned a badge "@badge" in "@name"', [
'@badge' => $badge_notification,
'@name' => $group
->label(),
]);
$url = Url::fromRoute('entity.group.canonical', [
'group' => $group
->id(),
])
->toString();
opigno_set_message($uid, $message, $url);
}
}
// Courses notifications and badges.
if ($current_step['typology'] == 'Module' && !empty($current_step['parent']) && $current_step['parent']['typology'] == 'Course') {
$course = Group::load($current_step['parent']['id']);
if ($course->badge_active->value) {
$badge_notification = '';
$save_badge = FALSE;
$course_steps = opigno_learning_path_get_steps($current_step['parent']['id'], $uid);
$course_last_step = end($course_steps);
$course_is_last = $course_last_step['cid'] === $current_step['cid'];
if ($course_is_last) {
// Badge notification for finished state.
if ($course->badge_criteria->value == 'finished') {
$badge_notification = $course->badge_name->value;
$save_badge = TRUE;
}
// Badge notification for successful finished state.
if ($course->badge_criteria->value == 'success' && $score >= $current_step['required score']) {
$badge_notification = $course->badge_name->value;
$save_badge = TRUE;
}
if (!empty($save_badge)) {
// Save badge.
try {
OpignoModuleBadges::opignoModuleSaveBadge($uid, $gid, 'Course', $current_step['parent']['id']);
} catch (\Exception $e) {
$this
->messenger()
->addMessage($e
->getMessage(), 'error');
}
}
if ($badge_notification) {
$message = $this
->t('You earned a badge "@badge" in "@name"', [
'@badge' => $badge_notification,
'@name' => $group
->label(),
]);
$url = Url::fromRoute('entity.group.canonical', [
'group' => $group
->id(),
])
->toString();
opigno_set_message($uid, $message, $url);
}
}
}
}
}
// Get module feedback.
$feedback_options = $opigno_module
->getResultsOptions();
if ($feedback_options) {
$feedback_option = array_filter($feedback_options, function ($option) use ($score) {
$min = (int) $option->option_start;
$max = (int) $option->option_end;
if (in_array($score, range($min, $max))) {
return TRUE;
}
});
if ($feedback_option) {
// Get only first feedback.
$feedback_option = reset($feedback_option);
$feedback['feedback'] = [
'#type' => 'container',
'#attributes' => [
'id' => 'module-feedback',
],
[
'#type' => 'html_tag',
'#tag' => 'h4',
'#attributes' => [
'class' => [
'feedback-summary',
],
],
'#value' => $feedback_option->option_summary,
],
];
// Put feedback in the beginning of array.
array_unshift($content, $feedback);
}
}
// Check if user has not results for module but already finished that skills tree.
if ($moduleHandler
->moduleExists('opigno_skills_system') && $opigno_module
->getSkillsActive() && $user_module_status
->isFinished()) {
$db_connection = \Drupal::service('database');
// Get current user's skills.
$uid = $this
->currentUser()
->id();
$query = $db_connection
->select('opigno_skills_statistic', 'o_s_s');
$query
->fields('o_s_s', [
'tid',
'score',
'progress',
'stage',
]);
$query
->condition('o_s_s.uid', $uid);
$user_skills = $query
->execute()
->fetchAllAssoc('tid');
// Check if user already finished that skills tree.
$successfully_finished = TRUE;
foreach ($skills_tree as $skill) {
if (!isset($user_skills[$skill->tid]) || $user_skills[$skill->tid]->stage != 0) {
$successfully_finished = FALSE;
}
}
$target_skill_entity = $term_storage
->load($target_skill);
if ($target_skill_entity) {
$target_skill_name = $target_skill_entity
->getName();
}
else {
$target_skill_name = $this
->t('N/A');
}
if (isset($_SESSION['successfully_finished'])) {
if ($successfully_finished) {
if ($_SESSION['successfully_finished'] == TRUE) {
$message = $this
->t('Congratulations, you master all the skills required by "@target_skill" skill\'s tree.', [
'@target_skill' => $target_skill_name,
]);
}
elseif ($user_module_status
->getOwnerId() == $uid) {
$message = $this
->t('You already master all the skills required by "@target_skill" skill\'s tree.', [
'@target_skill' => $target_skill_name,
]);
}
}
else {
$message = $this
->t('There are no activities for you right now from the "@target_skill" skill\'s tree. Try again later.', [
'@target_skill' => $target_skill_name,
]);
}
$message = [
'#type' => 'container',
'#markup' => $message,
'#attributes' => [
'class' => [
'form-module-results-message',
],
],
];
unset($_SESSION['successfully_finished']);
array_unshift($content, $message);
$content['#attached']['library'][] = 'opigno_skills_system/opigno_skills_entity';
}
}
// Check if all activities has 0 score.
// If has - immediately redirect to next step.
$has_min_score = FALSE;
foreach ($module_activities as $activity) {
if (isset($activity->max_score) && $activity->max_score > 0) {
$has_min_score = TRUE;
break;
}
}
// Redirect if module has all activities with 0 min score
// and HideResults option enabled.
if (!$has_min_score && $opigno_module
->getHideResults()) {
if (!$is_last && !in_array($current_step['typology'], [
'Meeting',
'ITL',
])) {
// Redirect to next step.
return $this
->redirect('opigno_learning_path.steps.next', [
'group' => $gid,
'parent_content' => $current_step['cid'],
]);
}
else {
// Redirect to homepage.
return $this
->redirect('entity.group.canonical', [
'group' => $gid,
]);
}
}
// Get link.
$content[] = $this
->getLinkOptions(FALSE, $gid, $is_last, $current_step);
}
elseif ($freeNavigation) {
// Get link.
$content[] = $this
->getLinkOptions(TRUE, $gid);
}
}
return $content;
}