19declare(strict_types=1);
61 ?
string $scope = self::DELETE_SCOPE_FILTERED,
64 $this->objId = $obj_id;
66 $this->activityId = $activity_id;
67 $this->usrId = $usr_id;
71 $this->endpointDefault = $this->lrsType->getLrsEndpoint();
73 'X-Experience-API-Version' =>
'1.0.3'
76 $this->defaultHeaders[
'Authorization'] = $this->lrsType->getBasicAuth();
84 public function delete():
bool
88 $resStatements = $allResponses[
'statements'];
89 $resStates = $allResponses[
'states'];
90 $defaultRejected = isset($resStatements[
'default']) && isset($resStatements[
'default'][
'state']) && $resStatements[
'default'][
'state'] ===
'rejected';
93 if (isset($resStatements[
'default']) && isset($resStatements[
'default'][
'value'])) {
94 $res = $resStatements[
'default'][
'value'];
95 $resBody = json_decode((
string)
$res->getBody(),
true);
96 $resArr[] = $resBody[
'_id'];
98 if (count($resArr) == 0) {
99 $this->log->debug(
"No data deleted");
100 return !$defaultRejected;
106 while ($t < $maxtime) {
112 $resBody = json_decode((
string)
$res->getBody(),
true);
113 if ($resBody && $resBody[
'edges'] && count($resBody[
'edges']) == 1) {
114 $doneDefault = $resBody[
'edges'][0][
'node'][
'done'];
115 $this->log->debug(
"doneDefault: " . $doneDefault);
137 if ($this->scope === self::DELETE_SCOPE_FILTERED) {
141 if ($this->scope === self::DELETE_SCOPE_ALL) {
144 if ($this->scope === self::DELETE_SCOPE_OWN) {
148 $this->log->debug(
'error: could not build filter');
151 $cf = array(
'filter' =>
$f);
152 $body = json_encode($cf);
153 $this->defaultHeaders[
'Content-Type'] =
'application/json; charset=utf-8';
154 $defaultUrl = $this->lrsType->getLrsEndpointDeleteLink();
155 $promisesStatements = [
156 'default' => $this->
sendCurlRequest(
'POST', $defaultUrl, $this->defaultHeaders, $body),
158 $promisesStates = array();
161 foreach ($urls as $i => $v) {
162 $promisesStates[
'default' . $i] = $this->
sendCurlRequest(
'DELETE', $v, $this->defaultHeaders, $body);
171 if ($deleteState && count($promisesStates) > 0) {
174 }
catch (Exception
$e) {
175 $this->log->debug(
'error:' .
$e->getMessage());
187 if (
$scope === self::DELETE_SCOPE_OWN) {
189 if (count(
$f) == 0) {
193 if (
$scope === self::DELETE_SCOPE_FILTERED) {
196 if ($scope === self::DELETE_SCOPE_ALL) {
199 $pipeline[] = array(
'$match' =>
$f);
200 $pipeline[] = array(
'$count' =>
'count');
201 $pquery = urlencode(json_encode($pipeline));
202 $query =
"pipeline={$pquery}";
203 $purl = $this->lrsType->getLrsEndpointStatementsAggregationLink();
208 $cnt = json_decode(
$response[
'body'],
true);
210 return (
int) $cnt[0]->count;
211 }
catch (Exception
$e) {
212 throw new Exception(
"LRS Connection Problems");
220 $defaultUrl = $this->
getBatchUrl($this->lrsType->getLrsEndpointBatchLink(), $batchId[0]);
224 foreach ($this->defaultHeaders as $key => $value) {
228 $ch = curl_init($defaultUrl);
229 curl_setopt_array($ch, [
230 CURLOPT_RETURNTRANSFER =>
true,
232 CURLOPT_TIMEOUT => 30,
233 CURLOPT_SSL_VERIFYPEER =>
true,
234 CURLOPT_FOLLOWLOCATION =>
true,
239 $body = curl_exec($ch);
240 $error = curl_error($ch);
241 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
245 throw new Exception(
"cURL error: $error");
249 'state' => ($httpCode >= 200 && $httpCode < 300) ?
'fulfilled' :
'rejected',
250 'value' => (
object) [
251 'status' => $httpCode,
256 }
catch (Exception
$e) {
257 $this->log->debug(
'error:' .
$e->getMessage());
259 'state' =>
'rejected',
260 'reason' =>
$e->getMessage()
273 $f = urlencode(json_encode(
$f));
282 foreach ($states as $i => $v) {
293 $f[
'statement.object.objectType'] =
'Activity';
294 $f[
'statement.object.id'] = [
295 '$regex' =>
'^' . preg_quote($this->activityId) .
''
298 $f[
'statement.actor.objectType'] =
'Agent';
304 $f[
'$or'][] = [
'statement.actor.mbox' =>
"mailto:{$cmixUser->getUsrIdent()}"];
306 if (count(
$f[
'$or']) == 0) {
319 $f[
'statement.object.objectType'] =
'Activity';
320 $f[
'statement.object.id'] = [
321 '$regex' =>
'^' . preg_quote($this->activityId) .
''
324 $f[
'statement.actor.objectType'] =
'Agent';
326 if ($this->
filter->getActor()) {
328 if ($cmixUser->getUsrId() == $this->filter->getActor()->getUsrId()) {
329 $f[
'$or'][] = [
'statement.actor.mbox' =>
"mailto:{$cmixUser->getUsrIdent()}"];
334 $f[
'$or'][] = [
'statement.actor.mbox' =>
"mailto:{$cmixUser->getUsrIdent()}"];
338 if ($this->
filter->getVerb()) {
339 $f[
'statement.verb.id'] = $this->
filter->getVerb();
342 if ($this->
filter->getStartDate() || $this->filter->getEndDate()) {
343 $f[
'statement.timestamp'] = array();
345 if ($this->
filter->getStartDate()) {
346 $f[
'statement.timestamp'][
'$gt'] = $this->
filter->getStartDate()->toXapiTimestamp();
349 if ($this->
filter->getEndDate()) {
350 $f[
'statement.timestamp'][
'$lt'] = $this->
filter->getEndDate()->toXapiTimestamp();
354 if (count(
$f[
'$or']) == 0) {
366 $f[
'statement.object.objectType'] =
'Activity';
367 $f[
'statement.object.id'] = [
368 '$regex' =>
'^' . preg_quote($this->activityId) .
''
370 $f[
'statement.actor.objectType'] =
'Agent';
372 $usrId = ($this->usrId !==
null) ? $this->usrId :
$DIC->user()->getId();
375 foreach ($cmixUsers as $cmixUser) {
376 $f[
'$or'][] = [
'statement.actor.mbox' =>
"mailto:{$cmixUser->getUsrIdent()}"];
378 if (count(
$f[
'$or']) == 0) {
390 if ($this->scope === self::DELETE_SCOPE_FILTERED && $this->
filter->getActor()) {
392 if ($cmixUser->getUsrId() == $this->filter->getActor()->getUsrId()) {
393 $user = $cmixUser->getUsrIdent();
394 $ret[] =
'activityId=' . urlencode($this->activityId) .
'&agent=' . urlencode(
'{"mbox":"mailto:' . $user .
'"}');
399 if ($this->scope === self::DELETE_SCOPE_OWN) {
400 $usrId = ($this->usrId !==
null) ? $this->usrId :
$DIC->user()->getId();
402 if ((
int) $cmixUser->getUsrId() ===
$usrId) {
403 $user = $cmixUser->getUsrIdent();
404 $ret[] =
'activityId=' . urlencode($this->activityId) .
'&agent=' . urlencode(
'{"mbox":"mailto:' . $user .
'"}');
409 if ($this->scope === self::DELETE_SCOPE_ALL) {
412 $user = $cmixUser->getUsrIdent();
413 $ret[] =
'activityId=' . urlencode($this->activityId) .
'&agent=' . urlencode(
'{"mbox":"mailto:' . $user .
'"}');
422 if ($this->scope === self::DELETE_SCOPE_ALL || $this->scope === self::DELETE_SCOPE_OWN) {
425 if ($this->
filter->getActor()) {
426 if ($this->
filter->getVerb() || $this->filter->getStartDate() || $this->filter->getEndDate()) {
438 if ($this->scope === self::DELETE_SCOPE_ALL) {
443 if ($this->scope === self::DELETE_SCOPE_OWN) {
444 $usrId = ($this->usrId !==
null) ? [$this->usrId] : [
$DIC->user()->getId()];
447 if ($this->scope === self::DELETE_SCOPE_FILTERED) {
449 $usrId = [$this->
filter->getActor()->getUsrId()];
456 $ch = curl_init(
$url);
458 $formattedHeaders = [];
459 foreach (
$headers as $key => $value) {
460 $formattedHeaders[] =
"$key: $value";
463 curl_setopt_array($ch, [
464 CURLOPT_RETURNTRANSFER =>
true,
465 CURLOPT_CUSTOMREQUEST => $method,
466 CURLOPT_HTTPHEADER => $formattedHeaders,
467 CURLOPT_CONNECTTIMEOUT => 10,
468 CURLOPT_TIMEOUT => 60,
469 CURLOPT_SSL_VERIFYPEER =>
true,
472 if ($body !==
null && in_array($method, [
'POST',
'PUT',
'PATCH'])) {
473 curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
476 $responseBody = curl_exec($ch);
477 $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
478 $error = curl_error($ch);
483 'status' => $statusCode,
484 'body' => $responseBody,
485 'error' => $error ?:
null,
490 $mh = curl_multi_init();
494 foreach ($requests as $key =>
$req) {
495 if (!is_array(
$req)) {
497 $method =
$req[
'method'] ??
'GET';
500 $body =
$req[
'body'] ??
null;
503 $method =
$req[
'method'] ??
'GET';
506 $body =
$req[
'body'] ??
null;
509 $ch = curl_init(
$url);
510 $formattedHeaders = [];
512 $formattedHeaders[] =
"$k: $v";
515 curl_setopt_array($ch, [
516 CURLOPT_RETURNTRANSFER =>
true,
517 CURLOPT_CUSTOMREQUEST => $method,
518 CURLOPT_HTTPHEADER => $formattedHeaders,
519 CURLOPT_CONNECTTIMEOUT => 10,
520 CURLOPT_TIMEOUT => 60,
521 CURLOPT_SSL_VERIFYPEER =>
true
524 if ($body !==
null && in_array($method, [
'POST',
'PUT',
'PATCH'])) {
525 curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
528 $handles[$key] = $ch;
529 curl_multi_add_handle(
$mh, $ch);
535 curl_multi_exec(
$mh, $running);
536 curl_multi_select(
$mh);
537 }
while ($running > 0);
541 foreach ($handles as $key => $ch) {
543 'state' =>
'fulfilled',
545 'status' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
546 'body' => curl_multi_getcontent($ch),
547 'error' => curl_error($ch) ?: null
551 curl_multi_remove_handle(
$mh, $ch);
555 curl_multi_close(
$mh);
Class ilCmiXapiStatementsDeleteRequest.
executeMultiCurl(array $requests)
__construct(int $obj_id, int $type_id, string $activity_id, ?int $usr_id=null, ?string $scope=self::DELETE_SCOPE_FILTERED, ?ilCmiXapiStatementsReportFilter $filter=null)
checkDeleteUsersForObject()
sendCurlRequest(string $method, string $url, array $headers=[], ?string $body=null)
getBatchUrl(string $url, string $batchId)
_lookUpDataCount($scope=null)
ilCmiXapiLrsType $lrsType
queryBatch(array $batchId)
ilCmiXapiStatementsReportFilter $filter
const DELETE_SCOPE_FILTERED
static deleteUsersForObject(int $objId, ?array $users=[])
static getInstancesByObjectIdAndUsrId(int $objId, int $usrId)
static getUsersForObject(int $objId, bool $asUsrId=false)
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
static appendUrlParameterString(string $a_url, string $a_par, bool $xml_style=false)
if(empty($ltiMessageHint)) $mh
filter(string $filter_id, array $class_path, string $cmd, bool $activated=true, bool $expanded=true)
catch(\Exception $e) $req