ILIAS  trunk Revision v11.0_alpha-1753-gb21ca8c4367
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilBadgeUserTableGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 namespace ILIAS\Badge;
22 
27 use ilLanguage;
33 use Generator;
35 use ilBadgeHandler;
36 use ilObject;
37 use ilBadge;
39 use ilUserQuery;
43 use ilTree;
45 use ilObjUser;
49 
51 {
52  private readonly Factory $factory;
53  private readonly Renderer $renderer;
55  private readonly ilLanguage $lng;
56  private readonly ilGlobalTemplateInterface $tpl;
57  private readonly ilTree $tree;
58  private readonly ilObjUser $user;
59  private DateFormat $date_format;
60  private bool $is_container_context = false;
74  private ?array $cached_records = null;
75 
76  public function __construct(
77  private readonly ?int $parent_ref_id = null,
78  private readonly ?ilBadge $award_badge = null,
79  private readonly ?int $parent_obj_id = null,
80  private readonly ?int $restrict_badge_id = null
81  ) {
82  global $DIC;
83 
84  $this->lng = $DIC->language();
85  $this->tpl = $DIC->ui()->mainTemplate();
86  $this->factory = $DIC->ui()->factory();
87  $this->renderer = $DIC->ui()->renderer();
88  $this->request = $DIC->http()->request();
89  $this->tree = $DIC->repositoryTree();
90  $this->user = $DIC->user();
91 
92  if ($this->parent_ref_id) {
93  $parent_type = ilObject::_lookupType($this->parent_ref_id, true);
94  if (\in_array($parent_type, ['grp', 'crs'], true)) {
95  $this->is_container_context = $this->parent_obj_id === null && $this->award_badge === null;
96  }
97  }
98  }
99 
113  private function getRecords(): array
114  {
115  if ($this->cached_records !== null) {
116  return $this->cached_records;
117  }
118 
120  $assignments = [];
121  $user_ids = [];
122  $rows = [];
123  $badges = [];
124 
125  $parent_obj_id = $this->parent_obj_id;
126  if (!$parent_obj_id && $this->parent_ref_id) {
127  $parent_obj_id = ilObject::_lookupObjId($this->parent_ref_id);
128  }
129 
130  if ($this->parent_ref_id) {
131  $user_ids = ilBadgeHandler::getInstance()->getUserIds($this->parent_ref_id, $parent_obj_id);
132  }
133 
134  $obj_ids = [$parent_obj_id];
135  if ($this->is_container_context) {
136  foreach ($this->tree->getSubTree($this->tree->getNodeData($this->parent_ref_id)) as $node) {
137  $obj_ids[] = (int) $node['obj_id'];
138  }
139  $obj_ids = array_unique($obj_ids);
140  }
141 
142  foreach ($obj_ids as $obj_id) {
143  foreach (ilBadge::getInstancesByParentId($obj_id) as $badge) {
144  $badges[$badge->getId()] = $badge;
145  }
146 
147  foreach (ilBadgeAssignment::getInstancesByParentId($obj_id) as $ass) {
148  if ($this->restrict_badge_id && $this->restrict_badge_id !== $ass->getBadgeId()) {
149  continue;
150  }
151 
152  if ($this->award_badge instanceof ilBadge &&
153  $ass->getBadgeId() !== $this->award_badge->getId()) {
154  continue;
155  }
156 
157  $assignments[$ass->getUserId()][] = $ass;
158  }
159  }
160 
161  if (!$user_ids) {
162  $user_ids = array_keys($assignments);
163  }
164 
165  $tmp['set'] = [];
166  if (\count($user_ids) > 0) {
167  $uquery = new ilUserQuery();
168  $uquery->setLimit(9999);
169  $uquery->setUserFilter($user_ids);
170  $tmp = $uquery->query();
171  }
172 
173  foreach ($tmp['set'] as $user) {
174  if (\array_key_exists($user['usr_id'], $assignments)) {
175  foreach ($assignments[$user['usr_id']] as $user_ass) {
176  $idx = $user_ass->getBadgeId() . '_' . $user_ass->getUserId();
177 
178  $badge = $badges[$user_ass->getBadgeId()];
179 
180  $parent = null;
181  $paren_sortable = null;
182  if ($this->is_container_context) {
183  $parent_metadata = $badge->getParentMeta();
184 
185  $parent = implode(' ', [
186  $this->renderer->render(
187  $this->factory->symbol()->icon()->custom(
188  ilObject::_getIcon($parent_metadata['id'], 'big', $parent_metadata['type']),
189  $this->lng->txt('obj_' . $parent_metadata['type'])
190  )
191  ),
192  $parent_metadata['title']
193  ]);
194  $paren_sortable = $parent_metadata['title'];
195  }
196 
197  $rows[] = [
198  'id' => $idx,
199  'name' => $user['lastname'] . ', ' . $user['firstname'],
200  'login' => $user['login'],
201  'type' => ilBadge::getExtendedTypeCaption($badge->getTypeInstance()),
202  'title' => $badge->getTitle(),
203  'issued' => (new DateTimeImmutable())
204  ->setTimestamp($user_ass->getTimestamp())
205  ->setTimezone(new \DateTimeZone($this->user->getTimeZone()))
206  ->format($this->date_format->toString()),
207  'issued_sortable' => (new DateTimeImmutable())
208  ->setTimestamp($user_ass->getTimestamp())
209  ->setTimezone(new \DateTimeZone($this->user->getTimeZone())),
210  'parent' => $parent,
211  'parent_sortable' => $paren_sortable,
212  ];
213  }
214  } elseif ($this->award_badge) {
215  $idx = $this->award_badge->getId() . '_' . $user['usr_id'];
216 
217  $rows[] = [
218  'id' => $idx,
219  'name' => $user['lastname'] . ', ' . $user['firstname'],
220  'login' => $user['login'],
221  'type' => '',
222  'title' => '',
223  'issued' => null,
224  'issued_sortable' => null,
225  'parent' => null,
226  'parent_sortable' => null,
227  ];
228  }
229  }
230 
231  $this->cached_records = $rows;
232 
233  return $rows;
234  }
235 
236  public function getRows(
237  DataRowBuilder $row_builder,
238  array $visible_column_ids,
239  Range $range,
240  Order $order,
241  ?array $filter_data,
242  ?array $additional_parameters
243  ): Generator {
244  $records = $this->getRecords();
245 
246  if ($order) {
247  [$order_field, $order_direction] = $order->join(
248  [],
249  fn($ret, $key, $value) => [$key, $value]
250  );
251  usort($records, static function (array $left, array $right) use ($order_field): int {
252  if (\in_array($order_field, ['name', 'login', 'type', 'title', 'parent'], true)) {
253  if ($order_field === 'parent') {
254  $order_field .= '_sortable';
255  }
256 
257  return \ilStr::strCmp(
258  $left[$order_field] ?? '',
259  $right[$order_field] ?? ''
260  );
261  }
262 
263  if ($order_field === 'issued') {
264  $order_field .= '_sortable';
265  return $left[$order_field] <=> $right[$order_field];
266  }
267 
268  return $left[$order_field] <=> $right[$order_field];
269  });
270 
271  if ($order_direction === ORDER::DESC) {
272  $records = array_reverse($records);
273  }
274  }
275 
276  if ($range) {
277  $records = \array_slice($records, $range->getStart(), $range->getLength());
278  }
279 
280  foreach ($records as $record) {
281  yield $row_builder->buildDataRow($record['id'], $record)->withDisabledAction(
282  'badge_award_badge',
283  $record['issued'] === null
284  )->withDisabledAction(
285  'badge_revoke_badge',
286  $record['issued'] !== null
287  );
288  }
289  }
290 
291  public function getTotalRowCount(
292  ?array $filter_data,
293  ?array $additional_parameters
294  ): ?int {
295  return \count($this->getRecords());
296  }
297 
301  public function getColumns(): array
302  {
303  $columns = [
304  'name' => $this->factory->table()->column()->text($this->lng->txt('name')),
305  'login' => $this->factory->table()->column()->text($this->lng->txt('login')),
306  'type' => $this->factory->table()->column()->text($this->lng->txt('type')),
307  'title' => $this->factory->table()->column()->text($this->lng->txt('title')),
308  // Cannot be a date column, because when awarding/revoking badges for uses, the list items may contain NULL values for `issued`
309  'issued' => $this->factory->table()->column()->text($this->lng->txt('badge_issued_on'))
310  ];
311 
312  if ($this->is_container_context) {
313  $columns['parent'] = $this->factory->table()->column()->text($this->lng->txt('object'));
314  }
315 
316  return $columns;
317  }
318 
322  private function getActions(
323  URLBuilder $url_builder,
324  URLBuilderToken $action_parameter_token,
325  URLBuilderToken $row_id_token,
326  ): array {
327  return ($this->award_badge instanceof ilBadge) ? [
328  'badge_award_badge' =>
329  $this->factory->table()->action()->multi(
330  $this->lng->txt('badge_award_badge'),
331  $url_builder->withParameter($action_parameter_token, 'assignBadge'),
332  $row_id_token
333  ),
334  'badge_revoke_badge' =>
335  $this->factory->table()->action()->multi(
336  $this->lng->txt('badge_remove_badge'),
337  $url_builder->withParameter($action_parameter_token, 'revokeBadge'),
338  $row_id_token
339  )
340  ] : [];
341  }
342 
343  public function renderTable(): void
344  {
345  $df = new \ILIAS\Data\Factory();
346  if ((int) $this->user->getTimeFormat() === ilCalendarSettings::TIME_FORMAT_12) {
347  $this->date_format = $df->dateFormat()->withTime12($this->user->getDateFormat());
348  } else {
349  $this->date_format = $df->dateFormat()->withTime24($this->user->getDateFormat());
350  }
351 
352  $table_uri = $df->uri($this->request->getUri()->__toString());
353  $url_builder = new URLBuilder($table_uri);
354  $query_params_namespace = ['tid'];
355 
356  [$url_builder, $action_parameter_token, $row_id_token] = $url_builder->acquireParameters(
357  $query_params_namespace,
358  'table_action',
359  'id',
360  );
361 
362  if ($this->award_badge instanceof ilBadge) {
363  $title = $this->lng->txt('badge_award_badge') . ': ' . $this->award_badge->getTitle();
364  } else {
365  $parent = '';
366  if ($this->parent_obj_id) {
367  $title = ilObject::_lookupTitle($this->parent_obj_id);
368  if (!$title) {
369  $title = ilObjectDataDeletionLog::get($this->parent_obj_id);
370  if ($title) {
371  $title = $title['title'];
372  }
373  }
374 
375  if ($this->restrict_badge_id) {
376  $badge = new ilBadge($this->restrict_badge_id);
377  $title .= ' - ' . $badge->getTitle();
378  }
379 
380  $parent = $title . ': ';
381  }
382  $title = $parent . $this->lng->txt('users');
383  }
384 
385  $table = $this->factory
386  ->table()
387  ->data($this, $title, $this->getColumns())
388  ->withId(self::class . '_' . $this->parent_ref_id)
389  ->withOrder(new Order('name', Order::ASC))
390  ->withActions($this->getActions($url_builder, $action_parameter_token, $row_id_token))
391  ->withRequest($this->request);
392 
393  $out = [$table];
394 
395  $this->tpl->setContent($this->renderer->render($out));
396  }
397 }
join($init, callable $fn)
Definition: Order.php:75
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
static getInstancesByParentId(int $a_parent_id, ?array $a_filter=null)
factory()
renderer()
getActions(URLBuilder $url_builder, URLBuilderToken $action_parameter_token, URLBuilderToken $row_id_token,)
Both the subject and the direction need to be specified when expressing an order. ...
Definition: Order.php:28
static _lookupObjId(int $ref_id)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static _lookupTitle(int $obj_id)
static getExtendedTypeCaption(ilBadgeType $a_type)
readonly ServerRequestInterface RequestInterface $request
$out
Definition: buildRTE.php:24
global $DIC
Definition: shib_login.php:22
__construct(private readonly ?int $parent_ref_id=null, private readonly ?ilBadge $award_badge=null, private readonly ?int $parent_obj_id=null, private readonly ?int $restrict_badge_id=null)
Builds data types.
Definition: Factory.php:35
static getInstancesByParentId(int $a_parent_obj_id)
readonly ilGlobalTemplateInterface $tpl
withParameter(URLBuilderToken $token, string|array $value)
Change an acquired parameter&#39;s value if the supplied token is valid.
Definition: URLBuilder.php:166
getRows(DataRowBuilder $row_builder, array $visible_column_ids, Range $range, Order $order, ?array $filter_data, ?array $additional_parameters)
URLBuilder.
Definition: URLBuilder.php:40
static _lookupType(int $id, bool $reference=false)
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:28
getTotalRowCount(?array $filter_data, ?array $additional_parameters)
Mainly for the purpose of pagination-support, it is important to know about the total number of recor...