ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
ilCmiXapiLaunchGUI Class Reference
+ Collaboration diagram for ilCmiXapiLaunchGUI:

Public Member Functions

 __construct (ilObjCmiXapi $object)
 
 executeCommand ()
 

Data Fields

const XAPI_PROXY_ENDPOINT = 'xapiproxy.php'
 

Protected Member Functions

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

Protected Attributes

ilObjCmiXapi $object
 
ilCmiXapiUser $cmixUser
 
bool $plugin = false
 

Private Member Functions

 log ()
 

Private Attributes

ilObjUser $user
 
ilCtrlInterface $ctrl
 

Detailed Description

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

Constructor & Destructor Documentation

◆ __construct()

ilCmiXapiLaunchGUI::__construct ( ilObjCmiXapi  $object)

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

45 {
46 $this->object = $object;
47 }

References $object.

Member Function Documentation

◆ buildAuthTokenFetchParam()

ilCmiXapiLaunchGUI::buildAuthTokenFetchParam ( )
protected
Exceptions
ilCmiXapiException

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

152 : string
153 {
154 $params = [
155 session_name() => session_id(),
156 'obj_id' => $this->object->getId(),
157 'ref_id' => $this->object->getRefId(),
158 'ilClientId' => CLIENT_ID
159 ];
160
161 $encryptionKey = ilCmiXapiAuthToken::getWacSalt();
162 return urlencode(base64_encode(openssl_encrypt(
163 json_encode($params),
165 $encryptionKey,
166 0,
168 )));
169 }
const CLIENT_ID
Definition: constants.php:41
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31

References $params, CLIENT_ID, 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 ( string  $token)
protected

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

69 : string
70 {
71 $launchLink = "";
72
73 if ($this->object->getSourceType() == ilObjCmiXapi::SRC_TYPE_REMOTE) {
74 $launchLink = $this->object->getLaunchUrl();
75 } elseif ($this->object->getSourceType() == ilObjCmiXapi::SRC_TYPE_LOCAL) {
76 if (preg_match("/^(https?:\/\/)/", $this->object->getLaunchUrl()) == 1) {
77 $launchLink = $this->object->getLaunchUrl();
78 } else {
79 $launchLink = implode('/', [
80 ILIAS_HTTP_PATH,
83 ]);
84
85 $launchLink .= DIRECTORY_SEPARATOR . $this->object->getLaunchUrl();
86 }
87 }
88
89 foreach ($this->getLaunchParameters($token) as $paramName => $paramValue) {
90 $launchLink = ilUtil::appendUrlParameterString($launchLink, "{$paramName}={$paramValue}");
91 }
92
93 return $launchLink;
94 }
getLaunchParameters(string $token)
static getWebspaceDir(string $mode="filesystem")
get webspace directory
static appendUrlParameterString(string $a_url, string $a_par, bool $xml_style=false)
$token
Definition: xapitoken.php:67

References ilUtil\appendUrlParameterString(), getLaunchParameters(), ilFileUtils\getWebspaceDir(), ILIAS\Repository\object(), 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 ( string  $token)
protected

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

Returns
array<string, mixed>
Exceptions
ilCmiXapiException
ilDateTimeException

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

221 : array
222 {
223 global $DIC;
224 $DIC->language()->loadLanguageModule("cmix");
225
226 $duration = '';
227 $lrsType = $this->object->getLrsType();
228 $defaultLrs = $lrsType->getLrsEndpoint();
229 $defaultBasicAuth = $lrsType->getBasicAuth();
230
231 $defaultHeaders = [
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'
236 ];
237
238 $registration = $this->cmixUser->getRegistration();
239 if ($registration == '') {
240 $registration = ilCmiXapiUser::generateRegistration($this->object, $this->user);
241 }
242
243 $activityId = $this->object->getActivityId();
244
245 // Profile URL
246 $profileParams = [
247 'agent' => json_encode($this->object->getStatementActor($this->cmixUser)),
248 'profileId' => 'cmi5LearnerPreferences'
249 ];
250 $defaultProfileUrl = $defaultLrs . "/agents/profile?" . ilCmiXapiAbstractRequest::buildQuery($profileParams);
251
252 // LaunchData URL
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'
259 ];
260 $defaultLaunchDataUrl = $defaultLrs . "/activities/state?" . ilCmiXapiAbstractRequest::buildQuery($launchDataParams);
261
262 $cmi5LearnerPreferencesObj = $this->getCmi5LearnerPreferences();
263 $cmi5LearnerPreferences = json_encode($cmi5LearnerPreferencesObj);
264 $lang = $cmi5LearnerPreferencesObj['languagePreference'];
265 $cmi5_session = ilObjCmiXapi::guidv4();
266
268 $oldSession = $tokenObject->getCmi5Session();
269 $oldSessionLaunchedTimestamp = '';
270 $abandoned = false;
271
272 if ($oldSession != null && !empty($oldSession)) {
273 $oldSessionData = json_decode($tokenObject->getCmi5SessionData());
274 $oldSessionLaunchedTimestamp = $oldSessionData->launchedTimestamp;
275 $tokenObject->delete();
276 $token = $this->getValidToken();
278 $lastStatement = $this->object->getLastStatement($oldSession);
279 if (isset($lastStatement[0]['statement']['verb']['id']) &&
280 $lastStatement[0]['statement']['verb']['id'] != ilCmiXapiVerbList::getInstance()->getVerbUri('terminated')) {
281 $abandoned = true;
282 $start = new DateTime($oldSessionLaunchedTimestamp);
283 $end = new DateTime($lastStatement[0]['statement']['timestamp']);
284 $diff = $end->diff($start);
286 }
287 }
288
289 $satisfied = false;
290 $lpMode = $this->object->getLPMode();
291 if ($lpMode === ilLPObjSettings::LP_MODE_DEACTIVATED) {
292 $satisfied = true;
293 }
294
295 $tokenObject->setCmi5Session($cmi5_session);
296 $now = new ilCmiXapiDateTime(time(), IL_CAL_UNIX);
297 $sessionData = [
298 'cmi5LearnerPreferences' => $cmi5LearnerPreferencesObj,
299 'launchedTimestamp' => $now->toXapiTimestamp()
300 ];
301 $tokenObject->setCmi5SessionData(json_encode($sessionData));
302 $tokenObject->update();
303
304 $defaultStatementsUrl = $defaultLrs . "/statements";
305
306 // 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']);
310
311 $requests = [
312 ['url' => $defaultProfileUrl, 'method' => 'POST', 'body' => $cmi5LearnerPreferences],
313 ['url' => $defaultLaunchDataUrl, 'method' => 'PUT', 'body' => $launchData],
314 ['url' => $launchedStatementUrl, 'method' => 'PUT', 'body' => json_encode($launchedStatement)]
315 ];
316
317 if ($abandoned) {
318 $abandonedStatement = $this->object->getAbandonedStatement($oldSession, $duration, $this->cmixUser);
319 $requests[] = [
320 'url' => $defaultStatementsUrl . '?statementId=' . urlencode($abandonedStatement['id']),
321 'method' => 'PUT',
322 'body' => json_encode($abandonedStatement)
323 ];
324 }
325
326 if ($satisfied) {
327 $satisfiedStatement = $this->object->getSatisfiedStatement($this->cmixUser);
328 $requests[] = [
329 'url' => $defaultStatementsUrl . '?statementId=' . urlencode($satisfiedStatement['id']),
330 'method' => 'PUT',
331 'body' => json_encode($satisfiedStatement)
332 ];
333 }
334
335 // --- Native cURL Multi ---
336 $mh = curl_multi_init();
337 $chs = [];
338
339 foreach ($requests as $req) {
340 $ch = curl_init();
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,
349 ]);
350 curl_multi_add_handle($mh, $ch);
351 $chs[] = $ch;
352 }
353
354 // Execute all
355 $running = 0;
356 do {
357 curl_multi_exec($mh, $running);
358 curl_multi_select($mh);
359 // usleep(10000); // 10ms Pause, schont CPU
360 } while ($running > 0);
361
362 // Collect responses
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");
368 }
369 curl_multi_remove_handle($mh, $ch);
370 curl_close($ch);
371 }
372
373 curl_multi_close($mh);
374
375 return [
376 'cmi5_session' => $cmi5_session,
377 'token' => $token
378 ];
379 }
$duration
const IL_CAL_UNIX
static buildQuery(array $params, $encoding=PHP_QUERY_RFC3986)
static getInstanceByToken(string $token)
static dateIntervalToISO860Duration(\DateInterval $d)
static generateRegistration(ilObjCmiXapi $obj, ilObjUser $user)
static guidv4(?string $data=null)
if(empty($ltiMessageHint)) $mh
Definition: ltiauth.php:64
catch(\Exception $e) $req
Definition: xapiproxy.php:78
global $DIC
Definition: shib_login.php:26

References $DIC, $duration, $mh, XapiProxy\$req, $token, ilCmiXapiAbstractRequest\buildQuery(), ilCmiXapiDateTime\dateIntervalToISO860Duration(), ilCmiXapiUser\generateRegistration(), getCmi5LearnerPreferences(), ilCmiXapiVerbList\getInstance(), ilCmiXapiAuthToken\getInstanceByToken(), getValidToken(), ilObjCmiXapi\guidv4(), IL_CAL_UNIX, log(), ilLPObjSettings\LP_MODE_DEACTIVATED, ILIAS\Repository\object(), and ILIAS\Repository\user().

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 49 of file class.ilCmiXapiLaunchGUI.php.

49 : void
50 {
51 global $DIC;
52 $this->user = $DIC->user();
53 $this->ctrl = $DIC->ctrl();
54 $this->launchCmd();
55 }

References $DIC, ILIAS\Repository\ctrl(), launchCmd(), and ILIAS\Repository\user().

+ Here is the call graph for this function:

◆ getAuthTokenFetchLink()

ilCmiXapiLaunchGUI::getAuthTokenFetchLink ( )
protected
Exceptions
ilCmiXapiException

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

140 : string
141 {
142 $link = ILIAS_HTTP_PATH . '/xapitoken.php';
143
145
146 return iLUtil::appendUrlParameterString($link, "param={$param}");
147 }
$param
Definition: xapitoken.php:44

References $param, and buildAuthTokenFetchParam().

Referenced by getLaunchParameters().

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

◆ getCmi5LearnerPreferences()

ilCmiXapiLaunchGUI::getCmi5LearnerPreferences ( )
protected
Returns
array<string, string>

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

203 : array
204 {
205 $language = $this->user->getLanguage();
206 $audio = "on";
207 return [
208 "languagePreference" => "{$language}",
209 "audioPreference" => "{$audio}"
210 ];
211 }

References ILIAS\Repository\user().

Referenced by CMI5preLaunch().

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

◆ getLaunchParameters()

ilCmiXapiLaunchGUI::getLaunchParameters ( string  $token)
protected
Returns
array<string, mixed>

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

99 : array
100 {
101 $params = [];
102
103 if ($this->object->isBypassProxyEnabled()) {
104 $params['endpoint'] = urlencode(rtrim($this->object->getLrsType()->getLrsEndpoint(), '/') . '/');
105 } else {
106 $params['endpoint'] = urlencode(rtrim(ILIAS_HTTP_PATH . '/' . self::XAPI_PROXY_ENDPOINT, '/') . '/');
107 }
108
109 if ($this->object->isAuthFetchUrlEnabled()) {
110 $params['fetch'] = urlencode($this->getAuthTokenFetchLink());
111 } else {
112 if ($this->object->isBypassProxyEnabled()) {
113 $params['auth'] = urlencode($this->object->getLrsType()->getBasicAuth());
114 } else {
115 $params['auth'] = urlencode('Basic ' . base64_encode(
116 CLIENT_ID . ':' . $token
117 ));
118 }
119 }
120
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)));
124 if ($this->object->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5) {
125 $registration = $this->cmixUser->getRegistration();
126 // for old CMI5 Content after switch commit but before cmi5 bugfix
127 if ($registration == '') {
128 $registration = ilCmiXapiUser::generateRegistration($this->object, $this->user);
129 }
130 $params['registration'] = $registration;
131 } else {
132 $params['registration'] = urlencode((string) ilCmiXapiUser::generateRegistration($this->object, $this->user));
133 }
134 return $params;
135 }

References $params, $token, CLIENT_ID, ilObjCmiXapi\CONT_TYPE_CMI5, ilCmiXapiUser\generateRegistration(), getAuthTokenFetchLink(), ILIAS\Repository\object(), and ILIAS\Repository\user().

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 171 of file class.ilCmiXapiLaunchGUI.php.

171 : string
172 {
174 $this->user->getId(),
175 $this->object->getRefId(),
176 $this->object->getId(),
177 $this->object->getLrsType()->getTypeId()
178 );
179 return $token;
180 }
static fillToken(int $usrId, int $refId, int $objId, int $lrsTypeId=0)

References $token, ilCmiXapiAuthToken\fillToken(), and ILIAS\Repository\user().

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 182 of file class.ilCmiXapiLaunchGUI.php.

182 : void
183 {
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) {
187 $user_ident = ilCmiXapiUser::getIdent($this->object->getPrivacyIdent(), $this->user);
188 $this->cmixUser->setUsrIdent($user_ident);
189
190 if ($this->object->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5) {
191 $this->cmixUser->setRegistration((string) ilCmiXapiUser::generateCMI5Registration($this->object->getId(), $this->user->getId()));
192 }
193 $this->cmixUser->save();
194 if (!ilObjUser::_isAnonymous($this->user->getId())) {
195 ilLPStatusWrapper::_updateStatus($this->object->getId(), $this->user->getId());
196 }
197 }
198 }
static getIdent(int $userIdentMode, ilObjUser $user)
static generateCMI5Registration(int $objId, int $usrId)
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
static _isAnonymous(int $usr_id)

References ilObjUser\_isAnonymous(), ilLPStatusWrapper\_updateStatus(), ilObjCmiXapi\CONT_TYPE_CMI5, ilCmiXapiUser\generateCMI5Registration(), ilCmiXapiUser\getIdent(), ILIAS\Repository\object(), and ILIAS\Repository\user().

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 57 of file class.ilCmiXapiLaunchGUI.php.

57 : void
58 {
59 $this->initCmixUser();
60 $token = $this->getValidToken();
61 if ($this->object->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5) {
62 $ret = $this->CMI5preLaunch($token);
63 $token = $ret['token'];
64 }
65 $launchLink = $this->buildLaunchLink($token);
66 $this->ctrl->redirectToURL($launchLink);
67 }
CMI5preLaunch(string $token)
Prelaunch post cmi5LearnerPreference (agent profile) post LMS.LaunchData.

References $token, buildLaunchLink(), CMI5preLaunch(), ilObjCmiXapi\CONT_TYPE_CMI5, ILIAS\Repository\ctrl(), getValidToken(), initCmixUser(), and ILIAS\Repository\object().

Referenced by executeCommand().

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

◆ log()

ilCmiXapiLaunchGUI::log ( )
private
Returns
ilLogger

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

384 : ilLogger
385 {
386 return \ilLoggerFactory::getLogger('cmix');
387 }
Component logger with individual log levels by component id.

Referenced by CMI5preLaunch().

+ Here is the caller graph for this function:

Field Documentation

◆ $cmixUser

ilCmiXapiUser ilCmiXapiLaunchGUI::$cmixUser
protected

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

◆ $ctrl

ilCtrlInterface ilCmiXapiLaunchGUI::$ctrl
private

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

◆ $object

ilObjCmiXapi ilCmiXapiLaunchGUI::$object
protected

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

Referenced by __construct().

◆ $plugin

bool ilCmiXapiLaunchGUI::$plugin = false
protected

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

◆ $user

ilObjUser ilCmiXapiLaunchGUI::$user
private

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

◆ XAPI_PROXY_ENDPOINT

const ilCmiXapiLaunchGUI::XAPI_PROXY_ENDPOINT = 'xapiproxy.php'

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


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