ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjectTranslationGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
28 
35 {
36  protected const CMD_LIST_TRANSLATIONS = 'listTranslations';
37  protected const CMD_SAVE_TRANSLATIONS = 'saveTranslations';
38  protected const CMD_ADD_TRANSLATION = 'addTranslation';
39  protected const CMD_DELETE_TRANSLATIONS = 'deleteTranslations';
40  protected const CMD_SAVE_LANGUAGES = 'saveLanguages';
41  protected const CMD_CONFIRM_REMOVE_LANGUAGES = 'confirmDeleteTranslations';
42  protected const CMD_SET_FALLBACK = 'setFallback';
43  protected const CMD_DEACTIVATE_CONTENT_MULTILANG = 'deactivateContentMultiLang';
44  protected const CMD_SAVE_CONTENT_TRANSLATION_ACTIVATION = 'saveContentTranslationActivation';
46  protected ilObjUser $user;
47  protected ilAccess $access;
48  protected ilLanguage $lng;
49  protected ilCtrl $ctrl;
55  protected Refinery $refinery;
56 
57  protected ilObjectGUI $obj_gui;
58  protected ilObject $obj;
60 
61  protected bool $title_descr_only = true;
62  protected bool $hide_description = false;
63  protected bool $fallback_lang_mode = true;
64  protected bool $support_content_translation = true;
65 
66  public function __construct($obj_gui)
67  {
69  global $DIC;
70 
71  $this->toolbar = $DIC['ilToolbar'];
72  $this->user = $DIC['ilUser'];
73  $this->access = $DIC['ilAccess'];
74  $this->lng = $DIC['lng'];
75  $this->ctrl = $DIC['ilCtrl'];
76  $this->tpl = $DIC['tpl'];
77  $this->ui_factory = $DIC['ui.factory'];
78  $this->ui_renderer = $DIC['ui.renderer'];
79  $this->post_wrapper = $DIC->http()->wrapper()->post();
80  $this->request = $DIC->http()->request();
81  $this->refinery = $DIC['refinery'];
82 
83 
84  $this->obj_gui = $obj_gui;
85  $this->obj = $obj_gui->getObject();
86 
87  $this->obj_trans = ilObjectTranslation::getInstance($this->obj->getId());
88  }
89 
90  public function hideDescription(bool $hide): void
91  {
92  $this->hide_description = $hide;
93  }
94 
95  public function supportContentTranslation(bool $content_translation): void
96  {
97  $this->support_content_translation = $content_translation;
98  }
99 
100  private function getTableValuesByObjects(): array
101  {
102  $data = [];
103  foreach ($this->obj_trans->getLanguages() as $k => $v) {
104  $data[$k]['default'] = (int) $v->isDefault();
105  $data[$k]['title'] = $v->getTitle();
106  $data[$k]['desc'] = $v->getDescription();
107  $data[$k]['lang'] = $v->getLanguageCode();
108  }
109  return $data;
110  }
111 
112  private function getTableValuesByRequest(): array
113  {
114  $vals = [];
115 
116  $titles = $this->post_wrapper->has('title')
117  ? $this->post_wrapper->retrieve(
118  'title',
119  $this->refinery->to()->listOf($this->refinery->kindlyTo()->string())
120  )
121  : [];
122 
123  $descriptions = $this->post_wrapper->has('desc')
124  ? $this->post_wrapper->retrieve(
125  'desc',
126  $this->refinery->to()->listOf($this->refinery->kindlyTo()->string())
127  )
128  : [];
129 
130  $languages = $this->post_wrapper->has('lang')
131  ? $this->post_wrapper->retrieve(
132  'lang',
133  $this->refinery->to()->listOf($this->refinery->kindlyTo()->string())
134  )
135  : [];
136 
137  $default = $this->post_wrapper->has('default')
138  ? $this->post_wrapper->retrieve(
139  'default',
140  $this->refinery->kindlyTo()->int()
141  )
142  : '';
143 
144  foreach ($titles as $k => $v) {
145  $vals[] = [
146  'title' => $v,
147  'desc' => $descriptions[$k],
148  'lang' => $languages[$k],
149  'default' => ($default == $k)
150  ];
151  }
152  return $vals;
153  }
154 
162  public function setTitleDescrOnlyMode(bool $val): void
163  {
164  $this->title_descr_only = $val;
165  }
166 
167  public function getTitleDescrOnlyMode(): bool
168  {
170  }
171 
172  public function setEnableFallbackLanguage(bool $val): void
173  {
174  $this->fallback_lang_mode = $val;
175  }
176 
177  public function getEnableFallbackLanguage(): bool
178  {
180  }
181 
182  public function executeCommand(): void
183  {
184  $commands = [
185  self::CMD_LIST_TRANSLATIONS,
186  self::CMD_SAVE_TRANSLATIONS,
187  self::CMD_ADD_TRANSLATION,
188  self::CMD_DELETE_TRANSLATIONS,
189  self::CMD_CONFIRM_REMOVE_LANGUAGES,
190  self::CMD_SAVE_LANGUAGES,
191  self::CMD_SAVE_CONTENT_TRANSLATION_ACTIVATION,
192  self::CMD_DEACTIVATE_CONTENT_MULTILANG,
193  self::CMD_SET_FALLBACK
194  ];
195 
196  $this->ctrl->getNextClass($this);
197  $cmd = $this->ctrl->getCmd(self::CMD_LIST_TRANSLATIONS);
198  if (!$this->access->checkAccess('write', '', $this->obj_gui->getRefId())) {
199  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('no_permission'));
200  $this->ctrl->redirect($this->obj_gui);
201  }
202  if (in_array($cmd, $commands)) {
203  $this->$cmd();
204  }
205  }
206 
207  public function listTranslations(bool $get_post_values = false, bool $add = false): void
208  {
209  $this->lng->loadLanguageModule(ilObject::_lookupType($this->obj->getId()));
210 
211  $add_langs_modal = $this->getAddLanguagesModal();
212  if ($this->getTitleDescrOnlyMode() || $this->obj_trans->getContentActivated()) {
213  $this->toolbar->addComponent(
214  $this->ui_factory->button()->standard(
215  $this->lng->txt('obj_add_languages'),
216  $add_langs_modal->getShowSignal()
217  )
218  );
219  }
220 
221  if ($this->support_content_translation) {
222  $content_translation_modal = $this->addContentTranslationToolbarActionAndRetrieveCorrespondingModal();
223  }
224 
225  $table = new ilObjectTranslation2TableGUI(
226  $this,
227  self::CMD_LIST_TRANSLATIONS,
228  !$this->hide_description,
229  'Translation',
230  $this->obj_trans->getMasterLanguage(),
232  $this->obj_trans->getFallbackLanguage()
233  );
234  if ($get_post_values) {
235  $table->setData($this->getTableValuesByRequest());
236  } else {
237  $table->setData($this->getTableValuesByObjects());
238  }
239  $page_content = $table->getHTML() . $this->ui_renderer->render($add_langs_modal);
240 
241  if (isset($content_translation_modal)) {
242  $page_content .= $this->ui_renderer->render($content_translation_modal);
243  }
244 
245  $this->tpl->setContent($page_content);
246  }
247 
248  private function getAddLanguagesModal(): Modal
249  {
250  return $this->ui_factory->modal()->roundtrip(
251  $this->lng->txt('confirm'),
252  null,
253  [
254  'langs' => $this->getMultiLangFormInput(true)
255  ],
256  $this->ctrl->getFormActionByClass(self::class, self::CMD_SAVE_LANGUAGES)
257  );
258  }
259 
261  {
262  $lang_var_postfix = '_multilang';
263  $deactivation_modal_text_tag = 'obj_deactivate_multilang_conf';
264  if ($this->getTitleDescrOnlyMode()) {
265  $lang_var_postfix = '_content_lang';
266  $deactivation_modal_text_tag = 'obj_deactivate_content_transl_conf';
267  }
268 
269  if ($this->getTitleDescrOnlyMode() && !$this->obj_trans->getContentActivated()) {
270  $this->tpl->setOnScreenMessage('info', $this->lng->txt('obj_multilang_title_descr_only'));
271  }
272 
273  $activate_modal = $this->getActivateMultilingualityModal();
274  if (!$this->obj_trans->getContentActivated()) {
275  $this->toolbar->addComponent(
276  $this->ui_factory->button()->standard(
277  $this->lng->txt('obj_activate' . $lang_var_postfix),
278  $activate_modal->getShowSignal()
279  )
280  );
281  return $activate_modal;
282  }
283 
284  $deactivate_modal = $this->getConfirmDeactivateMultilingualityModal($deactivation_modal_text_tag);
285  $this->toolbar->addComponent(
286  $this->ui_factory->button()->standard(
287  $this->lng->txt('obj_deactivate' . $lang_var_postfix),
288  $deactivate_modal->getShowSignal()
289  )
290  );
291  return $deactivate_modal;
292  }
293 
294  private function getConfirmDeactivateMultilingualityModal(string $text_tag): Modal
295  {
296  return $this->ui_factory->modal()->interruptive(
297  $this->lng->txt('confirm'),
298  $this->lng->txt($text_tag),
299  $this->ctrl->getLinkTargetByClass(self::class, self::CMD_DEACTIVATE_CONTENT_MULTILANG)
300  )->withActionButtonLabel($this->lng->txt('confirm'));
301  }
302 
304  {
305  return $this->ui_factory->modal()->roundtrip(
306  $this->lng->txt('confirm'),
307  $this->ui_factory->legacy($this->lng->txt('obj_select_master_lang')),
308  [
309  'lang' => $this->getMultiLangFormInput()
310  ],
311  $this->ctrl->getFormActionByClass(self::class, self::CMD_SAVE_CONTENT_TRANSLATION_ACTIVATION)
312  );
313  }
314 
315  public function saveTranslations(): void
316  {
317  // default language set?
318  if (!$this->post_wrapper->has('default') && $this->obj_trans->getMasterLanguage() === '') {
319  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_default_language'));
320  $this->listTranslations(true);
321  return;
322  }
323 
324  // all languages set?
325  $languages = $this->post_wrapper->has('lang')
326  ? $this->post_wrapper->retrieve(
327  'lang',
328  $this->refinery->kindlyTo()->dictOf(
329  $this->refinery->kindlyTo()->string()
330  )
331  )
332  : [];
333  if (array_key_exists('', $languages)) {
334  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_language_selected'));
335  $this->listTranslations(true);
336  return;
337  }
338 
339  // no single language is selected more than once?
340  if (count(array_unique($languages)) < count($languages)) {
341  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_multi_language_selected'));
342  $this->listTranslations(true);
343  return;
344  }
345 
346  // save the stuff
347  $this->obj_trans->setLanguages([]);
348 
349  $titles = $this->post_wrapper->has('title')
350  ? $this->post_wrapper->retrieve(
351  'title',
352  $this->refinery->kindlyTo()->dictOf(
353  $this->refinery->kindlyTo()->string()
354  )
355  )
356  : [];
357  $descriptions = $this->post_wrapper->has('desc')
358  ? $this->post_wrapper->retrieve(
359  'desc',
360  $this->refinery->kindlyTo()->dictOf(
361  $this->refinery->kindlyTo()->string()
362  )
363  )
364  : [];
365 
366  $post_default = $this->post_wrapper->has('default')
367  ? $this->post_wrapper->retrieve(
368  'default',
369  $this->refinery->kindlyTo()->int()
370  )
371  : null;
372 
373  $check = $this->post_wrapper->has('check')
374  ? $this->post_wrapper->retrieve(
375  'check',
376  $this->refinery->kindlyTo()->dictOf($this->refinery->kindlyTo()->string())
377  )
378  : [];
379 
380  if ($this->obj_trans->getFallbackLanguage() !== '') {
381  $obj_store_lang = $this->obj_trans->getFallbackLanguage();
382  } else {
383  $obj_store_lang = ($this->obj_trans->getMasterLanguage() != '')
384  ? $this->obj_trans->getMasterLanguage()
385  : $languages[$post_default];
386  }
387 
388  foreach ($titles as $k => $v) {
389  // update object data if default
390  $is_default = ($post_default === $k);
391 
392  // ensure master language is set as default
393  if ($this->obj_trans->getMasterLanguage() != '') {
394  $is_default = ($this->obj_trans->getMasterLanguage() === $languages[$k]);
395  }
396  if ($languages[$k] === $obj_store_lang) {
397  $this->obj->setTitle(ilUtil::stripSlashes($v));
398  $this->obj->setDescription(ilUtil::stripSlashes($descriptions[$k] ?? ''));
399  }
400 
401  $this->obj_trans->addLanguage(
402  ilUtil::stripSlashes($languages[$k]),
404  ilUtil::stripSlashes($descriptions[$k] ?? ''),
405  $is_default
406  );
407  }
408  $this->obj_trans->save();
409  if (method_exists($this->obj, 'setObjectTranslation')) {
410  $this->obj->setObjectTranslation($this->obj_trans);
411  }
412  $this->obj->update();
413 
414  $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
415  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
416  }
417 
418  public function getMultiLangFormInput(bool $add = false): Input
419  {
420  $options = ilMDLanguageItem::_getLanguages();
421 
422  if ($add) {
423  $master_lang = $this->obj_trans->getMasterLanguage();
424  $trafo = $this->refinery->custom()->transformation(
425  function (array $vs) use ($master_lang) {
426  $langs = [];
427  foreach ($vs as $v) {
428  if ($v !== $master_lang && $v !== '') {
429  $langs[] = $v;
430  }
431  }
432  return $langs;
433  }
434  );
435  return $this->ui_factory->input()->field()->multiSelect(
436  $this->lng->txt('obj_additional_langs'),
437  $options
438  )->withAdditionalTransformation($trafo);
439  }
440 
441  $trafo = $this->refinery->custom()->transformation(
442  fn($v) => in_array($v, ilMDLanguageItem::_getPossibleLanguageCodes()) ? $v : $this->lng->getDefaultLanguage()
443  );
444 
445  return $this->ui_factory->input()->field()->select(
446  $this->lng->txt('obj_master_lang'),
447  $options
449  ->withValue($this->user->getLanguage());
450  }
451 
452  public function saveContentTranslationActivation(): void
453  {
455  ->withRequest($this->request)
456  ->getData();
457  $this->obj_trans->setMasterLanguage($data['lang']);
458  if (!in_array($data['lang'], $this->obj_trans->getLanguages())) {
459  $this->obj_trans->addLanguage(
460  $data['lang'],
461  $this->obj->getTitle(),
462  $this->obj->getDescription(),
463  true
464  );
465  }
466  $this->obj_trans->save();
467 
468  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
469  }
470 
471  public function deactivateContentMultiLang(): void
472  {
473  if (!$this->getTitleDescrOnlyMode()) {
474  $this->obj_trans->setMasterLanguage('');
475  $this->obj_trans->setLanguages([]);
476  $this->obj_trans->save();
477  }
478  $this->obj_trans->deactivateContentTranslation();
479  if ($this->getTitleDescrOnlyMode()) {
480  $this->tpl->setOnScreenMessage('success', $this->lng->txt('obj_cont_transl_deactivated'), true);
481  } else {
482  $this->tpl->setOnScreenMessage('success', $this->lng->txt('obj_multilang_deactivated'), true);
483  }
484 
485  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
486  }
487 
488  public function saveLanguages(): void
489  {
490  $data = $this->getAddLanguagesModal()
491  ->withRequest($this->request)
492  ->getData();
493 
494  if ($data['langs'] === null || $data['langs'] === []) {
495  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('no_checkbox'), true);
496  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
497  }
498 
499  foreach ($data['langs'] as $lang) {
500  $this->obj_trans->addLanguage($lang, '', '', false);
501  }
502 
503  $this->obj_trans->save();
504  $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
505  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
506  }
507 
508  public function confirmDeleteTranslations(): void
509  {
510  $this->lng->loadLanguageModule('meta');
511  $trafo = $this->retrieveTrafoToRemoveDefaultLang();
512 
513  $languages = $this->post_wrapper->has('lang')
514  ? $this->post_wrapper->retrieve(
515  'lang',
516  $trafo
517  )
518  : [];
519 
520  $to_be_deleted = $this->post_wrapper->has('check')
521  ? $this->post_wrapper->retrieve(
522  'check',
523  $this->refinery->kindlyTo()->dictOf($this->refinery->kindlyTo()->string())
524  )
525  : [];
526 
527  if (count($to_be_deleted) === 0) {
528  $this->tpl->setOnScreenMessage('info', $this->lng->txt('no_checkbox'), true);
529  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
530  }
531 
532  $cgui = new ilConfirmationGUI();
533  $cgui->setFormAction($this->ctrl->getFormAction($this));
534  $cgui->setHeaderText($this->lng->txt('obj_conf_delete_lang'));
535  $cgui->setCancel($this->lng->txt('cancel'), self::CMD_LIST_TRANSLATIONS);
536  $cgui->setConfirm($this->lng->txt('remove'), self::CMD_DELETE_TRANSLATIONS);
537 
538  foreach (array_keys($to_be_deleted) as $index) {
539  if (!array_key_exists($index, $languages)) {
540  continue;
541  }
542  $cgui->addItem('lang[]', $languages[$index], $this->lng->txt('meta_l_' . $languages[$index]));
543  }
544 
545  $this->tpl->setContent($cgui->getHTML());
546  }
547 
548  public function deleteTranslations(): void
549  {
550  $trafo = $this->retrieveTrafoToRemoveDefaultLang();
551  $langs_to_be_deleted = $this->post_wrapper->has('lang')
552  ? $this->post_wrapper->retrieve(
553  'lang',
554  $trafo
555  )
556  : [];
557 
558  foreach ($langs_to_be_deleted as $lang) {
559  $this->obj_trans->removeLanguage($lang);
560  }
561  $this->obj_trans->save();
562  $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
563  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
564  }
565 
566  private function retrieveTrafoToRemoveDefaultLang(): callable
567  {
568  $default_lang = $this->obj_trans->getDefaultLanguage();
569  return $this->refinery->custom()->transformation(
570  function (?array $vs) use ($default_lang) {
571  if ($vs === null) {
572  return [];
573  }
574 
575  $langs = [];
576  foreach ($vs as $k => $v) {
577  if ($v !== $default_lang) {
578  $langs[$k] = (string) $v;
579  }
580  }
581  return $langs;
582  }
583  );
584  }
585 
586  public function setFallback(): void
587  {
588  // default language set?
589  $checkboxes = $this->post_wrapper->has('check')
590  ? $this->post_wrapper->retrieve(
591  'check',
592  $this->refinery->kindlyTo()->dictOf(
593  $this->refinery->kindlyTo()->int()
594  )
595  )
596  : [];
597 
598  if ($checkboxes === []) {
599  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('obj_select_one_language'));
600  $this->listTranslations(true);
601  return;
602  }
603  $checked = key($checkboxes);
604 
605  $languages = $this->post_wrapper->has('lang')
606  ? $this->post_wrapper->retrieve(
607  'lang',
608  $this->refinery->kindlyTo()->dictOf($this->refinery->kindlyTo()->string())
609  )
610  : [];
611 
612  $fallback_lang = $languages[$checked];
613  if ($fallback_lang !== $this->obj_trans->getFallbackLanguage()) {
614  $this->obj_trans->setFallbackLanguage($fallback_lang);
615  } else {
616  $this->obj_trans->setFallbackLanguage('');
617  }
618  $this->obj_trans->save();
619  $this->tpl->setOnScreenMessage('info', $this->lng->txt('msg_obj_modified'), true);
620  $this->ctrl->redirect($this, self::CMD_LIST_TRANSLATIONS);
621  }
622 }
This describes commonalities between the different modals.
Definition: Modal.php:34
setData(array $a_data)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
An entity that renders components to a string output.
Definition: Renderer.php:30
setTitleDescrOnlyMode(bool $val)
Some objects like learning modules do not support to translate only the title and the description...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
ilGlobalTemplateInterface $tpl
global $DIC
Definition: feed.php:28
__construct(VocabulariesInterface $vocabularies)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getConfirmDeactivateMultilingualityModal(string $text_tag)
Class ilObjectGUI Basic methods of all Output classes.
static getInstance(int $obj_id)
ArrayBasedRequestWrapper $post_wrapper
supportContentTranslation(bool $content_translation)
$lang
Definition: xapiexit.php:26
This describes commonalities between all inputs.
Definition: Input.php:46
$check
Definition: buildRTE.php:81
static _lookupType(int $id, bool $reference=false)
GUI class for object translation handling.
listTranslations(bool $get_post_values=false, bool $add=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...