ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilDclRecordListGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 {
23  public const GET_TABLE_ID = 'table_id';
24  public const GET_TABLEVIEW_ID = 'tableview_id';
25  public const GET_MODE = "mode";
26  public const MODE_VIEW = "view";
27  public const MODE_MANAGE = "manage";
28  public const CMD_LIST_RECORDS = 'listRecords';
29  public const CMD_SHOW = 'show';
30  public const CMD_CONFIRM_DELETE_RECORDS = 'confirmDeleteRecords';
31  public const CMD_CANCEL_DELETE = 'cancelDelete';
32  public const CMD_DELETE_RECORDS = 'deleteRecords';
33  public const CMD_SHOW_IMPORT_EXCEL = 'showImportExcel';
34 
37  protected \ILIAS\UI\Factory $ui_factory;
38  protected \ILIAS\UI\Renderer $renderer;
39 
43  protected string $mode = self::MODE_VIEW;
45  protected ?int $table_id;
46  protected int $obj_id;
48  protected ?int $tableview_id;
49  protected static array $available_modes = [self::MODE_VIEW, self::MODE_MANAGE];
50 
51  protected ilCtrl $ctrl;
53  protected ilLanguage $lng;
54  protected ilTabsGUI $tabs;
57  protected \ILIAS\ResourceStorage\Services $irss;
58  protected bool $filter_changed = false;
59 
63  public function __construct(ilObjDataCollectionGUI $a_parent_obj, int $table_id, int $tableview_id)
64  {
65  global $DIC;
66 
67  $this->ctrl = $DIC->ctrl();
68  $this->toolbar = $DIC->toolbar();
69  $this->lng = $DIC->language();
70  $this->tabs = $DIC->tabs();
71  $this->http = $DIC->http();
72  $this->refinery = $DIC->refinery();
73  $this->irss = $DIC->resourceStorage();
74  $this->access = $DIC->access();
75  $this->tpl = $DIC->ui()->mainTemplate();
76  $this->ui_factory = $DIC->ui()->factory();
77  $this->renderer = $DIC->ui()->renderer();
78 
79  $this->table_id = $table_id;
80  $this->tableview_id = $tableview_id;
81 
82  $this->obj_id = $a_parent_obj->getObject()->getId();
83  $this->parent_obj = $a_parent_obj;
84  $this->table_obj = ilDclCache::getTableCache($table_id);
85 
86  $this->ctrl->setParameterByClass(ilDclRecordEditGUI::class, self::GET_TABLE_ID, $this->table_id);
87  $this->ctrl->setParameterByClass(ilDclRecordEditGUI::class, self::GET_TABLEVIEW_ID, $this->tableview_id);
88  $this->ctrl->setParameterByClass(ilDclDetailedViewGUI::class, self::GET_TABLEVIEW_ID, $this->tableview_id);
89 
90  $this->mode = self::MODE_VIEW;
91 
92  if ($this->http->wrapper()->query()->has(self::GET_MODE)) {
93  $mode = $this->http->wrapper()->query()->retrieve(self::GET_MODE, $this->refinery->kindlyTo()->string());
94  if (in_array($mode, self::$available_modes, true)) {
95  $this->mode = $mode;
96  }
97  }
98  }
99 
100  public function getRefId(): int
101  {
102  return $this->parent_obj->getRefId();
103  }
104 
105  public function getObjId(): int
106  {
107  return $this->parent_obj->getObject()->getId();
108  }
109 
114  public function executeCommand(): void
115  {
116  if (!$this->checkAccess()) {
117  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
118  return;
119  }
120 
121  $this->ctrl->saveParameter($this, self::GET_MODE);
122  $cmd = $this->ctrl->getCmd(self::CMD_SHOW);
123 
124  // 'show' fills all filters with the predefined values from the tableview,
125  // whereas 'listRecords' handels the filters "normally", filling them from the POST-variable
126  switch ($cmd) {
127  case self::CMD_SHOW:
128  case self::CMD_CANCEL_DELETE:
129  case self::CMD_LIST_RECORDS:
130  $this->setSubTabs($this->mode);
131  $this->listRecords();
132  break;
133  case self::CMD_CONFIRM_DELETE_RECORDS:
134  $this->confirmDeleteRecords();
135  break;
136  case self::CMD_DELETE_RECORDS:
137  $this->deleteRecords();
138  break;
139  case self::CMD_SHOW_IMPORT_EXCEL:
140  $this->tabs->setBackTarget($this->lng->txt('back'), $this->ctrl->getLinkTarget($this));
141  $this->$cmd();
142  break;
143 
144  default:
145  $this->$cmd();
146  break;
147  }
148  }
149 
150  public function listRecords(): void
151  {
152  $list = $this->getRecordListTableGUI();
153 
154  $this->createSwitchers();
155 
156  $permission_to_add_or_import = ilObjDataCollectionAccess::hasPermissionToAddRecord(
157  $this->parent_obj->getRefId(),
159  ) && $this->table_obj->hasCustomFields();
160  if ($permission_to_add_or_import) {
161  $this->ctrl->setParameterByClass(ilDclRecordEditGUI::class, "record_id", null);
162 
163  $add_new = $this->ui_factory->button()->primary(
164  $this->lng->txt("dcl_add_new_record"),
165  $this->ctrl->getFormActionByClass(ilDclRecordEditGUI::class, "create")
166  );
167  $this->toolbar->addStickyItem($add_new);
168  }
169 
170  if ($permission_to_add_or_import && $this->table_obj->getImportEnabled()) {
171  $this->ctrl->setParameterByClass(ilDclRecordEditGUI::class, "record_id", null);
172 
173  $import_button = $this->ui_factory->button()->standard(
174  $this->lng->txt("dcl_import_records .xls"),
175  $this->ctrl->getFormActionByClass(ilDclRecordListGUI::class, self::CMD_SHOW_IMPORT_EXCEL)
176  );
177  $this->toolbar->addComponent($import_button);
178  }
179 
180  if (count($this->table_obj->getRecordFields()) == 0) {
181  $message = $this->lng->txt("dcl_no_fields_yet") . " "
183  $this->parent_obj->getRefId(),
185  ) ? $this->lng->txt("dcl_create_fields") : "");
186  $this->tpl->setOnScreenMessage('info', $message, true);
187  }
188 
189  $target = '';
190  if ($this->http->wrapper()->query()->has('table_id')) {
191  $target .= $this->http->wrapper()->query()->retrieve('table_id', $this->refinery->to()->string());
192  }
193  if ($this->http->wrapper()->query()->has('tableview_id')) {
194  $target .= '_' . $this->http->wrapper()->query()->retrieve('tableview_id', $this->refinery->to()->string());
195  }
196 
197  $this->tpl->setPermanentLink("dcl", $this->parent_obj->getRefId(), $target);
198 
199  if ($desc = $this->table_obj->getDescription()) {
200  $desc = $this->refinery->string()->markdown()->toHTML()->transform($desc);
201  $desc = '<div class="ilDclTableDescription">' . $desc . '</div>';
202  }
203  $this->tpl->setContent($desc . $list->getHTML());
204  }
205 
206  public function showImportExcel(?ilPropertyFormGUI $form = null): void
207  {
208  if (!$form) {
209  $form = $this->initImportForm();
210  }
211  $this->tpl->setContent($form->getHTML());
212  }
213 
218  {
219  $form = new ilPropertyFormGUI();
220 
221  $item = new ilCustomInputGUI();
222  $item->setHtml($this->lng->txt('dcl_file_format_description'));
223  $item->setTitle("Info");
224  $form->addItem($item);
225 
226  $file = new ilFileInputGUI($this->lng->txt("import_file"), "import_file");
227  $file->setSuffixes(['xlsx']);
228  $file->setRequired(true);
229  $form->addItem($file);
230 
231  $cb = new ilCheckboxInputGUI($this->lng->txt("dcl_simulate_import"), "simulate");
232  $cb->setInfo($this->lng->txt("dcl_simulate_info"));
233  $form->addItem($cb);
234 
235  $form->addCommandButton("importExcel", $this->lng->txt("import"));
236 
237  return $form;
238  }
239 
243  public function importExcel(): void
244  {
246  $this->parent_obj->getRefId(),
248  )) || !$this->table_obj->getImportEnabled()) {
249  throw new ilDclException($this->lng->txt("access_denied"));
250  }
251  $form = $this->initImportForm();
252  if ($form->checkInput()) {
253  $file = $form->getInput("import_file");
254  $file_location = $file["tmp_name"];
255  $simulate = $form->getInput("simulate");
256  $this->importRecords($file_location, (bool) $simulate);
257  } else {
258  $this->showImportExcel($form);
259  }
260  }
261 
265  private function importRecords(string $file, bool $simulate = false): void
266  {
267  $importer = new ilDclContentImporter($this->parent_obj->object->getRefId(), $this->table_id);
268  $result = $importer->import($file, $simulate);
269 
270  $this->endImport($result['line'], $result['warnings']);
271  }
272 
277  public function endImport(int $i, array $warnings): void
278  {
279  $output = new ilTemplate("tpl.dcl_import_terminated.html", true, true, "components/ILIAS/DataCollection");
280  $output->setVariable("IMPORT_TERMINATED", $this->lng->txt("dcl_import_terminated") . ": " . $i);
281  foreach ($warnings as $warning) {
282  $output->setCurrentBlock("warnings");
283  $output->setVariable("WARNING", $warning);
284  $output->parseCurrentBlock();
285  }
286 
287  $output->setVariable("BACK_LINK", $this->ctrl->getLinkTargetByClass(ilDclRecordListGUI::class, "listRecords"));
288  $output->setVariable("BACK", $this->lng->txt("back"));
289  $this->tpl->setContent($output->get());
290  }
291 
295  protected function applyFilter(): void
296  {
297  $table = new ilDclRecordListTableGUI($this, "listRecords", $this->table_obj, $this->tableview_id);
298  $table->initFilter();
299  $table->resetOffset();
300  $table->writeFilterToSession();
301  $this->filter_changed = true;
302  $this->listRecords();
303  }
304 
308  protected function resetFilter(): void
309  {
310  $table = new ilDclRecordListTableGUI($this, "show", $this->table_obj, $this->tableview_id);
311  $table->initFilter();
312  $table->resetOffset();
313  $table->resetFilter();
314  $this->filter_changed = true;
315  $this->listRecords();
316  }
317 
321  public function sendFile(): void
322  {
323  $hasIlFileHash = $this->http->wrapper()->query()->has('ilfilehash');
324  //need read access to receive file
325  if ($this->access->checkAccess('read', "", $this->parent_obj->getRefId())) {
326  // deliver temp-files
327  if ($hasIlFileHash) {
328  $filehash = $this->http->wrapper()->query()->retrieve(
329  'ilfilehash',
330  $this->refinery->kindlyTo()->string()
331  );
332  $field_id = $this->http->wrapper()->query()->retrieve('field_id', $this->refinery->kindlyTo()->int());
334 
335  $filepath = $_FILES["field_" . $field_id]['tmp_name'];
336  $filetitle = $_FILES["field_" . $field_id]['name'];
337 
338  ilFileDelivery::deliverFileLegacy($filepath, $filetitle);
339  } else {
340  $rec_id = $this->http->wrapper()
341  ->query()
342  ->retrieve('record_id', $this->refinery->kindlyTo()->int());
343 
344  $record = ilDclCache::getRecordCache($rec_id);
345  if (!$this->recordBelongsToCollection($record)) {
346  return;
347  }
348 
349  $field_id = $this->http->wrapper()
350  ->query()
351  ->retrieve('field_id', $this->refinery->kindlyTo()->string());
352 
353 
354 
355  // Find the current revision
356  $rid_string = $record->getRecordFieldValue($field_id);
357  $identification = $this->irss->manage()->find($rid_string);
358  if ($identification === null) {
359  return;
360  }
361  $current_revision = $this->irss->manage()->getCurrentRevision($identification);
362 
363  // Download the File
364  $this->irss->consume()
365  ->download($identification)
366  ->overrideFileName($current_revision->getTitle())
367  ->run();
368  }
369  }
370  }
371 
375  public function confirmDeleteRecords(): void
376  {
377  $this->tabs->clearTargets();
378 
379  $conf = new ilConfirmationGUI();
380  $conf->setFormAction($this->ctrl->getFormAction($this));
381  $conf->setHeaderText($this->lng->txt('dcl_confirm_delete_records'));
382 
383  $has_record_ids = $this->http->wrapper()->post()->has('record_ids');
384  $record_ids = [];
385  if ($has_record_ids) {
386  $record_ids = $this->http->wrapper()->post()->retrieve(
387  'record_ids',
388  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
389  );
390  }
391  $all_fields = $this->table_obj->getRecordFields();
392  foreach ($record_ids as $record_id) {
394  $record = ilDclCache::getRecordCache($record_id);
395  $record_data = "";
396  foreach ($all_fields as $field) {
397  $field_record = ilDclCache::getRecordFieldCache($record, $field);
398 
399  $record_representation = ilDclCache::getRecordRepresentation($field_record);
400  if ($record_representation->getConfirmationHTML() != false) {
401  $record_data .= $field->getTitle() . ": " . $record_representation->getConfirmationHTML() . "<br />";
402  }
403  }
404  $conf->addItem('record_ids[]', (string) $record->getId(), $record_data);
405  }
406  $conf->addHiddenItem('table_id', (string) $this->table_id);
407  $conf->setConfirm($this->lng->txt('dcl_delete_records'), self::CMD_DELETE_RECORDS);
408  $conf->setCancel($this->lng->txt('cancel'), self::CMD_CANCEL_DELETE);
409  $this->tpl->setContent($conf->getHTML());
410  }
411 
415  public function deleteRecords(): void
416  {
417  $has_record_ids = $this->http->wrapper()->post()->has('record_ids');
418  $record_ids = [];
419  if ($has_record_ids) {
420  $record_ids = $this->http->wrapper()->post()->retrieve(
421  'record_ids',
422  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
423  );
424  }
425 
426  // Invoke deletion
427  $n_skipped = 0;
428  foreach ($record_ids as $record_id) {
430  $record = ilDclCache::getRecordCache($record_id);
431  $ref_id = $this->parent_obj->getRefId();
432 
433  if ($record->hasPermissionToDelete($ref_id)) {
434  $record->doDelete();
435  } else {
436  $n_skipped++;
437  }
438  }
439 
440  $n_deleted = (count($record_ids) - $n_skipped);
441  if ($n_deleted) {
442  $message = sprintf(
443  $this->lng->txt('dcl_deleted_records'),
444  $n_deleted
445  );
446  $this->tpl->setOnScreenMessage('success', $message, true);
447  }
448  if ($n_skipped) {
449  $message = sprintf(
450  $this->lng->txt('dcl_skipped_delete_records'),
451  $n_skipped
452  );
453  $this->tpl->setOnScreenMessage('info', $message, true);
454  }
455  $this->ctrl->redirect($this, self::CMD_LIST_RECORDS);
456  }
457 
458  private function recordBelongsToCollection(ilDclBaseRecordModel $record): bool
459  {
460  $table = $record->getTable();
461  $obj_id = $this->parent_obj->object->getId();
462  $obj_id_rec = $table->getCollectionObject()->getId();
463 
464  return $obj_id == $obj_id_rec;
465  }
466 
467  protected function setSubTabs(string $active_mode = self::GET_MODE): void
468  {
469  $this->ctrl->setParameter($this, self::GET_MODE, self::MODE_VIEW);
470  $this->tabs->addSubTab(
471  self::MODE_VIEW,
472  $this->lng->txt('view'),
473  $this->ctrl->getLinkTarget($this, self::CMD_LIST_RECORDS)
474  );
475 
476  $ref_id = $this->http->wrapper()->query()->retrieve('ref_id', $this->refinery->kindlyTo()->int());
477  if ($this->table_obj->hasPermissionToDeleteRecords($ref_id)) {
478  $this->ctrl->setParameter($this, self::GET_MODE, self::MODE_MANAGE);
479  $this->tabs->addSubTab(
480  self::MODE_MANAGE,
481  $this->lng->txt('dcl_manage'),
482  $this->ctrl->getLinkTarget($this, self::CMD_LIST_RECORDS)
483  );
484  }
485  $this->tabs->activateSubTab($active_mode);
486  $this->ctrl->clearParameters($this);
487  }
488 
490  {
491  $table_obj = $this->table_obj;
492 
493  $list = new ilDclRecordListTableGUI($this, "listRecords", $table_obj, $this->tableview_id, $this->mode);
494  $list->initFilter();
495 
496  $list->setExternalSegmentation(true);
497  $list->setExternalSorting(true);
498  $list->determineOffsetAndOrder();
499 
500  if ($this->filter_changed) {
501  $list->resetOffset();
502  }
503 
504  $limit = $list->getLimit();
505  $offset = $list->getOffset();
506 
507  $data = $table_obj->getPartialRecords(
508  (string) $this->getRefId(),
509  $list->getOrderField(),
510  $list->getOrderDirection(),
511  $limit,
512  $offset,
513  $list->getFilter()
514  );
515  $records = $data['records'];
516  $total = $data['total'];
517 
518  $list->setMaxCount($total);
519  $list->setRecordData($records);
520 
521  $list->determineOffsetAndOrder();
522  $list->determineLimit();
523 
524  return $list;
525  }
526 
527  protected function createSwitchers(): void
528  {
529  if (ilObjDataCollectionAccess::hasWriteAccess($this->parent_obj->getRefId())) {
530  $tables = $this->parent_obj->object->getTables();
531  } else {
532  $tables = $this->parent_obj->object->getVisibleTables();
533  }
534 
535  $switcher = new ilDclSwitcher($this->toolbar, $this->ui_factory, $this->ctrl, $this->lng);
536  $switcher->addTableSwitcherToToolbar(
537  $tables,
538  self::class,
539  self::CMD_SHOW
540  );
541 
542  $switcher->addViewSwitcherToToolbar(
543  $this->table_obj->getVisibleTableViews(),
544  $this->getTableId(),
545  self::class,
546  self::CMD_SHOW
547  );
548  }
549 
550  protected function checkAccess(): bool
551  {
552  if (null === $this->table_id || null === $this->tableview_id) {
553  return false;
554  }
555 
556  return ilObjDataCollectionAccess::hasAccessTo(
557  $this->parent_obj->getRefId(),
560  );
561  }
562 
563  public function getTableId(): int
564  {
565  return $this->table_id;
566  }
567 
568  public function getTableviewId(): int
569  {
570  return $this->tableview_id;
571  }
572 }
setSubTabs(string $active_mode=self::GET_MODE)
ilObjDataCollectionGUI $parent_obj
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a file property in a property form.
ilGlobalTemplateInterface $tpl
recordBelongsToCollection(ilDclBaseRecordModel $record)
endImport(int $i, array $warnings)
End import.
renderer()
import(string $file, bool $simulate=false)
setSuffixes(array $a_suffixes)
static rebuildTempFileByHash(string $hash)
executeCommand()
execute command
sendFile()
send File to User
showImportExcel(?ilPropertyFormGUI $form=null)
__construct(ilObjDataCollectionGUI $a_parent_obj, int $table_id, int $tableview_id)
ILIAS HTTP Services $http
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static hasAccessToFields(int $ref_id, int $table_id)
ilObjDataCollectionGUI: ilInfoScreenGUI, ilNoteGUI, ilCommonActionDispatcherGUI ilObjDataCollectionG...
$ref_id
Definition: ltiauth.php:65
static http()
Fetches the global http state from ILIAS.
ILIAS Refinery Factory $refinery
getPartialRecords(string $ref_id, string $sort, string $direction, ?int $limit, int $offset, array $filter=[])
Return only the needed subset of record objects for the table, according to sorting, paging and filters.
global $DIC
Definition: shib_login.php:26
static getTableCache(?int $table_id=null)
static getRecordRepresentation(ilDclBaseRecordFieldModel $record_field)
Returns a record representation.
static hasWriteAccess(int $ref, ?int $user_id=0)
string $mode
Stores current mode active.
ILIAS ResourceStorage Services $irss
static getRecordCache(?int $record_id)
static hasPermissionToAddRecord(int $ref_id, int $table_id)
$message
Definition: xapiexit.php:31
static getRecordFieldCache(object $record, object $field)
importExcel()
Import Data from Excel sheet.
importRecords(string $file, bool $simulate=false)
Import records from Excel file.