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