ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjCmiXapi.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2019 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 
15 class ilObjCmiXapi extends ilObject2
16 {
17  const PLUGIN = false;
18 
19  const DB_TABLE_NAME = 'cmix_settings';
20  const DB_USERS_TABLE_NAME = 'cmix_users';
21  const DB_RESULTS_TABLE_NAME = 'cmix_results';
22 
26  protected $activationLimited;
30 
34  protected $lrsTypeId;
35 
39  protected $lrsType;
40 
44  protected $contentType;
45  const CONT_TYPE_GENERIC = 'generic';
46  const CONT_TYPE_CMI5 = 'cmi5';
47 
51  protected $sourceType;
52  const SRC_TYPE_REMOTE = 'remoteSource';
53  const SRC_TYPE_LOCAL = 'localSource';
54  const SRC_TYPE_EXTERNAL = 'externalSource';
55 
59  protected $activityId;
60 
64  protected $publisherId;
65 
69  protected $instructions;
70 
74  protected $launchUrl;
75 
79  protected $launchParameters;
80 
84  protected $moveOn;
85 
89  protected $entitlementKey;
90 
95 
99  protected $anonymousHomePage = false;
100  const ANONYMOUS_HOMEPAGE = 'https://example.org';
101 
105  protected $launchMethod;
106  const LAUNCH_METHOD_OWN_WIN = 'ownWin';
107  const LAUNCH_METHOD_NEW_WIN = 'newWin';
108  const LAUNCH_METHOD_IFRAME = 'iframe';
109 
113  protected $launchMode;
114  const LAUNCH_MODE_NORMAL = 'Normal';
115  const LAUNCH_MODE_BROWSE = 'Browse';
116  const LAUNCH_MODE_REVIEW = 'Review';
117 
122 
126  const LMS_MASTERY_SCORE = 0.7;
127  protected $masteryScore;
128 
133 
137  protected $userIdent;
145 
149  protected $userName;
150  const PRIVACY_NAME_NONE = 0;
154 
155 
160 
165 
169  protected $xmlManifest;
170 
174  protected $version;
175 
180 
182  protected $only_moveon = false;
183 
185  protected $achieved = true;
186 
188  protected $answered = true;
189 
191  protected $completed = true;
192 
194  protected $failed = true;
195 
197  protected $initialized = true;
198 
200  protected $passed = true;
201 
203  protected $progressed = true;
204 
206  protected $satisfied = true;
207 
209  protected $terminated = true;
210 
212  protected $hide_data = false;
213 
215  protected $timestamp = false;
216 
218  protected $duration = true;
219 
221  protected $no_substatements = false;
222 
224  protected $currentCmixUser = null;
225 
231  public function __construct($a_id = 0, $a_reference = true)
232  {
233  $this->lrsTypeId = 0;
234  //$this->lrsType = $lrsType;
235 
236  $this->contentType = self::CONT_TYPE_GENERIC;
237  $this->sourceType = self::SRC_TYPE_REMOTE;
238 
239  $this->activityId = '';
240 
241  $this->publisherId = '';
242 
243  $this->instructions = '';
244 
245  $this->launchUrl = '';
246  $this->launchParameters = '';
247  $this->moveOn = '';
248  $this->entitlementKey = '';
249 
250  $this->authFetchUrlEnabled = 0;
251 
252  $this->launchMethod = self::LAUNCH_METHOD_NEW_WIN;
253  $this->launchMode = self::LAUNCH_MODE_NORMAL;
254 
255  $this->switchToReviewEnabled = 1;
256 
257  $this->masteryScore = self::LMS_MASTERY_SCORE;
258  $this->keepLpStatusEnabled = 1;
259 
260  $this->userIdent = self::PRIVACY_IDENT_IL_UUID_USER_ID;
261  $this->userName = self::PRIVACY_NAME_NONE;
262  $this->userPrivacyComment = '';
263 
264  $this->currentCmixUser = null;
265 
266  $this->statementsReportEnabled = 0;
267 
268  $this->xmlManifest = '';
269  $this->version = 0;
270 
271  $this->bypassProxyEnabled = false;
272 
273  parent::__construct($a_id, $a_reference);
274  }
275 
276 
277  public static function getInstance($a_id = 0, $a_reference = true)
278  {
279  return new self($a_id, $a_reference);
280  }
281 
282  protected function initType() : void
283  {
284  $this->type = "cmix";
285  }
286 
290  public function getLrsTypeId()
291  {
292  return $this->lrsTypeId;
293  }
294 
298  public function setLrsTypeId($lrsTypeId)
299  {
300  $this->lrsTypeId = $lrsTypeId;
301  }
302 
306  public function getLrsType()
307  {
308  return $this->lrsType;
309  }
310 
314  public function setLrsType($lrsType)
315  {
316  $this->lrsType = $lrsType;
317  }
318 
319  public function initLrsType()
320  {
321  $this->setLrsType(new ilCmiXapiLrsType($this->getLrsTypeId()));
322  }
323 
327  public function getContentType()
328  {
329  return $this->contentType;
330  }
331 
335  public function setContentType($contentType)
336  {
337  //bug before 21-07-24
338  if ($contentType == "learning") {
339  $contentType = self::CONT_TYPE_GENERIC;
340  }
341  $this->contentType = $contentType;
342  }
343 
347  public function isMixedContentType() : bool
348  {
349  // after 21-07-24 and before cmi5 refactoring
350  // launched before cmi5 refactoring ident in: statement.actor.mbox
351  // launched after cmi5 refactoring ident in: statement.actor.account.name
352  return (($this->getContentType() == self::CONT_TYPE_CMI5) && empty($this->getPublisherId()));
353  }
354 
358  public function getSourceType()
359  {
360  return $this->sourceType;
361  }
362 
366  public function isSourceTypeRemote()
367  {
368  return $this->sourceType == self::SRC_TYPE_REMOTE;
369  }
370 
374  public function isSourceTypeExternal()
375  {
376  return $this->sourceType == self::SRC_TYPE_EXTERNAL;
377  }
378 
382  public function setSourceType($sourceType)
383  {
384  $this->sourceType = $sourceType;
385  }
386 
390  public function getActivityId()
391  {
392  return $this->activityId;
393  }
394 
398  public function setActivityId($activityId)
399  {
400  $this->activityId = $activityId;
401  }
402 
406  public function getPublisherId()
407  {
408  return $this->publisherId;
409  }
410 
414  public function setPublisherId($publisherId)
415  {
416  $this->publisherId = $publisherId;
417  }
418 
422  public function getInstructions()
423  {
424  return $this->instructions;
425  }
426 
431  {
432  $this->instructions = $instructions;
433  }
434 
438  public function getLaunchUrl()
439  {
440  return $this->launchUrl;
441  }
442 
446  public function setLaunchUrl($launchUrl)
447  {
448  $this->launchUrl = $launchUrl;
449  }
450 
454  public function getLaunchParameters()
455  {
457  }
458 
463  {
464  $this->launchParameters = $launchParameters;
465  }
466 
472  public function getMoveOn()
473  {
474  return $this->moveOn;
475  }
476 
482  public function setMoveOn($moveOn)
483  {
484  $this->moveOn = $moveOn;
485  }
486 
491  public function getLPMode()
492  {
493  $olp = ilObjectLP::getInstance($this->getId());
494  return $olp->getCurrentMode();
495  }
496 
501  public function getLMSMoveOn()
502  {
504  switch ($this->getLPMode()) {
507  break;
511  break;
515  break;
519  break;
520  }
521  return $moveOn;
522  }
523 
527  public function getEntitlementKey()
528  {
529  return $this->entitlementKey;
530  }
531 
536  {
537  $this->entitlementKey = $entitlementKey;
538  }
539 
543  public function isAuthFetchUrlEnabled()
544  {
546  }
547 
552  {
553  $this->authFetchUrlEnabled = $authFetchUrlEnabled;
554  }
555 
559  public function getLaunchMethod()
560  {
561  return $this->launchMethod;
562  }
563 
568  {
569  $this->launchMethod = $launchMethod;
570  }
571 
575  public function getLaunchMode()
576  {
577  return ucfirst($this->launchMode);
578  }
579 
583  public function setLaunchMode($launchMode)
584  {
585  $this->launchMode = ucfirst($launchMode);
586  }
587 
591  public function isSwitchToReviewEnabled()
592  {
594  }
595 
599  public function getSwitchToReviewEnabled()
600  {
602  }
603 
608  {
609  $this->switchToReviewEnabled = $switchToReviewEnabled;
610  }
611 
615  public function getMasteryScore()
616  {
617  return $this->masteryScore;
618  }
619 
624  {
625  $this->masteryScore = $masteryScore;
626  }
627 
631  public function getMasteryScorePercent()
632  {
633  return $this->masteryScore * 100;
634  }
635 
639  public function setMasteryScorePercent($masteryScorePercent)
640  {
641  $this->masteryScore = $masteryScorePercent / 100;
642  }
643 
647  public function isKeepLpStatusEnabled()
648  {
650  }
651 
656  {
657  $this->keepLpStatusEnabled = $keepLpStatusEnabled;
658  }
659 
663  public function getPrivacyIdent()
664  {
665  return $this->userIdent;
666  }
667 
671  public function setPrivacyIdent($userIdent)
672  {
673  $this->userIdent = $userIdent;
674  }
675 
679  public function getPrivacyName()
680  {
681  return $this->userName;
682  }
683 
687  public function setPrivacyName($userName)
688  {
689  $this->userName = $userName;
690  }
691 
695  public function getOnlyMoveon() : bool
696  {
697  return $this->only_moveon;
698  }
699 
703  public function setOnlyMoveon(bool $only_moveon)
704  {
705  $this->only_moveon = $only_moveon;
706  }
707 
711  public function getAchieved() : bool
712  {
713  return $this->achieved;
714  }
715 
719  public function setAchieved(bool $achieved)
720  {
721  $this->achieved = $achieved;
722  }
723 
727  public function getAnswered() : bool
728  {
729  return $this->answered;
730  }
731 
735  public function setAnswered(bool $answered)
736  {
737  $this->answered = $answered;
738  }
739 
743  public function getCompleted() : bool
744  {
745  return $this->completed;
746  }
747 
751  public function setCompleted(bool $completed)
752  {
753  $this->completed = $completed;
754  }
755 
759  public function getFailed() : bool
760  {
761  return $this->failed;
762  }
763 
767  public function setFailed(bool $failed)
768  {
769  $this->failed = $failed;
770  }
771 
775  public function getInitialized() : bool
776  {
777  return $this->initialized;
778  }
779 
783  public function setInitialized(bool $initialized)
784  {
785  $this->initialized = $initialized;
786  }
787 
791  public function getPassed() : bool
792  {
793  return $this->passed;
794  }
795 
799  public function setPassed(bool $passed)
800  {
801  $this->passed = $passed;
802  }
803 
807  public function getProgressed() : bool
808  {
809  return $this->progressed;
810  }
811 
815  public function setProgressed(bool $progressed)
816  {
817  $this->progressed = $progressed;
818  }
819 
823  public function getSatisfied() : bool
824  {
825  return $this->satisfied;
826  }
827 
831  public function setSatisfied(bool $satisfied)
832  {
833  $this->satisfied = $satisfied;
834  }
835 
839  public function getTerminated() : bool
840  {
841  return $this->terminated;
842  }
843 
847  public function setTerminated(bool $terminated)
848  {
849  $this->terminated = $terminated;
850  }
851 
855  public function getHideData() : bool
856  {
857  return $this->hide_data;
858  }
859 
863  public function setHideData(bool $hide_data)
864  {
865  $this->hide_data = $hide_data;
866  }
867 
871  public function getTimestamp() : bool
872  {
873  return $this->timestamp;
874  }
875 
879  public function setTimestamp(bool $timestamp)
880  {
881  $this->timestamp = $timestamp;
882  }
883 
887  public function getDuration() : bool
888  {
889  return $this->duration;
890  }
891 
895  public function setDuration(bool $duration)
896  {
897  $this->duration = $duration;
898  }
899 
903  public function getNoSubstatements() : bool
904  {
906  }
907 
911  public function setNoSubstatements(bool $no_substatements)
912  {
913  $this->no_substatements = $no_substatements;
914  }
915 
919  public function getUserPrivacyComment()
920  {
922  }
923 
928  {
929  $this->userPrivacyComment = $userPrivacyComment;
930  }
931 
935  public function isStatementsReportEnabled()
936  {
938  }
939 
944  {
945  $this->statementsReportEnabled = $statementsReportEnabled;
946  }
947 
951  public function getXmlManifest()
952  {
953  return $this->xmlManifest;
954  }
955 
959  public function setXmlManifest($xmlManifest)
960  {
961  $this->xmlManifest = $xmlManifest;
962  }
963 
967  public function getVersion()
968  {
969  return $this->version;
970  }
971 
975  public function setVersion($version)
976  {
977  $this->version = $version;
978  }
979 
983  public function isBypassProxyEnabled() : bool
984  {
986  }
987 
992  {
993  $this->bypassProxyEnabled = $bypassProxyEnabled;
994  }
995 
996  public function doRead()
997  {
998  $this->load();
999  }
1000 
1001  public function load()
1002  {
1003  global $DIC; /* @var \ILIAS\DI\Container $DIC */
1004 
1005  $query = "SELECT * FROM " . self::DB_TABLE_NAME . " WHERE obj_id = %s";
1006  $res = $DIC->database()->queryF($query, ['integer'], [$this->getId()]);
1007 
1008  while ($row = $DIC->database()->fetchAssoc($res)) {
1009  if ($row['lrs_type_id']) {
1010  $this->setLrsTypeId((int) $row['lrs_type_id']);
1011  $this->initLrsType();
1012  }
1013 
1014  $this->setContentType($row['content_type']);
1015  $this->setSourceType($row['source_type']);
1016 
1017  $this->setActivityId($row['activity_id']);
1018  $this->setPublisherId($row['publisher_id']);
1019  $this->setInstructions($row['instructions']);
1020 
1021  $this->setLaunchUrl($row['launch_url']);
1022  $this->setLaunchParameters($row['launch_parameters']);
1023  $this->setMoveOn($row['moveon']);
1024  $this->setEntitlementKey($row['entitlement_key']);
1025  $this->setAuthFetchUrlEnabled((bool) $row['auth_fetch_url']);
1026 
1027  $this->setLaunchMethod($row['launch_method']);
1028 
1029  $this->setLaunchMode($row['launch_mode']);
1030  $this->setSwitchToReviewEnabled((bool) $row['switch_to_review']);
1031  $this->setMasteryScore((float) $row['mastery_score']);
1032  $this->setKeepLpStatusEnabled((bool) $row['keep_lp']);
1033 
1034  $this->setPrivacyIdent($row['privacy_ident']);
1035  $this->setPrivacyName($row['privacy_name']);
1036 
1037  $this->setOnlyMoveon((bool) $row['only_moveon']);
1038  $this->setAchieved((bool) $row['achieved']);
1039  $this->setAnswered((bool) $row['answered']);
1040  $this->setCompleted((bool) $row['completed']);
1041  $this->setFailed((bool) $row['failed']);
1042  $this->setInitialized((bool) $row['initialized']);
1043  $this->setPassed((bool) $row['passed']);
1044  $this->setProgressed((bool) $row['progressed']);
1045  $this->setSatisfied((bool) $row['satisfied']);
1046  $this->setTerminated((bool) $row['c_terminated']);
1047  $this->setHideData((bool) $row['hide_data']);
1048  $this->setTimestamp((bool) $row['c_timestamp']);
1049  $this->setDuration((bool) $row['duration']);
1050  $this->setNoSubstatements((bool) $row['no_substatements']);
1051 
1052  $this->setUserPrivacyComment($row['usr_privacy_comment']);
1053 
1054  $this->setStatementsReportEnabled((bool) $row['show_statements']);
1055 
1056  $this->setXmlManifest($row['xml_manifest']);
1057  $this->setVersion((int) $row['version']);
1058 
1059  $this->setBypassProxyEnabled((bool) $row['bypass_proxy']);
1060 
1061  $this->setHighscoreEnabled((bool) $row['highscore_enabled']);
1062  $this->setHighscoreAchievedTS((bool) $row['highscore_achieved_ts']);
1063  $this->setHighscorePercentage((bool) $row['highscore_percentage']);
1064  $this->setHighscoreWTime((bool) $row['highscore_wtime']);
1065  $this->setHighscoreOwnTable((bool) $row['highscore_own_table']);
1066  $this->setHighscoreTopTable((bool) $row['highscore_top_table']);
1067  $this->setHighscoreTopNum((int) $row['highscore_top_num']);
1068  }
1069 
1071  }
1072 
1073  public function doUpdate()
1074  {
1075  $this->save();
1076  }
1077 
1078  public function save()
1079  {
1080  global $DIC; /* @var \ILIAS\DI\Container $DIC */
1081 
1082  $DIC->database()->replace(self::DB_TABLE_NAME, [
1083  'obj_id' => ['integer', $this->getId()]
1084  ], [
1085  'lrs_type_id' => ['integer', $this->getLrsTypeId()],
1086  'content_type' => ['text', $this->getContentType()],
1087  'source_type' => ['text', $this->getSourceType()],
1088  'activity_id' => ['text', $this->getActivityId()],
1089  'publisher_id' => ['text', $this->getPublisherId()],
1090  'instructions' => ['text', $this->getInstructions()],
1091  'launch_url' => ['text', $this->getLaunchUrl()],
1092  'launch_parameters' => ['text', $this->getLaunchParameters()],
1093  'moveon' => ['text', $this->getMoveOn()],
1094  'entitlement_key' => ['text', $this->getEntitlementKey()],
1095  'auth_fetch_url' => ['integer', (int) $this->isAuthFetchUrlEnabled()],
1096  'launch_method' => ['text', $this->getLaunchMethod()],
1097  'launch_mode' => ['text', $this->getLaunchMode()],
1098  'switch_to_review' => ['integer', (int) $this->isSwitchToReviewEnabled()],
1099  'mastery_score' => ['float', $this->getMasteryScore()],
1100  'keep_lp' => ['integer', (int) $this->isKeepLpStatusEnabled()],
1101  'privacy_ident' => ['integer', $this->getPrivacyIdent()],
1102  'privacy_name' => ['integer', $this->getPrivacyName()],
1103  'usr_privacy_comment' => ['text', $this->getUserPrivacyComment()],
1104  'show_statements' => ['integer', (int) $this->isStatementsReportEnabled()],
1105  'xml_manifest' => ['text', $this->getXmlManifest()],
1106  'version' => ['integer', $this->getVersion()],
1107  'bypass_proxy' => ['integer', (int) $this->isBypassProxyEnabled()],
1108  'highscore_enabled' => ['integer', (int) $this->getHighscoreEnabled()],
1109  'highscore_achieved_ts' => ['integer', (int) $this->getHighscoreAchievedTS()],
1110  'highscore_percentage' => ['integer', (int) $this->getHighscorePercentage()],
1111  'highscore_wtime' => ['integer', (int) $this->getHighscoreWTime()],
1112  'highscore_own_table' => ['integer', (int) $this->getHighscoreOwnTable()],
1113  'highscore_top_table' => ['integer', (int) $this->getHighscoreTopTable()],
1114  'highscore_top_num' => ['integer', (int) $this->getHighscoreTopNum()],
1115  'only_moveon' => ['integer', (int) $this->getOnlyMoveon()],
1116  'achieved' => ['integer', (int) $this->getAchieved()],
1117  'answered' => ['integer', (int) $this->getAnswered()],
1118  'completed' => ['integer', (int) $this->getCompleted()],
1119  'failed' => ['integer', (int) $this->getFailed()],
1120  'initialized' => ['integer', (int) $this->getInitialized()],
1121  'passed' => ['integer', (int) $this->getPassed()],
1122  'progressed' => ['integer', (int) $this->getProgressed()],
1123  'satisfied' => ['integer', (int) $this->getSatisfied()],
1124  'c_terminated' => ['integer', (int) $this->getTerminated()],
1125  'hide_data' => ['integer', (int) $this->getHideData()],
1126  'c_timestamp' => ['integer', (int) $this->getTimestamp()],
1127  'duration' => ['integer', (int) $this->getDuration()],
1128  'no_substatements' => ['integer', (int) $this->getNoSubstatements()]
1129  ]);
1130 
1132  }
1133 
1135  {
1136  if ($this->ref_id) {
1137  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1138  $activation = ilObjectActivation::getItem($this->ref_id);
1139  switch ($activation["timing_type"]) {
1141  $this->setActivationLimited(true);
1142  $this->setActivationStartingTime($activation["timing_start"]);
1143  $this->setActivationEndingTime($activation["timing_end"]);
1144  $this->setActivationVisibility($activation["visible"]);
1145  break;
1146 
1147  default:
1148  $this->setActivationLimited(false);
1149  break;
1150  }
1151  }
1152  }
1153 
1155  {
1156  if ($this->ref_id) {
1157  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1158  ilObjectActivation::getItem($this->ref_id);
1159 
1160  $item = new ilObjectActivation;
1161  if (!$this->isActivationLimited()) {
1163  } else {
1164  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1165  $item->setTimingStart($this->getActivationStartingTime());
1166  $item->setTimingEnd($this->getActivationEndingTime());
1167  $item->toggleVisible($this->getActivationVisibility());
1168  }
1169 
1170  $item->update($this->ref_id);
1171  }
1172  }
1173 
1175  {
1176  global $DIC; /* @var \ILIAS\DI\Container $DIC */
1177 
1178  $tableName = self::DB_TABLE_NAME;
1179 
1180  $query = "
1181  UPDATE {$tableName}
1182  SET privacy_ident = %s,
1183  privacy_name = %s,
1184  only_moveon = %s,
1185  achieved = %s,
1186  answered = %s,
1187  completed = %s,
1188  failed = %s,
1189  initialized = %s,
1190  passed = %s,
1191  progressed = %s,
1192  satisfied = %s,
1193  c_terminated = %s,
1194  hide_data = %s,
1195  c_timestamp = %s,
1196  duration = %s,
1197  no_substatements = %s
1198  WHERE lrs_type_id = %s
1199  ";
1200 
1201  $DIC->database()->manipulateF(
1202  $query,
1203  ['integer',
1204  'integer',
1205  'integer',
1206  'integer',
1207  'integer',
1208  'integer',
1209  'integer',
1210  'integer',
1211  'integer',
1212  'integer',
1213  'integer',
1214  'integer',
1215  'integer',
1216  'integer',
1217  'integer',
1218  'integer',
1219  'integer'
1220  ],
1221  [$lrsType->getPrivacyIdent(),
1222  $lrsType->getPrivacyName(),
1223  $lrsType->getOnlyMoveon(),
1224  $lrsType->getAchieved(),
1225  $lrsType->getAnswered(),
1226  $lrsType->getCompleted(),
1227  $lrsType->getFailed(),
1228  $lrsType->getInitialized(),
1229  $lrsType->getPassed(),
1230  $lrsType->getProgressed(),
1231  $lrsType->getSatisfied(),
1232  $lrsType->getTerminated(),
1233  $lrsType->getHideData(),
1234  $lrsType->getTimestamp(),
1235  $lrsType->getDuration(),
1236  $lrsType->getNoSubstatements(),
1237  $lrsType->getTypeId()
1238  ]
1239  );
1240  }
1241 
1243  {
1244  global $DIC; /* @var \ILIAS\DI\Container $DIC */
1245 
1246  $tableName = self::DB_TABLE_NAME;
1247 
1248  $query = "
1249  UPDATE {$tableName}
1250  SET bypass_proxy = %s
1251  WHERE lrs_type_id = %s
1252  ";
1253 
1254  $DIC->database()->manipulateF(
1255  $query,
1256  ['integer', 'integer'],
1257  [$lrsType->isBypassProxyEnabled(), $lrsType->getTypeId()]
1258  );
1259  }
1260 
1262  {
1263  global $DIC; /* @var \ILIAS\DI\Container $DIC */
1264 
1265  $query = "
1266  SELECT DISTINCT s.obj_id FROM " . self::DB_TABLE_NAME . " s
1267  INNER JOIN " . self::DB_USERS_TABLE_NAME . " u ON u.obj_id = s.obj_id
1268  WHERE bypass_proxy = %s
1269  ";
1270 
1271  $res = $DIC->database()->queryF($query, array('integer'), array(1));
1272 
1273  $objects = array();
1274 
1275  while ($row = $DIC->database()->fetchAssoc($res)) {
1276  $objects[] = $row['obj_id'];
1277  }
1278 
1279  return $objects;
1280  }
1281 
1282 
1283 
1286 
1290  protected $_highscore_enabled = 0;
1291 
1292 
1296  protected $anonymity = 0;
1297 
1302 
1306  protected $_highscore_percentage = 1;
1307 
1311  protected $_highscore_wtime = 1;
1312 
1316  protected $_highscore_own_table = 1;
1317 
1321  protected $_highscore_top_table = 1;
1322 
1326  protected $_highscore_top_num = 10;
1327 
1331 
1332 
1333 
1339  public function setHighscoreEnabled($a_enabled)
1340  {
1341  $this->_highscore_enabled = (bool) $a_enabled;
1342  }
1343 
1349  public function getHighscoreEnabled()
1350  {
1351  return (bool) $this->_highscore_enabled;
1352  }
1353 
1359  public function setHighscoreAchievedTS($a_achieved_ts)
1360  {
1361  $this->_highscore_achieved_ts = (bool) $a_achieved_ts;
1362  }
1363 
1369  public function getHighscoreAchievedTS()
1370  {
1371  return (bool) $this->_highscore_achieved_ts;
1372  }
1373 
1379  public function setHighscorePercentage($a_percentage)
1380  {
1381  $this->_highscore_percentage = (bool) $a_percentage;
1382  }
1383 
1389  public function getHighscorePercentage()
1390  {
1391  return (bool) $this->_highscore_percentage;
1392  }
1393 
1399  public function setHighscoreWTime($a_wtime)
1400  {
1401  $this->_highscore_wtime = (bool) $a_wtime;
1402  }
1403 
1409  public function getHighscoreWTime()
1410  {
1411  return (bool) $this->_highscore_wtime;
1412  }
1413 
1419  public function setHighscoreOwnTable($a_own_table)
1420  {
1421  $this->_highscore_own_table = (bool) $a_own_table;
1422  }
1423 
1429  public function getHighscoreOwnTable()
1430  {
1431  return (bool) $this->_highscore_own_table;
1432  }
1433 
1439  public function setHighscoreTopTable($a_top_table)
1440  {
1441  $this->_highscore_top_table = (bool) $a_top_table;
1442  }
1443 
1449  public function getHighscoreTopTable()
1450  {
1451  return (bool) $this->_highscore_top_table;
1452  }
1453 
1460  public function setHighscoreTopNum($a_top_num)
1461  {
1462  $this->_highscore_top_num = (int) $a_top_num;
1463  }
1464 
1473  public function getHighscoreTopNum($a_retval = 10)
1474  {
1475  $retval = $a_retval;
1476  if ((int) $this->_highscore_top_num != 0) {
1477  $retval = $this->_highscore_top_num;
1478  }
1479 
1480  return $retval;
1481  }
1482 
1486  public function getHighscoreMode()
1487  {
1488  switch (true) {
1489  case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
1490  return self::HIGHSCORE_SHOW_ALL_TABLES;
1491 
1492  case $this->getHighscoreTopTable():
1493  return self::HIGHSCORE_SHOW_TOP_TABLE;
1494 
1495  case $this->getHighscoreOwnTable():
1496  default:
1497  return self::HIGHSCORE_SHOW_OWN_TABLE;
1498  }
1499  }
1500 
1504  public function setHighscoreMode($mode)
1505  {
1506  switch ($mode) {
1507  case self::HIGHSCORE_SHOW_ALL_TABLES:
1508  $this->setHighscoreTopTable(1);
1509  $this->setHighscoreOwnTable(1);
1510  break;
1511 
1512  case self::HIGHSCORE_SHOW_TOP_TABLE:
1513  $this->setHighscoreTopTable(1);
1514  $this->setHighscoreOwnTable(0);
1515  break;
1516 
1517  case self::HIGHSCORE_SHOW_OWN_TABLE:
1518  default:
1519  $this->setHighscoreTopTable(0);
1520  $this->setHighscoreOwnTable(1);
1521  break;
1522  }
1523  }
1524 
1525  /* End GET/SET for highscore feature*/
1526 
1527 
1528  public function getDataSetMapping()
1529  {
1530  if (null === ($lrsTypeId = $this->getLrsTypeId())) {
1531  $this->doRead();
1532  }
1533  $mapping = [
1534  'obj_id' => $this->getId(),
1535  'lrs_type_id' => $this->getLrsTypeId(),
1536  'content_type' => $this->getContentType(),
1537  'source_type' => $this->getSourceType(),
1538  'activity_id' => $this->getActivityId(),
1539  'publisher_id' => $this->getPublisherId(),
1540  'instructions' => $this->getInstructions(),
1541  'launch_url' => $this->getLaunchUrl(),
1542  'launch_parameters' => $this->getLaunchParameters(),
1543  'moveon' => $this->getMoveOn(),
1544  'entitlement_key' => $this->getEntitlementKey(),
1545  'auth_fetch_url' => (int) $this->isAuthFetchUrlEnabled(),
1546  'launch_method' => $this->getLaunchMethod(),
1547  'launch_mode' => $this->getLaunchMode(),
1548  'switch_to_review' => (int) $this->isSwitchToReviewEnabled(),
1549  'mastery_score' => $this->getMasteryScore(),
1550  'keep_lp' => (int) $this->isKeepLpStatusEnabled(),
1551  'privacy_ident' => $this->getPrivacyIdent(),
1552  'privacy_name' => $this->getPrivacyName(),
1553  'usr_privacy_comment' => $this->getUserPrivacyComment(),
1554  'show_statements' => (int) $this->isStatementsReportEnabled(),
1555  'xml_manifest' => $this->getXmlManifest(),
1556  'version' => $this->getVersion(),
1557  'highscore_enabled' => (int) $this->getHighscoreEnabled(),
1558  'highscore_achieved_ts' => (int) $this->getHighscoreAchievedTS(),
1559  'highscore_percentage' => (int) $this->getHighscorePercentage(),
1560  'highscore_wtime' => (int) $this->getHighscoreWTime(),
1561  'highscore_own_table' => (int) $this->getHighscoreOwnTable(),
1562  'highscore_top_table' => (int) $this->getHighscoreTopTable(),
1563  'highscore_top_num' => (int) $this->getHighscoreTopNum(),
1564  'only_moveon' => (int) $this->getOnlyMoveon(),
1565  'achieved' => (int) $this->getAchieved(),
1566  'answered' => (int) $this->getAnswered(),
1567  'completed' => (int) $this->getCompleted(),
1568  'failed' => (int) $this->getFailed(),
1569  'initialized' => (int) $this->getInitialized(),
1570  'passed' => (int) $this->getPassed(),
1571  'progressed' => (int) $this->getProgressed(),
1572  'satisfied' => (int) $this->getSatisfied(),
1573  'c_terminated' => (int) $this->getTerminated(),
1574  'hide_data' => (int) $this->getHideData(),
1575  'c_timestamp' => (int) $this->getTimestamp(),
1576  'duration' => (int) $this->getDuration(),
1577  'no_substatements' => (int) $this->getNoSubstatements()
1578  //'bypass_proxy' => (int) $this->isBypassProxyEnabled()
1579  ];
1580  return $mapping;
1581  }
1582 
1590  protected function doCloneObject($new_obj, $a_target_id, $a_copy_id = null, $a_omit_tree = false)
1591  {
1592  global $DIC; /* @var \ILIAS\DI\Container $DIC */
1593 
1594  $this->cloneMetaData($new_obj);
1595 
1596  $new_obj->setLrsTypeId($this->getLrsTypeId());
1597  $new_obj->setContentType($this->getContentType());
1598  $new_obj->setSourceType($this->getSourceType());
1599  $new_obj->setActivityId($this->getActivityId());
1600  $new_obj->setPublisherId($this->getPublisherId());
1601  $new_obj->setInstructions($this->getInstructions());
1602  $new_obj->setLaunchUrl($this->getLaunchUrl());
1603  $new_obj->setLaunchParameters($this->getLaunchParameters());
1604  $new_obj->setMoveOn($this->getMoveOn());
1605  $new_obj->setEntitlementKey($this->getEntitlementKey());
1606  $new_obj->setAuthFetchUrlEnabled($this->isAuthFetchUrlEnabled());
1607  $new_obj->setLaunchMethod($this->getLaunchMethod());
1608  $new_obj->setLaunchMode($this->getLaunchMode());
1609  $new_obj->setSwitchToReviewEnabled($this->isSwitchToReviewEnabled());
1610  $new_obj->setMasteryScore($this->getMasteryScore());
1611  $new_obj->setKeepLpStatusEnabled($this->isKeepLpStatusEnabled());
1612  $new_obj->setPrivacyIdent($this->getPrivacyIdent());
1613  $new_obj->setPrivacyName($this->getPrivacyName());
1614  $new_obj->setUserPrivacyComment($this->getUserPrivacyComment());
1615  $new_obj->setStatementsReportEnabled($this->isStatementsReportEnabled());
1616  $new_obj->setXmlManifest($this->getXmlManifest());
1617  $new_obj->setVersion($this->getVersion());
1618  $new_obj->setHighscoreEnabled($this->getHighscoreEnabled());
1619  $new_obj->setHighscoreAchievedTS($this->getHighscoreAchievedTS());
1620  $new_obj->setHighscorePercentage($this->getHighscorePercentage());
1621  $new_obj->setHighscoreWTime($this->getHighscoreWTime());
1622  $new_obj->setHighscoreOwnTable($this->getHighscoreOwnTable());
1623  $new_obj->setHighscoreTopTable($this->getHighscoreTopTable());
1624  $new_obj->setHighscoreTopNum($this->getHighscoreTopNum());
1625  $new_obj->setBypassProxyEnabled($this->isBypassProxyEnabled());
1626  $new_obj->setOnlyMoveon($this->getOnlyMoveon());
1627  $new_obj->setAchieved($this->getAchieved());
1628  $new_obj->setAnswered($this->getAnswered());
1629  $new_obj->setCompleted($this->getCompleted());
1630  $new_obj->setFailed($this->getFailed());
1631  $new_obj->setInitialized($this->getInitialized());
1632  $new_obj->setPassed($this->getPassed());
1633  $new_obj->setProgressed($this->getProgressed());
1634  $new_obj->setSatisfied($this->getSatisfied());
1635  $new_obj->setTerminated($this->getTerminated());
1636  $new_obj->setHideData($this->getHideData());
1637  $new_obj->setTimestamp($this->getTimestamp());
1638  $new_obj->setDuration($this->getDuration());
1639  $new_obj->setNoSubstatements($this->getNoSubstatements());
1640  $new_obj->update();
1641 
1642  if ($this->getSourceType() == self::SRC_TYPE_LOCAL) {
1643  $dirUtil = new ilCmiXapiContentUploadImporter($new_obj);
1644  $dirUtil->ensureCreatedObjectDirectory();
1645  $newDir = implode(DIRECTORY_SEPARATOR, [\ilUtil::getWebspaceDir(), $dirUtil->getWebDataDirRelativeObjectDirectory()]);
1646  $dirUtil = new ilCmiXapiContentUploadImporter($this);
1647  $thisDir = implode(DIRECTORY_SEPARATOR, [\ilUtil::getWebspaceDir(), $dirUtil->getWebDataDirRelativeObjectDirectory()]);
1648  ilUtil::rCopy($thisDir, $newDir);
1649  }
1650  }
1651 
1652  protected function doDelete()
1653  {
1654  global $DIC;
1655  $ilDB = $DIC['ilDB'];
1656 
1657  // delete file data entry
1658  $query = "DELETE FROM " . self::DB_TABLE_NAME . " WHERE obj_id = " . $ilDB->quote($this->getId(), 'integer');
1659  $ilDB->manipulate($query);
1660 
1661  // delete history entries
1662  require_once("./Services/History/classes/class.ilHistory.php");
1664 
1665  // delete entire directory and its content
1666  $dirUtil = new ilCmiXapiContentUploadImporter($this);
1667  $thisDir = implode(DIRECTORY_SEPARATOR, [\ilUtil::getWebspaceDir(), $dirUtil->getWebDataDirRelativeObjectDirectory()]);
1668  if (is_dir($thisDir)) {
1669  ilUtil::delDir($thisDir);
1670  }
1671 
1672  // delete meta data
1673  $this->deleteMetaData();
1674 
1675  //delete results
1676  $query = "DELETE FROM " . self::DB_RESULTS_TABLE_NAME .
1677  " WHERE obj_id = " . $ilDB->quote($this->getId(), 'integer') . " ";
1678  $ilDB->manipulate($query);
1679 
1680  // TODO check xapidel
1681  }
1682 
1683  public function getRegistrations()
1684  {
1685  global $DIC;
1686  $res = $DIC->database()->queryF(
1687  "SELECT DISTINCT registration FROM " . self::DB_USERS_TABLE_NAME . " WHERE obj_id = %s",
1688  array('text'),
1689  array($this->getId())
1690  );
1691  $ret = [];
1692  while ($row = $DIC->database()->fetchAssoc($res)) {
1693  $ret[] = $row['registration'];
1694  }
1695  return $ret;
1696  }
1697 
1698  public static function guidv4($data = null)
1699  {
1700  // Generate 16 bytes (128 bits) of random data or use the data passed into the function.
1701  $data = $data ?? random_bytes(16);
1702  assert(strlen($data) == 16);
1703 
1704  // Set version to 0100
1705  $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
1706  // Set bits 6-7 to 10
1707  $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
1708 
1709  // Output the 36 character UUID.
1710  return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
1711  }
1712 
1713  public function getCurrentCmixUser()
1714  {
1715  global $DIC;
1716  if (null === $this->currentCmixUser) {
1717  $this->currentCmixUser = new ilCmiXapiUser($this->getId(), $DIC->user()->getId(), $this->getPrivacyIdent());
1718  }
1719  return $this->currentCmixUser;
1720  }
1721 
1722  public function getSessionId($cmixUser = null)
1723  {
1724  if (null === $cmixUser) {
1725  $cmixUser = $this->getCurrentCmixUser();
1726  }
1727  return ilCmiXapiAuthToken::getCmi5SessionByUsrIdAndObjIdAndRefId($cmixUser->getUsrId(), $this->getId(), $this->getRefId());
1728  }
1729 
1733  public function getLaunchData($cmixUser = null, $lang = 'en')
1734  {
1735  if (null === $cmixUser) {
1736  $cmixUser = $this->getCurrentCmixUser();
1737  }
1738  // ToDo
1739  $moveOn = $this->getLMSMoveOn();
1740  if (!$moveOn || $moveOn == '') {
1741  $moveOn = 'Completed';
1742  }
1743  $launchMode = $this->getLaunchMode();
1744  // only check switch if self::LAUNCH_MODE_NORMAL
1745  if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1746  if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1747  $launchMode = self::LAUNCH_MODE_REVIEW;
1748  }
1749  }
1750  $ctxTemplate = [
1751  "contextTemplate" => $this->getLaunchedContextTemplate($cmixUser),
1752  "launchMode" => ucfirst($launchMode),
1753  "launchMethod" => "OwnWindow",
1754  "moveOn" => $moveOn
1755  ];
1756  $lmsLaunchMethod = $this->getLaunchMethod();
1757  if ($lmsLaunchMethod === "ownWin") {
1758  include_once('./Services/Link/classes/class.ilLink.php');
1759  $href = ilLink::_getStaticLink(
1760  $this->getRefId(),
1761  $this->getType()
1762  );
1763  $ctxTemplate['returnURL'] = $href;
1764  } else {
1765  $ctxTemplate['returnURL'] = ILIAS_HTTP_PATH . "/Modules/CmiXapi/xapiexit.php?lang={$lang}";
1766  }
1767  if (!empty($this->getMasteryScore())) {
1768  $ctxTemplate['masteryScore'] = $this->getMasteryScore();
1769  }
1770  if (!empty($this->getLaunchParameters())) {
1771  $ctxTemplate['launchParameters'] = $this->getLaunchParameters();
1772  }
1773  if (!empty($this->getEntitlementKey())) {
1774  $ctxTemplate['entitlementKey'] = array("courseStructure" => $this->getEntitlementKey());
1775  }
1776  return $ctxTemplate;
1777  }
1778 
1779  public function getLaunchedContextTemplate($cmixUser = null)
1780  {
1781  if (null === $cmixUser) {
1782  $cmixUser = $this->getCurrentCmixUser();
1783  }
1784  $launchMode = $this->getLaunchMode();
1785  // only check switch if self::LAUNCH_MODE_NORMAL
1786  if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1787  if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1788  $launchMode = self::LAUNCH_MODE_REVIEW;
1789  }
1790  }
1791  $extensions = $this->getStatementExtensions($cmixUser);
1792  $extensions['https://w3id.org/xapi/cmi5/context/extensions/launchmode'] = $launchMode;
1793  if (!empty($this->getLMSMoveOn())) {
1794  $extensions['https://w3id.org/xapi/cmi5/context/extensions/moveon'] = $this->getLMSMoveOn();
1795  }
1796  if (!empty($this->getLaunchParameters())) {
1797  $extensions['https://w3id.org/xapi/cmi5/context/extensions/launchparameters'] = $this->getLaunchParameters();
1798  }
1799  if (!empty($this->getMasteryScore())) {
1800  $extensions['https://w3id.org/xapi/cmi5/context/extensions/masteryscore'] = $this->getMasteryScore();
1801  }
1802  $contextTemplate = array(
1803  "contextActivities" => $this->getStatementContextActivities(),
1804  "extensions" => $extensions
1805  );
1806  return $contextTemplate;
1807  }
1808 
1812  public function getStatement(string $verb, $cmixUser = null)
1813  {
1814  if (null === $cmixUser) {
1815  $cmixUser = $this->getCurrentCmixUser();
1816  }
1817  $id = self::guidv4();
1818  $actor = $this->getStatementActor($cmixUser);
1819  $verbUri = ilCmiXapiVerbList::getInstance()->getVerbUri($verb);
1820  $extensions = $this->getStatementExtensions($cmixUser);
1821  $registration = $cmixUser->getRegistration();
1822  $contextActivities = $this->getStatementContextActivities();
1823  $object = $this->getStatementObject();
1824  $statement = array(
1825  'id' => $id,
1826  'actor' => $actor,
1827  'verb' =>
1828  array(
1829  'id' => $verbUri
1830  ),
1831  'context' =>
1832  array(
1833  'extensions' => $extensions,
1834  'registration' => $registration,
1835  'contextActivities' => $contextActivities
1836  ),
1837  'object' => $object
1838  );
1839  return $statement;
1840  }
1841 
1845  public function getStatementActor($cmixUser = null)
1846  {
1847  global $DIC;
1848  if (null === $cmixUser) {
1849  $cmixUser = $this->getCurrentCmixUser();
1850  }
1851  $user = new ilObjUser($cmixUser->getUsrId()); // ToDo: Caching Names
1852  $name = ilCmiXapiUser::getName($this->getPrivacyName(), $user);
1853  if ($name == '') {
1854  $this->log()->error('error: no name in cmixuser');
1855  $name = 'UNDEFINED';
1856  }
1857  $homePage = ($this->anonymousHomePage == true) ? self::ANONYMOUS_HOMEPAGE : self::iliasUrl();
1858  if ($this->getContentType() == self::CONT_TYPE_CMI5) {
1859  $actor = [
1860  'objectType' => 'Agent',
1861  'account' => [
1862  'homePage' => $homePage,
1863  'name' => $cmixUser->getUsrIdent()
1864  ]
1865  ];
1866  if ($name !== '') {
1867  $actor['name'] = $name;
1868  }
1869  } else {
1870  $actor = [
1871  'objectType' => 'Agent',
1872  'mbox' => 'mailto:' . $cmixUser->getUsrIdent()
1873  ];
1874  if ($name !== '') {
1875  $actor['name'] = $name;
1876  }
1877  }
1878  return $actor;
1879  }
1880 
1884  public function getStatementExtensions($cmixUser = null)
1885  {
1886  if (null === $cmixUser) {
1887  $cmixUser = $this->getCurrentCmixUser();
1888  }
1889  $extensions = array(
1890  'https://w3id.org/xapi/cmi5/context/extensions/sessionid' => $this->getSessionId($cmixUser),
1891  'https://ilias.de/cmi5/activityid' => $this->getActivityId()
1892  );
1893  return $extensions;
1894  }
1895 
1900  {
1901  $publisherId = $this->getPublisherId();
1902  $activityId = $this->getActivityId();
1903  if (empty($publisherId)) {
1905  }
1906  $ctxActivities = array(
1907  "grouping" => [
1908  [
1909  "objectType" => "Activity",
1910  "id" => "{$publisherId}",
1911  'definition' =>
1912  array(
1913  'name' =>
1914  array(
1915  'de-DE' => $this->getTitle(),
1916  'en-US' => $this->getTitle()
1917  ),
1918  'description' =>
1919  array(
1920  'de-DE' => $this->getDescription(),
1921  'en-US' => $this->getDescription()
1922  )
1923  )]
1924  ],
1925  "category" => [
1926  [
1927  "id" => "https://w3id.org/xapi/cmi5/context/categories/cmi5",
1928  "objectType" => "Activity"
1929  ]
1930  ]
1931  );
1932  return $ctxActivities;
1933  }
1934 
1935  public function getStatementObject()
1936  {
1937  $object = array(
1938  'id' => $this->getActivityId(),
1939  'definition' =>
1940  array(
1941  'name' =>
1942  array(
1943  'de-DE' => $this->getTitle(),
1944  'en-US' => $this->getTitle()
1945  ),
1946  'description' =>
1947  array(
1948  'de-DE' => $this->getDescription(),
1949  'en-US' => $this->getDescription()
1950  )
1951  )
1952  );
1953  return $object;
1954  }
1955 
1956  public function getLaunchedStatement($cmixUser = null)
1957  {
1958  if (null === $cmixUser) {
1959  $cmixUser = $this->getCurrentCmixUser();
1960  }
1961  $launchMode = $this->getLaunchMode();
1962  // only check switch if self::LAUNCH_MODE_NORMAL
1963  if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1964  if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1965  $launchMode = self::LAUNCH_MODE_REVIEW;
1966  }
1967  }
1968 
1969  $statement = $this->getStatement('launched', $cmixUser);
1970  $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/launchmode'] = $launchMode;
1971  if (!empty($this->getLMSMoveOn())) {
1972  $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/moveon'] = $this->getLMSMoveOn();
1973  }
1974  if (!empty($this->getLaunchParameters())) {
1975  $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/launchparameters'] = $this->getLaunchParameters();
1976  }
1977  if (!empty($this->getMasteryScore())) {
1978  $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/masteryscore'] = $this->getMasteryScore();
1979  }
1980  return $statement;
1981  }
1982 
1983  public function getAbandonedStatement($sessionId, $duration, $cmixUser = null)
1984  {
1985  if (null === $cmixUser) {
1986  $cmixUser = $this->getCurrentCmixUser();
1987  }
1988  $statement = $this->getStatement('abandoned', $cmixUser);
1989  // overwrite session with abandoned oldSession
1990  $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/sessionid'] = $sessionId;
1991  $statement['result'] = array(
1992  'duration' => $duration
1993  );
1994  return $statement;
1995  }
1996 
1997  public function getSatisfiedStatement($cmixUser = null)
1998  {
1999  if (null === $cmixUser) {
2000  $cmixUser = $this->getCurrentCmixUser();
2001  }
2002  $statement = $this->getStatement('satisfied', $cmixUser);
2003  // add type, see https://aicc.github.io/CMI-5_Spec_Current/samples/scenarios/16-not_applicable-no_launch/#satisfied-statement
2004  // see also: https://github.com/AICC/CMI-5_Spec_Current/blob/quartz/cmi5_spec.md#verbs_satisfied
2005  $type = "https://w3id.org/xapi/cmi5/activitytype/course";
2006  $statement['object']['definition']['type'] = $type;
2007  $statement['context']['contextActivities']['grouping'][0]['definition']['type'] = $type;
2008  return $statement;
2009  }
2010 
2014  public function getLastStatement($sess)
2015  {
2016  global $DIC;
2017  $lrsType = $this->getLrsType();
2018 
2019  //$this->getLrsEndpoint())) . '/api/' . self::ENDPOINT_AGGREGATE_SUFFIX;
2020  $defaultLrs = $lrsType->getLrsEndpointStatementsAggregationLink();
2021  //$fallbackLrs = $lrsType->getLrsFallbackEndpoint();
2022  $defaultBasicAuth = $lrsType->getBasicAuth();
2023  //$fallbackBasicAuth = $lrsType->getFallbackBasicAuth();
2024  $defaultHeaders = [
2025  'X-Experience-API-Version' => '1.0.3',
2026  'Authorization' => $defaultBasicAuth,
2027  'Cache-Control' => 'no-cache, no-store, must-revalidate'
2028  ];
2029  /*
2030  $fallbackHeaders = [
2031  'X-Experience-API-Version' => '1.0.3',
2032  'Authorization' => $fallbackBasicAuth,
2033  'Content-Type' => 'application/json;charset=utf-8',
2034  'Cache-Control' => 'no-cache, no-store, must-revalidate'
2035  ];
2036  */
2037  $pipeline = json_encode($this->getLastStatementPipline($sess));
2038  $defaultLastStatementUrl = $defaultLrs . "?pipeline=" . urlencode($pipeline);
2039  $client = new GuzzleHttp\Client();
2040  $req_opts = array(
2041  GuzzleHttp\RequestOptions::VERIFY => true,
2042  GuzzleHttp\RequestOptions::CONNECT_TIMEOUT => 10,
2043  GuzzleHttp\RequestOptions::HTTP_ERRORS => false
2044  );
2045  $defaultLastStatementRequest = new GuzzleHttp\Psr7\Request(
2046  'GET',
2047  $defaultLastStatementUrl,
2048  $defaultHeaders
2049  );
2050  $promises = array();
2051  $promises['defaultLastStatement'] = $client->sendAsync($defaultLastStatementRequest, $req_opts);
2052  try {
2053  $responses = GuzzleHttp\Promise\Utils::settle($promises)->wait();
2054  $body = '';
2055  ilCmiXapiAbstractRequest::checkResponse($responses['defaultLastStatement'], $body, [200]);
2056  return json_decode($body, JSON_OBJECT_AS_ARRAY);
2057  } catch (Exception $e) {
2058  $this->log()->error('error:' . $e->getMessage());
2059  return null;
2060  }
2061  }
2062 
2063  public function getLastStatementPipline($sess)
2064  {
2065  global $DIC;
2066  $pipeline = array();
2067 
2068  // filter activityId
2069  $match = array();
2070  $match['statement.object.objectType'] = 'Activity';
2071  $match['statement.actor.objectType'] = 'Agent';
2072 
2073  $activityId = array();
2074 
2075  if ($this->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5 && !$this->isMixedContentType()) {
2076  // https://github.com/AICC/CMI-5_Spec_Current/blob/quartz/cmi5_spec.md#963-extensions
2077  $activityId['statement.context.extensions.https://ilias&46;de/cmi5/activityid'] = $this->getActivityId();
2078  } else {
2079  $activityQuery = [
2080  '$regex' => '^' . preg_quote($this->getActivityId()) . ''
2081  ];
2082  $activityId['$or'] = [];
2083  $activityId['$or'][] = ['statement.object.id' => $activityQuery];
2084  $activityId['$or'][] = ['statement.context.contextActivities.parent.id' => $activityQuery];
2085  $activityId['$or'][] = ['statement.context.contextActivities.grouping.id' => $activityQuery];
2086  }
2087 
2088  $sessionId = array();
2089  $sessionId['statement.context.extensions.https://w3id&46;org/xapi/cmi5/context/extensions/sessionid'] = $sess;
2090  $match['$and'] = array();
2091  $match['$and'][] = $activityId;
2092  $match['$and'][] = $sessionId;
2093  $sort = array('statement.timestamp' => -1);
2094  $project = array('statement.timestamp' => 1, 'statement.verb.id' => 1);
2095  $pipeline[] = array('$match' => $match);
2096  $pipeline[] = array('$sort' => $sort);
2097  $pipeline[] = array('$limit' => 1);
2098  $pipeline[] = array('$project' => $project);
2099 
2100  return $pipeline;
2101  }
2102 
2103  public static function iliasUrl()
2104  {
2105  $regex = '/^(https?\:\/\/[^\/]+).*/';
2106  preg_match($regex, $GLOBALS['DIC']->http()->request()->getUri(), $request_parts);
2107  return $request_parts[1];
2108  }
2109 
2110  public static function log()
2111  {
2112  global $log;
2113  if (self::PLUGIN) {
2114  return $log;
2115  } else {
2116  return \ilLoggerFactory::getLogger('cmix');
2117  }
2118  }
2119 
2120 
2124  public function isActivationLimited()
2125  {
2126  return $this->activationLimited;
2127  }
2128 
2129 
2134  {
2135  $this->activationLimited = $activationLimited;
2136  }
2137 
2141  public function getActivationStartingTime()
2142  {
2144  }
2145 
2150  {
2151  $this->activationStartingTime = $activationStartingTime;
2152  }
2153 
2157  public function getActivationEndingTime()
2158  {
2160  }
2161 
2166  {
2167  $this->activationEndingTime = $activationEndingTime;
2168  }
2169 
2173  public function getActivationVisibility()
2174  {
2176  }
2177 
2182  {
2183  $this->activationVisibility = $activationVisibility;
2184  }
2185 }
setDuration(bool $duration)
doCloneObject($new_obj, $a_target_id, $a_copy_id=null, $a_omit_tree=false)
Clone object.
setAuthFetchUrlEnabled($authFetchUrlEnabled)
setInstructions($instructions)
setEntitlementKey($entitlementKey)
static getName($userNameMode, ilObjUser $user)
getLaunchedStatement($cmixUser=null)
const PRIVACY_IDENT_IL_UUID_SHA256URL
getSessionId($cmixUser=null)
static getObjectsHavingBypassProxyEnabledAndRegisteredUsers()
getHighscoreTopTable()
Gets, if the top-rankings table should be shown.
$data
Definition: storeScorm.php:23
static rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
getHighscoreWTime()
Gets if the column with the workingtime should be shown.
const MOVEON_NOT_APPLICABLE
setNoSubstatements(bool $no_substatements)
setOnlyMoveon(bool $only_moveon)
setAchieved(bool $achieved)
setLaunchUrl($launchUrl)
static getItem($a_ref_id)
Get item data.
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
setMasteryScore($masteryScore)
getHighscoreTopNum($a_retval=10)
Gets the number of entries which are to be shown in the top-rankings table.
getAbandonedStatement($sessionId, $duration, $cmixUser=null)
setContentType($contentType)
const PRIVACY_IDENT_IL_UUID_RANDOM
static updatePrivacySettingsFromLrsType(ilCmiXapiLrsType $lrsType)
setLaunchMode($launchMode)
const PRIVACY_IDENT_IL_UUID_EXT_ACCOUNT
getHighscoreOwnTable()
Gets if the own rankings table should be shown.
const PRIVACY_IDENT_REAL_EMAIL
getStatementExtensions($cmixUser=null)
Minimal extensions.
setBypassProxyEnabled(bool $bypassProxyEnabled)
if($format !==null) $name
Definition: metadata.php:230
setActivationEndingTime($activationEndingTime)
setTerminated(bool $terminated)
const PRIVACY_IDENT_IL_UUID_SHA256
setFailed(bool $failed)
static http()
Fetches the global http state from ILIAS.
setHighscoreTopTable($a_top_table)
Sets if the top-rankings table should be shown.
setPassed(bool $passed)
foreach($_POST as $key=> $value) $res
getHighscoreEnabled()
Gets the setting which determines if the highscore feature is enabled.
getId()
get object id public
setLrsTypeId($lrsTypeId)
setKeepLpStatusEnabled($keepLpStatusEnabled)
setCompleted(bool $completed)
getStatementActor($cmixUser=null)
statement actor
static getCmi5SessionByUsrIdAndObjIdAndRefId(int $usrId, int $objId, $refId=null)
setActivationLimited($activationLimited)
getLastStatement($sess)
get latest statement from session
getLastStatementPipline($sess)
global $DIC
Definition: goto.php:24
static getInstance($a_id=0, $a_reference=true)
setSwitchToReviewEnabled($switchToReviewEnabled)
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
setActivationStartingTime($activationStartingTime)
__construct($a_id=0, $a_reference=true)
ilObjCmiXapi constructor.
$query
setXmlManifest($xmlManifest)
const PRIVACY_IDENT_IL_UUID_LOGIN
static guidv4($data=null)
setHighscoreEnabled($a_enabled)
Sets if the highscore feature should be enabled.
setPrivacyIdent($userIdent)
setLaunchParameters($launchParameters)
setInitialized(bool $initialized)
setTimingType($a_type)
Set timing type.
const PRIVACY_IDENT_IL_UUID_USER_ID
setProgressed(bool $progressed)
setPublisherId($publisherId)
$lang
Definition: xapiexit.php:8
getSatisfiedStatement($cmixUser=null)
setActivityId($activityId)
setSatisfied(bool $satisfied)
setActivationVisibility($activationVisibility)
getLaunchedContextTemplate($cmixUser=null)
setPrivacyName($userName)
getLaunchData($cmixUser=null, $lang='en')
LMS.LaunchData.
static checkResponse($response, &$body, $allowedStatus=[200, 204])
$activationLimited
repository object activation settings (handled by ilObject)
__construct(Container $dic, ilPlugin $plugin)
setTimestamp(bool $timestamp)
const LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED
setAnswered(bool $answered)
getStatementContextActivities()
Minimal statementActivities.
getHighscorePercentage()
Gets if the percentage column should be shown.
global $ilDB
$ret
Definition: parser.php:6
setHighscoreOwnTable($a_own_table)
Sets if the table with the own ranking should be shown.
setStatementsReportEnabled($statementsReportEnabled)
static _removeEntriesForObject($a_obj_id)
remove all history entries for an object
getStatement(string $verb, $cmixUser=null)
blueprint statement
setHideData(bool $hide_data)
static updateByPassProxyFromLrsType(ilCmiXapiLrsType $lrsType)
setLaunchMethod($launchMethod)
setSourceType($sourceType)
setMasteryScorePercent($masteryScorePercent)
setHighscoreWTime($a_wtime)
Sets if the workingtime of the scores should be shown.
static getInstance($a_obj_id)
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static getWebspaceDir($mode="filesystem")
get webspace directory
const MOVEON_COMPLETED_OR_PASSED
Class ilObjectActivation.
setHighscoreAchievedTS($a_achieved_ts)
Sets if the date and time of the scores achievement should be displayed.
setHighscoreTopNum($a_top_num)
Sets the number of entries which are to be shown in the top-rankings table.
setUserPrivacyComment($userPrivacyComment)
getHighscoreAchievedTS()
Returns if date and time of the scores achievement should be displayed.
cloneMetaData($target_obj)
setHighscorePercentage($a_percentage)
Sets if the percentages of the scores pass should be shown.