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 }
An exception for terminatinating execution or to throw for unit testing.
setXapiProxyRequest($xapiProxyRequest)
Definition: XapiProxy.php:92
handleStatementEvaluation($xapiStatement)
Definition: XapiProxy.php:206
__construct($client, $token, $plugin=false)
Definition: XapiProxy.php:11
setValue(&$obj, $path, $value)
Definition: XapiProxy.php:235
setRequestParams($request)
Definition: XapiProxy.php:17
setXapiProxyResponse($xapiProxyResponse)
Definition: XapiProxy.php:102
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.
static getInstanceByObjId($a_obj_id, $stop_on_error=true)
get an instance of an Ilias object by object id
const ANONYMOUS_USER_ID
Definition: constants.php:25
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
global $DIC
Definition: goto.php:24
$i
Definition: metadata.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$ret
Definition: parser.php:6
$token
Definition: xapitoken.php:52