ILIAS  trunk Revision v11.0_alpha-1715-g7fc467680fb
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
Table.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
33 
34 class Table implements DataRetrieval
35 {
36  private const FILTER_ID = 'perm_table_filter';
37  private const FILTER_FIELD_ACTION = 'action';
38  private const FILTER_FIELD_PERIOD = 'period';
39 
40  private const COLUMN_DATE = 'created';
41  private const COLUMN_NAME = 'name';
42  private const COLUMN_LOGIN = 'login';
43  private const COLUMN_ACTION = 'action';
44  private const COLUMN_CHANGES = 'changes';
45 
49  private ?array $filter_data;
50 
51  private array $action_map = [];
52  private array $operations = [];
53 
54  public function __construct(
55  private readonly \ilRbacLog $rbac_log,
56  private readonly UIFactory $ui_factory,
57  private readonly DataFactory $data_factory,
58  private readonly \ilLanguage $lng,
59  private readonly \ilCtrl $ctrl,
60  private readonly \ilUIService $ui_service,
61  private readonly \ilObjectDefinition $object_definition,
62  private readonly RequestInterface $request,
63  \ilRbacReview $rbac_review,
64  private readonly \ilObjUser $current_user,
65  private readonly \ilObjectGUI $gui_object
66  ) {
67  $this->action_map = [
68  \ilRbacLog::EDIT_PERMISSIONS => $this->lng->txt('rbac_log_edit_permissions'),
69  \ilRbacLog::MOVE_OBJECT => $this->lng->txt('rbac_log_move_object'),
70  \ilRbacLog::LINK_OBJECT => $this->lng->txt('rbac_log_link_object'),
71  \ilRbacLog::COPY_OBJECT => $this->lng->txt('rbac_log_copy_object'),
72  \ilRbacLog::CREATE_OBJECT => $this->lng->txt('rbac_log_create_object'),
73  \ilRbacLog::EDIT_TEMPLATE => $this->lng->txt('rbac_log_edit_template'),
74  \ilRbacLog::EDIT_TEMPLATE_EXISTING => $this->lng->txt('rbac_log_edit_template_existing'),
75  \ilRbacLog::CHANGE_OWNER => $this->lng->txt('rbac_log_change_owner')
76  ];
77 
78  foreach ($rbac_review->getOperations() as $op) {
79  $this->operations[$op['ops_id']] = $op['operation'];
80  }
81  }
82 
83  public function getTableAndFilter(): array
84  {
85  return [
86  $this->getFilter(),
87  $this->getTable()
88  ];
89  }
90 
91  private function getTable(): DataTable
92  {
93  $cf = $this->ui_factory->table()->column();
94 
95  return $this->ui_factory->table()->data(
96  $this,
97  $this->lng->txt('rbac_log'),
98  [
99  self::COLUMN_DATE => $cf->date(
100  $this->lng->txt('date'),
101  $this->buildUserDateTimeFormat()
102  ),
103  self::COLUMN_NAME => $cf->text($this->lng->txt('name')),
104  self::COLUMN_LOGIN => $cf->text($this->lng->txt('login')),
105  self::COLUMN_ACTION => $cf->text($this->lng->txt('action')),
106  self::COLUMN_CHANGES => $cf->text($this->lng->txt('rbac_changes'))
107  ->withIsSortable(false)
108  ],
109  )->withRequest($this->request);
110  }
111 
112  private function getFilter(): Filter
113  {
114  $ff = $this->ui_factory->input()->field();
115 
116  $inputs = [
117  self::FILTER_FIELD_ACTION => $ff->multiSelect(
118  $this->lng->txt('action'),
120  ),
121  self::FILTER_FIELD_PERIOD => $ff->duration($this->lng->txt('date'))
122  ];
123 
124  $active = array_fill(0, count($inputs), true);
125 
126  $filter = $this->ui_service->filter()->standard(
127  self::FILTER_ID,
128  $this->ctrl->getFormActionByClass([get_class($this->gui_object), \ilPermissionGUI::class], 'log'),
129  $inputs,
130  $active,
131  true,
132  true
133  );
134  $this->filter_data = $this->applyFilterValuesTrafos($this->ui_service->filter()->getData($filter));
135  return $filter;
136  }
137 
138  public function getRows(
139  DataRowBuilder $row_builder,
140  array $visible_column_ids,
141  Range $range,
142  Order $order,
143  ?array $filter_data,
144  ?array $additional_parameters
145  ): \Generator {
146  $log_data = $this->rbac_log->getLogItems(
147  $this->getRefId(),
148  $range,
149  $order,
150  $this->filter_data
151  );
152 
153  foreach ($log_data as $entry) {
154  $user_data = \ilObjUser::_lookupName($entry['user_id']);
155  yield $row_builder->buildDataRow(
156  (string) $entry['log_id'],
157  [
158  self::COLUMN_DATE => (new \DateTimeImmutable('@' . $entry['created']))
159  ->setTimezone(new \DateTimeZone($this->current_user->getTimeZone())),
160  self::COLUMN_NAME => "{$user_data['lastname']}, {$user_data['firstname']}",
161  self::COLUMN_LOGIN => $user_data['login'],
162  self::COLUMN_ACTION => $this->action_map[$entry['action']] ?? '',
163  self::COLUMN_CHANGES => $this->buildChangeColumn($entry['action'], $entry['data'] ?? [])
164  ]
165  );
166  }
167  }
168 
169  public function getTotalRowCount(
170  ?array $filter_data,
171  ?array $additional_parameters
172  ): ?int {
173  return $this->rbac_log->getLogItemsCount($this->getRefId(), $filter_data);
174  }
175 
176  private function getRefId(): int
177  {
178  // special case: role folder should display root folder entries
179  if ($this->gui_object->getRefId() === ROLE_FOLDER_ID) {
180  return ROOT_FOLDER_ID;
181  }
182  return $this->gui_object->getRefId();
183  }
184 
186  {
187  $user_format = $this->current_user->getDateFormat();
188  if ($this->current_user->getTimeFormat() == \ilCalendarSettings::TIME_FORMAT_24) {
189  return $this->data_factory->dateFormat()->withTime24($user_format);
190  }
191  return $this->data_factory->dateFormat()->withTime12($user_format);
192  }
193 
194  private function applyFilterValuesTrafos(array $filter_values): array
195  {
196  $transformed_values = [
197  'action' => $filter_values['action']
198  ];
199  if (isset($filter_values['period'][0])) {
200  $transformed_values['from'] = (new \DateTimeImmutable(
201  $filter_values['period'][0],
202  new \DateTimeZone($this->current_user->getTimeZone())
203  ))->getTimestamp();
204  }
205  if (isset($filter_values['period'][1])) {
206  $transformed_values['to'] = (new \DateTimeImmutable(
207  $filter_values['period'][1] . '23:59:59',
208  new \DateTimeZone($this->current_user->getTimeZone())
209  ))->getTimestamp();
210  }
211  return $transformed_values;
212  }
213 
214  private function buildChangeColumn(int $action, array $data): string
215  {
216  if ($action === \ilRbacLog::CHANGE_OWNER) {
217  $user_name = \ilObjUser::_lookupFullname($data[0] ?? 0);
218  return "{$this->lng->txt('rbac_log_changed_owner')}: {$user_name}";
219  }
220 
221  if ($action === \ilRbacLog::EDIT_TEMPLATE) {
222  return $this->parseChangesTemplate($data);
223  }
224 
225  return $this->parseChangesFaPa($data);
226  }
227 
228  private function parseChangesFaPa(array $raw): string
229  {
230  $result = [];
231 
232  if (isset($raw['src']) && is_int($raw['src'])) {
233  $obj_id = \ilObject::_lookupObjectId($raw['src']);
234  if ($obj_id) {
235  $result[] = "{$this->lng->txt('rbac_log_source_object')}: "
236  . '<a href="' . \ilLink::_getLink($raw['src']) . '">'
237  . \ilObject::_lookupTitle($obj_id) . '</a>';
238  }
239 
240  // added only
241  foreach ($raw['ops'] as $role_id => $ops) {
242  foreach ($ops as $op) {
243  $result[] = sprintf(
244  $this->lng->txt('rbac_log_operation_add'),
246  ) . ': ' . $this->getOPCaption($this->gui_object->getObject()->getType(), $op);
247  }
248  }
249  } elseif (isset($raw['ops'])) {
250  foreach ($raw['ops'] as $role_id => $actions) {
251  foreach ($actions as $action => $ops) {
252  foreach ((array) $ops as $op) {
253  $result[] = sprintf(
254  $this->lng->txt('rbac_log_operation_' . $action),
256  ) . ': ' . $this->getOPCaption($this->gui_object->getObject()->getType(), $op);
257  }
258  }
259  }
260  }
261 
262  if (isset($raw['inht'])) {
263  foreach ($raw['inht'] as $action => $role_ids) {
264  foreach ((array) $role_ids as $role_id) {
265  $result[] = sprintf(
266  $this->lng->txt('rbac_log_inheritance_' . $action),
268  );
269  }
270  }
271  }
272 
273  return implode('<br>', $result);
274  }
275 
276  private function parseChangesTemplate(array $raw): string
277  {
278  $result = [];
279  foreach ($raw as $type => $actions) {
280  foreach ($actions as $action => $ops) {
281  foreach ($ops as $op) {
282  $result[] = sprintf(
283  $this->lng->txt('rbac_log_operation_' . $action),
284  $this->lng->txt('obj_' . $type)
285  ) . ': ' . $this->getOPCaption($type, $op);
286  }
287  }
288  }
289  return implode('<br>', $result);
290  }
291 
292  private function getOPCaption(string $type, array|int|string $op): string
293  {
294  if (is_array($op)) {
295  return array_reduce(
296  $op,
297  fn(string $c, array|int|string $v) => $c === ''
298  ? $this->getOPCaption($type, $v)
299  : $c . ',' . $this->getOPCaption($type, $v),
300  ''
301  );
302  }
303 
304  if (!isset($this->operations[$op])) {
305  return '';
306  }
307 
308  $op_id = $this->operations[$op];
309  if (substr($op_id, 0, 7) !== 'create_') {
310  return $this->getNonCreateTranslation($type, $op_id);
311  }
312 
313  return $this->getCreateTranslation($type, $op_id);
314  }
315 
316  private function getNonCreateTranslation(string $type, string $op_id): string
317  {
318  $perm = $this->getTranslationFromPlugin($type, $op_id);
319  if ($this->isTranslated($perm, $op_id)) {
320  return $perm;
321  }
322 
323  if ($this->lng->exists($type . '_' . $op_id . '_short')) {
324  return $this->lng->txt($type . '_' . $op_id . '_short');
325  }
326 
327  return $this->lng->txt($op_id);
328  }
329 
330  private function getCreateTranslation(string $type, string $op_id): string
331  {
332  $obj_type = substr($op_id, 7, strlen($op_id));
333  $perm = $this->getTranslationFromPlugin($obj_type, $op_id);
334 
335  if ($this->isTranslated($perm, $op_id)) {
336  return $perm;
337  }
338 
339  return $this->lng->txt('rbac_' . $op_id);
340  }
341 
342  private function getTranslationFromPlugin(string $type, string $op_id): ?string
343  {
344  if ($this->object_definition->isPlugin($type)) {
345  return \ilObjectPlugin::lookupTxtById($type, $op_id);
346  }
347  return null;
348  }
349 
350  private function isTranslated(?string $perm, string $op_id): bool
351  {
352  return $perm !== null && strpos($perm, $op_id) === false;
353  }
354 }
const ROOT_FOLDER_ID
Definition: constants.php:32
static _lookupFullname(int $a_user_id)
getOPCaption(string $type, array|int|string $op)
Definition: Table.php:292
getTranslationFromPlugin(string $type, string $op_id)
Definition: Table.php:342
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...
Definition: Table.php:169
const CHANGE_OWNER
static _lookupName(int $a_user_id)
lookup user name
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
applyFilterValuesTrafos(array $filter_values)
Definition: Table.php:194
$c
Definition: deliver.php:25
getCreateTranslation(string $type, string $op_id)
Definition: Table.php:330
Both the subject and the direction need to be specified when expressing an order. ...
Definition: Order.php:28
buildDataRow(string $id, array $record)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
const EDIT_PERMISSIONS
const CREATE_OBJECT
static _lookupTitle(int $obj_id)
getRows(DataRowBuilder $row_builder, array $visible_column_ids, Range $range, Order $order, ?array $filter_data, ?array $additional_parameters)
This is called by the table to retrieve rows; map data-records to rows using the $row_builder e...
Definition: Table.php:138
A Date Format provides a format definition akin to PHP&#39;s date formatting options, but stores the sing...
Definition: DateFormat.php:26
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getTranslation(string $a_role_title)
Class ilObjectGUI Basic methods of all Output classes.
static _lookupObjectId(int $ref_id)
const COPY_OBJECT
const LINK_OBJECT
parseChangesTemplate(array $raw)
Definition: Table.php:276
const ROLE_FOLDER_ID
Definition: constants.php:34
buildChangeColumn(int $action, array $data)
Definition: Table.php:214
getOperations()
get all possible operations
global $lng
Definition: privfeed.php:31
const EDIT_TEMPLATE_EXISTING
parseChangesFaPa(array $raw)
Definition: Table.php:228
const EDIT_TEMPLATE
const MOVE_OBJECT
isTranslated(?string $perm, string $op_id)
Definition: Table.php:350
class ilRbacLog Log changes in Rbac-related settings
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:28
__construct(private readonly \ilRbacLog $rbac_log, private readonly UIFactory $ui_factory, private readonly DataFactory $data_factory, private readonly \ilLanguage $lng, private readonly \ilCtrl $ctrl, private readonly \ilUIService $ui_service, private readonly \ilObjectDefinition $object_definition, private readonly RequestInterface $request, \ilRbacReview $rbac_review, private readonly \ilObjUser $current_user, private readonly \ilObjectGUI $gui_object)
Definition: Table.php:54
getNonCreateTranslation(string $type, string $op_id)
Definition: Table.php:316