ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
Table.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use ILIAS\UI\Factory as UIFactory;
24use ILIAS\UI\Component\Table\Data as DataTable;
31use ILIAS\Data\Factory as DataFactory;
32use Psr\Http\Message\RequestInterface;
33
34class 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'),
119 $this->action_map
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,
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}
getNonCreateTranslation(string $type, string $op_id)
Definition: Table.php:316
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
buildChangeColumn(int $action, array $data)
Definition: Table.php:214
getCreateTranslation(string $type, string $op_id)
Definition: Table.php:330
parseChangesFaPa(array $raw)
Definition: Table.php:228
applyFilterValuesTrafos(array $filter_values)
Definition: Table.php:194
parseChangesTemplate(array $raw)
Definition: Table.php:276
getOPCaption(string $type, array|int|string $op)
Definition: Table.php:292
isTranslated(?string $perm, string $op_id)
Definition: Table.php:350
__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
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
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
A Date Format provides a format definition akin to PHP's date formatting options, but stores the sing...
Definition: DateFormat.php:27
Builds data types.
Definition: Factory.php:36
Both the subject and the direction need to be specified when expressing an order.
Definition: Order.php:29
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:29
Class ilCtrl provides processing control methods.
language handling
static _getTranslation(string $a_role_title)
User class.
static _lookupFullname(int $a_user_id)
static _lookupName(int $a_user_id)
parses the objects.xml it handles the xml-description of all ilias objects
Class ilObjectGUI Basic methods of all Output classes.
static _lookupObjectId(int $ref_id)
static _lookupTitle(int $obj_id)
class ilRbacLog Log changes in Rbac-related settings
const EDIT_PERMISSIONS
const COPY_OBJECT
const MOVE_OBJECT
const EDIT_TEMPLATE_EXISTING
const CHANGE_OWNER
const LINK_OBJECT
const EDIT_TEMPLATE
const CREATE_OBJECT
class ilRbacReview Contains Review functions of core Rbac.
getOperations()
get all possible operations
Filter service.
const ROLE_FOLDER_ID
Definition: constants.php:34
const ROOT_FOLDER_ID
Definition: constants.php:32
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This describes commonalities between all filters.
Definition: Filter.php:34
buildDataRow(string $id, array $record)
This describes a Data Table.
Definition: Data.php:31
global $lng
Definition: privfeed.php:31