ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilObjCmiXapi.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
31{
32 public const PLUGIN = false;
33
34 public const DB_TABLE_NAME = 'cmix_settings';
35 public const DB_USERS_TABLE_NAME = 'cmix_users';
36 public const DB_RESULTS_TABLE_NAME = 'cmix_results';
37
41 protected ?bool $activationLimited = null;
42 protected ?int $activationStartingTime = null;
43 protected ?int $activationEndingTime = null;
44 protected ?bool $activationVisibility = null;
45
46 protected ?int $lrsTypeId;
47
49
50 protected string $contentType;
51 public const CONT_TYPE_GENERIC = 'generic';
52 public const CONT_TYPE_CMI5 = 'cmi5';
53
54 protected string $sourceType;
55 public const SRC_TYPE_REMOTE = 'remoteSource';
56 public const SRC_TYPE_LOCAL = 'localSource';
57 public const SRC_TYPE_EXTERNAL = 'externalSource';
58
59 protected string $activityId;
60
61 protected string $publisherId;
62
63 protected string $instructions;
64
65 protected string $launchUrl;
66
67 protected string $launchParameters;
68
69 protected string $moveOn;
70
71 protected string $entitlementKey;
72
73 protected bool $authFetchUrlEnabled = false;
74
75 protected bool $anonymousHomePage = false;
76 public const ANONYMOUS_HOMEPAGE = 'https://example.org';
77
78 protected string $launchMethod;
79 public const LAUNCH_METHOD_OWN_WIN = 'ownWin';
80 public const LAUNCH_METHOD_NEW_WIN = 'newWin';
81 public const LAUNCH_METHOD_IFRAME = 'iframe';
82
83 protected string $launchMode;
84 public const LAUNCH_MODE_NORMAL = 'Normal';
85 public const LAUNCH_MODE_BROWSE = 'Browse';
86 public const LAUNCH_MODE_REVIEW = 'Review';
87
88 protected bool $switchToReviewEnabled = false;
89
90 protected float $masteryScore;
91 public const LMS_MASTERY_SCORE = 0.7;
92
93 protected bool $keepLpStatusEnabled = false;
94
95 protected int $userIdent;
99 public const PRIVACY_IDENT_REAL_EMAIL = 3;
103
104 protected int $userName;
105 public const PRIVACY_NAME_NONE = 0;
106 public const PRIVACY_NAME_FIRSTNAME = 1;
107 public const PRIVACY_NAME_LASTNAME = 2;
108 public const PRIVACY_NAME_FULLNAME = 3;
109
110 protected string $userPrivacyComment = "";
111
112 protected bool $statementsReportEnabled = false;
113
114 protected string $xmlManifest = "";
115
116 protected int $version;
117
118 protected bool $bypassProxyEnabled = false;
119
120 protected bool $only_moveon = false;
121
122 protected bool $achieved = true;
123
124 protected bool $answered = true;
125
126 protected bool $completed = true;
127
128 protected bool $failed = true;
129
130 protected bool $initialized = true;
131
132 protected bool $passed = true;
133
134 protected bool $progressed = true;
135
136 protected bool $satisfied = true;
137
138 protected bool $terminated = true;
139
140 protected bool $hide_data = false;
141
142 protected bool $timestamp = false;
143
144 protected bool $duration = true;
145
146 protected bool $no_substatements = false;
147
148 protected int $deleteData = 0;
149
151
153
157 public function __construct(int $a_id = 0, bool $a_reference = true)
158 {
159 global $DIC;
160 $this->database = $DIC->database();
161
162 $this->lrsTypeId = 0;
163
164 $this->contentType = self::CONT_TYPE_GENERIC;
165 $this->sourceType = self::SRC_TYPE_REMOTE;
166
167 $this->activityId = '';
168
169 $this->publisherId = '';
170
171 $this->instructions = '';
172
173 $this->launchUrl = '';
174 $this->launchParameters = '';
175 $this->moveOn = '';
176 $this->entitlementKey = '';
177
178 $this->authFetchUrlEnabled = false;
179
180 $this->launchMethod = self::LAUNCH_METHOD_NEW_WIN;
181 $this->launchMode = self::LAUNCH_MODE_NORMAL;
182
183 $this->switchToReviewEnabled = true;
184
185 $this->masteryScore = self::LMS_MASTERY_SCORE;
186 $this->keepLpStatusEnabled = true;
187
188 $this->userIdent = self::PRIVACY_IDENT_IL_UUID_USER_ID;
189 $this->userName = self::PRIVACY_NAME_NONE;
190 $this->userPrivacyComment = '';
191
192 $this->currentCmixUser = null;
193
194 $this->statementsReportEnabled = false;
195
196 $this->xmlManifest = '';
197 $this->version = 0;
198
199 $this->bypassProxyEnabled = false;
200
201 parent::__construct($a_id, $a_reference);
202 }
203
204
205 public static function getInstance(int $a_id = 0, bool $a_reference = true): \ilObjCmiXapi
206 {
207 return new self($a_id, $a_reference);
208 }
209
210 protected function initType(): void
211 {
212 $this->type = "cmix";
213 }
214
215 public function getLrsTypeId(): ?int
216 {
217 return $this->lrsTypeId;
218 }
219
220 public function setLrsTypeId(int $lrsTypeId): void
221 {
222 $this->lrsTypeId = $lrsTypeId;
223 }
224
225 public function getLrsType(): \ilCmiXapiLrsType
226 {
227 return $this->lrsType;
228 }
229
230 public function setLrsType(\ilCmiXapiLrsType $lrsType): void
231 {
232 $this->lrsType = $lrsType;
233 }
234
235 public function initLrsType(): void
236 {
237 $this->setLrsType(new ilCmiXapiLrsType($this->getLrsTypeId()));
238 }
239
240 public function getContentType(): string
241 {
242 return $this->contentType;
243 }
244
245 public function setContentType(string $contentType): void
246 {
247 //bug before 21-07-24
248 if ($contentType == "learning") {
250 }
251 $this->contentType = $contentType;
252 }
253
254 public function isMixedContentType(): bool
255 {
256 // after 21-07-24 and before cmi5 refactoring
257 // launched before cmi5 refactoring ident in: statement.actor.mbox
258 // launched after cmi5 refactoring ident in: statement.actor.account.name
259 return (($this->getContentType() == self::CONT_TYPE_CMI5) && empty($this->getPublisherId()));
260 }
261
262 public function getSourceType(): string
263 {
264 return $this->sourceType;
265 }
266
267 public function isSourceTypeRemote(): bool
268 {
269 return $this->sourceType == self::SRC_TYPE_REMOTE;
270 }
271
272 public function isSourceTypeExternal(): bool
273 {
274 return $this->sourceType == self::SRC_TYPE_EXTERNAL;
275 }
276
277 public function setSourceType(string $sourceType): void
278 {
279 $this->sourceType = $sourceType;
280 }
281
282 public function getActivityId(): string
283 {
284 return $this->activityId;
285 }
286
287 public function setActivityId(string $activityId): void
288 {
289 $this->activityId = $activityId;
290 }
291
292 public function getPublisherId(): string
293 {
294 return $this->publisherId;
295 }
296
297 public function setPublisherId(string $publisherId): void
298 {
299 $this->publisherId = $publisherId;
300 }
301
302 public function getInstructions(): string
303 {
304 return $this->instructions;
305 }
306
307 public function setInstructions(string $instructions): void
308 {
309 $this->instructions = $instructions;
310 }
311
312 public function getLaunchUrl(): string
313 {
314 return $this->launchUrl;
315 }
316
317 public function setLaunchUrl(string $launchUrl): void
318 {
319 $this->launchUrl = $launchUrl;
320 }
321
322 public function getLaunchParameters(): string
323 {
325 }
326
327 public function setLaunchParameters(string $launchParameters): void
328 {
329 $this->launchParameters = $launchParameters;
330 }
331
336 public function getMoveOn(): string
337 {
338 return $this->moveOn;
339 }
340
345 public function setMoveOn(string $moveOn): void
346 {
347 $this->moveOn = $moveOn;
348 }
349
354 public function getLPMode(): int
355 {
356 $olp = ilObjectLP::getInstance($this->getId());
357 return $olp->getCurrentMode();
358 }
359
364 public function getLMSMoveOn(): string
365 {
367 switch ($this->getLPMode()) {
370 break;
374 break;
378 break;
382 break;
383 }
384 return $moveOn;
385 }
386
387 public function getEntitlementKey(): string
388 {
390 }
391
392 public function setEntitlementKey(string $entitlementKey): void
393 {
394 $this->entitlementKey = $entitlementKey;
395 }
396
397 public function isAuthFetchUrlEnabled(): bool
398 {
400 }
401
403 {
404 $this->authFetchUrlEnabled = $authFetchUrlEnabled;
405 }
406
407 public function getLaunchMethod(): string
408 {
409 return $this->launchMethod;
410 }
411
412 public function setLaunchMethod(string $launchMethod): void
413 {
414 $this->launchMethod = $launchMethod;
415 }
416
417 public function getLaunchMode(): string
418 {
419 return ucfirst($this->launchMode);
420 }
421
422 public function setLaunchMode(string $launchMode): void
423 {
424 $this->launchMode = ucfirst($launchMode);
425 }
426
427 public function isSwitchToReviewEnabled(): bool
428 {
430 }
431
432 public function getSwitchToReviewEnabled(): bool
433 {
435 }
436
438 {
439 $this->switchToReviewEnabled = $switchToReviewEnabled;
440 }
441
442 public function getMasteryScore(): float
443 {
444 return $this->masteryScore;
445 }
446
447 public function setMasteryScore(float $masteryScore): void
448 {
449 $this->masteryScore = $masteryScore;
450 }
451
452 public function getMasteryScorePercent(): float
453 {
454 return $this->masteryScore * 100;
455 }
456
457 public function setMasteryScorePercent(float $masteryScorePercent): void
458 {
459 $this->masteryScore = $masteryScorePercent / 100;
460 }
461
462 public function isKeepLpStatusEnabled(): bool
463 {
465 }
466
468 {
469 $this->keepLpStatusEnabled = $keepLpStatusEnabled;
470 }
471
472 public function getPrivacyIdent(): int
473 {
474 return $this->userIdent;
475 }
476
477 public function setPrivacyIdent(int $userIdent): void
478 {
479 $this->userIdent = $userIdent;
480 }
481
482 public function getPrivacyName(): int
483 {
484 return $this->userName;
485 }
486
487 public function setPrivacyName(int $userName): void
488 {
489 $this->userName = $userName;
490 }
491
492 public function getOnlyMoveon(): bool
493 {
494 return $this->only_moveon;
495 }
496
497 public function setOnlyMoveon(bool $only_moveon): void
498 {
499 $this->only_moveon = $only_moveon;
500 }
501
502 public function getAchieved(): bool
503 {
504 return $this->achieved;
505 }
506
507 public function setAchieved(bool $achieved): void
508 {
509 $this->achieved = $achieved;
510 }
511
512 public function getAnswered(): bool
513 {
514 return $this->answered;
515 }
516
517 public function setAnswered(bool $answered): void
518 {
519 $this->answered = $answered;
520 }
521
522 public function getCompleted(): bool
523 {
524 return $this->completed;
525 }
526
527 public function setCompleted(bool $completed): void
528 {
529 $this->completed = $completed;
530 }
531
532 public function getFailed(): bool
533 {
534 return $this->failed;
535 }
536
537 public function setFailed(bool $failed): void
538 {
539 $this->failed = $failed;
540 }
541
542 public function getInitialized(): bool
543 {
544 return $this->initialized;
545 }
546
547 public function setInitialized(bool $initialized): void
548 {
549 $this->initialized = $initialized;
550 }
551
552 public function getPassed(): bool
553 {
554 return $this->passed;
555 }
556
557 public function setPassed(bool $passed): void
558 {
559 $this->passed = $passed;
560 }
561
562 public function getProgressed(): bool
563 {
564 return $this->progressed;
565 }
566
567 public function setProgressed(bool $progressed): void
568 {
569 $this->progressed = $progressed;
570 }
571
572 public function getSatisfied(): bool
573 {
574 return $this->satisfied;
575 }
576
577 public function setSatisfied(bool $satisfied): void
578 {
579 $this->satisfied = $satisfied;
580 }
581
582 public function getTerminated(): bool
583 {
584 return $this->terminated;
585 }
586
587 public function setTerminated(bool $terminated): void
588 {
589 $this->terminated = $terminated;
590 }
591
592 public function getHideData(): bool
593 {
594 return $this->hide_data;
595 }
596
597 public function setHideData(bool $hide_data): void
598 {
599 $this->hide_data = $hide_data;
600 }
601
602 public function getTimestamp(): bool
603 {
604 return $this->timestamp;
605 }
606
607 public function setTimestamp(bool $timestamp): void
608 {
609 $this->timestamp = $timestamp;
610 }
611
612 public function getDuration(): bool
613 {
614 return $this->duration;
615 }
616
617 public function setDuration(bool $duration): void
618 {
619 $this->duration = $duration;
620 }
621
622 public function getNoSubstatements(): bool
623 {
625 }
626
627 public function setNoSubstatements(bool $no_substatements): void
628 {
629 $this->no_substatements = $no_substatements;
630 }
631
632 public function getDeleteData(): int
633 {
634 return $this->deleteData;
635 }
636
637 public function setDeleteData(int $deleteData): void
638 {
639 $this->deleteData = $deleteData;
640 }
641
642 public function getUserPrivacyComment(): string
643 {
645 }
646
647 public function setUserPrivacyComment(string $userPrivacyComment): void
648 {
649 $this->userPrivacyComment = $userPrivacyComment;
650 }
651
652 public function isStatementsReportEnabled(): bool
653 {
655 }
656
658 {
659 $this->statementsReportEnabled = $statementsReportEnabled;
660 }
661
662 public function getXmlManifest(): string
663 {
664 return $this->xmlManifest;
665 }
666
667 public function setXmlManifest(string $xmlManifest): void
668 {
669 $this->xmlManifest = $xmlManifest;
670 }
671
672 public function getVersion(): int
673 {
674 return $this->version;
675 }
676
677 public function setVersion(int $version): void
678 {
679 $this->version = $version;
680 }
681
682 public function isBypassProxyEnabled(): bool
683 {
685 }
686
687 public function setBypassProxyEnabled(bool $bypassProxyEnabled): void
688 {
689 $this->bypassProxyEnabled = $bypassProxyEnabled;
690 }
691
692 //todo?
693 protected function doRead(): void
694 {
695 $this->load();
696 }
697
698 protected function load(): void
699 {
700 $query = "SELECT * FROM " . self::DB_TABLE_NAME . " WHERE obj_id = %s";
701 $res = $this->database->queryF($query, ['integer'], [$this->getId()]);
702
703 while ($row = $this->database->fetchAssoc($res)) {
704 if ($row['lrs_type_id']) {
705 $this->setLrsTypeId((int) $row['lrs_type_id']);
706 $this->initLrsType();
707 }
708
709 $this->setContentType((string) $row['content_type']);
710 $this->setSourceType((string) $row['source_type']);
711
712 $this->setActivityId((string) $row['activity_id']);
713 $this->setPublisherId((string) $row['publisher_id']);
714 $this->setInstructions((string) $row['instructions']);
715
716 $this->setLaunchUrl((string) $row['launch_url']);
717 $this->setLaunchParameters((string) $row['launch_parameters']);
718 $this->setMoveOn((string) $row['moveon']);
719 $this->setEntitlementKey((string) $row['entitlement_key']);
720 $this->setAuthFetchUrlEnabled((bool) $row['auth_fetch_url']);
721
722 $this->setLaunchMethod((string) $row['launch_method']);
723
724 $this->setLaunchMode((string) $row['launch_mode']);
725 $this->setSwitchToReviewEnabled((bool) $row['switch_to_review']);
726 $this->setMasteryScore((float) $row['mastery_score']);
727 $this->setKeepLpStatusEnabled((bool) $row['keep_lp']);
728
729 $this->setPrivacyIdent((int) $row['privacy_ident']);
730 $this->setPrivacyName((int) $row['privacy_name']);
731
732 $this->setOnlyMoveon((bool) $row['only_moveon']);
733 $this->setAchieved((bool) $row['achieved']);
734 $this->setAnswered((bool) $row['answered']);
735 $this->setCompleted((bool) $row['completed']);
736 $this->setFailed((bool) $row['failed']);
737 $this->setInitialized((bool) $row['initialized']);
738 $this->setPassed((bool) $row['passed']);
739 $this->setProgressed((bool) $row['progressed']);
740 $this->setSatisfied((bool) $row['satisfied']);
741 $this->setTerminated((bool) $row['c_terminated']);
742 $this->setHideData((bool) $row['hide_data']);
743 $this->setTimestamp((bool) $row['c_timestamp']);
744 $this->setDuration((bool) $row['duration']);
745 $this->setNoSubstatements((bool) $row['no_substatements']);
746 $this->setDeleteData((int) $row['delete_data']);
747
748 $this->setUserPrivacyComment((string) $row['usr_privacy_comment']);
749
750 $this->setStatementsReportEnabled((bool) $row['show_statements']);
751
752 $this->setXmlManifest((string) $row['xml_manifest']);
753 $this->setVersion((int) $row['version']);
754
755 $this->setBypassProxyEnabled((bool) $row['bypass_proxy']);
756
757 $this->setHighscoreEnabled((bool) $row['highscore_enabled']);
758 $this->setHighscoreAchievedTS((bool) $row['highscore_achieved_ts']);
759 $this->setHighscorePercentage((bool) $row['highscore_percentage']);
760 $this->setHighscoreWTime((bool) $row['highscore_wtime']);
761 $this->setHighscoreOwnTable((bool) $row['highscore_own_table']);
762 $this->setHighscoreTopTable((bool) $row['highscore_top_table']);
763 $this->setHighscoreTopNum((int) $row['highscore_top_num']);
764 }
765
767 }
768
769 //todo?
770 protected function doUpdate(): void
771 {
772 $this->save();
773 }
774
775 public function save(): void
776 {
777 global $DIC; /* @var \ILIAS\DI\Container $DIC */
778 // not possible: Move Global Access to Constructor
779 $DIC->database()->replace(self::DB_TABLE_NAME, [
780 'obj_id' => ['integer', $this->getId()]
781 ], [
782 'lrs_type_id' => ['integer', $this->getLrsTypeId()],
783 'content_type' => ['text', $this->getContentType()],
784 'source_type' => ['text', $this->getSourceType()],
785 'activity_id' => ['text', $this->getActivityId()],
786 'publisher_id' => ['text', $this->getPublisherId()],
787 'instructions' => ['text', $this->getInstructions()],
788 'launch_url' => ['text', $this->getLaunchUrl()],
789 'launch_parameters' => ['text', $this->getLaunchParameters()],
790 'moveon' => ['text', $this->getMoveOn()],
791 'entitlement_key' => ['text', $this->getEntitlementKey()],
792 'auth_fetch_url' => ['integer', (int) $this->isAuthFetchUrlEnabled()],
793 'launch_method' => ['text', $this->getLaunchMethod()],
794 'launch_mode' => ['text', $this->getLaunchMode()],
795 'switch_to_review' => ['integer', (int) $this->isSwitchToReviewEnabled()],
796 'mastery_score' => ['float', $this->getMasteryScore()],
797 'keep_lp' => ['integer', (int) $this->isKeepLpStatusEnabled()],
798 'privacy_ident' => ['integer', $this->getPrivacyIdent()],
799 'privacy_name' => ['integer', $this->getPrivacyName()],
800 'usr_privacy_comment' => ['text', $this->getUserPrivacyComment()],
801 'show_statements' => ['integer', (int) $this->isStatementsReportEnabled()],
802 'xml_manifest' => ['text', $this->getXmlManifest()],
803 'version' => ['integer', $this->getVersion()],
804 'bypass_proxy' => ['integer', (int) $this->isBypassProxyEnabled()],
805 'highscore_enabled' => ['integer', (int) $this->getHighscoreEnabled()],
806 'highscore_achieved_ts' => ['integer', (int) $this->getHighscoreAchievedTS()],
807 'highscore_percentage' => ['integer', (int) $this->getHighscorePercentage()],
808 'highscore_wtime' => ['integer', (int) $this->getHighscoreWTime()],
809 'highscore_own_table' => ['integer', (int) $this->getHighscoreOwnTable()],
810 'highscore_top_table' => ['integer', (int) $this->getHighscoreTopTable()],
811 'highscore_top_num' => ['integer', $this->getHighscoreTopNum()],
812 'only_moveon' => ['integer', (int) $this->getOnlyMoveon()],
813 'achieved' => ['integer', (int) $this->getAchieved()],
814 'answered' => ['integer', (int) $this->getAnswered()],
815 'completed' => ['integer', (int) $this->getCompleted()],
816 'failed' => ['integer', (int) $this->getFailed()],
817 'initialized' => ['integer', (int) $this->getInitialized()],
818 'passed' => ['integer', (int) $this->getPassed()],
819 'progressed' => ['integer', (int) $this->getProgressed()],
820 'satisfied' => ['integer', (int) $this->getSatisfied()],
821 'c_terminated' => ['integer', (int) $this->getTerminated()],
822 'hide_data' => ['integer', (int) $this->getHideData()],
823 'c_timestamp' => ['integer', (int) $this->getTimestamp()],
824 'duration' => ['integer', (int) $this->getDuration()],
825 'no_substatements' => ['integer', (int) $this->getNoSubstatements()],
826 'delete_data' => ['integer', $this->getDeleteData()]
827 ]);
828
830 }
831
832 protected function loadRepositoryActivationSettings(): void
833 {
834 if ($this->ref_id) {
835 $activation = ilObjectActivation::getItem($this->ref_id);
836 switch ($activation["timing_type"]) {
838 $this->setActivationLimited(true);
839 if (!is_null($activation["timing_start"])) {
840 $activation["timing_start"] = (int) $activation["timing_start"];
841 }
842 $this->setActivationStartingTime($activation["timing_start"]);
843 if (!is_null($activation["timing_end"])) {
844 $activation["timing_end"] = (int) $activation["timing_end"];
845 }
846 $this->setActivationEndingTime($activation["timing_end"]);
847 $this->setActivationVisibility((bool) $activation["visible"]);
848 break;
849
850 default:
851 $this->setActivationLimited(false);
852 break;
853 }
854 }
855 }
856
857 protected function saveRepositoryActivationSettings(): void
858 {
859 if ($this->ref_id) {
860 ilObjectActivation::getItem($this->ref_id);
861
862 $item = new ilObjectActivation();
863 if (!$this->isActivationLimited()) {
864 $item->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
865 } else {
866 $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
867 $item->setTimingStart($this->getActivationStartingTime());
868 $item->setTimingEnd($this->getActivationEndingTime());
869 $item->toggleVisible($this->getActivationVisibility());
870 }
871
872 $item->update($this->ref_id);
873 }
874 }
875
877 {
878 global $DIC; /* @var \ILIAS\DI\Container $DIC */
879 //not possible: Move Global Access to Constructor
880 $tableName = self::DB_TABLE_NAME;
881
882 $query = "
883 UPDATE {$tableName}
884 SET privacy_ident = %s,
885 privacy_name = %s,
886 only_moveon = %s,
887 achieved = %s,
888 answered = %s,
889 completed = %s,
890 failed = %s,
891 initialized = %s,
892 passed = %s,
893 progressed = %s,
894 satisfied = %s,
895 c_terminated = %s,
896 hide_data = %s,
897 c_timestamp = %s,
898 duration = %s,
899 no_substatements = %s,
900 delete_data = %s
901 WHERE lrs_type_id = %s
902 ";
903
904 $DIC->database()->manipulateF(
905 $query,
906 ['integer',
907 'integer',
908 'integer',
909 'integer',
910 'integer',
911 'integer',
912 'integer',
913 'integer',
914 'integer',
915 'integer',
916 'integer',
917 'integer',
918 'integer',
919 'integer',
920 'integer',
921 'integer',
922 'integer',
923 'integer'
924 ],
943 ]
944 );
945 }
946
948 {
949 global $DIC; /* @var \ILIAS\DI\Container $DIC */
950 // not possible: Move Global Access to Constructor
951 $tableName = self::DB_TABLE_NAME;
952
953 $query = "
954 UPDATE {$tableName}
955 SET bypass_proxy = %s
956 WHERE lrs_type_id = %s
957 ";
958
959 $DIC->database()->manipulateF(
960 $query,
961 ['integer', 'integer'],
963 );
964 }
965
970 {
971 global $DIC; /* @var \ILIAS\DI\Container $DIC */
972 // not possible: Move Global Access to Constructor
973 $query = "
974 SELECT DISTINCT s.obj_id FROM " . self::DB_TABLE_NAME . " s
975 INNER JOIN " . self::DB_USERS_TABLE_NAME . " u ON u.obj_id = s.obj_id
976 WHERE bypass_proxy = %s
977 ";
978
979 $res = $DIC->database()->queryF($query, array('integer'), array(1));
980
981 $objects = array();
982
983 while ($row = $DIC->database()->fetchAssoc($res)) {
984 $objects[] = (int) $row['obj_id'];
985 }
986
987 return $objects;
988 }
989
990
991
994
995 protected bool $_highscore_enabled = false;
996
997 protected int $anonymity = 0;
998
999 protected bool $_highscore_achieved_ts = true;
1000
1001 protected bool $_highscore_percentage = true;
1002
1003 protected bool $_highscore_wtime = true;
1004
1005 protected bool $_highscore_own_table = true;
1006
1007 protected bool $_highscore_top_table = true;
1008
1009 protected int $_highscore_top_num = 10;
1010
1014
1018 public function setHighscoreEnabled(bool $a_enabled): void
1019 {
1020 $this->_highscore_enabled = $a_enabled;
1021 }
1022
1027 public function getHighscoreEnabled(): bool
1028 {
1030 }
1031
1035 public function setHighscoreAchievedTS(bool $a_achieved_ts): void
1036 {
1037 $this->_highscore_achieved_ts = $a_achieved_ts;
1038 }
1039
1044 public function getHighscoreAchievedTS(): bool
1045 {
1047 }
1048
1052 public function setHighscorePercentage(bool $a_percentage): void
1053 {
1054 $this->_highscore_percentage = $a_percentage;
1055 }
1056
1061 public function getHighscorePercentage(): bool
1062 {
1064 }
1065
1069 public function setHighscoreWTime(bool $a_wtime): void
1070 {
1071 $this->_highscore_wtime = $a_wtime;
1072 }
1073
1078 public function getHighscoreWTime(): bool
1079 {
1081 }
1082
1087 public function setHighscoreOwnTable(bool $a_own_table): void
1088 {
1089 $this->_highscore_own_table = $a_own_table;
1090 }
1091
1096 public function getHighscoreOwnTable(): bool
1097 {
1099 }
1100
1104 public function setHighscoreTopTable(bool $a_top_table): void
1105 {
1106 $this->_highscore_top_table = $a_top_table;
1107 }
1108
1113 public function getHighscoreTopTable(): bool
1114 {
1116 }
1117
1123 public function setHighscoreTopNum(int $a_top_num): void
1124 {
1125 $this->_highscore_top_num = $a_top_num;
1126 }
1127
1134 public function getHighscoreTopNum(?int $a_retval = 10): ?int
1135 {
1136 $retval = $a_retval;
1137 if ($this->_highscore_top_num != 0) {
1138 $retval = $this->_highscore_top_num;
1139 }
1140
1141 return $retval;
1142 }
1143
1144 public function getHighscoreMode(): int
1145 {
1146 switch (true) {
1147 case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
1149
1150 case $this->getHighscoreTopTable():
1152
1153 case $this->getHighscoreOwnTable():
1154 default:
1156 }
1157 }
1158
1159
1160 public function setHighscoreMode(int $mode): void
1161 {
1162 switch ($mode) {
1164 $this->setHighscoreTopTable(true);
1165 $this->setHighscoreOwnTable(true);
1166 break;
1167
1169 $this->setHighscoreTopTable(true);
1170 $this->setHighscoreOwnTable(false);
1171 break;
1172
1174 default:
1175 $this->setHighscoreTopTable(false);
1176 $this->setHighscoreOwnTable(true);
1177 break;
1178 }
1179 }
1180
1181 /* End GET/SET for highscore feature */
1182
1186 public function getDataSetMapping(): array
1187 {
1188 if (null === ($lrsTypeId = $this->getLrsTypeId())) {
1189 $this->doRead();
1190 }
1191 return [
1192 'obj_id' => $this->getId(),
1193 'lrs_type_id' => $this->getLrsTypeId(),
1194 'content_type' => $this->getContentType(),
1195 'source_type' => $this->getSourceType(),
1196 'activity_id' => $this->getActivityId(),
1197 'publisher_id' => $this->getPublisherId(),
1198 'instructions' => $this->getInstructions(),
1199 'launch_url' => $this->getLaunchUrl(),
1200 'launch_parameters' => $this->getLaunchParameters(),
1201 'moveon' => $this->getMoveOn(),
1202 'entitlement_key' => $this->getEntitlementKey(),
1203 'auth_fetch_url' => (int) $this->isAuthFetchUrlEnabled(),
1204 'launch_method' => $this->getLaunchMethod(),
1205 'launch_mode' => $this->getLaunchMode(),
1206 'switch_to_review' => (int) $this->isSwitchToReviewEnabled(),
1207 'mastery_score' => $this->getMasteryScore(),
1208 'keep_lp' => (int) $this->isKeepLpStatusEnabled(),
1209 'privacy_ident' => $this->getPrivacyIdent(),
1210 'privacy_name' => $this->getPrivacyName(),
1211 'usr_privacy_comment' => $this->getUserPrivacyComment(),
1212 'show_statements' => (int) $this->isStatementsReportEnabled(),
1213 'xml_manifest' => $this->getXmlManifest(),
1214 'version' => $this->getVersion(),
1215 'highscore_enabled' => (int) $this->getHighscoreEnabled(),
1216 'highscore_achieved_ts' => (int) $this->getHighscoreAchievedTS(),
1217 'highscore_percentage' => (int) $this->getHighscorePercentage(),
1218 'highscore_wtime' => (int) $this->getHighscoreWTime(),
1219 'highscore_own_table' => (int) $this->getHighscoreOwnTable(),
1220 'highscore_top_table' => (int) $this->getHighscoreTopTable(),
1221 'highscore_top_num' => $this->getHighscoreTopNum(),
1222 'only_moveon' => (int) $this->getOnlyMoveon(),
1223 'achieved' => (int) $this->getAchieved(),
1224 'answered' => (int) $this->getAnswered(),
1225 'completed' => (int) $this->getCompleted(),
1226 'failed' => (int) $this->getFailed(),
1227 'initialized' => (int) $this->getInitialized(),
1228 'passed' => (int) $this->getPassed(),
1229 'progressed' => (int) $this->getProgressed(),
1230 'satisfied' => (int) $this->getSatisfied(),
1231 'c_terminated' => (int) $this->getTerminated(),
1232 'hide_data' => (int) $this->getHideData(),
1233 'c_timestamp' => (int) $this->getTimestamp(),
1234 'duration' => (int) $this->getDuration(),
1235 'no_substatements' => (int) $this->getNoSubstatements(),
1236 'delete_data' => (int) $this->getDeleteData()
1237 //'bypass_proxy' => (int) $this->isBypassProxyEnabled()
1238 ];
1239 }
1240
1246 protected function doCloneObject(ilObject2 $new_obj, int $a_target_id, ?int $a_copy_id = null): void
1247 {
1248 assert($new_obj instanceof ilObjCmiXapi);
1249
1250 $this->cloneMetaData($new_obj);
1251
1252 $new_obj->setLrsTypeId($this->getLrsTypeId());
1253 $new_obj->setContentType($this->getContentType());
1254 $new_obj->setSourceType($this->getSourceType());
1255 $new_obj->setActivityId($this->getActivityId());
1256 $new_obj->setPublisherId($this->getPublisherId());
1257 $new_obj->setInstructions($this->getInstructions());
1258 $new_obj->setLaunchUrl($this->getLaunchUrl());
1259 $new_obj->setLaunchParameters($this->getLaunchParameters());
1260 $new_obj->setMoveOn($this->getMoveOn());
1261 $new_obj->setEntitlementKey($this->getEntitlementKey());
1262 $new_obj->setAuthFetchUrlEnabled($this->isAuthFetchUrlEnabled());
1263 $new_obj->setLaunchMethod($this->getLaunchMethod());
1264 $new_obj->setLaunchMode($this->getLaunchMode());
1265 $new_obj->setSwitchToReviewEnabled($this->isSwitchToReviewEnabled());
1266 $new_obj->setMasteryScore($this->getMasteryScore());
1267 $new_obj->setKeepLpStatusEnabled($this->isKeepLpStatusEnabled());
1268 $new_obj->setPrivacyIdent($this->getPrivacyIdent());
1269 $new_obj->setPrivacyName($this->getPrivacyName());
1270 $new_obj->setUserPrivacyComment($this->getUserPrivacyComment());
1271 $new_obj->setStatementsReportEnabled($this->isStatementsReportEnabled());
1272 $new_obj->setXmlManifest($this->getXmlManifest());
1273 $new_obj->setVersion($this->getVersion());
1274 $new_obj->setHighscoreEnabled($this->getHighscoreEnabled());
1275 $new_obj->setHighscoreAchievedTS($this->getHighscoreAchievedTS());
1276 $new_obj->setHighscorePercentage($this->getHighscorePercentage());
1277 $new_obj->setHighscoreWTime($this->getHighscoreWTime());
1278 $new_obj->setHighscoreOwnTable($this->getHighscoreOwnTable());
1279 $new_obj->setHighscoreTopTable($this->getHighscoreTopTable());
1280 $new_obj->setHighscoreTopNum($this->getHighscoreTopNum());
1281 $new_obj->setBypassProxyEnabled($this->isBypassProxyEnabled());
1282 $new_obj->setOnlyMoveon($this->getOnlyMoveon());
1283 $new_obj->setAchieved($this->getAchieved());
1284 $new_obj->setAnswered($this->getAnswered());
1285 $new_obj->setCompleted($this->getCompleted());
1286 $new_obj->setFailed($this->getFailed());
1287 $new_obj->setInitialized($this->getInitialized());
1288 $new_obj->setPassed($this->getPassed());
1289 $new_obj->setProgressed($this->getProgressed());
1290 $new_obj->setSatisfied($this->getSatisfied());
1291 $new_obj->setTerminated($this->getTerminated());
1292 $new_obj->setHideData($this->getHideData());
1293 $new_obj->setTimestamp($this->getTimestamp());
1294 $new_obj->setDuration($this->getDuration());
1295 $new_obj->setNoSubstatements($this->getNoSubstatements());
1296 $new_obj->setDeleteData($this->getDeleteData());
1297 $new_obj->update();
1298
1299 if ($this->getSourceType() == self::SRC_TYPE_LOCAL) {
1300 $dirUtil = new ilCmiXapiContentUploadImporter($new_obj);
1301 $dirUtil->ensureCreatedObjectDirectory();
1302 $newDir = implode(DIRECTORY_SEPARATOR, [ilFileUtils::getWebspaceDir(), $dirUtil->getWebDataDirRelativeObjectDirectory()]);
1303 $dirUtil = new ilCmiXapiContentUploadImporter($this);
1304 $thisDir = implode(DIRECTORY_SEPARATOR, [ilFileUtils::getWebspaceDir(), $dirUtil->getWebDataDirRelativeObjectDirectory()]);
1305 ilFileUtils::rCopy($thisDir, $newDir);
1306 }
1307 }
1308
1309 protected function doDelete(): void
1310 {
1311 // delete file data entry
1312 $query = "DELETE FROM " . self::DB_TABLE_NAME . " WHERE obj_id = " . $this->database->quote($this->getId(), 'integer');
1313 $this->database->manipulate($query);
1315
1316 // delete entire directory and its content
1317 $dirUtil = new ilCmiXapiContentUploadImporter($this);
1318 $thisDir = implode(DIRECTORY_SEPARATOR, [ilFileUtils::getWebspaceDir(), $dirUtil->getWebDataDirRelativeObjectDirectory()]);
1319 if (is_dir($thisDir)) {
1320 ilFileUtils::delDir($thisDir);
1321 }
1322
1323 // delete meta data
1324 $this->deleteMetaData();
1325
1326 //delete results
1327 $query = "DELETE FROM " . self::DB_RESULTS_TABLE_NAME .
1328 " WHERE obj_id = " . $this->database->quote($this->getId(), 'integer');
1329 $this->database->manipulate($query);
1330
1331 // TODO check xapidel
1332 }
1333
1334 // /**
1335 // * @return string[]
1336 // */
1337 // public function getRegistrations() : array
1338 // {
1339 // global $DIC;
1340 // $res = $DIC->database()->queryF(
1341 // "SELECT DISTINCT registration FROM " . self::DB_USERS_TABLE_NAME . " WHERE obj_id = %s",
1342 // array('text'),
1343 // array($this->getId())
1344 // );
1345 // $ret = [];
1346 // while ($row = $DIC->database()->fetchAssoc($res)) {
1347 // $ret[] = (string) $row['registration'];
1348 // }
1349 // return $ret;
1350 // }
1351
1355 public static function guidv4(?string $data = null): string
1356 {
1357 // Generate 16 bytes (128 bits) of random data or use the data passed into the function.
1358 $data ??= random_bytes(16);
1359 assert(strlen($data) == 16);
1360
1361 // Set version to 0100
1362 $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
1363 // Set bits 6-7 to 10
1364 $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
1365
1366 // Output the 36 character UUID.
1367 return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
1368 }
1369
1371 {
1372 global $DIC;
1373 if (null === $this->currentCmixUser) {
1374 $this->currentCmixUser = new ilCmiXapiUser($this->getId(), $DIC->user()->getId(), $this->getPrivacyIdent());
1375 }
1377 }
1378
1382 public function getSessionId(?ilCmiXapiUser $cmixUser = null): string
1383 {
1384 if (null === $cmixUser) {
1385 $cmixUser = $this->getCurrentCmixUser();
1386 }
1387 return ilCmiXapiAuthToken::getCmi5SessionByUsrIdAndObjIdAndRefId($cmixUser->getUsrId(), $this->getId(), $this->getRefId());
1388 }
1389
1394 public function getLaunchData(?ilCmiXapiUser $cmixUser = null, string $lang = 'en'): array
1395 {
1396 if (null === $cmixUser) {
1397 $cmixUser = $this->getCurrentCmixUser();
1398 }
1399 // ToDo
1400 $moveOn = $this->getLMSMoveOn();
1401 if (!$moveOn || $moveOn == '') {
1402 $moveOn = 'Completed';
1403 }
1404 $launchMode = $this->getLaunchMode();
1405 // only check switch if self::LAUNCH_MODE_NORMAL
1406 if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1407 if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1409 }
1410 }
1411 $ctxTemplate = [
1412 "contextTemplate" => $this->getLaunchedContextTemplate($cmixUser),
1413 "launchMode" => ucfirst($launchMode),
1414 "launchMethod" => "OwnWindow",
1415 "moveOn" => $moveOn
1416 ];
1417 $lmsLaunchMethod = $this->getLaunchMethod();
1418 if ($lmsLaunchMethod === "ownWin") {
1419 $href = ilLink::_getStaticLink(
1420 $this->getRefId(),
1421 $this->getType()
1422 );
1423 $ctxTemplate['returnURL'] = $href;
1424 } else {
1425 $ctxTemplate['returnURL'] = ILIAS_HTTP_PATH . "/components/ILIAS/CmiXapi/xapiexit.php?lang={$lang}";
1426 }
1427 if (!empty($this->getMasteryScore())) {
1428 $ctxTemplate['masteryScore'] = $this->getMasteryScore();
1429 }
1430 if (!empty($this->getLaunchParameters())) {
1431 $ctxTemplate['launchParameters'] = $this->getLaunchParameters();
1432 }
1433 if (!empty($this->getEntitlementKey())) {
1434 $ctxTemplate['entitlementKey'] = array("courseStructure" => $this->getEntitlementKey());
1435 }
1436 return $ctxTemplate;
1437 }
1438
1442 public function getLaunchedContextTemplate(?ilCmiXapiUser $cmixUser = null): array
1443 {
1444 if (null === $cmixUser) {
1445 $cmixUser = $this->getCurrentCmixUser();
1446 }
1447 $launchMode = $this->getLaunchMode();
1448 // only check switch if self::LAUNCH_MODE_NORMAL
1449 if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1450 if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1452 }
1453 }
1454 $extensions = $this->getStatementExtensions($cmixUser);
1455 $extensions['https://w3id.org/xapi/cmi5/context/extensions/launchmode'] = $launchMode;
1456 if (!empty($this->getLMSMoveOn())) {
1457 $extensions['https://w3id.org/xapi/cmi5/context/extensions/moveon'] = $this->getLMSMoveOn();
1458 }
1459 if (!empty($this->getLaunchParameters())) {
1460 $extensions['https://w3id.org/xapi/cmi5/context/extensions/launchparameters'] = $this->getLaunchParameters();
1461 }
1462 if (!empty($this->getMasteryScore())) {
1463 $extensions['https://w3id.org/xapi/cmi5/context/extensions/masteryscore'] = $this->getMasteryScore();
1464 }
1465 return array(
1466 "contextActivities" => $this->getStatementContextActivities(),
1467 "extensions" => $extensions
1468 );
1469 }
1470
1476 public function getStatement(string $verb, ?ilCmiXapiUser $cmixUser = null): array
1477 {
1478 if (null === $cmixUser) {
1479 $cmixUser = $this->getCurrentCmixUser();
1480 }
1481 $id = self::guidv4();
1482 $actor = $this->getStatementActor($cmixUser);
1483 $verbUri = ilCmiXapiVerbList::getInstance()->getVerbUri($verb);
1484 $extensions = $this->getStatementExtensions($cmixUser);
1485 $registration = $cmixUser->getRegistration();
1486 $contextActivities = $this->getStatementContextActivities();
1487 $object = $this->getStatementObject();
1488 return array(
1489 'id' => $id,
1490 'actor' => $actor,
1491 'verb' =>
1492 array(
1493 'id' => $verbUri
1494 ),
1495 'context' =>
1496 array(
1497 'extensions' => $extensions,
1498 'registration' => $registration,
1499 'contextActivities' => $contextActivities
1500 ),
1501 'object' => $object
1502 );
1503 }
1504
1509 public function getStatementActor(?ilCmiXapiUser $cmixUser = null): array
1510 {
1511 global $DIC;
1512 if (null === $cmixUser) {
1513 $cmixUser = $this->getCurrentCmixUser();
1514 }
1515 $user = new ilObjUser($cmixUser->getUsrId()); // ToDo: Caching Names
1516 $name = ilCmiXapiUser::getName($this->getPrivacyName(), $user);
1517 if ($name == '') {
1518 $this->log()->error('error: no name in cmixuser');
1519 $name = 'UNDEFINED';
1520 }
1521 $homePage = ($this->anonymousHomePage == true) ? self::ANONYMOUS_HOMEPAGE : self::iliasUrl();
1522 if ($this->getContentType() == self::CONT_TYPE_CMI5) {
1523 $actor = [
1524 'objectType' => 'Agent',
1525 'account' => [
1526 'homePage' => $homePage,
1527 'name' => $cmixUser->getUsrIdent()
1528 ]
1529 ];
1530 if ($name !== '') {
1531 $actor['name'] = $name;
1532 }
1533 } else {
1534 $actor = [
1535 'objectType' => 'Agent',
1536 'mbox' => 'mailto:' . $cmixUser->getUsrIdent()
1537 ];
1538 if ($name !== '') {
1539 $actor['name'] = $name;
1540 }
1541 }
1542 return $actor;
1543 }
1544
1550 public function getStatementExtensions(?ilCmiXapiUser $cmixUser = null): array
1551 {
1552 if (null === $cmixUser) {
1553 $cmixUser = $this->getCurrentCmixUser();
1554 }
1555 return array(
1556 'https://w3id.org/xapi/cmi5/context/extensions/sessionid' => $this->getSessionId($cmixUser),
1557 'https://ilias.de/cmi5/activityid' => $this->getActivityId()
1558 );
1559 }
1560
1565 public function getStatementContextActivities(): array
1566 {
1567 $publisherId = $this->getPublisherId();
1568 $activityId = $this->getActivityId();
1569 if (empty($publisherId)) {
1571 }
1572 return array(
1573 "grouping" => [
1574 [
1575 "objectType" => "Activity",
1576 "id" => "{$publisherId}",
1577 'definition' =>
1578 array(
1579 'name' =>
1580 array(
1581 'de-DE' => $this->getTitle(),
1582 'en-US' => $this->getTitle()
1583 ),
1584 'description' =>
1585 array(
1586 'de-DE' => $this->getDescription(),
1587 'en-US' => $this->getDescription()
1588 )
1589 )]
1590 ],
1591 "category" => [
1592 [
1593 "id" => "https://w3id.org/xapi/cmi5/context/categories/cmi5",
1594 "objectType" => "Activity"
1595 ]
1596 ]
1597 );
1598 }
1599
1603 public function getStatementObject(): array
1604 {
1605 return array(
1606 'id' => $this->getActivityId(),
1607 'definition' =>
1608 array(
1609 'name' =>
1610 array(
1611 'de-DE' => $this->getTitle(),
1612 'en-US' => $this->getTitle()
1613 ),
1614 'description' =>
1615 array(
1616 'de-DE' => $this->getDescription(),
1617 'en-US' => $this->getDescription()
1618 )
1619 )
1620 );
1621 }
1622
1627 public function getLaunchedStatement(?ilCmiXapiUser $cmixUser = null): array
1628 {
1629 if (null === $cmixUser) {
1630 $cmixUser = $this->getCurrentCmixUser();
1631 }
1632 $launchMode = $this->getLaunchMode();
1633 // only check switch if self::LAUNCH_MODE_NORMAL
1634 if ($launchMode == self::LAUNCH_MODE_NORMAL) {
1635 if ($cmixUser->getSatisfied() && $this->isSwitchToReviewEnabled()) {
1637 }
1638 }
1639
1640 $statement = $this->getStatement('launched', $cmixUser);
1641 $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/launchmode'] = $launchMode;
1642 if (!empty($this->getLMSMoveOn())) {
1643 $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/moveon'] = $this->getLMSMoveOn();
1644 }
1645 if (!empty($this->getLaunchParameters())) {
1646 $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/launchparameters'] = $this->getLaunchParameters();
1647 }
1648 if (!empty($this->getMasteryScore())) {
1649 $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/masteryscore'] = $this->getMasteryScore();
1650 }
1651 return $statement;
1652 }
1653
1658 public function getAbandonedStatement(?string $sessionId, ?string $duration, ?ilCmiXapiUser $cmixUser = null): array
1659 {
1660 if (null === $cmixUser) {
1661 $cmixUser = $this->getCurrentCmixUser();
1662 }
1663 $statement = $this->getStatement('abandoned', $cmixUser);
1664 // overwrite session with abandoned oldSession
1665 $statement['context']['extensions']['https://w3id.org/xapi/cmi5/context/extensions/sessionid'] = $sessionId;
1666 $statement['result'] = array(
1667 'duration' => $duration
1668 );
1669 return $statement;
1670 }
1671
1676 public function getSatisfiedStatement(?ilCmiXapiUser $cmixUser = null): array
1677 {
1678 if (null === $cmixUser) {
1679 $cmixUser = $this->getCurrentCmixUser();
1680 }
1681 $statement = $this->getStatement('satisfied', $cmixUser);
1682 // add type, see https://aicc.github.io/CMI-5_Spec_Current/samples/scenarios/16-not_applicable-no_launch/#satisfied-statement
1683 // see also: https://github.com/AICC/CMI-5_Spec_Current/blob/quartz/cmi5_spec.md#verbs_satisfied
1684 $type = "https://w3id.org/xapi/cmi5/activitytype/course";
1685 $statement['object']['definition']['type'] = $type;
1686 $statement['context']['contextActivities']['grouping'][0]['definition']['type'] = $type;
1687 return $statement;
1688 }
1689
1694 public function getLastStatement(string $sess): mixed
1695 {
1696 global $DIC;
1697 $lrsType = $this->getLrsType();
1698
1699 //$this->getLrsEndpoint())) . '/api/' . self::ENDPOINT_AGGREGATE_SUFFIX;
1701 //$fallbackLrs = $lrsType->getLrsFallbackEndpoint();
1702 $defaultBasicAuth = $lrsType->getBasicAuth();
1703 //$fallbackBasicAuth = $lrsType->getFallbackBasicAuth();
1704 $defaultHeaders = [
1705 'X-Experience-API-Version' => '1.0.3',
1706 'Authorization' => $defaultBasicAuth,
1707 'Cache-Control' => 'no-cache, no-store, must-revalidate'
1708 ];
1709 /*
1710 $fallbackHeaders = [
1711 'X-Experience-API-Version' => '1.0.3',
1712 'Authorization' => $fallbackBasicAuth,
1713 'Content-Type' => 'application/json;charset=utf-8',
1714 'Cache-Control' => 'no-cache, no-store, must-revalidate'
1715 ];
1716 */
1717 $pipeline = json_encode($this->getLastStatementPipline($sess));
1718 $defaultLastStatementUrl = $defaultLrs . "?pipeline=" . urlencode($pipeline);
1719 $client = new GuzzleHttp\Client();
1720 $req_opts = array(
1721 GuzzleHttp\RequestOptions::VERIFY => true,
1722 GuzzleHttp\RequestOptions::CONNECT_TIMEOUT => 10,
1723 GuzzleHttp\RequestOptions::HTTP_ERRORS => false
1724 );
1725 $defaultLastStatementRequest = new GuzzleHttp\Psr7\Request(
1726 'GET',
1727 $defaultLastStatementUrl,
1728 $defaultHeaders
1729 );
1730 $promises = array();
1731 $promises['defaultLastStatement'] = $client->sendAsync($defaultLastStatementRequest, $req_opts);
1732 try {
1733 $responses = GuzzleHttp\Promise\Utils::settle($promises)->wait();
1734 $body = '';
1735 ilCmiXapiAbstractRequest::checkResponse($responses['defaultLastStatement'], $body, [200]);
1736 return json_decode($body, (bool) JSON_OBJECT_AS_ARRAY);
1737 } catch (Exception $e) {
1738 $this->log()->error('error:' . $e->getMessage());
1739 return null;
1740 }
1741 }
1742
1746 public function getLastStatementPipline(string $sess): array
1747 {
1748 global $DIC;
1749 $pipeline = array();
1750
1751 // filter activityId
1752 $match = array();
1753 $match['statement.object.objectType'] = 'Activity';
1754 $match['statement.actor.objectType'] = 'Agent';
1755
1756 $activityId = array();
1757
1758 if ($this->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5 && !$this->isMixedContentType()) {
1759 // https://github.com/AICC/CMI-5_Spec_Current/blob/quartz/cmi5_spec.md#963-extensions
1760 $activityId['statement.context.extensions.https://ilias&46;de/cmi5/activityid'] = $this->getActivityId();
1761 } else {
1762 $activityQuery = [
1763 '$regex' => '^' . preg_quote($this->getActivityId()) . ''
1764 ];
1765 $activityId['$or'] = [];
1766 $activityId['$or'][] = ['statement.object.id' => $activityQuery];
1767 $activityId['$or'][] = ['statement.context.contextActivities.parent.id' => $activityQuery];
1768 }
1769
1770 $sessionId = array();
1771 $sessionId['statement.context.extensions.https://w3id&46;org/xapi/cmi5/context/extensions/sessionid'] = $sess;
1772 $match['$and'] = array();
1773 $match['$and'][] = $activityId;
1774 $match['$and'][] = $sessionId;
1775 $sort = array('statement.timestamp' => -1);
1776 $project = array('statement.timestamp' => 1, 'statement.verb.id' => 1);
1777 $pipeline[] = array('$match' => $match);
1778 $pipeline[] = array('$sort' => $sort);
1779 $pipeline[] = array('$limit' => 1);
1780 $pipeline[] = array('$project' => $project);
1781
1782 return $pipeline;
1783 }
1784
1785 public static function iliasUrl(): string
1786 {
1787 global $DIC;
1788 $regex = '/^(https?:\/\/[^\/]+).*/';
1789 preg_match($regex, (string) $DIC->http()->request()->getUri(), $request_parts);
1790 return $request_parts[1];
1791 }
1792
1793 public static function log(): ilLogger
1794 {
1795 if (self::PLUGIN) {
1796 global $log;
1797 return $log;
1798 } else {
1799 return \ilLoggerFactory::getLogger('cmix');
1800 }
1801 }
1802
1803
1804 public function isActivationLimited(): ?bool
1805 {
1807 }
1808
1809
1810 public function setActivationLimited(bool $activationLimited): void
1811 {
1812 $this->activationLimited = $activationLimited;
1813 }
1814
1815 public function getActivationStartingTime(): ?int
1816 {
1818 }
1819
1820 public function setActivationStartingTime(?int $activationStartingTime = null): void
1821 {
1822 $this->activationStartingTime = $activationStartingTime;
1823 }
1824
1825 public function getActivationEndingTime(): ?int
1826 {
1828 }
1829
1830 public function setActivationEndingTime(?int $activationEndingTime = null): void
1831 {
1832 $this->activationEndingTime = $activationEndingTime;
1833 }
1834
1835 public function getActivationVisibility(): ?bool
1836 {
1838 }
1839
1841 {
1842 $this->activationVisibility = $activationVisibility;
1843 }
1844}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
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
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_COMPL_OR_PASSED_WITH_FAILED
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)
setOnlyMoveon(bool $only_moveon)
getHighscoreWTime()
Gets if the column with the workingtime should be shown.
setHideData(bool $hide_data)
getHighscoreTopNum(?int $a_retval=10)
Gets the number of entries which are to be shown in the top-rankings table.
setPrivacyName(int $userName)
setContentType(string $contentType)
getLPMode()
only for internal LMS usage
setNoSubstatements(bool $no_substatements)
ilCmiXapiUser $currentCmixUser
getSessionId(?ilCmiXapiUser $cmixUser=null)
static getObjectsHavingBypassProxyEnabledAndRegisteredUsers()
ilDBInterface $database
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)
setPublisherId(string $publisherId)
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)
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
doCloneObject(ilObject2 $new_obj, int $a_target_id, ?int $a_copy_id=null)
bool $activationLimited
repository object activation settings (handled by ilObject)
setAnswered(bool $answered)
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)
setLrsTypeId(int $lrsTypeId)
const PRIVACY_IDENT_IL_UUID_LOGIN
setDeleteData(int $deleteData)
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
setMasteryScorePercent(float $masteryScorePercent)
const PRIVACY_IDENT_IL_UUID_SHA256
setProgressed(bool $progressed)
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
getLaunchData(?ilCmiXapiUser $cmixUser=null, string $lang='en')
LMS.LaunchData.
getStatementContextActivities()
Minimal statementActivities.
setInitialized(bool $initialized)
getHighscoreOwnTable()
Gets if the own rankings table should be shown.
getLastStatement(string $sess)
get latest statement from session
setCompleted(bool $completed)
__construct(int $a_id=0, bool $a_reference=true)
ilObjCmiXapi constructor.
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.
setActivationLimited(bool $activationLimited)
setPassed(bool $passed)
getHighscoreEnabled()
Gets the setting which determines if the highscore feature is enabled.
setActivationStartingTime(?int $activationStartingTime=null)
setVersion(int $version)
setLaunchUrl(string $launchUrl)
setLrsType(\ilCmiXapiLrsType $lrsType)
setUserPrivacyComment(string $userPrivacyComment)
setEntitlementKey(string $entitlementKey)
setHighscoreEnabled(bool $a_enabled)
Sets if the highscore feature should be enabled.
static updatePrivacySettingsFromLrsType(ilCmiXapiLrsType $lrsType)
static updateByPassProxyFromLrsType(ilCmiXapiLrsType $lrsType)
setFailed(bool $failed)
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)
getAbandonedStatement(?string $sessionId, ?string $duration, ?ilCmiXapiUser $cmixUser=null)
setActivityId(string $activityId)
getLastStatementPipline(string $sess)
getStatementActor(?ilCmiXapiUser $cmixUser=null)
statement actor
setPrivacyIdent(int $userIdent)
User class.
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.
static getItem(int $ref_id)
static getInstance(int $obj_id)
ilLogger $log
ilObjUser $user
string $type
$client
Interface ilDBInterface.
$res
Definition: ltiservices.php:69
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $DIC
Definition: shib_login.php:26
$lang
Definition: xapiexit.php:25