ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
XapiProxyPolyFill.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
20 namespace 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 }
$res
Definition: ltiservices.php:69
exit
Definition: login.php:28
static getInstanceByToken(string $token)
$objId
Definition: xapitoken.php:57
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: DataService.php:21
$client
static http()
Fetches the global http state from ILIAS.
if(!file_exists(getcwd() . '/ilias.ini.php'))
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: confirmReg.php:20
$log
Definition: result.php:33
$token
Definition: xapitoken.php:70
static saveProxySuccess(int $objId, int $usrId, int $privacyIdent)
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
getLrsTypeAndMoreByToken()
hybrid function, maybe two distinct functions would be better?
$query
__construct(string $client, string $token, ?bool $plugin=false)