3declare(strict_types=1);
155 public function __construct(
int $a_id = 0,
bool $a_reference =
true)
158 $this->database =
$DIC->database();
160 $this->lrsTypeId = 0;
165 $this->activityId =
'';
167 $this->publisherId =
'';
169 $this->instructions =
'';
171 $this->launchUrl =
'';
172 $this->launchParameters =
'';
174 $this->entitlementKey =
'';
176 $this->authFetchUrlEnabled =
false;
181 $this->switchToReviewEnabled =
true;
184 $this->keepLpStatusEnabled =
true;
188 $this->userPrivacyComment =
'';
190 $this->currentCmixUser =
null;
192 $this->statementsReportEnabled =
false;
194 $this->xmlManifest =
'';
197 $this->bypassProxyEnabled =
false;
205 return new self($a_id, $a_reference);
210 $this->type =
"cmix";
355 return $olp->getCurrentMode();
417 return ucfirst($this->launchMode);
452 return $this->masteryScore * 100;
457 $this->masteryScore = $masteryScorePercent / 100;
686 protected function load(): void
688 $query =
"SELECT * FROM " . self::DB_TABLE_NAME .
" WHERE obj_id = %s";
691 while ($row = $this->database->fetchAssoc(
$res)) {
692 if ($row[
'lrs_type_id']) {
706 $this->
setMoveOn((
string) $row[
'moveon']);
766 $DIC->database()->replace(self::DB_TABLE_NAME, [
767 'obj_id' => [
'integer', $this->
getId()]
777 'moveon' => [
'text', $this->
getMoveOn()],
790 'version' => [
'integer', $this->
getVersion()],
800 'achieved' => [
'integer', (
int) $this->
getAchieved()],
801 'answered' => [
'integer', (
int) $this->
getAnswered()],
802 'completed' => [
'integer', (
int) $this->
getCompleted()],
803 'failed' => [
'integer', (
int) $this->
getFailed()],
805 'passed' => [
'integer', (
int) $this->
getPassed()],
807 'satisfied' => [
'integer', (
int) $this->
getSatisfied()],
809 'hide_data' => [
'integer', (
int) $this->
getHideData()],
810 'c_timestamp' => [
'integer', (
int) $this->
getTimestamp()],
811 'duration' => [
'integer', (
int) $this->
getDuration()],
822 switch ($activation[
"timing_type"]) {
825 if (!is_null($activation[
"timing_start"])) {
826 $activation[
"timing_start"] = (
int) $activation[
"timing_start"];
829 if (!is_null($activation[
"timing_end"])) {
830 $activation[
"timing_end"] = (
int) $activation[
"timing_end"];
858 $item->update($this->ref_id);
870 SET privacy_ident = %s,
885 no_substatements = %s
886 WHERE lrs_type_id = %s
889 $DIC->database()->manipulateF(
938 SET bypass_proxy = %s
939 WHERE lrs_type_id = %s
942 $DIC->database()->manipulateF(
944 [
'integer',
'integer'],
957 SELECT DISTINCT s.obj_id FROM " . self::DB_TABLE_NAME .
" s
958 INNER JOIN " . self::DB_USERS_TABLE_NAME .
" u ON u.obj_id = s.obj_id
959 WHERE bypass_proxy = %s
962 $res =
$DIC->database()->queryF(
$query, array(
'integer'), array(1));
966 while ($row =
$DIC->database()->fetchAssoc(
$res)) {
967 $objects[] = (
int) $row[
'obj_id'];
1003 $this->_highscore_enabled = $a_enabled;
1020 $this->_highscore_achieved_ts = $a_achieved_ts;
1037 $this->_highscore_percentage = $a_percentage;
1054 $this->_highscore_wtime = $a_wtime;
1072 $this->_highscore_own_table = $a_own_table;
1089 $this->_highscore_top_table = $a_top_table;
1108 $this->_highscore_top_num = $a_top_num;
1119 $retval = $a_retval;
1120 if ($this->_highscore_top_num != 0) {
1175 'obj_id' => $this->
getId(),
1242 $new_obj->setMoveOn($this->
getMoveOn());
1268 $new_obj->setFailed($this->
getFailed());
1270 $new_obj->setPassed($this->
getPassed());
1282 $dirUtil->ensureCreatedObjectDirectory();
1293 $query =
"DELETE FROM " . self::DB_TABLE_NAME .
" WHERE obj_id = " . $this->database->quote($this->
getId(),
'integer');
1294 $this->database->manipulate(
$query);
1300 if (is_dir($thisDir)) {
1308 $query =
"DELETE FROM " . self::DB_RESULTS_TABLE_NAME .
1309 " WHERE obj_id = " . $this->database->quote($this->
getId(),
'integer');
1310 $this->database->manipulate(
$query);
1339 $data ??= random_bytes(16);
1340 assert(strlen(
$data) == 16);
1348 return vsprintf(
'%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(
$data), 4));
1354 if (
null === $this->currentCmixUser) {
1355 $this->currentCmixUser =
new ilCmiXapiUser($this->
getId(), $DIC->user()->getId(), $this->getPrivacyIdent());
1365 if (
null === $cmixUser) {
1378 if (
null === $cmixUser) {
1383 if (!$moveOn ||
$moveOn ==
'') {
1388 if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1389 if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1396 "launchMethod" =>
"OwnWindow",
1400 if ($lmsLaunchMethod ===
"ownWin") {
1401 if (is_int($launchedByRefId)) {
1412 $ctxTemplate[
'returnURL'] = $href;
1414 $ctxTemplate[
'returnURL'] = ILIAS_HTTP_PATH .
"/Modules/CmiXapi/xapiexit.php?lang={$lang}";
1423 $ctxTemplate[
'entitlementKey'] = array(
"courseStructure" => $this->
getEntitlementKey());
1425 return $ctxTemplate;
1433 if (
null === $cmixUser) {
1438 if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1439 if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1444 $extensions[
'https://w3id.org/xapi/cmi5/context/extensions/launchmode'] =
$launchMode;
1446 $extensions[
'https://w3id.org/xapi/cmi5/context/extensions/moveon'] = $this->
getLMSMoveOn();
1449 $extensions[
'https://w3id.org/xapi/cmi5/context/extensions/launchparameters'] = $this->
getLaunchParameters();
1452 $extensions[
'https://w3id.org/xapi/cmi5/context/extensions/masteryscore'] = $this->
getMasteryScore();
1456 "extensions" => $extensions
1467 if (
null === $cmixUser) {
1474 $registration = $cmixUser->getRegistration();
1486 'extensions' => $extensions,
1487 'registration' => $registration,
1488 'contextActivities' => $contextActivities
1501 if (
null === $cmixUser) {
1507 $this->
log()->error(
'error: no name in cmixuser');
1508 $name =
'UNDEFINED';
1510 $homePage = ($this->anonymousHomePage ==
true) ? self::ANONYMOUS_HOMEPAGE : self::iliasUrl();
1513 'objectType' =>
'Agent',
1515 'homePage' => $homePage,
1516 'name' => $cmixUser->getUsrIdent()
1520 $actor[
'name'] =
$name;
1524 'objectType' =>
'Agent',
1525 'mbox' =>
'mailto:' . $cmixUser->getUsrIdent()
1528 $actor[
'name'] =
$name;
1541 if (
null === $cmixUser) {
1545 'https://w3id.org/xapi/cmi5/context/extensions/sessionid' => $this->
getSessionId($cmixUser),
1546 'https://ilias.de/cmi5/activityid' => $this->
getActivityId()
1564 "objectType" =>
"Activity",
1565 "id" =>
"{$publisherId}",
1582 "id" =>
"https://w3id.org/xapi/cmi5/context/categories/cmi5",
1583 "objectType" =>
"Activity"
1618 if (
null === $cmixUser) {
1623 if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1624 if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1629 $statement = $this->
getStatement(
'launched', $cmixUser);
1630 $statement[
'context'][
'extensions'][
'https://w3id.org/xapi/cmi5/context/extensions/launchmode'] =
$launchMode;
1632 $statement[
'context'][
'extensions'][
'https://w3id.org/xapi/cmi5/context/extensions/moveon'] = $this->
getLMSMoveOn();
1635 $statement[
'context'][
'extensions'][
'https://w3id.org/xapi/cmi5/context/extensions/launchparameters'] = $this->
getLaunchParameters();
1638 $statement[
'context'][
'extensions'][
'https://w3id.org/xapi/cmi5/context/extensions/masteryscore'] = $this->
getMasteryScore();
1649 if (
null === $cmixUser) {
1652 $statement = $this->
getStatement(
'abandoned', $cmixUser);
1654 $statement[
'context'][
'extensions'][
'https://w3id.org/xapi/cmi5/context/extensions/sessionid'] = $sessionId;
1655 $statement[
'result'] = array(
1667 if (
null === $cmixUser) {
1670 $statement = $this->
getStatement(
'satisfied', $cmixUser);
1673 $type =
"https://w3id.org/xapi/cmi5/activitytype/course";
1674 $statement[
'object'][
'definition'][
'type'] =
$type;
1675 $statement[
'context'][
'contextActivities'][
'grouping'][0][
'definition'][
'type'] =
$type;
1694 'X-Experience-API-Version' =>
'1.0.3',
1695 'Authorization' => $defaultBasicAuth,
1696 'Cache-Control' =>
'no-cache, no-store, must-revalidate'
1707 $defaultLastStatementUrl = $defaultLrs .
"?pipeline=" . urlencode($pipeline);
1708 $client =
new GuzzleHttp\Client();
1710 GuzzleHttp\RequestOptions::VERIFY =>
true,
1711 GuzzleHttp\RequestOptions::CONNECT_TIMEOUT => 10,
1712 GuzzleHttp\RequestOptions::HTTP_ERRORS =>
false
1714 $defaultLastStatementRequest =
new GuzzleHttp\Psr7\Request(
1716 $defaultLastStatementUrl,
1719 $promises = array();
1720 $promises[
'defaultLastStatement'] =
$client->sendAsync($defaultLastStatementRequest, $req_opts);
1722 $responses = GuzzleHttp\Promise\Utils::settle($promises)->wait();
1725 return json_decode($body, (
bool) JSON_OBJECT_AS_ARRAY);
1726 }
catch (Exception
$e) {
1727 $this->
log()->error(
'error:' . $e->getMessage());
1738 $pipeline = array();
1742 $match[
'statement.object.objectType'] =
'Activity';
1743 $match[
'statement.actor.objectType'] =
'Agent';
1749 $activityId[
'statement.context.extensions.https://ilias&46;de/cmi5/activityid'] = $this->
getActivityId();
1754 $activityId[
'$or'] = [];
1755 $activityId[
'$or'][] = [
'statement.object.id' => $activityQuery];
1756 $activityId[
'$or'][] = [
'statement.context.contextActivities.parent.id' => $activityQuery];
1759 $sessionId = array();
1760 $sessionId[
'statement.context.extensions.https://w3id&46;org/xapi/cmi5/context/extensions/sessionid'] = $sess;
1761 $match[
'$and'] = array();
1763 $match[
'$and'][] = $sessionId;
1764 $sort = array(
'statement.timestamp' => -1);
1765 $project = array(
'statement.timestamp' => 1,
'statement.verb.id' => 1);
1766 $pipeline[] = array(
'$match' => $match);
1767 $pipeline[] = array(
'$sort' => $sort);
1768 $pipeline[] = array(
'$limit' => 1);
1769 $pipeline[] = array(
'$project' => $project);
1777 $regex =
'/^(https?:\/\/[^\/]+).*/';
1778 preg_match($regex, (
string)
$DIC->http()->request()->getUri(), $request_parts);
1779 return $request_parts[1];
1788 return \ilLoggerFactory::getLogger(
'cmix');
static checkResponse(array $response, &$body, array $allowedStatus=[200, 204])
static getCmi5SessionByUsrIdAndObjIdAndRefId(int $usrId, int $objId, ?int $refId=null)
const MOVEON_COMPLETED_OR_PASSED
const MOVEON_NOT_APPLICABLE
getLrsEndpointStatementsAggregationLink()
static getName(int $userNameMode, ilObjUser $user)
static getWebspaceDir(string $mode="filesystem")
get webspace directory
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static rCopy(string $a_sdir, string $a_tdir, bool $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
static _removeEntriesForObject(int $a_obj_id)
remove all history entries for an object
const LP_MODE_CMIX_COMPLETED_OR_PASSED
const LP_MODE_CMIX_COMPL_WITH_FAILED
const LP_MODE_CMIX_PASSED
const LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED
const LP_MODE_DEACTIVATED
const LP_MODE_CMIX_COMPLETED
const LP_MODE_CMIX_PASSED_WITH_FAILED
static _getStaticLink(?int $a_ref_id, string $a_type='', bool $a_fallback_goto=true, string $append="")
Get static link.
Component logger with individual log levels by component id.
getStatement(string $verb, ?ilCmiXapiUser $cmixUser=null)
blueprint statement
setActivationEndingTime(?int $activationEndingTime=null)
setDuration(bool $duration)
setBypassProxyEnabled(bool $bypassProxyEnabled)
setHighscoreMode(int $mode)
bool $_highscore_top_table
setOnlyMoveon(bool $only_moveon)
bool $activationVisibility
getHighscoreWTime()
Gets if the column with the workingtime should be shown.
setHideData(bool $hide_data)
const DB_RESULTS_TABLE_NAME
bool $_highscore_own_table
getHighscoreTopNum(?int $a_retval=10)
Gets the number of entries which are to be shown in the top-rankings table.
getActivationStartingTime()
const PRIVACY_NAME_FULLNAME
setPrivacyName(int $userName)
setContentType(string $contentType)
getActivationEndingTime()
const LAUNCH_METHOD_NEW_WIN
getLPMode()
only for internal LMS usage
const PRIVACY_NAME_FIRSTNAME
setNoSubstatements(bool $no_substatements)
ilCmiXapiUser $currentCmixUser
getSessionId(?ilCmiXapiUser $cmixUser=null)
getActivationVisibility()
static getObjectsHavingBypassProxyEnabledAndRegisteredUsers()
setActivationVisibility(bool $activationVisibility)
setHighscoreWTime(bool $a_wtime)
Sets if the workingtime of the scores should be shown.
const PRIVACY_IDENT_IL_UUID_USER_ID
setLaunchMethod(string $launchMethod)
getLaunchData(?ilCmiXapiUser $cmixUser=null, string $lang='en', ?int $launchedByRefId=null)
LMS.LaunchData.
setPublisherId(string $publisherId)
const HIGHSCORE_SHOW_ALL_TABLES
setHighscoreTopNum(int $a_top_num)
Sets the number of entries which are to be shown in the top-rankings table.
getHighscorePercentage()
Gets if the percentage column should be shown.
setSwitchToReviewEnabled(bool $switchToReviewEnabled)
setLaunchParameters(string $launchParameters)
getSwitchToReviewEnabled()
const HIGHSCORE_SHOW_TOP_TABLE
setSatisfied(bool $satisfied)
setTimestamp(bool $timestamp)
getHighscoreAchievedTS()
Returns if date and time of the scores achievement should be displayed.
setTerminated(bool $terminated)
const PRIVACY_IDENT_IL_UUID_RANDOM
const DB_USERS_TABLE_NAME
loadRepositoryActivationSettings()
doCloneObject(ilObject2 $new_obj, int $a_target_id, ?int $a_copy_id=null)
saveRepositoryActivationSettings()
bool $activationLimited
repository object activation settings (handled by ilObject)
setAnswered(bool $answered)
int $activationStartingTime
getLaunchedContextTemplate(?ilCmiXapiUser $cmixUser=null)
getHighscoreTopTable()
Gets, if the top-rankings table should be shown.
setSourceType(string $sourceType)
setStatementsReportEnabled(bool $statementsReportEnabled)
bool $_highscore_enabled
HIGHSCORE.
setHighscoreOwnTable(bool $a_own_table)
Sets if the table with the own ranking should be shown.
getStatementExtensions(?ilCmiXapiUser $cmixUser=null)
Minimal extensions.
getSatisfiedStatement(?ilCmiXapiUser $cmixUser=null)
static guidv4(?string $data=null)
bool $keepLpStatusEnabled
setLrsTypeId(int $lrsTypeId)
const PRIVACY_IDENT_IL_UUID_LOGIN
setAchieved(bool $achieved)
getLaunchedStatement(?ilCmiXapiUser $cmixUser=null)
setMoveOn(string $moveOn)
Attention: this is the original moveOn from course import should only be set on import!
setLaunchMode(string $launchMode)
getMoveOn()
Attention: this is the original imported moveOn for using in LaunchData and LaunchStatement use getLM...
const PRIVACY_IDENT_REAL_EMAIL
bool $statementsReportEnabled
setMasteryScorePercent(float $masteryScorePercent)
const PRIVACY_IDENT_IL_UUID_SHA256
setProgressed(bool $progressed)
string $userPrivacyComment
getLMSMoveOn()
for CMI5 statements | state moveOn values
setInstructions(string $instructions)
setXmlManifest(string $xmlManifest)
const PRIVACY_IDENT_IL_UUID_EXT_ACCOUNT
setHighscoreTopTable(bool $a_top_table)
Sets if the top-rankings table should be shown.
ilCmiXapiLrsType $lrsType
bool $_highscore_percentage
bool $_highscore_achieved_ts
const PRIVACY_NAME_LASTNAME
getStatementContextActivities()
Minimal statementActivities.
isStatementsReportEnabled()
setInitialized(bool $initialized)
getHighscoreOwnTable()
Gets if the own rankings table should be shown.
bool $authFetchUrlEnabled
getLastStatement(string $sess)
get latest statement from session
setCompleted(bool $completed)
__construct(int $a_id=0, bool $a_reference=true)
ilObjCmiXapi constructor.
const HIGHSCORE_SHOW_OWN_TABLE
const PRIVACY_IDENT_IL_UUID_SHA256URL
setMasteryScore(float $masteryScore)
setHighscoreAchievedTS(bool $a_achieved_ts)
Sets if the date and time of the scores achievement should be displayed.
bool $switchToReviewEnabled
setActivationLimited(bool $activationLimited)
getHighscoreEnabled()
Gets the setting which determines if the highscore feature is enabled.
setActivationStartingTime(?int $activationStartingTime=null)
setLaunchUrl(string $launchUrl)
setLrsType(\ilCmiXapiLrsType $lrsType)
setUserPrivacyComment(string $userPrivacyComment)
setEntitlementKey(string $entitlementKey)
const LAUNCH_METHOD_IFRAME
setHighscoreEnabled(bool $a_enabled)
Sets if the highscore feature should be enabled.
static updatePrivacySettingsFromLrsType(ilCmiXapiLrsType $lrsType)
static updateByPassProxyFromLrsType(ilCmiXapiLrsType $lrsType)
isSwitchToReviewEnabled()
setKeepLpStatusEnabled(bool $keepLpStatusEnabled)
setAuthFetchUrlEnabled(bool $authFetchUrlEnabled)
setHighscorePercentage(bool $a_percentage)
Sets if the percentages of the scores pass should be shown.
static getInstance(int $a_id=0, bool $a_reference=true)
int $activationEndingTime
getAbandonedStatement(?string $sessionId, ?string $duration, ?ilCmiXapiUser $cmixUser=null)
setActivityId(string $activityId)
getLastStatementPipline(string $sess)
getStatementActor(?ilCmiXapiUser $cmixUser=null)
statement actor
setPrivacyIdent(int $userIdent)
const LAUNCH_METHOD_OWN_WIN
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
cloneMetaData(ilObject $target_obj)
Copy meta data.
Class ilObjectActivation.
const TIMINGS_DEACTIVATED
static getItem(int $ref_id)
static getInstance(int $obj_id)
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc