ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
XapiProxyPolyFill.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20namespace XapiProxy;
21
23{
24 protected string $client;
25 protected string $token;
26
27 protected bool $plugin = false;
28 protected string $table_prefix;
29 protected ?\ilCmiXapiLrsType $lrsType = null;
30 protected ?\ilCmiXapiAuthToken $authToken = null;
31 protected ?int $objId = null;
32 protected ?array $specificAllowedStatements = null;
33 protected ?array $replacedValues = null;
34 protected bool $blockSubStatements = false;
35 protected array $cmdParts = [];
36 protected string $method;
37
38 protected string $defaultLrsEndpoint = '';
39 protected string $defaultLrsKey = '';
40 protected string $defaultLrsSecret = '';
41
42 protected string $fallbackLrsEndpoint = '';
43 protected string $fallbackLrsKey = '';
44 protected string $fallbackLrsSecret = '';
45
46 public const PARTS_REG = '/^(.*?xapiproxy\.php)(\/([^?]+)?\??(.*))/'; //'/^(.*?xapiproxy\.php)(\/([^\?]+)?\??.*)/';
47
48 protected array $sniffVerbs = array(
49 "http://adlnet.gov/expapi/verbs/completed" => "completed",
50 "http://adlnet.gov/expapi/verbs/passed" => "passed",
51 "http://adlnet.gov/expapi/verbs/failed" => "failed",
52 "http://adlnet.gov/expapi/verbs/satisfied" => "passed"
53 );
54
55 public const TERMINATED_VERB = "http://adlnet.gov/expapi/verbs/terminated";
56
57 public function __construct(string $client, string $token, ?bool $plugin = false)
58 {
59 $this->client = $client;
60 $this->token = $token;
61 $this->plugin = $plugin;
62 $this->table_prefix = $this->plugin ? "xxcf" : "cmix";
63 preg_match(self::PARTS_REG, (string) $GLOBALS['DIC']->http()->request()->getUri(), $this->cmdParts);
64 $this->method = strtolower($GLOBALS['DIC']->http()->request()->getMethod());
65 }
66
67 public function log(): \ilLogger
68 {
69 if ($this->plugin) {
70 global $log;
71 return $log;
72 } else {
73 return \ilLoggerFactory::getLogger('cmix');
74 }
75 }
76
77 public function msg(string $msg): string
78 {
79 if ($this->plugin) {
80 return "XapiCmi5Plugin: " . $msg;
81 } else {
82 return $msg;
83 }
84 }
85
86 public function initLrs(): void
87 {
88 $this->log()->debug($this->msg('initLrs'));
89 // if ($this->plugin) {
90 // try {
91 // $authToken = \ilXapiCmi5AuthToken::getInstanceByToken($this->token);
92 // }
93 // catch (\ilXapiCmi5Exception $e) {
94 // $this->log()->error($this->msg($e->getMessage()));
95 // header('HTTP/1.1 401 Unauthorized');
96 // header('Access-Control-Allow-Origin: '.$_SERVER["HTTP_ORIGIN"]);
97 // header('Access-Control-Allow-Credentials: true');
98 // exit;
99 // }
100 // $this->authToken = $authToken;
101 // $this->getLrsTypePlugin();
102 // }
103 // else {
104 try {
105 $authToken = \ilCmiXapiAuthToken::getInstanceByToken($this->token);
106 } catch (\ilCmiXapiException $e) {
107 $this->log()->error($this->msg($e->getMessage()));
108 header('HTTP/1.1 401 Unauthorized');
109 header('Access-Control-Allow-Origin: ' . $_SERVER["HTTP_ORIGIN"]);
110 header('Access-Control-Allow-Credentials: true');
111 exit;
112 }
113
114 $this->authToken = $authToken;
115 $this->getLrsType();
116 // }
117 }
118
119 private function getLrsTypePlugin(): void
120 {
121 try {
122 $lrsType = $this->getLrsTypeAndMoreByToken();
123 if ($lrsType == null) {
124 // why not using $log?
125 $GLOBALS['DIC']->logger()->root()->log("XapiCmi5Plugin: 401 Unauthorized for token");
126 header('HTTP/1.1 401 Unauthorized');
127 header('Access-Control-Allow-Origin: ' . $_SERVER["HTTP_ORIGIN"]);
128 header('Access-Control-Allow-Credentials: true');
129 exit;
130 }
131 // $this->defaultLrsEndpoint = $lrsType->getDefaultLrsEndpoint();
132 // $this->defaultLrsKey = $lrsType->getDefaultLrsKey();
133 // $this->defaultLrsSecret = $lrsType->getDefaultLrsSecret();
134 //
135 // $this->fallbackLrsEndpoint = $lrsType->getFallbackLrsEndpoint();
136 // $this->fallbackLrsKey = $lrsType->getFallbackLrsKey();
137 // $this->fallbackLrsSecret = $lrsType->getFallbackLrsSecret();
138
139 $this->lrsType = $lrsType;
140 } catch (\Exception $e) {
141 // why not using $log?
142 $GLOBALS['DIC']->logger()->root()->log("XapiCmi5Plugin: " . $e->getMessage());
143 header('HTTP/1.1 401 Unauthorized');
144 header('Access-Control-Allow-Origin: ' . $_SERVER["HTTP_ORIGIN"]);
145 header('Access-Control-Allow-Credentials: true');
146 exit;
147 }
148 }
149
153 private function getLrsType(): \ilCmiXapiLrsType
154 { // Core new > 6
155 try {
156 $lrsType = $this->getLrsTypeAndMoreByToken();
157 $this->defaultLrsEndpoint = $lrsType->getLrsEndpoint();
158 $this->defaultLrsKey = $lrsType->getLrsKey();
159 $this->defaultLrsSecret = $lrsType->getLrsSecret();
160 $this->lrsType = $lrsType;
161 // one query IS better :-)
162 // $lrsType = new ilCmiXapiLrsType($authToken->getLrsTypeId());
163 $objId = $this->authToken->getObjId();
164 $this->objId = $objId;
165 if (!$lrsType->isAvailable()) {
166 throw new \ilCmiXapiException(
167 'lrs endpoint (id=' . $this->authToken->getLrsTypeId() . ') unavailable (responded 401-unauthorized)'
168 );
169 }
170 } catch (\ilCmiXapiException $e) {
171 $this->log()->error($this->msg($e->getMessage()));
172 header('Access-Control-Allow-Origin: ' . $_SERVER["HTTP_ORIGIN"]);
173 header('Access-Control-Allow-Credentials: true');
174 header('HTTP/1.1 401 Unauthorized');
175 exit;
176 }
177 \ilCmiXapiUser::saveProxySuccess($this->authToken->getObjId(), $this->authToken->getUsrId(), $this->lrsType->getPrivacyIdent());
178 return $lrsType;
179 }
180
186 {
187 $type_id = null;
188 $lrs = null;
189 $db = $GLOBALS['DIC']->database();
190 $query = "SELECT {$this->table_prefix}_settings.lrs_type_id,
191 {$this->table_prefix}_settings.only_moveon,
192 {$this->table_prefix}_settings.achieved,
193 {$this->table_prefix}_settings.answered,
194 {$this->table_prefix}_settings.completed,
195 {$this->table_prefix}_settings.failed,
196 {$this->table_prefix}_settings.initialized,
197 {$this->table_prefix}_settings.passed,
198 {$this->table_prefix}_settings.progressed,
199 {$this->table_prefix}_settings.satisfied,
200 {$this->table_prefix}_settings.c_terminated,
201 {$this->table_prefix}_settings.hide_data,
202 {$this->table_prefix}_settings.c_timestamp,
203 {$this->table_prefix}_settings.duration,
204 {$this->table_prefix}_settings.no_substatements,
205 {$this->table_prefix}_settings.privacy_ident
206 FROM {$this->table_prefix}_settings, {$this->table_prefix}_token
207 WHERE {$this->table_prefix}_settings.obj_id = {$this->table_prefix}_token.obj_id AND {$this->table_prefix}_token.token = " . $db->quote($this->token, 'text');
208
209 $res = $db->query($query);
210 while ($row = $db->fetchObject($res)) {
211 $type_id = (int) $row->lrs_type_id;
212 if ($type_id) {
213 // $lrs = ($this->plugin) ? new \ilXapiCmi5LrsType($type_id) : new \ilCmiXapiLrsType($type_id);
214 $lrs = new \ilCmiXapiLrsType($type_id);
215 }
216
217 $sarr = [];
218 if ((bool) $row->only_moveon) {
219 if ((bool) $row->achieved) {
220 $sarr[] = "https://w3id.org/xapi/dod-isd/verbs/achieved";
221 }
222 if ((bool) $row->answered) {
223 $sarr[] = "http://adlnet.gov/expapi/verbs/answered";
224 $sarr[] = "https://w3id.org/xapi/dod-isd/verbs/answered";
225 }
226 if ((bool) $row->completed) {
227 $sarr[] = "http://adlnet.gov/expapi/verbs/completed";
228 $sarr[] = "https://w3id.org/xapi/dod-isd/verbs/completed";
229 }
230 if ((bool) $row->failed) {
231 $sarr[] = "http://adlnet.gov/expapi/verbs/failed";
232 }
233 if ((bool) $row->initialized) {
234 $sarr[] = "http://adlnet.gov/expapi/verbs/initialized";
235 $sarr[] = "https://w3id.org/xapi/dod-isd/verbs/initialized";
236 }
237 if ((bool) $row->passed) {
238 $sarr[] = "http://adlnet.gov/expapi/verbs/passed";
239 }
240 if ((bool) $row->progressed) {
241 $sarr[] = "http://adlnet.gov/expapi/verbs/progressed";
242 }
243 if ((bool) $row->satisfied) {
244 $sarr[] = "https://w3id.org/xapi/adl/verbs/satisfied";
245 }
246 if ((bool) $row->c_terminated) {
247 $sarr[] = "http://adlnet.gov/expapi/verbs/terminated";
248 }
249 if (count($sarr) > 0) {
250 $this->specificAllowedStatements = $sarr;
251 $this->log()->debug($this->msg('getSpecificAllowedStatements: ' . var_export($this->specificAllowedStatements, true)));
252 }
253 }
254 if ((bool) $row->hide_data) {
255 $rarr = array();
256 if ((bool) $row->c_timestamp) {
257 $rarr['timestamp'] = '1970-01-01T00:00:00.000Z';
258 }
259 if ((bool) $row->duration) {
260 $rarr['result.duration'] = 'PT00.000S';
261 }
262 if (count($rarr) > 0) {
263 $this->replacedValues = $rarr;
264 $this->log()->debug($this->msg('getReplacedValues: ' . var_export($this->replacedValues, true)));
265 }
266 }
267 if ((bool) $row->no_substatements) {
268 $this->blockSubStatements = true;
269 $this->log()->debug($this->msg('getBlockSubStatements: ' . $this->blockSubStatements));
270 }
271 $lrs->setPrivacyIdent((int) $row->privacy_ident);
272 }
273 return $lrs;
274 }
275}
__construct(string $client, string $token, ?bool $plugin=false)
getLrsTypeAndMoreByToken()
hybrid function, maybe two distinct functions would be better?
static getInstanceByToken(string $token)
static saveProxySuccess(int $objId, int $usrId, int $privacyIdent)
Component logger with individual log levels by component id.
exit
$client
$log
Definition: ltiresult.php:34
$res
Definition: ltiservices.php:69
static http()
Fetches the global http state from ILIAS.
$_SERVER['HTTP_HOST']
Definition: raiseError.php:26
if(!file_exists('../ilias.ini.php'))
$GLOBALS["DIC"]
Definition: wac.php:54
$token
Definition: xapitoken.php:70
$objId
Definition: xapitoken.php:57