ILIAS  release_7 Revision v7.30-3-g800a261c036
XapiProxy.php
Go to the documentation of this file.
1 <?php
2  namespace XapiProxy;
3 
4  require_once __DIR__ . '/XapiProxyPolyFill.php';
5 
7  {
10 
11  public function __construct($client, $token, $plugin = false)
12  {
14  $this->log()->debug($this->msg('proxy initialized'));
15  }
16 
17  public function setRequestParams($request)
18  {
19  preg_match(self::PARTS_REG, $request->getUri(), $this->cmdParts);
20  }
21 
22  public function token()
23  {
24  return $this->token;
25  }
26 
27  public function client()
28  {
29  return $this->client;
30  }
31 
32  public function lrsType()
33  {
34  return $this->lrsType;
35  }
36 
37  public function replacedValues()
38  {
39  return $this->replacedValues;
40  }
41 
42  public function specificAllowedStatements()
43  {
44  return $this->specificAllowedStatements;
45  }
46 
47  public function blockSubStatements()
48  {
49  return $this->blockSubStatements;
50  }
51 
52  public function cmdParts()
53  {
54  return $this->cmdParts;
55  }
56 
57  public function method()
58  {
59  return $this->method;
60  }
61 
62  public function getDefaultLrsEndpoint()
63  {
64  return $this->defaultLrsEndpoint;
65  }
66 
67  public function getDefaultLrsKey()
68  {
69  return $this->defaultLrsKey;
70  }
71 
72  public function getDefaultLrsSecret()
73  {
74  return $this->defaultLrsSecret;
75  }
76 
77  public function getFallbackLrsEndpoint()
78  {
79  return $this->fallbackLrsEndpoint;
80  }
81 
82  public function getFallbackLrsKey()
83  {
84  return $this->fallbackLrsKey;
85  }
86 
87  public function getFallbackLrsSecret()
88  {
89  return $this->fallbackLrsSecret;
90  }
91 
92  public function setXapiProxyRequest($xapiProxyRequest)
93  {
94  $this->xapiProxyRequest = $xapiProxyRequest;
95  }
96 
97  public function getXapiProxyRequest()
98  {
99  return $this->xapiProxyRequest;
100  }
101 
102  public function setXapiProxyResponse($xapiProxyResponse)
103  {
104  $this->xapiProxyResponse = $xapiProxyResponse;
105  }
106 
107  public function getXapiProxyResponse()
108  {
109  return $this->xapiProxyResponse;
110  }
111 
112  public function processStatements($request, $body)
113  {
114  // everything is allowed
115  if (!is_array($this->specificAllowedStatements) && !$this->blockSubStatements) {
116  $this->log()->debug($this->msg("all statement are allowed"));
117  return null;
118  }
119  $obj = json_decode($body, false);
120  // single statement object
121  if (is_object($obj) && isset($obj->verb)) {
122  $this->log()->debug($this->msg("json is object and statement"));
123  $isSubStatement = $this->isSubStatementCheck($obj);
124  $verb = $obj->verb->id;
125  if ($this->blockSubStatements && $isSubStatement) {
126  $this->log()->debug($this->msg("sub-statement is NOT allowed, fake response - " . $verb));
127  $this->xapiProxyResponse->fakeResponseBlocked(null);
128  }
129  // $specificAllowedStatements
130  if (!is_array($this->specificAllowedStatements)) {
131  return null;
132  }
133  if (in_array($verb, $this->specificAllowedStatements)) {
134  $this->log()->debug($this->msg("statement is allowed, do nothing - " . $verb));
135  return null;
136  } else {
137  $this->log()->debug($this->msg("statement is NOT allowed, fake response - " . $verb));
138  $this->xapiProxyResponse->fakeResponseBlocked(null);
139  }
140  }
141  // array of statement objects
142  if (is_array($obj) && count($obj) > 0 && isset($obj[0]->verb)) {
143  $this->log()->debug($this->msg("json is array of statements"));
144  $ret = array();
145  $up = array();
146  for ($i = 0; $i < count($obj); $i++) {
147  array_push($ret, $obj[$i]->id); // push every statementid for fakePostResponse
148  $isSubStatement = $this->isSubStatementCheck($obj[$i]);
149  $verb = $obj[$i]->verb->id;
150  if ($this->blockSubStatements && $isSubStatement) {
151  $this->log()->debug($this->msg("sub-statement is NOT allowed - " . $verb));
152  } else {
153  if (!is_array($this->specificAllowedStatements) || (is_array($this->specificAllowedStatements) && in_array($verb, $this->specificAllowedStatements))) {
154  $this->log()->debug($this->msg("statement is allowed - " . $verb));
155  array_push($up, $obj[$i]);
156  }
157  }
158  }
159  if (count($up) === 0) { // nothing allowed
160  $this->log()->debug($this->msg("no allowed statements in array - fake response..."));
161  $this->xapiProxyResponse->fakeResponseBlocked($ret);
162  } elseif (count($up) !== count($ret)) { // mixed request with allowed and not allowed statements
163  $this->log()->debug($this->msg("mixed with allowed and unallowed statements"));
164  return array($up,$ret);
165  } else {
166  // just return nothing
167  return null;
168  }
169  }
170  return null;
171  }
172 
173  public function modifyBody($body)
174  {
175  $obj = json_decode($body, false);
176 
177  if (json_last_error() != JSON_ERROR_NONE) {
178  // JSON is not valid
179  $this->log()->error($this->msg(json_last_error_msg()));
180  return $body;
181  }
182 
183  // $log->debug(json_encode($obj, JSON_PRETTY_PRINT)); // only in DEBUG mode for better performance
184  if (is_object($obj)) {
185  if (is_array($this->replacedValues)) {
186  foreach ($this->replacedValues as $key => $value) {
187  $this->setValue($obj, $key, $value);
188  }
189  }
190  $this->handleStatementEvaluation($obj); // ToDo
191  }
192 
193  if (is_array($obj)) {
194  for ($i = 0; $i < count($obj); $i++) {
195  if (is_array($this->replacedValues)) {
196  foreach ($this->replacedValues as $key => $value) {
197  $this->setValue($obj[$i], $key, $value);
198  }
199  }
200  $this->handleStatementEvaluation($obj[$i]); // ToDo
201  }
202  }
203  return json_encode($obj);
204  }
205 
206  private function handleStatementEvaluation($xapiStatement)
207  {
208  global $DIC;
209  if ($this->plugin) {
210  require_once __DIR__ . '/../class.ilObjXapiCmi5.php';
211  // ToDo: handle terminate -> delete session
212  $this->setStatus($xapiStatement);
213  } else {
214  /* @var $object */
215  $object = \ilObjectFactory::getInstanceByObjId($this->authToken->getObjId());
216  if ((string) $object->getLaunchMode() === (string) \ilObjCmiXapi::LAUNCH_MODE_NORMAL) {
217  // ToDo: check function hasContextActivitiesParentNotEqualToObject!
218  $statementEvaluation = new \ilXapiStatementEvaluation($this->log(), $object);
219  $statementEvaluation->evaluateStatement($xapiStatement, $this->authToken->getUsrId());
220 
221  if ($this->authToken->getUsrId() != ANONYMOUS_USER_ID) {
223  $this->authToken->getObjId(),
224  $this->authToken->getUsrId()
225  );
226  }
227  }
228  if ($xapiStatement->verb->id == self::TERMINATED_VERB) {
229  // ToDo : only cmi5 or also xapi? authToken object still used after that?
230  $this->authToken->delete();
231  }
232  }
233  }
234 
235  private function setValue(&$obj, $path, $value)
236  {
237  $path_components = explode('.', $path);
238  if (count($path_components) == 1) {
239  if (property_exists($obj, $path_components[0])) {
240  $obj->{$path_components[0]} = $value;
241  }
242  } else {
243  if (property_exists($obj, $path_components[0])) {
244  $this->setValue($obj->{array_shift($path_components)}, implode('.', $path_components), $value);
245  }
246  }
247  }
248 
249  private function setStatus($obj)
250  {
251  if (isset($obj->verb) && isset($obj->actor) && isset($obj->object)) {
252  $verb = $obj->verb->id;
253  $score = 'NOT_SET';
254  if (array_key_exists($verb, $this->sniffVerbs)) {
255  // check context
256  if ($this->isSubStatementCheck($obj)) {
257  $this->log()->debug($this->msg("statement is sub-statement, ignore status verb " . $verb));
258  return;
259  }
260  if (isset($obj->result) && isset($obj->result->score) && isset($obj->result->score->scaled)) {
261  $score = $obj->result->score->scaled;
262  }
263  $this->log()->debug($this->msg("handleLPStatus: " . $this->sniffVerbs[$verb] . " : " . $score));
264  \ilObjXapiCmi5::handleLPStatusFromProxy($this->client, $this->token, $this->sniffVerbs[$verb], $score);//UK check
265  }
266  }
267  }
268 
269  private function isSubStatementCheck($obj)
270  {
271  $object = \ilObjectFactory::getInstanceByObjId($this->authToken->getObjId()); // get ActivityId in Constructor for better performance, is also used in handleEvaluationStatement
272  $objActivityId = $object->getActivityId();
273  $statementActivityId = $obj->object->id;
274  if ($statementActivityId != $objActivityId) {
275  $this->log()->debug($this->msg("statement object id " . $statementActivityId . " != activityId " . $objActivityId));
276  $this->log()->debug($this->msg("is Substatement"));
277  return true;
278  } else {
279  $this->log()->debug($this->msg("is not Substatement"));
280  return false;
281  }
282  }
283  }
const ANONYMOUS_USER_ID
Definition: constants.php:25
processStatements($request, $body)
Definition: XapiProxy.php:112
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
setRequestParams($request)
Definition: XapiProxy.php:17
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
setXapiProxyRequest($xapiProxyRequest)
Definition: XapiProxy.php:92
$token
Definition: xapitoken.php:52
global $DIC
Definition: goto.php:24
__construct($client, $token, $plugin=false)
Definition: XapiProxy.php:11
static getInstanceByObjId($a_obj_id, $stop_on_error=true)
get an instance of an Ilias object by object id
setXapiProxyResponse($xapiProxyResponse)
Definition: XapiProxy.php:102
__construct(Container $dic, ilPlugin $plugin)
$ret
Definition: parser.php:6
setValue(&$obj, $path, $value)
Definition: XapiProxy.php:235
handleStatementEvaluation($xapiStatement)
Definition: XapiProxy.php:206
$i
Definition: metadata.php:24