Redefine the Issued page template - Refs BT#10651

ofaj
José Loguercio 9 years ago
parent c213a51f83
commit db67ecc254
  1. 233
      main/badge/issued.php
  2. 53
      main/inc/lib/skill.lib.php
  3. 177
      main/template/default/skill/issued.tpl

@ -3,41 +3,39 @@
/**
* Show information about the issued badge
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
* @author José Loguercio Silva <jose.loguercio@beeznest.com>
* @package chamilo.badge
*/
require_once '../inc/global.inc.php';
require_once '../inc/lib/baker.lib.php';
$userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
$skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
$issue = isset($_REQUEST['issue']) ? intval($_REQUEST['issue']) : 0;
if (!isset($_GET['user'], $_GET['skill'])) {
if (!$issue) {
header('Location: ' . api_get_path(WEB_PATH));
exit;
}
$entityManager = Database::getManager();
$user = $entityManager->find('ChamiloUserBundle:User', $_GET['user']);
$skill = $entityManager->find('ChamiloCoreBundle:Skill', $_GET['skill']);
$skillIssue = $entityManager->find('ChamiloCoreBundle:SkillRelUser', $issue);
$skillRepo = $entityManager->getRepository('ChamiloCoreBundle:Skill');
$skillLevelRepo = $entityManager->getRepository('ChamiloSkillBundle:Level');
if (!$user || !$skill) {
if (!$skillIssue) {
Display::addFlash(
Display::return_message(get_lang('NoResults'), 'error')
Display::return_message(get_lang('TheUserXNotYetAchievedTheSkillX'), 'error')
);
header('Location: ' . api_get_path(WEB_PATH));
exit;
}
$skillUserRepo = $entityManager->getRepository('ChamiloCoreBundle:SkillRelUser');
$userSkills = $skillUserRepo->findBy([
'userId' => $user->getId(),
'skillId' => $skill->getId()
]);
$user = $skillIssue->getUser();
$skill = $skillIssue->getSkill();
if (!$userSkills) {
if (!$user || !$skill) {
Display::addFlash(
Display::return_message(get_lang('TheUserXNotYetAchievedTheSkillX'), 'error')
Display::return_message(get_lang('NoResults'), 'error')
);
header('Location: ' . api_get_path(WEB_PATH));
@ -59,50 +57,161 @@ $skillInfo = [
'courses' => []
];
// Open Graph Markup
$htmlHeadXtra[] = "
<meta property='og:type' content='article' />
<meta property='og:title' content='".sprintf(get_lang('IHaveObtainedSkillXOnY'), $skillInfo['name'], api_get_setting('siteName'))."' />
<meta property='og:url' content='".api_get_path(WEB_PATH)."badge/".$skillId."/user/".$userId."' />
<meta property='og:url' content='".api_get_path(WEB_PATH)."badge/".$issue."' />
<meta property='og:description' content='".$skillInfo['description']."' />
<meta property='og:image' content='".$skillInfo['badge_image']."' />
";
$badgeAssertions = [];
$currentUserId = api_get_user_id();
$currentUser = $entityManager->find('ChamiloUserBundle:User', $currentUserId);
$allowDownloadExport = $currentUser ? $currentUser->getId() === $user->getId() : false;
$allowComment = $currentUser ? Skill::userCanAddFeedbackToUser($currentUser, $user) : false;
$skillIssueDate = api_get_local_time($skillIssue->getAcquiredSkillAt());
$currentSkillLevel = $skillLevelRepo->find(['id' => $skillIssue->getAcquiredLevel()])->getName();
$argumentationAuthor = api_get_user_info($skillIssue->getArgumentationAuthorId());
$skillIssueInfo = [
'id' => $skillIssue->getId(),
'datetime' => api_format_date($skillIssueDate, DATE_TIME_FORMAT_SHORT),
'acquired_level' => $currentSkillLevel,
'argumentation_author_id' => $skillIssue->getArgumentationAuthorId(),
'argumentation_author_name' => api_get_person_name($argumentationAuthor['firstname'], $argumentationAuthor['lastname']),
'argumentation' => $skillIssue->getArgumentation(),
'source_name' => $skillIssue->getSourceName(),
'user_id' => $skillIssue->getUser()->getId(),
'user_complete_name' => $skillIssue->getUser()->getCompleteName(),
'skill_id' => $skillIssue->getSkill()->getId(),
'skill_badge_image' => $skillIssue->getSkill()->getWebIconPath(),
'skill_name' => $skillIssue->getSkill()->getName(),
'skill_short_code' => $skillIssue->getSkill()->getShortCode(),
'skill_description' => $skillIssue->getSkill()->getDescription(),
'skill_criteria' => $skillIssue->getSkill()->getCriteria(),
'badge_assertion' => $skillIssue->getAssertionUrl(),
'comments' => [],
'feedback_average' => $skillIssue->getAverage()
];
foreach ($userSkills as $userSkill) {
$sessionId = 0;
$course = $entityManager->find('ChamiloCoreBundle:Course', $userSkill->getCourseId());
$courseName = $course ? $course->getTitle() : '';
$skillIssueComments = $skillIssue->getComments(true);
if ($userSkill->getSessionId()) {
$session = $entityManager->find('ChamiloCoreBundle:Session', $userSkill->getSessionId());
$sessionId = $session->getId();
$courseName = "[{$session->getName()}] {$course->getTitle()}";
}
$userId = $skillIssueInfo['user_id'];
$skillId = $skillIssueInfo['skill_id'];
$userSkillDate = api_get_local_time($userSkill->getAcquiredSkillAt());
$skillInfo['courses'][] = [
'name' => $courseName,
'date_issued' => api_format_date($userSkillDate, DATE_TIME_FORMAT_LONG)
foreach ($skillIssueComments as $comment) {
$commentDate = api_get_local_time($comment->getFeedbackDateTime());
$skillIssueInfo['comments'][] = [
'text' => $comment->getFeedbackText(),
'value' => $comment->getFeedbackValue(),
'giver_complete_name' => $comment->getFeedbackGiver()->getCompleteName(),
'datetime' => api_format_date($commentDate, DATE_TIME_FORMAT_SHORT)
];
}
$acquiredLevel = [];
$profile = $skillRepo->find($skillId)->getProfile();
if (!$profile) {
$assertionUrl = api_get_path(WEB_CODE_PATH) . "badge/assertion.php?";
$assertionUrl .= http_build_query(array(
'user' => $user->getId(),
'skill' => $skill->getId(),
'course' => $userSkill->getCourseId(),
'session' => $userSkill->getSessionId()
));
$skillRelSkill = new SkillRelSkill();
$parents = $skillRelSkill->get_skill_parents($skillId);
$badgeAssertions[] = $assertionUrl;
krsort($parents);
foreach ($parents as $parent) {
$skillParentId = $parent['skill_id'];
$profile = $skillRepo->find($skillParentId)->getProfile();
if ($profile) {
break;
}
if (!$profile && $parent['parent_id'] == 0) {
$profile = $skillLevelRepo->findAll();
$profile = $profile[0];
}
}
}
$allowExport = api_get_user_id() == $user->getId();
if ($profile) {
$profileId = $profile->getId();
$levels = $skillLevelRepo->findBy([
'profile' => $profileId
]);
foreach ($levels as $level) {
$profileLevels[$level->getPosition()][$level->getId()] = $level->getName();
}
ksort($profileLevels); // Sort the array by Position.
foreach ($profileLevels as $profileLevel) {
$profileId = key($profileLevel);
$acquiredLevel[$profileId] = $profileLevel[$profileId];
}
}
if ($allowExport) {
$formAcquiredLevel = new FormValidator('acquired_level');
$formAcquiredLevel->addSelect('acquired_level', get_lang('AcquiredLevel'), $acquiredLevel);
$formAcquiredLevel->addHidden('user', $skillIssue->getUser()->getId());
$formAcquiredLevel->addHidden('issue', $skillIssue->getId());
$formAcquiredLevel->addButtonSend(get_lang('Save'));
if ($formAcquiredLevel->validate() && $allowComment) {
$values = $formAcquiredLevel->exportValues();
$level = $skillLevelRepo->find(intval($values['acquired_level']));
$skillIssue->setAcquiredLevel($level);
$entityManager->persist($skillIssue);
$entityManager->flush();
header("Location: " . $skillIssue->getIssueUrl());
exit;
}
$form = new FormValidator('comment');
$form->addTextarea('comment', get_lang('NewComment'), ['rows' => 4]);
$form->applyFilter('comment', 'trim');
$form->addRule('comment', get_lang('ThisFieldIsRequired'), 'required');
$form->addSelect(
'value',
[get_lang('Value'), get_lang('RateTheSkillInPractice')],
['-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
);
$form->addHidden('user', $skillIssue->getUser()->getId());
$form->addHidden('issue', $skillIssue->getId());
$form->addButtonSend(get_lang('Send'));
if ($form->validate() && $allowComment) {
$values = $form->exportValues();
$skillUserComment = new Chamilo\CoreBundle\Entity\SkillRelUserComment();
$skillUserComment
->setFeedbackDateTime(new DateTime)
->setFeedbackGiver($currentUser)
->setFeedbackText($values['comment'])
->setFeedbackValue($values['value'] ? $values['value'] : null)
->setSkillRelUser($skillIssue);
$entityManager->persist($skillUserComment);
$entityManager->flush();
header("Location: " . $skillIssue->getIssueUrl());
exit;
}
$badgeInfoError = "";
$personalBadge = "";
if ($allowDownloadExport) {
$backpack = 'https://backpack.openbadges.org/';
$configBackpack = api_get_setting('openbadges_backpack');
@ -112,28 +221,27 @@ if ($allowExport) {
}
$htmlHeadXtra[] = '<script src="' . $backpack . 'issuer.js"></script>';
}
$badgeInfoError = false;
$personalBadge = "";
if ($skill->getIcon()) {
$unbakedBadge = file_get_contents(
api_get_path(SYS_UPLOAD_PATH) . "badges/" . $skill->getIcon()
);
$objSkill = new Skill();
$assertionUrl = $skillIssueInfo['badge_assertion'];
$skills = $objSkill->get($skillId);
$unbakedBadge = api_get_path(SYS_UPLOAD_PATH) . "badges/".$skills['icon'];
if (!is_file($unbakedBadge)) {
$unbakedBadge = api_get_path(WEB_CODE_PATH).'img/icons/128/badges-default.png';
}
$unbakedBadge = file_get_contents($unbakedBadge);
$badgeInfoError = false;
$personalBadge = "";
$png = new PNGImageBaker($unbakedBadge);
if ($png->checkChunks("tEXt", "openbadges")) {
$bakedInfo = $png->addChunk("tEXt", "openbadges", $assertionUrl);
$bakedBadge = UserManager::getUserPathById($userId, "system") . 'badges';
$bakedBadge = UserManager::getUserPathById($userId, "system");
$bakedBadge = $bakedBadge.'badges';
if (!file_exists($bakedBadge)) {
mkdir($bakedBadge, api_get_permissions_for_new_directories(), true);
}
$skillRelUserId = $userSkills[0]->getId();
$skillRelUserId = $skillIssueInfo['id'];
if (!file_exists($bakedBadge . "/badge_" . $skillRelUserId)) {
file_put_contents($bakedBadge . "/badge_" . $skillRelUserId . ".png", $bakedInfo);
}
@ -141,7 +249,6 @@ if ($skill->getIcon()) {
//Process to validate a baked badge
$badgeContent = file_get_contents($bakedBadge . "/badge_" . $skillRelUserId . ".png");
$verifyBakedBadge = $png->extractBadgeInfo($badgeContent);
if (!is_array($verifyBakedBadge)) {
$badgeInfoError = true;
}
@ -153,17 +260,15 @@ if ($skill->getIcon()) {
}
}
$template = new Template('');
$template->assign('skill_info', $skillInfo);
$template->assign('user_info', $userInfo);
$template->assign('allow_export', $allowExport);
$template = new Template(get_lang('IssuedBadgeInformation'));
$template->assign('issue_info', $skillIssueInfo);
$template->assign('allow_comment', $allowComment);
$template->assign('allow_download_export', $allowDownloadExport);
$template->assign('comment_form', $form->returnForm());
$template->assign('acquired_level_form', $formAcquiredLevel->returnForm());
$template->assign('badge_error', $badgeInfoError);
$template->assign('personal_badge', $personalBadge);
if ($allowExport) {
$template->assign('assertions', $badgeAssertions);
}
$content = $template->fetch(
$template->get_template('skill/issued.tpl')
);

@ -891,7 +891,7 @@ class Skill extends Model
public function get_user_skills($user_id, $get_skill_data = false)
{
$user_id = intval($user_id);
$sql = 'SELECT DISTINCT s.id, s.name, s.icon
$sql = 'SELECT DISTINCT s.id, s.name, s.icon, u.id as issue
FROM '.$this->table_skill_rel_user.' u
INNER JOIN '.$this->table.' s
ON u.skill_id = s.id
@ -1448,4 +1448,55 @@ class Skill extends Model
return Database::store_result($result, 'ASSOC');
}
/**
* Check if the $fromUser can comment the $toUser skill issue
* @param Chamilo\UserBundle\Entity\User $fromUser
* @param Chamilo\UserBundle\Entity\User $toUser
* @return boolean
*/
public static function userCanAddFeedbackToUser($fromUser, $toUser)
{
if (api_is_platform_admin()) {
return true;
}
$entityManager = Database::getManager();
$userRepo = $entityManager->getRepository('ChamiloUserBundle:User');
$fromUserStatus = $fromUser->getStatus();
switch ($fromUserStatus) {
case SESSIONADMIN:
if (api_get_setting('allow_session_admins_to_manage_all_sessions') === 'true') {
if ($toUser->getCreatorId() === $fromUser->getId()) {
return true;
}
}
$sessionAdmins = $userRepo->getSessionAdmins($toUser);
foreach ($sessionAdmins as $sessionAdmin) {
if ($sessionAdmin->getId() !== $fromUser->getId()) {
continue;
}
return true;
}
break;
case STUDENT_BOSS:
$studentBosses = $userRepo->getStudentBosses($toUser);
foreach ($studentBosses as $studentBoss) {
if ($studentBoss->getId() !== $fromUser->getId()) {
continue;
}
return true;
}
case DRH:
return UserManager::is_user_followed_by_drh($toUser->getId(), $fromUser->getId());
}
return false;
}
}

@ -1,79 +1,138 @@
<div class="row issued">
<div class="col-md-4">
<figure class="thumbnail">
<img class="img-responsive" src="{{ skill_info.badge_image }}" alt="{{ skill_info.name }}">
<figcaption class="caption text-center">
<p class="name-badge text-center">{{ skill_info.name }}</p>
</figcaption>
</figure>
<div class="panel panel-default">
<div class="panel-heading">{{ 'SkillAcquiredAt'|get_lang }}</div>
<div class="panel-body">
{% for course in skill_info.courses %}
<p>
{% if course.name %}
<em class="fa fa-clock-o fa-fw"></em> {{ 'TimeXThroughCourseY'|get_lang|format(course.date_issued, course.name) }}
{% else %}
<em class="fa fa-clock-o fa-fw"></em> {{ course.date_issued }}
{% endif %}
</p>
{% endfor %}
</div>
<div class="col-md-5">
<div class="thumbnail">
<figure class="text-center">
<img class="img-responsive center-block" src="{{ issue_info.skill_badge_image }}" alt="{{ issue_info.skill_name }}">
<figcaption>
<p class="lead">{{ issue_info.skill_name }}</p>
{% if issue_info.skill_short_code %}
<p>{{ issue_info.skill_short_code }}</p>
{% endif %}
</figcaption>
</figure>
<div class="caption">
{% if issue_info.skill_description %}
<p>{{ issue_info.skill_description }}</p>
{% endif %}
{% if issue_info.skill_criteria %}
<h3>{{ 'CriteriaToEarnTheBadge'|get_lang }}</h3>
<p>{{ issue_info.skill_criteria }}</p>
{% endif %}
</div>
{% if badge_error %}
<div class="alert alert-danger"> {{ 'BakedBadgeProblem'|get_lang }}</div>
{% elseif personal_badge is not empty %}
<p class="text-center">
<a href="{{ personal_badge }}" class="btn btn-primary" target="_new" download="badge">
<em class="fa fa-download fa-fw"></em> {{ 'DownloadBadge'|get_lang }}
</a>
</p>
{% endif %}
{% if allow_export %}
</div>
{% if allow_download_export %}
{% if badge_error %}
<hr>
<div class="alert alert-danger"> {{ 'BakedBadgeProblem'|get_lang }}</div>
{% else %}
<p class="text-center">
<a href="{{ personal_badge }}" class="btn btn-primary" target="_new" download="badge">
<em class="fa fa-download fa-fw"></em> {{ 'DownloadBadge'|get_lang }}
</a>
</p>
{% endif %}
<hr>
<p class="text-center">
<a href="#" class="btn btn-success" id="badge-export-button">
<em class="fa fa-external-link-square fa-fw"></em> {{ 'ExportBadge'|get_lang }}
</a>
</p>
<div class='col-md-12 text-center'>
<h5><b> {{ 'ShareWithYourFriends' | get_lang }} </b></h5>
<a href='http://www.facebook.com/sharer.php?u={{ _p.web }}badge/{{ skill_info.id }}/user/{{ user_info.id }}' target='_new'>
<em class='fa fa-facebook-square fa-3x text-info' aria-hidden='true'></em>
</a>
<a href='https://twitter.com/home?status={{ 'IHaveObtainedSkillXOnY' | get_lang |format(skill_info.name, _s.site_name)}} - {{ _p.web }}badge/{{ skill_info.id }}/user/{{ user_info.id }}' target='_new'>
<em class='fa fa-twitter-square fa-3x text-light' aria-hidden='true'></em>
</a>
</div>
{% endif %}
<div class='col-md-12 text-center'>
<h5><b> {{ 'ShareWithYourFriends' | get_lang }} </b></h5>
<a href='http://www.facebook.com/sharer.php?u={{ _p.web }}badge/{{ skill_info.id }}/user/{{ user_info.id }}' target='_new'>
<em class='fa fa-facebook-square fa-3x text-info' aria-hidden='true'></em>
</a>
<a href='https://twitter.com/home?status={{ 'IHaveObtainedSkillXOnY' | get_lang |format(skill_info.name, _s.site_name)}} - {{ _p.web }}badge/{{ skill_info.id }}/user/{{ user_info.id }}' target='_new'>
<em class='fa fa-twitter-square fa-3x text-light' aria-hidden='true'></em>
</a>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-body">
<h4 class="title-badge">{{ 'RecipientDetails'|get_lang }}</h4>
<p class="lead">{{ user_info.complete_name }}</p>
<h4 class="title-badge">{{ 'BadgeDetails'|get_lang }}</h4>
<h4 class="title-badge">{{ 'Name'|get_lang }}</h4>
<p>{{ skill_info.name }}</p>
{% if skill_info.short_code %}
<h4 class="title-badge">{{ 'ShortCode'|get_lang }}</h4>
<p>{{ skill_info.short_code }}</p>
<div class="col-md-7">
<h3>{{ 'RecipientDetails'|get_lang }}</h3>
<p class="lead">{{ issue_info.user_complete_name }}</p>
<h4>{{ 'SkillAcquiredAt'|get_lang }}</h4>
<ul class="fa-ul">
<li>
{% if issue_info.source_name %}
<em class="fa-li fa fa-clock-o fa-fw"></em> {{ 'TimeXThroughCourseY'|get_lang|format(issue_info.datetime, issue_info.source_name) }}
{% else %}
<em class="fa-li fa fa-clock-o fa-fw"></em> {{ issue_info.datetime }}
{% endif %}
{% if issue_info.argumentation %}
{% if issue_info.argumentation %}
<b><p style="font-style: italic;">{{ 'UserXIndicated'|get_lang|format(issue_info.argumentation_author_name) }} </p></b>
{% endif %}
<p>{{ issue_info.argumentation }}</p>
{% endif %}
</li>
</ul>
<h4>{{ 'AcquiredLevel'|get_lang }}</h4>
<ul class="fa-ul">
<li>
<em class="fa-li fa fa-check-circle-o fa-fw"></em> {{ issue_info.acquired_level }}
</li>
</ul>
{% if allow_comment %}
<hr>
<div class="panel panel-info">
<div class="panel-heading">
<em class="fa fa-check-circle-o fa-fw" aria-hidden="true"></em> {{ 'ChangeAcquiredLevel'|get_lang }}
</div>
<div class="panel-body">
{{ acquired_level_form }}
</div>
</div>
<hr>
<div class="panel panel-info">
<div class="panel-heading">
<em class="fa fa-comment-o fa-fw" aria-hidden="true"></em> {{ 'XComments'|get_lang|format(issue_info.comments|length) }}
/
<em class="fa fa-thumbs-o-up fa-fw" aria-hidden="true"></em> {{ 'AverageRatingX'|get_lang|format(issue_info.feedback_average) }}
</div>
<div class="panel-body">
{{ comment_form }}
<hr>
{% for comment in issue_info.comments %}
<article class="media">
<div class="media-body">
<h4 class="media-heading">{{ comment.giver_complete_name }}</h4>
<p><small>{{ comment.datetime }}</small></p>
<p>{{ comment.text }}</p>
</div>
<div class="media-right text-right">
<div style="width: 80px;">
{% if comment.value %}
<em class="fa fa-certificate fa-fw" aria-label="{{ 'AverageRating' }}"></em>
<span class="sr-only">{{ 'AverageRating' }}</span> {{ comment.value }}
{% endif %}
</div>
</div>
</article>
{% else %}
<p>{{ 'WithoutComment'|get_lang }}</p>
{% endfor %}
</div>
</div>
{% else %}
<hr>
<p class="lead">
<em class="fa fa-comment-o fa-fw" aria-hidden="true"></em> {{ 'XComments'|get_lang|format(issue_info.comments|length) }}
/
<em class="fa fa-thumbs-o-up fa-fw" aria-hidden="true"></em> {{ 'AverageRatingX'|get_lang|format(issue_info.feedback_average) }}
</p>
{% endif %}
<h4 class="title-badge">{{ 'Description'|get_lang }}</h4>
<p>{{ skill_info.description }}</p>
<h4 class="title-badge">{{ 'CriteriaToEarnTheBadge'|get_lang }}</h4>
<p>{{ skill_info.criteria }}</p>
</div>
</div>
</div>
</div>
{% if allow_export %}
{% if allow_download_export %}
<script>
$(document).on('ready', function () {
$('#badge-export-button').on('click', function (e) {
e.preventDefault();
OpenBadges.issue({{ assertions|json_encode() }});
OpenBadges.issue({{ issue_info.badge_assertion|json_encode() }});
});
});
</script>
{% endif %}
{% endif %}
Loading…
Cancel
Save