XAPI: Allow get attempts reports for tincan launch - refs BT#16742

pull/3680/head
Angel Fernando Quiroz Campos 5 years ago
parent b0e0e49a59
commit 7f8a7f9ae0
  1. 4
      plugin/xapi/launch/list.php
  2. 167
      plugin/xapi/launch/stats.php
  3. 118
      plugin/xapi/launch/stats_attempts.ajax.php
  4. 7
      plugin/xapi/src/XApiPlugin.php

@ -61,6 +61,10 @@ $table->set_column_filter(
1,
function ($id) use ($cidReq) {
$actions = [];
$actions[] = Display::url(
Display::return_icon('statistics.png', get_lang('Reporting')),
"stats.php?$cidReq&id=$id"
);
$actions[] = Display::url(
Display::return_icon('edit.png', get_lang('Edit')),
"edit.php?$cidReq&edit=$id"

@ -0,0 +1,167 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\XApi\ToolLaunch;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
require_once __DIR__.'/../../../main/inc/global.inc.php';
api_protect_course_script(true);
api_protect_teacher_script();
$request = HttpRequest::createFromGlobals();
$em = Database::getManager();
$toolLaunch = $em->find(
ToolLaunch::class,
$request->query->getInt('id')
);
if (null === $toolLaunch) {
header('Location: '.api_get_course_url());
exit;
}
$course = api_get_course_entity();
$session = api_get_session_entity();
$cidReq = api_get_cidreq();
$plugin = XApiPlugin::create();
$table = new SortableTable(
'tbl_xapi',
function () use ($course, $session) {
if ($session) {
return CourseManager::get_student_list_from_course_code(
$course->getCode(),
true,
$session->getId(),
null,
null,
true,
0,
true
);
}
return CourseManager::get_student_list_from_course_code(
$course->getCode(),
false,
0,
null,
null,
true,
0,
true
);
},
function ($start, $limit, $orderBy, $orderDir) use ($course, $session) {
if ($session) {
$students = CourseManager::get_student_list_from_course_code(
$course->getCode(),
true,
$session->getId(),
null,
null,
true,
0,
false,
$start,
$limit
);
} else {
$students = CourseManager::get_student_list_from_course_code(
$course->getCode(),
false,
0,
null,
null,
true,
0,
false,
$start,
$limit
);
}
return array_map(
function (array $studentInfo) {
return [
$studentInfo['firstname'],
$studentInfo['lastname'],
$studentInfo['id'],
];
},
$students
);
}
);
$table->set_header(0, get_lang('FirstName'), false);
$table->set_header(1, get_lang('LastName'), false);
$table->set_header(2, get_lang('Attempts'), false, [], ['style' => 'width: 65%;']);
$table->set_column_filter(
2,
function ($id) use ($toolLaunch) {
return Display::button(
"xapi_state_$id",
get_lang('ShowAllAttempts'),
[
'class' => 'btn btn-default btn_xapi_attempts',
'data-student' => $id,
'data-tool' => $toolLaunch->getId(),
]
);
}
);
$table->set_additional_parameters(
[
'id' => $toolLaunch->getId(),
'cidReq' => $course->getCode(),
'id_session' => $session ? $session->getId() : 0,
]
);
// View
$interbreadcrumb[] = [
'name' => $plugin->get_title(),
'url' => 'list.php',
];
$htmlHeadXtra[] = "<script>
$(function () {
$('.btn_xapi_attempts').on('click', function () {
var \$self = $(this);
\$self
.prop('disabled', true)
.html('<em class=\"fa fa-spinner fa-pulse\"></em> ".get_lang('Loading')."');
$.post(
'stats_attempts.ajax.php?' + _p.web_cid_query,
\$self.data(),
function (response) {
\$self.parent().html(response);
}
);
});
})
</script>";
$actions = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
"list.php?$cidReq"
);
$view = new Template($toolLaunch->getTitle());
$view->assign(
'actions',
Display::toolbarAction('xapi_actions', [$actions])
);
$view->assign('header', $toolLaunch->getTitle());
$view->assign(
'content',
Display::page_subheader(get_lang('Reporting'), null, 'h4').PHP_EOL.$table->return_table()
);
$view->display_one_col_template();

@ -0,0 +1,118 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\XApi\ToolLaunch;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Xabbuh\XApi\Common\Exception\NotFoundException;
use Xabbuh\XApi\Common\Exception\XApiException;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Agent;
use Xabbuh\XApi\Model\InverseFunctionalIdentifier;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\State;
require_once __DIR__.'/../../../main/inc/global.inc.php';
$request = HttpRequest::createFromGlobals();
$course = api_get_course_entity();
$session = api_get_session_entity();
if (!$request->isXmlHttpRequest()
|| !api_is_allowed_to_edit()
|| !$course
) {
echo Display::return_message(get_lang('NotAllowed'), 'error');
exit;
}
$plugin = XApiPlugin::create();
$em = Database::getManager();
$toolLaunch = $em->find(
ToolLaunch::class,
$request->request->getInt('tool')
);
$student = api_get_user_entity($request->request->getInt('student'));
if (!$toolLaunch || !$student) {
echo Display::return_message(get_lang('NoResults'), 'error');
exit;
}
$userIsSubscribedToCourse = CourseManager::is_user_subscribed_in_course(
$student->getId(),
$course->getCode(),
!!$session,
$session ? $session->getId() : 0
);
if (!$userIsSubscribedToCourse) {
echo Display::return_message(get_lang('NotAllowed'), 'error');
exit;
}
$cidReq = api_get_cidreq();
$xApiStateClient = $plugin->getXApiStateClient(
$toolLaunch->getLrsUrl(),
$toolLaunch->getLrsAuthUsername(),
$toolLaunch->getLrsAuthPassword()
);
$activity = new Activity(
IRI::fromString($toolLaunch->getActivityId())
);
$actor = new Agent(
InverseFunctionalIdentifier::withMbox(
IRI::fromString('mailto:'.$student->getEmail())
),
$student->getCompleteName()
);
try {
$stateDocument = $xApiStateClient->getDocument(
new State(
$activity,
$actor,
$plugin->generateIri('tool-'.$toolLaunch->getId(), 'state')->getValue()
)
);
} catch (NotFoundException $notFoundException) {
echo Display::return_message($notFoundException->getMessage(), 'error');
exit;
} catch (XApiException $exception) {
echo Display::return_message($exception->getMessage(), 'error');
exit;
}
if ($stateDocument) {
$table = new HTML_Table(['class' => 'data_table table table-bordered']);
$table->setHeaderContents(0, 0, $plugin->get_lang('ActivityFirstLaunch'));
$table->setHeaderContents(0, 1, $plugin->get_lang('ActivityLastLaunch'));
$i = 1;
foreach ($stateDocument->getData()->getData() as $attempt) {
$firstLaunch = api_convert_and_format_date(
$attempt[XApiPlugin::STATE_FIRST_LAUNCH],
DATE_TIME_FORMAT_LONG
);
$lastLaunch = api_convert_and_format_date(
$attempt[XApiPlugin::STATE_LAST_LAUNCH],
DATE_TIME_FORMAT_LONG
);
$table->setCellContents($i, 0, $firstLaunch);
$table->setCellContents($i, 1, $lastLaunch);
$i++;
}
$table->updateColAttributes(0, ['class' => 'text-center']);
$table->updateColAttributes(1, ['class' => 'text-center']);
$table->display();
}

@ -220,6 +220,13 @@ class XApiPlugin extends Plugin implements HookPluginInterface
return $this->createXApiClient()->getStatementsApiClient();
}
public function getXApi($lrsUrl = null, $lrsAuthUsername = null, $lrsAuthPassword = null)
{
$this
->createXApiClient($lrsUrl, $lrsAuthUsername, $lrsAuthPassword)
->getStateApiClient()->getDocument();
}
/**
* @param string|null $lrsUrl
* @param string|null $lrsAuthUsername

Loading…
Cancel
Save