ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
TranslationsTable.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use ILIAS\ILIASObject\Properties\Properties as ObjectProperties;
24use ILIAS\UI\Factory as UIFactory;
25use ILIAS\UI\Renderer as UIRenderer;
30use ILIAS\UI\Component\Component as UIComponent;
31use ILIAS\UI\Component\Modal\RoundTrip as RoundtripModal;
32use ILIAS\UI\Component\Modal\Interruptive as InterruptiveModal;
37use ILIAS\Language\Language as SystemLanguage;
38use ILIAS\HTTP\Services as HTTPService;
39use ILIAS\Refinery\Factory as Refinery;
41
43{
44 private const QUERY_PARAMETER_NAME_SPACE = ['obj', 'trans'];
45 private const TOKEN_STRING_ACTION = 'a';
46 private const TOKEN_STRING_ROW_ID = 't';
48
49 public const ACTION_EDIT = 'e';
50 public const ACTION_MAKE_DEFAULT = 'md';
51 public const ACTION_DELETE = 'd';
52
57
58 private ?RoundtripModal $modal_with_error = null;
59
63 public function __construct(
64 private readonly UIFactory $ui_factory,
65 private readonly UIRenderer $ui_renderer,
66 private readonly SystemLanguage $lng,
67 private readonly Refinery $refinery,
68 private readonly \ilGlobalTemplateInterface $tpl,
69 private readonly HTTPService $http,
70 private readonly \ilCtrl $ctrl,
71 private Translations $translations,
72 private readonly ObjectProperties $object_properties,
73 URI $here_uri
74 ) {
75 [
80 ] = (new URLBuilder($here_uri))->acquireParameters(
81 self::QUERY_PARAMETER_NAME_SPACE,
82 self::TOKEN_STRING_ACTION,
83 self::TOKEN_STRING_ROW_ID,
84 self::TOKEN_STRING_ACTON_AFFECTED_ITEMS
85 );
86 }
87
88 public function runAction(): void
89 {
90 $action = $this->http->wrapper()->query()->retrieve(
91 $this->token_action->getName(),
92 $this->refinery->byTrying([
93 $this->refinery->kindlyTo()->string(),
94 $this->refinery->always('')
95 ])
96 );
97
98 if ($action === '') {
99 return;
100 }
101
102 match ($action) {
103 self::ACTION_EDIT => $this->editTranslation(),
104 self::ACTION_MAKE_DEFAULT => $this->makeDefault(),
105 self::ACTION_DELETE => $this->deleteTranslations()
106 };
107 }
108
109 public function getTable(): array
110 {
111 $content = [];
112 if ($this->modal_with_error !== null) {
113 $content[] = $this->modal_with_error;
114 }
115
116 $content[] = $this->ui_factory->table()->data(
117 $this,
118 $this->lng->txt('available_languages'),
119 $this->getColumns()
120 )->withActions($this->getActions())
121 ->withRequest($this->http->request());
122
123 return $content;
124 }
125
126 public function getRows(
127 DataRowBuilder $row_builder,
128 array $visible_column_ids,
130 Order $order,
131 mixed $additional_viewcontrol_data,
132 mixed $filter_data,
133 mixed $additional_parameters
134 ): \Generator {
135 foreach ($this->translations->getLanguages() as $langauge) {
136 yield $langauge->toRow($row_builder, $this->lng);
137 }
138 }
139
140 public function getTotalRowCount(
141 mixed $additional_viewcontrol_data,
142 mixed $filter_data,
143 mixed $additional_parameters
144 ): ?int {
145 return count($this->translations->getLanguages());
146 }
147
148
149 private function getColumns(): array
150 {
151 $cf = $this->ui_factory->table()->column();
152 $columns = [
153 'language' => $cf->text($this->lng->txt('language')),
154 ];
155 if ($this->translations->getContentTranslationActivated()) {
156 $columns['base'] = $cf->boolean(
157 $this->lng->txt('obj_base_lang'),
158 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_checked.svg', '', 'small'),
159 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_unchecked.svg', '', 'small')
160 );
161 }
162
163 return $columns + [
164 'default' => $cf->boolean(
165 $this->lng->txt('default'),
166 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_checked.svg', '', 'small'),
167 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_unchecked.svg', '', 'small')
168 ),
169 'title' => $cf->text($this->lng->txt('title')),
170 'description' => $cf->text($this->lng->txt('description')),
171 ];
172
173 }
174
175 private function getActions(): array
176 {
177 if ($this->translations->migrationMissing()) {
178 return [];
179 }
180 return [
181 self::ACTION_EDIT => $this->ui_factory->table()->action()->single(
182 $this->lng->txt('edit'),
183 $this->url_builder->withParameter(
184 $this->token_action,
185 self::ACTION_EDIT
186 ),
187 $this->token_row_id
188 )->withAsync(),
189 self::ACTION_MAKE_DEFAULT => $this->ui_factory->table()->action()->single(
190 $this->lng->txt('make_default_language'),
191 $this->url_builder->withParameter(
192 $this->token_action,
193 self::ACTION_MAKE_DEFAULT
194 ),
195 $this->token_row_id
196 ),
197 self::ACTION_DELETE => $this->ui_factory->table()->action()->standard(
198 $this->lng->txt('delete'),
199 $this->url_builder->withParameter(
200 $this->token_action,
201 self::ACTION_DELETE
202 ),
203 $this->token_row_id
204 )->withAsync()
205 ];
206 }
207
208 private function editTranslation(): void
209 {
210 if ($this->http->wrapper()->query()->retrieve(
211 $this->token_action_affected_items->getName(),
212 $this->refinery->kindlyTo()->string()
213 ) === '') {
214 $this->sendAsync(
215 $this->buildEditLanguageModal(
216 $this->retrieveAffectedItemsFromQuery()[0]
217 )
218 );
219 }
220
221 $modal = $this->buildEditLanguageModal(
222 $this->http->wrapper()->query()->retrieve(
223 $this->token_action_affected_items->getName(),
224 $this->refinery->kindlyTo()->string()
225 )
226 )->withRequest($this->http->request());
227 $data = $modal->getData();
228 if ($data === null) {
229 $this->modal_with_error = $modal->withOnLoad($modal->getShowSignal());
230 return;
231 }
232
233 $this->translations = $this->translations->withLanguage($data[0]);
234 $this->object_properties->storePropertyTranslations(
235 $this->translations
236 );
237
238 $this->object_properties->storePropertyTranslations(
239 $this->translations->withLanguage($data[0])
240 );
241 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
242 $this->ctrl->redirectByClass($this->ctrl->getCurrentClassPath());
243 }
244
245 private function makeDefault(): void
246 {
247 $this->translations = $this->translations->withDefaultLanguage(
248 $this->retrieveAffectedItemsFromQuery()[0]
249 );
250 $this->object_properties->storePropertyTranslations(
251 $this->translations
252 );
253 }
254
255 private function deleteTranslations(): void
256 {
257 if ($this->http->wrapper()->query()->retrieve(
258 $this->token_action_affected_items->getName(),
259 $this->refinery->byTrying([
260 $this->refinery->kindlyTo()->string(),
261 $this->refinery->kindlyTo()->listOf(
262 $this->refinery->kindlyTo()->string()
263 )
264 ])
265 ) === '') {
266 $this->sendAsync(
267 $this->buildConfirmationModal(
268 $this->retrieveAffectedItemsFromQueryForDeletion()
269 )
270 );
271 }
272
273 $this->object_properties->storePropertyTranslations(
274 array_reduce(
275 $this->http->wrapper()->post()->retrieve(
276 'interruptive_items',
277 $this->refinery->kindlyTo()->listOf(
278 $this->refinery->kindlyTo()->string()
279 )
280 ),
281 static fn(Translations $c, string $v): Translations => $c->withoutLanguage($v),
282 $this->translations
283 )
284 );
285 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
286 $this->ctrl->redirectByClass($this->ctrl->getCurrentClassPath());
287 }
288
289 private function buildEditLanguageModal(string $language_code): RoundtripModal
290 {
291 return $this->ui_factory->modal()->roundtrip(
292 $this->lng->txt('edit_language'),
293 null,
294 $this->translations->getLaguageForCode(
295 $language_code
296 )->toForm(
297 $this->lng,
298 $this->ui_factory->input()->field(),
299 $this->refinery
300 ),
301 $this->url_builder
302 ->withParameter($this->token_action, self::ACTION_EDIT)
303 ->withParameter($this->token_action_affected_items, $language_code)
304 ->buildURI()->__toString()
305 );
306 }
307
308 private function buildConfirmationModal(array $languages_to_delete): InterruptiveModal
309 {
310 return $this->ui_factory->modal()->interruptive(
311 $this->lng->txt('confirm'),
312 $this->lng->txt('obj_conf_delete_lang'),
313 $this->url_builder
314 ->withParameter($this->token_action, self::ACTION_DELETE)
315 ->withParameter($this->token_action_affected_items, $languages_to_delete)
316 ->buildURI()->__toString()
317 )->withAffectedItems(
318 array_map(
319 fn(string $v): InterruptiveItem => $this->ui_factory->modal()
320 ->interruptiveItem()->standard($v, $this->lng->txt("meta_l_{$v}")),
321 $languages_to_delete
322 )
323 );
324 }
325
327 {
328 $affected_items = $this->retrieveAffectedItemsFromQuery();
329 if (in_array($this->translations->getDefaultLanguage(), $affected_items)
330 || in_array($this->translations->getBaseLanguage(), $affected_items)) {
331 $this->sendAsync(
332 $this->ui_factory->messageBox()->failure(
333 $this->lng->txt('default_base_lang_not_deletable')
334 )
335 );
336 }
337 return $affected_items;
338 }
339
340 private function retrieveAffectedItemsFromQuery(): array
341 {
342 $affected_items = [];
343 if ($this->http->wrapper()->query()->has($this->token_row_id->getName())) {
344 $affected_items = $this->http->wrapper()->query()->retrieve(
345 $this->token_row_id->getName(),
346 $this->refinery->byTrying(
347 [
348 $this->refinery->container()->mapValues(
349 $this->refinery->kindlyTo()->string()
350 ),
351 $this->refinery->always([])
352 ]
353 )
354 );
355 }
356 if ($affected_items === []) {
357 $this->sendAsync(
358 $this->ui_factory->messageBox()->failure(
359 $this->lng->txt('no_checkbox')
360 )
361 );
362 }
363
364 return $affected_items;
365 }
366
367 private function sendAsync(UIComponent $response): void
368 {
369 $this->http->saveResponse(
370 $this->http->response()->withBody(
371 Streams::ofString(
372 $this->ui_renderer->renderAsync($response)
373 )
374 )
375 );
376 $this->http->sendResponse();
377 $this->http->close();
378 }
379}
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
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
The scope of this class is split ilias-conform URI's into components.
Definition: URI.php:35
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
Class Services.
Definition: Services.php:38
__construct(private readonly UIFactory $ui_factory, private readonly UIRenderer $ui_renderer, private readonly SystemLanguage $lng, private readonly Refinery $refinery, private readonly \ilGlobalTemplateInterface $tpl, private readonly HTTPService $http, private readonly \ilCtrl $ctrl, private Translations $translations, private readonly ObjectProperties $object_properties, URI $here_uri)
getTotalRowCount(mixed $additional_viewcontrol_data, mixed $filter_data, mixed $additional_parameters)
Mainly for the purpose of pagination-support, it is important to know about the total number of recor...
getRows(DataRowBuilder $row_builder, array $visible_column_ids, Range $range, Order $order, mixed $additional_viewcontrol_data, mixed $filter_data, mixed $additional_parameters)
This is called by the table to retrieve rows; map data-records to rows using the $row_builder e....
Class handles translation mode for an object.
Class ilCtrl provides processing control methods.
$http
Definition: deliver.php:30
$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...
A component is the most general form of an entity in the UI.
Definition: Component.php:28
An entity that renders components to a string output.
Definition: Renderer.php:31
static http()
Fetches the global http state from ILIAS.
global $lng
Definition: privfeed.php:31
$response
Definition: xapitoken.php:90