ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
ilCmiXapiLaunchGUI Class Reference
+ Collaboration diagram for ilCmiXapiLaunchGUI:

Public Member Functions

 __construct (ilObjCmiXapi $object)
 
 executeCommand ()
 

Data Fields

const XAPI_PROXY_ENDPOINT = 'Modules/CmiXapi/xapiproxy.php'
 

Protected Member Functions

 launchCmd ()
 
 buildLaunchLink ($token)
 
 getLaunchParameters ($token)
 
 getAuthTokenFetchLink ()
 
 buildAuthTokenFetchParam ()
 
 getValidToken ()
 
 initCmixUser ()
 
 getCmi5LearnerPreferences ()
 
 CMI5preLaunch ($token)
 Prelaunch post cmi5LearnerPreference (agent profile) post LMS.LaunchData. More...
 

Protected Attributes

 $object
 
 $cmixUser
 
 $plugin = false
 

Private Member Functions

 log ()
 

Detailed Description

Definition at line 15 of file class.ilCmiXapiLaunchGUI.php.

Constructor & Destructor Documentation

◆ __construct()

ilCmiXapiLaunchGUI::__construct ( ilObjCmiXapi  $object)
Parameters
ilObjCmiXapi$object

Definition at line 37 of file class.ilCmiXapiLaunchGUI.php.

38 {
39 $this->object = $object;
40 }

References $object.

Member Function Documentation

◆ buildAuthTokenFetchParam()

ilCmiXapiLaunchGUI::buildAuthTokenFetchParam ( )
protected
Returns
string
Exceptions
ilCmiXapiException

Definition at line 145 of file class.ilCmiXapiLaunchGUI.php.

146 {
147 $params = [
148 session_name() => session_id(),
149 'obj_id' => $this->object->getId(),
150 'ref_id' => $this->object->getRefId(),
151 'ilClientId' => CLIENT_ID
152 ];
153
154 $encryptionKey = ilCmiXapiAuthToken::getWacSalt();
155
156 $param = urlencode(base64_encode(openssl_encrypt(
157 json_encode($params),
159 $encryptionKey,
160 0,
162 )));
163 return $param;
164 }
$param
Definition: xapitoken.php:31

References $param, ilCmiXapiAuthToken\getWacSalt(), ilCmiXapiAuthToken\OPENSSL_ENCRYPTION_METHOD, and ilCmiXapiAuthToken\OPENSSL_IV.

Referenced by getAuthTokenFetchLink().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildLaunchLink()

ilCmiXapiLaunchGUI::buildLaunchLink (   $token)
protected

Definition at line 61 of file class.ilCmiXapiLaunchGUI.php.

62 {
63 if ($this->object->getSourceType() == ilObjCmiXapi::SRC_TYPE_REMOTE) {
64 $launchLink = $this->object->getLaunchUrl();
65 } elseif ($this->object->getSourceType() == ilObjCmiXapi::SRC_TYPE_LOCAL) {
66 if (preg_match("/^(https?:\/\/)/",$this->object->getLaunchUrl()) == 1) {
67 $launchLink = $this->object->getLaunchUrl();
68 } else {
69 $launchLink = implode('/', [
72 ]);
73
74 $launchLink .= DIRECTORY_SEPARATOR . $this->object->getLaunchUrl();
75 }
76 }
77
78 foreach ($this->getLaunchParameters($token) as $paramName => $paramValue) {
79 $launchLink = ilUtil::appendUrlParameterString($launchLink, "{$paramName}={$paramValue}");
80 }
81
82 return $launchLink;
83 }
static appendUrlParameterString($a_url, $a_par, $xml_style=false)
append URL parameter string ("par1=value1&par2=value2...") to given URL string
static getWebspaceDir($mode="filesystem")
get webspace directory
$token
Definition: xapitoken.php:57

References $token, ilUtil\appendUrlParameterString(), getLaunchParameters(), ilUtil\getWebspaceDir(), ILIAS_HTTP_PATH, ilCmiXapiContentUploadImporter\RELATIVE_CONTENT_DIRECTORY_NAMEBASE, ilObjCmiXapi\SRC_TYPE_LOCAL, and ilObjCmiXapi\SRC_TYPE_REMOTE.

Referenced by launchCmd().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CMI5preLaunch()

ilCmiXapiLaunchGUI::CMI5preLaunch (   $token)
protected

Prelaunch post cmi5LearnerPreference (agent profile) post LMS.LaunchData.

Definition at line 224 of file class.ilCmiXapiLaunchGUI.php.

225 {
226 global $DIC;
227
228 $lrsType = $this->object->getLrsType();
229 $defaultLrs = $lrsType->getLrsEndpoint();
230 //$fallbackLrs = $lrsType->getLrsFallbackEndpoint();
231 $defaultBasicAuth = $lrsType->getBasicAuth();
232 //$fallbackBasicAuth = $lrsType->getFallbackBasicAuth();
233 $defaultHeaders = [
234 'X-Experience-API-Version' => '1.0.3',
235 'Authorization' => $defaultBasicAuth,
236 'Content-Type' => 'application/json;charset=utf-8',
237 'Cache-Control' => 'no-cache, no-store, must-revalidate'
238 ];
239
240 $registration = $this->cmixUser->getRegistration();
241 // for old CMI5 Content after switch commit but before cmi5 bugfix
242 if ($registration == '')
243 {
244 $registration = ilCmiXapiUser::generateRegistration($this->object, $DIC->user());
245 }
246
247 $activityId = $this->object->getActivityId();
248
249 // profile
250 $profileParams = [];
251 $defaultAgentProfileUrl = $defaultLrs . "/agents/profile";
252 $profileParams['agent'] = json_encode($this->object->getStatementActor($this->cmixUser));
253 $profileParams['profileId'] = 'cmi5LearnerPreferences';
254 $defaultProfileUrl = $defaultAgentProfileUrl . '?' . ilCmiXapiAbstractRequest::buildQuery($profileParams);
255
256 // launchData
257 $launchDataParams = [];
258 $defaultStateUrl = $defaultLrs . "/activities/state";
259 //$launchDataParams['agent'] = $this->buildCmi5ActorParameter();
260 $launchDataParams['agent'] = json_encode($this->object->getStatementActor($this->cmixUser));
261 $launchDataParams['activityId'] = $activityId;
262 $launchDataParams['activity_id'] = $activityId;
263 $launchDataParams['registration'] = $registration;
264 $launchDataParams['stateId'] = 'LMS.LaunchData';
265 $defaultLaunchDataUrl = $defaultStateUrl . '?' . ilCmiXapiAbstractRequest::buildQuery($launchDataParams);
266 $cmi5LearnerPreferencesObj = $this->getCmi5LearnerPreferences();
267 $cmi5LearnerPreferences = json_encode($cmi5LearnerPreferencesObj);
268 $lang = $cmi5LearnerPreferencesObj['languagePreference'];
269 $cmi5_session = ilObjCmiXapi::guidv4();
271 $oldSession = $tokenObject->getCmi5Session();
272 $oldSessionLaunchedTimestamp = '';
273 $abandoned = false;
274 // cmi5_session already exists?
275 if (!empty($oldSession)) {
276 $oldSessionData = json_decode($tokenObject->getCmi5SessionData());
277 $oldSessionLaunchedTimestamp = $oldSessionData->launchedTimestamp;
278 $tokenObject->delete();
279 $token = $this->getValidToken();
281 $lastStatement = $this->object->getLastStatement($oldSession);
282 // should never be 'terminated', because terminated statement is sniffed from proxy -> token delete
283 if ($lastStatement[0]['statement']['verb']['id'] != ilCmiXapiVerbList::getInstance()->getVerbUri('terminated'))
284 {
285 $abandoned = true;
286 $start = new DateTime($oldSessionLaunchedTimestamp);
287 $end = new DateTime($lastStatement[0]['statement']['timestamp']);
288 $diff = $end->diff($start);
290 }
291 }
292 // satisfied on launch?
293 // see: https://github.com/AICC/CMI-5_Spec_Current/blob/quartz/cmi5_spec.md#moveon
294 // https://aicc.github.io/CMI-5_Spec_Current/samples/
295 // Session that includes the absolute minimum data, and is associated with a NotApplicable Move On criteria
296 // which results in immediate satisfaction of the course upon registration creation. Includes Satisfied Statement.
297 $satisfied = false;
298 $lpMode = $this->object->getLPMode();
299 // only do this, if we decide to map the moveOn NotApplicable to ilLPObjSettings::LP_MODE_DEACTIVATED on import and settings editing
300 // and what about user result status?
301 if ($lpMode === ilLPObjSettings::LP_MODE_DEACTIVATED) {
302 $satisfied = true;
303 }
304
305 $tokenObject->setCmi5Session($cmi5_session);
306 $sessionData = array();
307 $sessionData['cmi5LearnerPreferences'] = $cmi5LearnerPreferencesObj;
308 //https://www.php.net/manual/de/class.dateinterval.php
309 $now = new ilCmiXapiDateTime(time(), IL_CAL_UNIX);
310 $sessionData['launchedTimestamp'] = $now->toXapiTimestamp(); // required for abandoned statement duration, don't want another roundtrip to lrs ...puhhh
311 $tokenObject->setCmi5SessionData(json_encode($sessionData));
312 $tokenObject->update();
313 $defaultStatementsUrl = $defaultLrs . "/statements";
314
315 // launchedStatement
316 $launchData = json_encode($this->object->getLaunchData($this->cmixUser,$lang));
317 $launchedStatement = $this->object->getLaunchedStatement($this->cmixUser);
318 $launchedStatementParams = [];
319 $launchedStatementParams['statementId'] = $launchedStatement['id'];
320 $defaultLaunchedStatementUrl = $defaultStatementsUrl . '?' . ilCmiXapiAbstractRequest::buildQuery($launchedStatementParams);
321
322 // abandonedStatement
323 if ($abandoned) {
324 $abandonedStatement = $this->object->getAbandonedStatement($oldSession, $duration, $this->cmixUser);
325 $abandonedStatementParams = [];
326 $abandonedStatementParams['statementId'] = $abandonedStatement['id'];
327 $defaultAbandonedStatementUrl = $defaultStatementsUrl . '?' . ilCmiXapiAbstractRequest::buildQuery($abandonedStatementParams);
328 }
329 // abandonedStatement
330 if ($satisfied) {
331 $satisfiedStatement = $this->object->getSatisfiedStatement($this->cmixUser);
332 $satisfiedStatementParams = [];
333 $satisfiedStatementParams['statementId'] = $satisfiedStatement['id'];
334 $defaultSatisfiedStatementUrl = $defaultStatementsUrl . '?' . ilCmiXapiAbstractRequest::buildQuery($satisfiedStatementParams);
335 }
336 $client = new GuzzleHttp\Client();
337 $req_opts = array(
338 GuzzleHttp\RequestOptions::VERIFY => true,
339 GuzzleHttp\RequestOptions::CONNECT_TIMEOUT => 10,
340 GuzzleHttp\RequestOptions::HTTP_ERRORS => false
341 );
342 $defaultProfileRequest = new GuzzleHttp\Psr7\Request(
343 'POST',
344 $defaultProfileUrl,
345 $defaultHeaders,
346 $cmi5LearnerPreferences
347 );
348 $defaultLaunchDataRequest = new GuzzleHttp\Psr7\Request(
349 'PUT',
350 $defaultLaunchDataUrl,
351 $defaultHeaders,
352 $launchData
353 );
354 $defaultLaunchedStatementRequest = new GuzzleHttp\Psr7\Request(
355 'PUT',
356 $defaultLaunchedStatementUrl,
357 $defaultHeaders,
358 json_encode($launchedStatement)
359 );
360 if ($abandoned) {
361 $defaultAbandonedStatementRequest = new GuzzleHttp\Psr7\Request(
362 'PUT',
363 $defaultAbandonedStatementUrl,
364 $defaultHeaders,
365 json_encode($abandonedStatement)
366 );
367 }
368 if ($satisfied) {
369 $defaultSatisfiedStatementRequest = new GuzzleHttp\Psr7\Request(
370 'PUT',
371 $defaultSatisfiedStatementUrl,
372 $defaultHeaders,
373 json_encode($satisfiedStatement)
374 );
375 }
376 $promises = array();
377 $promises['defaultProfile'] = $client->sendAsync($defaultProfileRequest, $req_opts);
378 $promises['defaultLaunchData'] = $client->sendAsync($defaultLaunchDataRequest, $req_opts);
379 $promises['defaultLaunchedStatement'] = $client->sendAsync($defaultLaunchedStatementRequest, $req_opts);
380 if ($abandoned) {
381 $promises['defaultAbandonedStatement'] = $client->sendAsync($defaultAbandonedStatementRequest, $req_opts);
382 }
383 if ($satisfied) {
384 $promises['defaultSatisfiedStatement'] = $client->sendAsync($defaultSatisfiedStatementRequest, $req_opts);
385 }
386 try
387 {
388 $responses = GuzzleHttp\Promise\Utils::settle($promises)->wait();
389 $body = '';
390 foreach ($responses as $response) {
392 }
393 }
394 catch(Exception $e)
395 {
396 $this->log()->error('error:' . $e->getMessage());
397 }
398 return array('cmi5_session' => $cmi5_session, 'token' => $token);
399 }
const IL_CAL_UNIX
static buildQuery(array $params, $encoding=PHP_QUERY_RFC3986)
static checkResponse($response, &$body, $allowedStatus=[200, 204])
static dateIntervalToISO860Duration(\DateInterval $d)
static generateRegistration(ilObjCmiXapi $obj, ilObjUser $user)
static guidv4($data=null)
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
$response
$lang
Definition: xapiexit.php:8
$DIC
Definition: xapitoken.php:46

References $client, $DIC, Vendor\Package\$e, $lang, $response, $token, ilCmiXapiAbstractRequest\buildQuery(), ilCmiXapiAbstractRequest\checkResponse(), ilCmiXapiDateTime\dateIntervalToISO860Duration(), ilCmiXapiUser\generateRegistration(), getCmi5LearnerPreferences(), ilCmiXapiVerbList\getInstance(), ilCmiXapiAuthToken\getInstanceByToken(), getValidToken(), ilObjCmiXapi\guidv4(), IL_CAL_UNIX, log(), and ilLPObjSettings\LP_MODE_DEACTIVATED.

Referenced by launchCmd().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ executeCommand()

ilCmiXapiLaunchGUI::executeCommand ( )

Definition at line 42 of file class.ilCmiXapiLaunchGUI.php.

43 {
44 $this->launchCmd();
45 }

References launchCmd().

+ Here is the call graph for this function:

◆ getAuthTokenFetchLink()

ilCmiXapiLaunchGUI::getAuthTokenFetchLink ( )
protected

Definition at line 129 of file class.ilCmiXapiLaunchGUI.php.

130 {
131 $link = implode('/', [
132 ILIAS_HTTP_PATH, 'Modules', 'CmiXapi', 'xapitoken.php'
133 ]);
134
136 $link = iLUtil::appendUrlParameterString($link, "param={$param}");
137
138 return $link;
139 }

References $param, buildAuthTokenFetchParam(), and ILIAS_HTTP_PATH.

Referenced by getLaunchParameters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCmi5LearnerPreferences()

ilCmiXapiLaunchGUI::getCmi5LearnerPreferences ( )
protected

Definition at line 207 of file class.ilCmiXapiLaunchGUI.php.

208 {
209 global $DIC;
210 $language = $DIC->user()->getLanguage();
211 $audio = "on";
212 $prefs = [
213 "languagePreference" => "{$language}",
214 "audioPreference" => "{$audio}"
215 ];
216 return $prefs;
217 }

References $DIC.

Referenced by CMI5preLaunch().

+ Here is the caller graph for this function:

◆ getLaunchParameters()

ilCmiXapiLaunchGUI::getLaunchParameters (   $token)
protected

Definition at line 85 of file class.ilCmiXapiLaunchGUI.php.

86 {
87 global $DIC; /* @var \ILIAS\DI\Container $DIC */
88
89 $params = [];
90
91 if ($this->object->isBypassProxyEnabled()) {
92 $params['endpoint'] = urlencode(rtrim($this->object->getLrsType()->getLrsEndpoint(), '/') . '/');
93 } else {
94 $params['endpoint'] = urlencode(rtrim(ILIAS_HTTP_PATH . '/' . self::XAPI_PROXY_ENDPOINT, '/') . '/');
95 }
96
97 if ($this->object->isAuthFetchUrlEnabled()) {
98 $params['fetch'] = urlencode($this->getAuthTokenFetchLink());
99 } else {
100 if ($this->object->isBypassProxyEnabled()) {
101 $params['auth'] = urlencode($this->object->getLrsType()->getBasicAuth());
102 } else {
103 $params['auth'] = urlencode('Basic ' . base64_encode(
104 CLIENT_ID . ':' . $token
105 ));
106 }
107 }
108
109 $params['activity_id'] = urlencode($this->object->getActivityId());
110 $params['activityId'] = urlencode($this->object->getActivityId());
111 $params['actor'] = urlencode(json_encode($this->object->getStatementActor($this->cmixUser)));
112 if ($this->object->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5)
113 {
114 $registration = $this->cmixUser->getRegistration();
115 // for old CMI5 Content after switch commit but before cmi5 bugfix
116 if ($registration == '')
117 {
118 $registration = ilCmiXapiUser::generateRegistration($this->object, $DIC->user());
119 }
120 $params['registration'] = $registration;
121 }
122 else
123 {
124 $params['registration'] = urlencode(ilCmiXapiUser::generateRegistration($this->object, $DIC->user()));
125 }
126 return $params;
127 }

References $DIC, $token, ilObjCmiXapi\CONT_TYPE_CMI5, ilCmiXapiUser\generateRegistration(), getAuthTokenFetchLink(), and ILIAS_HTTP_PATH.

Referenced by buildLaunchLink().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getValidToken()

ilCmiXapiLaunchGUI::getValidToken ( )
protected

Definition at line 166 of file class.ilCmiXapiLaunchGUI.php.

167 {
168 global $DIC; /* @var \ILIAS\DI\Container $DIC */
169
171 $DIC->user()->getId(),
172 $this->object->getRefId(),
173 $this->object->getId(),
174 $this->object->getLrsType()->getTypeId()
175 );
176 return $token;
177 }
static fillToken($usrId, $refId, $objId, $lrsTypeId=0)

References $DIC, $token, and ilCmiXapiAuthToken\fillToken().

Referenced by CMI5preLaunch(), and launchCmd().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initCmixUser()

ilCmiXapiLaunchGUI::initCmixUser ( )
protected

Definition at line 179 of file class.ilCmiXapiLaunchGUI.php.

180 {
181 global $DIC; /* @var \ILIAS\DI\Container $DIC */
182
183 $doLpUpdate = false;
184
185 // if (!ilCmiXapiUser::exists($this->object->getId(), $DIC->user()->getId())) {
186 // $doLpUpdate = true;
187 // }
188
189 $this->cmixUser = new ilCmiXapiUser($this->object->getId(), $DIC->user()->getId(), $this->object->getPrivacyIdent());
190 $user_ident = $this->cmixUser->getUsrIdent();
191 if ($user_ident == '' || $user_ident == null) {
192 $user_ident = ilCmiXapiUser::getIdent($this->object->getPrivacyIdent(), $DIC->user());
193 $this->cmixUser->setUsrIdent($user_ident);
194
195 if ($this->object->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5)
196 {
197 $this->cmixUser->setRegistration(ilCmiXapiUser::generateCMI5Registration($this->object->getId(), $DIC->user()->getId()));
198 }
199 $this->cmixUser->save();
200 ilLPStatusWrapper::_updateStatus($this->object->getId(), $DIC->user()->getId());
201 }
202 // if ($doLpUpdate) {
203 // ilLPStatusWrapper::_updateStatus($this->object->getId(), $DIC->user()->getId());
204 // }
205 }
static getIdent($userIdentMode, ilObjUser $user)
static generateCMI5Registration($objId, $usrId)
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.

References $DIC, ilLPStatusWrapper\_updateStatus(), ilObjCmiXapi\CONT_TYPE_CMI5, ilCmiXapiUser\generateCMI5Registration(), and ilCmiXapiUser\getIdent().

Referenced by launchCmd().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ launchCmd()

ilCmiXapiLaunchGUI::launchCmd ( )
protected

Definition at line 47 of file class.ilCmiXapiLaunchGUI.php.

48 {
49 global $DIC; /* @var \ILIAS\DI\Container $DIC */
50
51 $this->initCmixUser();
52 $token = $this->getValidToken();
53 if ($this->object->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5) {
54 $ret = $this->CMI5preLaunch($token);
55 $token = $ret['token'];
56 }
57 $launchLink = $this->buildLaunchLink($token);
58 $DIC->ctrl()->redirectToURL($launchLink);
59 }
CMI5preLaunch($token)
Prelaunch post cmi5LearnerPreference (agent profile) post LMS.LaunchData.
$ret
Definition: parser.php:6

References $DIC, $ret, $token, buildLaunchLink(), CMI5preLaunch(), ilObjCmiXapi\CONT_TYPE_CMI5, getValidToken(), and initCmixUser().

Referenced by executeCommand().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log()

ilCmiXapiLaunchGUI::log ( )
private

Definition at line 401 of file class.ilCmiXapiLaunchGUI.php.

401 {
402 global $log;
403 if ($this->plugin) {
404 return $log;
405 }
406 else {
407 return \ilLoggerFactory::getLogger('cmix');
408 }
409 }
$log
Definition: result.php:15

References $log.

Referenced by CMI5preLaunch().

+ Here is the caller graph for this function:

Field Documentation

◆ $cmixUser

ilCmiXapiLaunchGUI::$cmixUser
protected

Definition at line 27 of file class.ilCmiXapiLaunchGUI.php.

◆ $object

ilCmiXapiLaunchGUI::$object
protected

Definition at line 22 of file class.ilCmiXapiLaunchGUI.php.

Referenced by __construct().

◆ $plugin

ilCmiXapiLaunchGUI::$plugin = false
protected

Definition at line 32 of file class.ilCmiXapiLaunchGUI.php.

◆ XAPI_PROXY_ENDPOINT

const ilCmiXapiLaunchGUI::XAPI_PROXY_ENDPOINT = 'Modules/CmiXapi/xapiproxy.php'

Definition at line 17 of file class.ilCmiXapiLaunchGUI.php.


The documentation for this class was generated from the following file: