ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilCmiXapiStatementsReportLinkBuilder.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2019 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 
16 {
20  protected function buildPipeline() : array
21  {
22  $pipeline = array();
23 
24  $pipeline[] = $this->buildFilterStage();
25 
26  $pipeline[] = $this->buildOrderingStage();
27 
28  $pipeline[] = array('$facet' => array(
29  'stage1' => array(
30  array('$group' => array('_id' => null, 'count' => array('$sum' => 1) ))
31  ),
32  'stage2' => $this->buildLimitStage()
33  ));
34 
35  $pipeline[] = array('$unwind' => '$stage1');
36 
37  $pipeline[] = array('$project' => array(
38  'maxcount' => '$stage1.count',
39  'statements' => '$stage2.statement'
40  ));
41 
43  //$log->debug("aggregation pipeline:\n" . json_encode($pipeline, JSON_PRETTY_PRINT));
44 
45  return $pipeline;
46  }
47 
48  protected function buildLimitStage()
49  {
50  $stage = array(
51  array('$skip' => (int) $this->filter->getOffset())
52  );
53 
54  if ($this->filter->getLimit()) {
55  $stage[] = array('$limit' => (int) $this->filter->getLimit());
56  }
57  return $stage;
58  }
59 
60  protected function buildFilterStage()
61  {
62  $cmi5_extensions_query = false;
63 
64  $stage = array();
65  $stage['statement.object.objectType'] = 'Activity';
66  $stage['statement.actor.objectType'] = 'Agent';
67  if ($this->filter->getVerb()) {
68  $stage['statement.verb.id'] = $this->filter->getVerb();
69  }
70 
71  if ($this->filter->getStartDate() || $this->filter->getEndDate()) {
72  $stage['statement.timestamp'] = array();
73 
74  if ($this->filter->getStartDate()) {
75  $stage['statement.timestamp']['$gt'] = $this->filter->getStartDate()->toXapiTimestamp();
76  }
77 
78  if ($this->filter->getEndDate()) {
79  $stage['statement.timestamp']['$lt'] = $this->filter->getEndDate()->toXapiTimestamp();
80  }
81  }
82 
83  $obj = $this->getObj();
84  $activityId = array();
85 
86  if ($cmi5_extensions_query == true && $obj->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5 && !$obj->isMixedContentType())
87  {
88  // https://github.com/AICC/CMI-5_Spec_Current/blob/quartz/cmi5_spec.md#963-extensions
89  $activityId['statement.context.extensions.https://ilias&46;de/cmi5/activityid'] = $obj->getActivityId();
90  }
91  else
92  {
93  // for case-insensive: '$regex' => '(?i)^' . preg_quote($this->filter->getActivityId()) . ''
94  $activityQuery = [
95  '$regex' => '^' . preg_quote($this->filter->getActivityId()) . ''
96  ];
97  $activityId['$or'] = [];
98  // ToDo : restriction to exact activityId?
99  // query existing activityId in grouping? we have not enough control over acticityId in xapi statements
100  // another way put the obj_id into a generated registration, but we are not sure that content will put this into statement context
101  // $activityId['$or'][] = ['statement.object.id' => "{$this->filter->getActivityId()}"];
102  $activityId['$or'][] = ['statement.object.id' => $activityQuery];
103  $activityId['$or'][] = ['statement.context.contextActivities.parent.id' => $activityQuery];
104  $activityId['$or'][] = ['statement.context.contextActivities.grouping.id' => $activityQuery];
105  }
106 
107  $actor = array();
108 
109  // mixed
110  if ($obj instanceof ilObjCmiXapi && $obj->isMixedContentType())
111  {
112  if ($this->filter->getActor())
113  {
114  // could be registration query but so what...
115  foreach (ilCmiXapiUser::getUserIdents($this->getObjId(), $this->filter->getActor()->getUsrId()) as $usrIdent)
116  {
117  $actor['$or'][] = ['statement.actor.mbox' => "mailto:{$usrIdent}"]; // older statements
118  $actor['$or'][] = ['statement.actor.account.name' => "{$usrIdent}"];
119  }
120  // not launched yet?
121  if (count($actor) == 0)
122  {
123  $actor['$or'][] = ['statement.actor.mbox' => "mailto:{$this->filter->getActor()->getUsrIdent()}"]; // older statements
124  $actor['$or'][] = ['statement.actor.account.name' => "{$this->filter->getActor()->getUsrIdent()}"];
125  }
126  }
127  else
128  {
129  $actor['$or'] = [];
130  foreach (ilCmiXapiUser::getUsersForObject($this->getObjId()) as $cmixUser) {
131  $actor['$or'][] = ['statement.actor.mbox' => "mailto:{$cmixUser->getUsrIdent()}"];
132  $actor['$or'][] = ['statement.actor.account.name' => "{$cmixUser->getUsrIdent()}"];
133  }
134  }
135  }
136  elseif ($obj instanceof ilObjCmiXapi && $obj->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5)
137  {
138  if ($this->filter->getActor())
139  {
140  $cmixUser = $this->filter->getActor();
141  $actor['statement.context.registration'] = $cmixUser->getRegistration();
142  }
143  }
144  else
145  {
146  if ($this->filter->getActor())
147  {
148  foreach (ilCmiXapiUser::getUserIdents($this->getObjId(), $this->filter->getActor()->getUsrId()) as $usrIdent)
149  {
150  $actor['$or'][] = ['statement.actor.mbox' => "mailto:{$usrIdent}"];
151  }
152  // not launched yet?
153  if (count($actor) == 0)
154  {
155  $actor['statement.actor.mbox'] = $this->filter->getActor()->getUsrIdent();
156  }
157  }
163  else
164  {
165  $actor['$or'] = [];
166  foreach (ilCmiXapiUser::getUsersForObject($this->getObjId()) as $cmixUser) {
167  $actor['$or'][] = ['statement.actor.mbox' => "mailto:{$cmixUser->getUsrIdent()}"];
168  }
169  }
170  }
171  $stage['$and'] = [];
172  $stage['$and'][] = $activityId;
173  if (count($actor) > 0) {
174  $stage['$and'][] = $actor;
175  }
176  return array('$match' => $stage);
177  }
178 
179  protected function buildOrderingStage()
180  {
181  $obj = $this->getObj();
182  $actor = '';
183  if ($obj instanceof ilObjLTIConsumer) {
184  if ($obj->getProvider()->getPrivacyName() != ilObjCmiXapi::PRIVACY_NAME_NONE) {
185  $actor = 'statement.actor.name';
186  }
187  } else {
188  if ($obj->getPrivacyName() != ilObjCmiXapi::PRIVACY_NAME_NONE) {
189  $actor = 'statement.actor.name';
190  } else {
191  if ($obj->getContentType() == ilObjCmiXapi::CONT_TYPE_CMI5) {
192  if ($obj->getPublisherId() == '') // old
193  {
194  $actor = 'statement.actor.mbox';
195  } else {
196  $actor = 'statement.actor.account.name';
197  }
198 
199  } else {
200  $actor = 'statement.actor.mbox';
201  }
202  }
203  }
204  switch ($this->filter->getOrderField()) {
205  case 'object': // definition/description are displayed in the Table if not empty => sorting not alphabetical on displayed fields
206  $field = 'statement.object.id';
207  break;
208 
209  case 'verb':
210  $field = 'statement.verb.id';
211  break;
212 
213  case 'actor':
214  $field = $actor;
215  break;
216 
217  case 'date':
218  default:
219  $field = 'statement.timestamp';
220  break;
221  }
222 
223  $orderingFields = array(
224  $field => $this->filter->getOrderDirection() == 'desc' ? -1 : 1
225  );
226 
227  return array('$sort' => $orderingFields);
228  }
229 }
static getUsersForObject($objId, $asUsrId=false)
static getUserIdents($objId, $usrId)
$log
Definition: result.php:15
static getLogger($a_component_id)
Get component logger.