19declare(strict_types=1);
52 $this->
user = $DIC->user();
53 $this->
ctrl = $DIC->ctrl();
66 $this->
ctrl->redirectToURL($launchLink);
74 $launchLink = $this->
object->getLaunchUrl();
76 if (preg_match(
"/^(https?:\/\/)/", $this->
object->getLaunchUrl()) == 1) {
77 $launchLink = $this->
object->getLaunchUrl();
79 $launchLink = implode(
'/', [
85 $launchLink .= DIRECTORY_SEPARATOR . $this->
object->getLaunchUrl();
103 if ($this->
object->isBypassProxyEnabled()) {
104 $params[
'endpoint'] = urlencode(rtrim($this->
object->getLrsType()->getLrsEndpoint(),
'/') .
'/');
106 $params[
'endpoint'] = urlencode(rtrim(ILIAS_HTTP_PATH .
'/' . self::XAPI_PROXY_ENDPOINT,
'/') .
'/');
109 if ($this->
object->isAuthFetchUrlEnabled()) {
112 if ($this->
object->isBypassProxyEnabled()) {
113 $params[
'auth'] = urlencode($this->
object->getLrsType()->getBasicAuth());
115 $params[
'auth'] = urlencode(
'Basic ' . base64_encode(
121 $params[
'activity_id'] = urlencode($this->
object->getActivityId());
122 $params[
'activityId'] = urlencode($this->
object->getActivityId());
123 $params[
'actor'] = urlencode(json_encode($this->
object->getStatementActor($this->cmixUser)));
125 $registration = $this->cmixUser->getRegistration();
127 if ($registration ==
'') {
130 $params[
'registration'] = $registration;
142 $link = ILIAS_HTTP_PATH .
'/xapitoken.php';
146 return iLUtil::appendUrlParameterString($link,
"param={$param}");
155 session_name() => session_id(),
156 'obj_id' => $this->
object->getId(),
157 'ref_id' => $this->
object->getRefId(),
162 return urlencode(base64_encode(openssl_encrypt(
174 $this->
user->getId(),
175 $this->object->getRefId(),
176 $this->object->getId(),
177 $this->object->getLrsType()->getTypeId()
184 $this->cmixUser =
new ilCmiXapiUser($this->
object->getId(), $this->user->getId(), $this->object->getPrivacyIdent());
185 $user_ident = $this->cmixUser->getUsrIdent();
186 if ($user_ident ==
'' || $user_ident ==
null) {
188 $this->cmixUser->setUsrIdent($user_ident);
193 $this->cmixUser->save();
205 $language = $this->
user->getLanguage();
208 "languagePreference" =>
"{$language}",
209 "audioPreference" =>
"{$audio}"
224 $DIC->language()->loadLanguageModule(
"cmix");
227 $lrsType = $this->
object->getLrsType();
228 $defaultLrs = $lrsType->getLrsEndpoint();
229 $defaultBasicAuth = $lrsType->getBasicAuth();
232 'X-Experience-API-Version: 1.0.3',
233 'Authorization: ' . $defaultBasicAuth,
234 'Content-Type: application/json;charset=utf-8',
235 'Cache-Control: no-cache, no-store, must-revalidate'
238 $registration = $this->cmixUser->getRegistration();
239 if ($registration ==
'') {
243 $activityId = $this->
object->getActivityId();
247 'agent' => json_encode($this->
object->getStatementActor($this->cmixUser)),
248 'profileId' =>
'cmi5LearnerPreferences'
253 $launchDataParams = [
254 'agent' => json_encode($this->
object->getStatementActor($this->cmixUser)),
255 'activityId' => $activityId,
256 'activity_id' => $activityId,
257 'registration' => $registration,
258 'stateId' =>
'LMS.LaunchData'
263 $cmi5LearnerPreferences = json_encode($cmi5LearnerPreferencesObj);
264 $lang = $cmi5LearnerPreferencesObj[
'languagePreference'];
268 $oldSession = $tokenObject->getCmi5Session();
269 $oldSessionLaunchedTimestamp =
'';
272 if ($oldSession !=
null && !empty($oldSession)) {
273 $oldSessionData = json_decode($tokenObject->getCmi5SessionData());
274 $oldSessionLaunchedTimestamp = $oldSessionData->launchedTimestamp;
275 $tokenObject->delete();
278 $lastStatement = $this->
object->getLastStatement($oldSession);
279 if (isset($lastStatement[0][
'statement'][
'verb'][
'id']) &&
282 $start =
new DateTime($oldSessionLaunchedTimestamp);
283 $end =
new DateTime($lastStatement[0][
'statement'][
'timestamp']);
284 $diff = $end->diff($start);
290 $lpMode = $this->
object->getLPMode();
295 $tokenObject->setCmi5Session($cmi5_session);
298 'cmi5LearnerPreferences' => $cmi5LearnerPreferencesObj,
299 'launchedTimestamp' => $now->toXapiTimestamp()
301 $tokenObject->setCmi5SessionData(json_encode($sessionData));
302 $tokenObject->update();
304 $defaultStatementsUrl = $defaultLrs .
"/statements";
307 $launchData = json_encode($this->
object->getLaunchData($DIC->language()->txt(
'cmiexit'), $this->cmixUser));
308 $launchedStatement = $this->
object->getLaunchedStatement($this->cmixUser);
309 $launchedStatementUrl = $defaultStatementsUrl .
'?statementId=' . urlencode($launchedStatement[
'id']);
312 [
'url' => $defaultProfileUrl,
'method' =>
'POST',
'body' => $cmi5LearnerPreferences],
313 [
'url' => $defaultLaunchDataUrl,
'method' =>
'PUT',
'body' => $launchData],
314 [
'url' => $launchedStatementUrl,
'method' =>
'PUT',
'body' => json_encode($launchedStatement)]
318 $abandonedStatement = $this->
object->getAbandonedStatement($oldSession,
$duration, $this->cmixUser);
320 'url' => $defaultStatementsUrl .
'?statementId=' . urlencode($abandonedStatement[
'id']),
322 'body' => json_encode($abandonedStatement)
327 $satisfiedStatement = $this->
object->getSatisfiedStatement($this->cmixUser);
329 'url' => $defaultStatementsUrl .
'?statementId=' . urlencode($satisfiedStatement[
'id']),
331 'body' => json_encode($satisfiedStatement)
336 $mh = curl_multi_init();
339 foreach ($requests as
$req) {
341 curl_setopt_array($ch, [
342 CURLOPT_URL =>
$req[
'url'],
343 CURLOPT_CUSTOMREQUEST =>
$req[
'method'],
344 CURLOPT_HTTPHEADER => $defaultHeaders,
345 CURLOPT_POSTFIELDS =>
$req[
'body'],
346 CURLOPT_RETURNTRANSFER =>
true,
347 CURLOPT_TIMEOUT => 10,
348 CURLOPT_SSL_VERIFYPEER =>
true,
350 curl_multi_add_handle(
$mh, $ch);
357 curl_multi_exec(
$mh, $running);
358 curl_multi_select(
$mh);
360 }
while ($running > 0);
363 foreach ($chs as $ch) {
364 $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
365 $body = curl_multi_getcontent($ch);
366 if (!in_array($status, [200, 204])) {
367 $this->
log()->error(
"CMI5preLaunch HTTP error $status: $body");
369 curl_multi_remove_handle(
$mh, $ch);
373 curl_multi_close(
$mh);
376 'cmi5_session' => $cmi5_session,
386 return \ilLoggerFactory::getLogger(
'cmix');
static buildQuery(array $params, $encoding=PHP_QUERY_RFC3986)
static fillToken(int $usrId, int $refId, int $objId, int $lrsTypeId=0)
static getInstanceByToken(string $token)
const OPENSSL_ENCRYPTION_METHOD
const RELATIVE_CONTENT_DIRECTORY_NAMEBASE
static dateIntervalToISO860Duration(\DateInterval $d)
getCmi5LearnerPreferences()
buildLaunchLink(string $token)
const XAPI_PROXY_ENDPOINT
buildAuthTokenFetchParam()
__construct(ilObjCmiXapi $object)
getLaunchParameters(string $token)
CMI5preLaunch(string $token)
Prelaunch post cmi5LearnerPreference (agent profile) post LMS.LaunchData.
static getIdent(int $userIdentMode, ilObjUser $user)
static generateRegistration(ilObjCmiXapi $obj, ilObjUser $user)
static generateCMI5Registration(int $objId, int $usrId)
static getWebspaceDir(string $mode="filesystem")
get webspace directory
const LP_MODE_DEACTIVATED
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
Component logger with individual log levels by component id.
static guidv4(?string $data=null)
static _isAnonymous(int $usr_id)
static appendUrlParameterString(string $a_url, string $a_par, bool $xml_style=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if(empty($ltiMessageHint)) $mh
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
catch(\Exception $e) $req