ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
Table.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
23 use ilYuiUtil;
24 use iljQueryUtil;
25 use Closure;
29 use ilTable2GUI;
34 
35 class Table extends ilTable2GUI implements TableSelection
36 {
38  private readonly array $columns;
40  private array $sel = [];
41 
42  public function __construct(?object $gui, string $command, TableInterface $table)
43  {
44  global $DIC;
45  $apply = fn($proc) => fn(array $args) => $proc(...$args);
46  $translate = fn(string $txt, ...$args) => [$txt, ...$args];
47 
48  $id = substr(md5($table->name()), 0, 30);
49  $this->setId($id);
50  $this->columns = array_map($apply($translate), $table->columns());
51  $this->setFormName($id);
52  $config = new SmoothTableConfig($this);
53  $table->config($config);
54  parent::__construct($gui, $command);
55  $config->flush();
56  $this->setFormAction($this->ctrl->getFormAction($this->getParentObject(), $command));
57  $this->setRowTemplate('legacy-table-row.html', 'components/ILIAS/LegalDocuments');
58  array_map($apply($this->addColumn(...)), $this->visibleColumns());
59  $this->setShowRowsSelector(false);
60  $this->setExternalSorting(true);
61  $this->setExternalSegmentation(true);
62  iljQueryUtil::initjQuery($DIC->ui()->mainTemplate());
63  ilYuiUtil::initPanel(false, $DIC->ui()->mainTemplate());
64  ilYuiUtil::initOverlay($DIC->ui()->mainTemplate());
65  $DIC->ui()->mainTemplate()->addJavaScript('assets/js/Form.js');
66  $this->determineOffsetAndOrder();
67  $this->setData($table->rows($this));
68  }
69 
70  public function setMaxCount(int $a_max_count): void
71  {
72  $this->setShowRowsSelector(true);
73  parent::setMaxCount($a_max_count);
74  }
75 
76  public function setSelectableColumns(string ...$names): void
77  {
78  $this->sel = array_merge($this->sel, $names);
79  }
80 
81  public function selection(): array
82  {
83  return array_flip($this->sel);
84  }
85 
86  public function getSelectableColumns(): array
87  {
88  return array_map(fn($x) => ['txt' => $x[0]], array_intersect_key(
89  $this->columns,
90  $this->selection()
91  ));
92  }
93 
94  public function filter(): array
95  {
96  return array_column(array_map(
97  fn($input) => [
98  $input->getPostVar(),
99  $input->getValue()
100  ],
101  $this->filterInputs()
102  ), 1, 0);
103  }
104 
105  public function render(): string
106  {
107  return parent::render() . $this->renderModals();
108  }
109 
110  protected function isColumnVisible(int $index): bool
111  {
112  return true;
113  }
114 
115  private function visibleColumns(): array
116  {
117  $restore_key_order = fn($array) => array_intersect_key($this->columns, $array);
118  $base = array_diff_key($this->columns, $this->selection());
119 
120  return $restore_key_order(array_merge($base, array_intersect_key($this->columns, $this->getSelectedColumns())));
121  }
122 
126  private function resetParameters(array $parameters): void
127  {
128  $this->applyParamters(array_map(static fn(): string => '', $parameters));
129  }
130 
134  private function applyParamters(array $parameters): void
135  {
136  foreach ($parameters as $key => $value) {
137  $this->ctrl->setParameter($this->getParentObject(), $key, $value);
138  }
139  }
140 
141  protected function fillRow(array $a_set): void
142  {
143  $this->requireKeys(array_keys($this->columns), $a_set);
144  $set = array_intersect_key($a_set, $this->visibleColumns());
145  $this->tpl->setVariable('VALUE', join('', array_map($this->tableCellOfField(...), $set)));
146  }
147 
148  protected function tableCellOfField($x): string
149  {
150  return sprintf('<td>%s</td>', $this->asString($x));
151  }
152 
156  private function asString($x): string
157  {
158  $is_component = fn($x): bool => $x instanceof Component;
159 
160  if ($is_component($x) || (is_array($x) && array_filter($x, fn($x) => !$is_component($x)) === [])) {
161  global $DIC;
162  return $DIC->ui()->renderer()->render($this->removeModals($x));
163  } elseif ($x instanceof Closure) {
164  return $x();
165  } elseif (is_string($x)) {
166  return htmlentities($x);
167  }
168 
169  throw new InvalidArgumentException('Value must be either: Component|list<Component>|Closure|string. Given: ' . var_export($x, true));
170  }
171 
172  protected function txt(string $key): string
173  {
174  return $key === '' ? '' : $this->lng->txt($key);
175  }
176 
181  private function requireKeys(array $required, array $given): void
182  {
183  $given = array_keys($given);
184  $missing = $this->intersect($required, $this->diff($required, $given));
185  if ([] !== $missing) {
186  throw new InvalidArgumentException('Missing keys: ' . join(', ', $missing));
187  }
188  }
189 
190  private function diff(array $a, array $b): array
191  {
192  return array_filter($a, fn($x) => !$this->has($x, $b));
193  }
194 
195  private function intersect(array $a, array $b): array
196  {
197  return array_filter($a, fn($x) => $this->has($x, $b));
198  }
199 
200  private function has($x, array $array): bool
201  {
202  return in_array($x, $array, true);
203  }
204 
205  private function filterInputs(): array
206  {
207  return [
208  ...$this->getFilterItems(),
209  ...$this->getFilterItems(true),
210  ];
211  }
212 
213  public function setupFilter(string $reset_command): void
214  {
215  global $DIC;
216  $this->initFilter();
217  $this->setFilterCommand($this->getParentCmd());
218  $this->setResetCommand($reset_command);
219  $this->determineSelectedFilters();
220  if ($DIC->ctrl()->getCmd() === $reset_command) {
221  $this->resetFilter();
222  } elseif (strtoupper($DIC->http()->request()->getMethod()) === 'POST') {
223  $this->writeFilterToSession();
224  } else {
225  $read = static fn(ilFormPropertyGUI $x) => $x->readFromSession();
226  array_map($read, $this->getFilterItems());
227  array_map($read, array_filter($this->getFilterItems(true), fn($x) => $this->isFilterSelected($x->getPostVar())));
228  }
229  }
230 
231  private function renderModals(): string
232  {
233  global $DIC;
234 
235  return $DIC->ui()->renderer()->render($this->flatMap(
236  fn($x) => $this->flatMap(fn($x) => array_filter($this->asArray($x), $this->isModal(...)), $x),
237  $this->getData()
238  ));
239  }
240 
241  private function removeModals($x): array
242  {
243  return array_filter($this->asArray($x), fn($x) => !$this->isModal($x));
244  }
245 
246  private function flatMap(callable $proc, array $a): array
247  {
248  return array_merge(...array_values(array_map($proc, $a)));
249  }
250 
251  private function asArray($x): array
252  {
253  return is_array($x) ? $x : [$x];
254  }
255 
256  private function isModal($x): bool
257  {
258  return $x instanceof Modal;
259  }
260 }
This describes commonalities between the different modals.
Definition: Modal.php:34
setData(array $a_data)
intersect(array $a, array $b)
Definition: Table.php:195
This class takes care of the order in which the methods must be called.
setFormAction(string $a_form_action, bool $a_multipart=false)
setResetCommand(string $a_val, string $a_caption="")
diff(array $a, array $b)
Definition: Table.php:190
requireKeys(array $required, array $given)
Definition: Table.php:181
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
flatMap(callable $proc, array $a)
Definition: Table.php:246
setFormName(string $a_name="")
applyParamters(array $parameters)
Definition: Table.php:134
setId(string $a_val)
resetParameters(array $parameters)
Definition: Table.php:126
__construct(?object $gui, string $command, TableInterface $table)
Definition: Table.php:42
isFilterSelected(string $a_col)
Is given filter selected?
setupFilter(string $reset_command)
Definition: Table.php:213
setExternalSorting(bool $a_val)
setShowRowsSelector(bool $a_value)
Toggle rows-per-page selector.
static initjQuery(?ilGlobalTemplateInterface $a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template
setSelectableColumns(string ... $names)
Definition: Table.php:76
setRowTemplate(string $a_template, string $a_template_dir="")
Set row template.
setFilterCommand(string $a_val, string $a_caption="")
global $DIC
Definition: shib_login.php:26
$txt
Definition: error.php:31
__construct(Container $dic, ilPlugin $plugin)
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
addColumn(string $a_text, string $a_sort_field="", string $a_width="", bool $a_is_checkbox_action_column=false, string $a_class="", string $a_tooltip="", bool $a_tooltip_with_html=false)
getFilterItems(bool $a_optionals=false)
setMaxCount(int $a_max_count)
Definition: Table.php:70
determineOffsetAndOrder(bool $a_omit_offset=false)
static initPanel(bool $a_resize=false, ?ilGlobalTemplateInterface $a_main_tpl=null)
Init yui panel used in Modules/Test, Services/TermsOfService (Jan 2022)
static initOverlay(?ilGlobalTemplateInterface $a_main_tpl=null)
Init YUI Overlay module used in Modules/Test, Services/TermsOfService, Services/Tracking, Services/UIComponent.
setExternalSegmentation(bool $a_val)