ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjLanguageExtGUI.php
Go to the documentation of this file.
1 <?php
2 
20 declare(strict_types=1);
21 
26 
27 require_once("./Services/Object/classes/class.ilObjectGUI.php");
28 require_once("Services/Language/classes/class.ilObjLanguageAccess.php");
29 
30 
46 {
47  private const ILIAS_LANGUAGE_MODULE = "Services/Language";
48  private string $langmode;
49  protected HTTPServices $http;
50  protected Refinery $refinery;
62  public function __construct($a_data, int $a_id = 0, bool $a_call_by_reference = false)
63  {
64  global $DIC;
65  $ilClientIniFile = $DIC->clientIni();
66  $ilCtrl = $DIC->ctrl();
67  $lng = $DIC->language();
68  $this->http = $DIC->http();
69  $this->refinery = $DIC->refinery();
70 
71  // language maintenance strings are defined in administration
72  $lng->loadLanguageModule("administration");
73  $lng->loadLanguageModule("meta");
74 
75  // view mode ('translate' or empty) determins available table filters
76  $ilCtrl->saveParameter($this, "view_mode");
77 
78  // type and id of get the bound object
79  $this->type = "lng";
80  $obj_id_get = 0;
81  if ($this->http->wrapper()->query()->has("obj_id")) {
82  $obj_id_get = $this->http->wrapper()->query()->retrieve("obj_id", $this->refinery->kindlyTo()->int());
83  }
84  if (!$this->id = $obj_id_get) {
86  }
87 
88  // do all generic GUI initialisations
89  parent::__construct($a_data, $this->id, false, true);
90 
91  // initialize the array to store session variables for extended language maintenance
92  if (!is_array($this->getSession())) {
93  ilSession::set("lang_ext_maintenance", array());
94  }
95  // $this->session = &$_SESSION["lang_ext_maintenance"];// Todo-PHP8-Review This property is not defined, here and in other methods in this class
96 
97  // read the lang mode
98  $this->langmode = $ilClientIniFile->readVariable("system", "LANGMODE");
99  }
100 
107  protected function assignObject(): void
108  {
109  require_once("Services/Language/classes/class.ilObjLanguageExt.php");
110  $this->object = new ilObjLanguageExt($this->id);
111  }
112 
117  public function getId(): int
118  {
119  return $this->id;
120  }
121 
125  public function executeCommand(): void
126  {
127  global $DIC;
128  $ilHelp = $DIC->help();
129 
131  $this->error->raiseError($this->lng->txt("permission_denied"), $this->error->MESSAGE);
132  exit;
133  }
134 
135  $cmd = $this->ctrl->getCmd("view") . "Object";
136  $this->$cmd();
137 
138  $ilHelp->setScreenIdComponent("lng");
139  }
140 
144  public function cancelObject(): void
145  {
146  $this->viewObject();
147  }
148 
152  protected function getViewTable(): \ilLanguageExtTableGUI
153  {
154  // create and configure the table object
155  include_once "./Services/Language/classes/class.ilLanguageExtTableGUI.php";
156  $table_gui = new ilLanguageExtTableGUI($this, "view", array(
157  "langmode" => $this->langmode,
158  "lang_key" => $this->object->key,
159  ));
160 
161  return $table_gui;
162  }
163 
167  public function viewObject(int $changesSuccessBool = 0): void
168  {
169  global $DIC;
170  $tpl = $DIC["tpl"];
171 
172  // get the view table
173  $table_gui = $this->getViewTable();
174 
175  // get the remarks in database
176  $comments = $this->object->getAllRemarks();
177 
178  $compare_comments = [];
179  $missing_entries = [];
180 
181  // set the language to compare with
182  // get the default values if the compare language is the same
183  $compare = $table_gui->getFilterItemByPostVar("compare")->getValue();
184  if ($compare == $this->object->key) {
185  $compare_object = $this->object->getGlobalLanguageFile();
186  $compare_content = $compare_object->getAllValues();
187  $compare_comments = $compare_object->getAllComments();
188  }
189 
190  // page translation mode:
191  // - the table is filtered by a list of modules and topics
193  // get the selection of modules and topics from request or session
196 
197  $reset_offset_get = false;
198  if ($this->http->wrapper()->query()->has("reset_offset")) {
199  $reset_offset_get = $this->http->wrapper()->query()->retrieve(
200  "reset_offset",
201  $this->refinery->kindlyTo()->bool()
202  );
203  }
204 
205  // first call for translation
206  if ($reset_offset_get) {
207  $table_gui->resetOffset();
208  }
209 
210  if (!isset($compare_content)) {
211  $compare_content = ilObjLanguageExt::_getValues(
212  $compare,
213  $modules,
214  $topics
215  );
216 
217  $compare_comments = ilObjLanguageExt::_getRemarks($compare);
218  }
219 
220  $translations = ilObjLanguageExt::_getValues(
221  $this->object->key,
222  $modules,
223  $topics
224  );
225 
226  // enable adding new entries
227  $db_found = array();
228  foreach ($translations as $name => $translation) {
229  $keys = explode($this->lng->separator, $name);
230  $db_found[] = $keys[1];
231  }
232  $missing_entries = array_diff($topics, $db_found);
233  } else { // normal view mode:
234  // - the table is filtered manually by module, mode and pattern
235  $filter_mode = $table_gui->getFilterItemByPostVar("mode")->getValue();
236  $filter_pattern = $table_gui->getFilterItemByPostVar("pattern")->getValue();
237  $filter_module = $table_gui->getFilterItemByPostVar("module")->getValue();
238  $filter_module = $filter_module === "all" ? "" : $filter_module;
239  $filter_modules = $filter_module ? array($filter_module) : array();
240  $filter_identifier = $table_gui->getFilterItemByPostVar("identifier")->getValue();
241  $filter_topics = $filter_identifier ? array($filter_identifier) : array();
242 
243  if (!isset($compare_content)) {
244  $compare_content = ilObjLanguageExt::_getValues(
245  $compare,
246  $filter_modules,
247  $filter_topics
248  );
249 
250  $compare_comments = ilObjLanguageExt::_getRemarks($compare);
251  }
252 
253  switch ($filter_mode) {
254  case "changed":
255  $translations = $this->object->getChangedValues(
256  $filter_modules,
257  $filter_pattern,
258  $filter_topics
259  );
260  break;
261 
262  case "added": //langmode only
263  $translations = $this->object->getAddedValues(
264  $filter_modules,
265  $filter_pattern,
266  $filter_topics
267  );
268  break;
269 
270  case "unchanged":
271  $translations = $this->object->getUnchangedValues(
272  $filter_modules,
273  $filter_pattern,
274  $filter_topics
275  );
276  break;
277 
278  case "commented":
279  $translations = $this->object->getCommentedValues(
280  $filter_modules,
281  $filter_pattern,
282  $filter_topics
283  );
284  break;
285 
286  case "dbremarks":
287  $translations = $this->object->getAllValues(
288  $filter_modules,
289  $filter_pattern,
290  $filter_topics
291  );
292 
293  $translations = array_intersect_key($translations, $comments);
294  break;
295 
296  case "equal":
297  $translations = $this->object->getAllValues(
298  $filter_modules,
299  $filter_pattern,
300  $filter_topics
301  );
302 
303  $translations = array_intersect_assoc($translations, $compare_content);
304  break;
305 
306  case "different":
307  $translations = $this->object->getAllValues(
308  $filter_modules,
309  $filter_pattern,
310  $filter_topics
311  );
312 
313  $translations = array_diff_assoc($translations, $compare_content);
314  break;
315 
316  case "conflicts":
317  $former_file = $this->object->getDataPath() . "/ilias_" . $this->object->key . ".lang";
318  if (!is_readable($former_file)) {
319  $this->tpl->setOnScreenMessage('failure', sprintf($this->lng->txt("language_former_file_missing"), $former_file)
320  . '<br />' . $this->lng->txt("language_former_file_description"), false);
321  $translations = array();
322  break;
323  }
324  $global_file_obj = $this->object->getGlobalLanguageFile();
325  $former_file_obj = new ilLanguageFile($former_file);
326  $former_file_obj->read();
327  $global_changes = array_diff_assoc(
328  $global_file_obj->getAllValues(),
329  $former_file_obj->getAllValues()
330  );
331  if (!count($global_changes)) {
332  $this->tpl->setOnScreenMessage('info', sprintf($this->lng->txt("language_former_file_equal"), $former_file)
333  . '<br />' . $this->lng->txt("language_former_file_description"), false);
334  $translations = array();
335  break;
336  }
337  $translations = $this->object->getChangedValues(
338  $filter_modules,
339  $filter_pattern,
340  $filter_topics
341  );
342 
343  $translations = array_intersect_key($translations, $global_changes);
344  break;
345 
346  case "all":
347  default:
348  $translations = $this->object->getAllValues(
349  $filter_modules,
350  $filter_pattern,
351  $filter_topics
352  );
353  }
354  }
355 
356  // prepare the the data for the table
357  $data = array();
358  foreach ($translations as $name => $translation) {
359  $keys = explode($this->lng->separator, $name);
360  $row = array();
361 
362  $row["module"] = $keys[0];
363  $row["topic"] = $keys[1];
364  $row["name"] = $name;
365  $row["translation"] = $translation;
366  $row["comment"] = $comments[$name] ?? "";
367  $row["default"] = $compare_content[$name] ?? "";
368  $row["default_comment"] = $compare_comments[$name] ?? "";
369 
370  $data[] = $row;
371  }
372 
373  if ($changesSuccessBool) {
374  $tpl->setVariable("MESSAGE", $this->getSuccessMessage());
375  }
376 
377  // render and show the table
378  $table_gui->setData($data);
379  $tpl->setContent($table_gui->getHTML() . $this->buildMissingEntries($missing_entries));
380  }
381 
385  public function applyFilterObject(): void
386  {
387  $table_gui = $this->getViewTable();
388  $table_gui->writeFilterToSession(); // writes filter to session
389  $table_gui->resetOffset(); // sets record offest to 0 (first page)
390  $this->viewObject();
391  }
392 
396  public function resetFilterObject(): void
397  {
398  $table_gui = $this->getViewTable();
399  $table_gui->resetOffset(); // sets record offest to 0 (first page)
400  $table_gui->resetFilter(); // clears filter
401  $this->viewObject();
402  }
403 
407  public function saveObject(): void
408  {
409  // no changes have been made yet
410  $changesSuccessBool = 0;
411  // prepare the values to be saved
412  $save_array = array();
413  $remarks_array = array();
414  $post = (array) ($this->http->request()->getParsedBody() ?? []);
415  foreach ($post as $key => $value) {
416  $orginal_key = $key;
417  // mantis #25237
418  // @see https://php.net/manual/en/language.variables.external.php
419  $key = str_replace(["_POSTDOT_", "_POSTSPACE_"], [".", " "], $key);
420 
421  // example key of variable: 'common#:#access'
422  // example key of comment: 'common#:#access#:#comment'
423  $keys = explode($this->lng->separator, ilUtil::stripSlashes($key));
424 
425  if (count($keys) === 2) {
426  // avoid line breaks
427  $value = preg_replace("/(\015\012)|(\015)|(\012)/", "<br />", $value);
428  $value = str_replace("<<", "«", $value);
429  $value = ilUtil::stripSlashes($value, true, "<strong><em><u><strike><ol><li><ul><p><div><i><b><code><sup><pre><gap><a><img><bdo><br><span>");
430  $save_array[$key] = $value;
431 
432  // the comment has the key of the language with the suffix
433  $remarks_array[$key] = $post[$orginal_key . $this->lng->separator . "comment"];
434  }
435  }
436 
437  // save the translations
438  ilObjLanguageExt::_saveValues($this->object->key, $save_array, $remarks_array);
439 
440  // set successful changes bool to true;
441  $changesSuccessBool = 1;
442 
443  // view the list
444  $this->viewObject($changesSuccessBool);
445  }
446 
450  public function importObject(): void
451  {
452  $form = $this->initNewImportForm();
453  $this->tpl->setContent($form->getHTML());
454  }
455 
456  protected function initNewImportForm(): ilPropertyFormGUI
457  {
458  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
459  $form = new ilPropertyFormGUI();
460  $form->setFormAction($this->ctrl->getFormAction($this));
461  $form->setTitle($this->lng->txt("language_import_file"));
462  $form->addCommandButton("upload", $this->lng->txt("upload"));
463 
464  $fu = new ilFileInputGUI($this->lng->txt("file"), "userfile");
465  $fu->setRequired(true);
466  $form->addItem($fu);
467 
468  $rg = new ilRadioGroupInputGUI($this->lng->txt("language_mode_existing"), "mode_existing");
469  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_keepall"), "keepall");
470  $ro->setInfo($this->lng->txt("language_mode_existing_keepall_info"));
471  $rg->addOption($ro);
472  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_keepnew"), "keepnew");
473  $ro->setInfo($this->lng->txt("language_mode_existing_keepnew_info"));
474  $rg->addOption($ro);
475  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_replace"), "replace");
476  $ro->setInfo($this->lng->txt("language_mode_existing_replace_info"));
477  $rg->addOption($ro);
478  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_delete"), "delete");
479  $ro->setInfo($this->lng->txt("language_mode_existing_delete_info"));
480  $rg->addOption($ro);
481  $rg->setValue($this->getSession()["import"]["mode_existing"] ?? "keepall");
482  $form->addItem($rg);
483 
484  return $form;
485  }
486 
490  public function uploadObject(): void
491  {
492  global $DIC;
493 
494  $form = $this->initNewImportForm();
495  if ($form->checkInput()) {
496  $post_mode_existing = $this->http->request()->getParsedBody()['mode_existing'] ?? "";
497  // save form inputs for next display
498  $tmp["import"]["mode_existing"] = ilUtil::stripSlashes($post_mode_existing);
499  ilSession::set("lang_ext_maintenance", $tmp);
500  try {
501  $upload = $DIC->upload();
502  //mantis #41617
503  if (!$upload->hasBeenProcessed()) {
504  $upload->process();
505  }
506 
507 
508  if (!$upload->hasUploads()) {
509  throw new ilException($DIC->language()->txt("upload_error_file_not_found"));
510  }
511  $UploadResult = $upload->getResults()[$_FILES["userfile"]["tmp_name"]];
512 
513  $ProcessingStatus = $UploadResult->getStatus();
514  if ($ProcessingStatus->getCode() === ProcessingStatus::REJECTED) {
515  throw new ilException($ProcessingStatus->getMessage());
516  }
517 
518  // todo: refactor when importLanguageFile() is able to work with the new Filesystem service
519  $tempfile = ilFileUtils::ilTempnam() . ".sec";
520  $upload->moveOneFileTo($UploadResult, '', Location::TEMPORARY, basename($tempfile), true);
521  $this->object->importLanguageFile($tempfile, $post_mode_existing);
522 
523  $tempfs = $DIC->filesystem()->temp();
524  $tempfs->delete(basename($tempfile));
525  } catch (Exception $e) {
526  $this->tpl->setOnScreenMessage('failure', $e->getMessage(), true);
527  $this->ctrl->redirect($this, 'import');
528  }
529 
530  $this->tpl->setOnScreenMessage(
531  'success',
532  sprintf($this->lng->txt("language_file_imported"), $_FILES["userfile"]["name"]),
533  true
534  );
535  $this->ctrl->redirect($this, "import");
536  }
537 
538  $form->setValuesByPost();
539  $this->tpl->setContent($form->getHTML());
540  }
541 
545  public function exportObject(): void
546  {
547  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
548  $form = new ilPropertyFormGUI();
549  $form->setFormAction($this->ctrl->getFormAction($this));
550  $form->setTitle($this->lng->txt("language_export_file"));
551  $form->setPreventDoubleSubmission(false);
552  $form->addCommandButton("download", $this->lng->txt("download"));
553 
554  $rg = new ilRadioGroupInputGUI($this->lng->txt("language_file_scope"), "scope");
555  $ro = new ilRadioOption($this->lng->txt("language_scope_global"), "global");
556  $ro->setInfo($this->lng->txt("language_scope_global_info"));
557  $rg->addOption($ro);
558  $ro = new ilRadioOption($this->lng->txt("language_scope_local"), "local");
559  $ro->setInfo($this->lng->txt("language_scope_local_info"));
560  $rg->addOption($ro);
561  if ($this->langmode) {
562  $ro = new ilRadioOption($this->lng->txt("language_scope_added"), "added");
563  $ro->setInfo($this->lng->txt("language_scope_added_info"));
564  $rg->addOption($ro);
565  }
566  $ro = new ilRadioOption($this->lng->txt("language_scope_unchanged"), "unchanged");
567  $ro->setInfo($this->lng->txt("language_scope_unchanged_info"));
568  $rg->addOption($ro);
569  if ($this->langmode) {
570  $ro = new ilRadioOption($this->lng->txt("language_scope_merged"), "merged");
571  $ro->setInfo($this->lng->txt("language_scope_merged_info"));
572  $rg->addOption($ro);
573  }
574 
575  $rg->setValue($this->getSession()["export"]["scope"] ?? "global");
576  $form->addItem($rg);
577 
578  $this->tpl->setContent($form->getHTML());
579  }
580 
584  public function downloadObject(): void
585  {
586  $post_scope = $this->http->request()->getParsedBody()['scope'] ?? "";
587  // save the selected scope
588  $tmp["export"]["scope"] = ilUtil::stripSlashes($post_scope);
589  ilSession::set("lang_ext_maintenance", $tmp);
590 
591  $filename = "ilias_" . $this->object->key . '_'
592  . str_replace(".", "_", substr(ILIAS_VERSION, 0, strpos(ILIAS_VERSION, " ")))
593  . "-" . date("Y-m-d")
594  . ".lang." . $this->getSession()["export"]["scope"];
595 
596  $global_file_obj = $this->object->getGlobalLanguageFile();
597  $local_file_obj = new ilLanguageFile($filename, $this->object->key, $post_scope);
598 
599  if ($post_scope === "global") {
600  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
601  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
602  $local_file_obj->setAllValues($this->object->getAllValues());
603  if ($this->langmode) {
604  $local_file_obj->setAllComments($this->object->getAllRemarks());
605  }
606  } elseif ($post_scope === "local") {
607  $local_file_obj->setParam("based_on", $global_file_obj->getParam("version"));
608  $local_file_obj->setAllValues($this->object->getChangedValues());
609  if ($this->langmode) {
610  $local_file_obj->setAllComments($this->object->getAllRemarks());
611  }
612  } elseif ($post_scope === "added") { // langmode only
613  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
614  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
615  $local_file_obj->setAllValues($this->object->getAddedValues());
616  $local_file_obj->setAllComments($this->object->getAllRemarks());
617  } elseif ($post_scope === "unchanged") {
618  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
619  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
620  $local_file_obj->setAllValues($this->object->getUnchangedValues());
621  if ($this->langmode) {
622  $local_file_obj->setAllComments($this->object->getAllRemarks());
623  }
624  } elseif ($post_scope === "merged") { // langmode only
625  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
626  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
627  $local_file_obj->setAllValues($this->object->getMergedValues());
628  $local_file_obj->setAllComments($this->object->getMergedRemarks());
629  }
630 
631  ilUtil::deliverData($local_file_obj->build(), $filename);
632  }
633 
637  public function maintainObject(): void
638  {
639  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
640  $form = new ilPropertyFormGUI();
641  $form->setFormAction($this->ctrl->getFormAction($this));
642  $form->setTitle($this->lng->txt("language_maintenance"));
643  $form->setPreventDoubleSubmission(false);
644  $form->addCommandButton("maintainExecute", $this->lng->txt("language_process_maintenance"));
645 
646  $rg = new ilRadioGroupInputGUI($this->lng->txt("language_maintain_local_changes"), "maintain");
647  $ro = new ilRadioOption($this->lng->txt("language_load_local_changes"), "load");
648  $ro->setInfo(sprintf($this->lng->txt("language_load_local_changes_info"), $this->object->key));
649  $rg->addOption($ro);
650  $ro = new ilRadioOption($this->lng->txt("language_clear_local_changes"), "clear");
651  $ro->setInfo(sprintf($this->lng->txt("language_clear_local_changes_info"), $this->object->key));
652  $rg->addOption($ro);
653  if ($this->langmode) {
654  $ro = new ilRadioOption($this->lng->txt("language_delete_local_additions"), "delete_added");
655  $ro->setInfo(sprintf($this->lng->txt("language_delete_local_additions_info"), $this->object->key));
656  $rg->addOption($ro);
657  $ro = new ilRadioOption($this->lng->txt("language_remove_local_file"), "remove_local_file");
658  $ro->setInfo(sprintf($this->lng->txt("language_remove_local_file_info"), $this->object->key));
659  $rg->addOption($ro);
660  $ro = new ilRadioOption($this->lng->txt("language_merge_local_changes"), "merge");
661  $ro->setInfo(sprintf($this->lng->txt("language_merge_local_changes_info"), $this->object->key));
662  $rg->addOption($ro);
663  }
664  $ro = new ilRadioOption($this->lng->txt("language_save_dist"), "save_dist");
665  $ro->setInfo(sprintf($this->lng->txt("language_save_dist_info"), $this->object->key));
666  $rg->addOption($ro);
667  $rg->setValue($this->getSession()["maintain"] ?? "load");
668  $form->addItem($rg);
669 
670  $this->tpl->setContent($form->getHTML());
671  }
672 
673  public function maintainExecuteObject(): void
674  {
675  $post_maintain = $this->http->request()->getParsedBody()['maintain'] ?? "";
676  if (isset($post_maintain)) {
677  $tmp["maintain"] = ilUtil::stripSlashes($post_maintain);
678  ilSession::set("lang_ext_maintenance", $tmp);
679  }
680 
681  switch ($post_maintain) {
682  // save the global language file for merge after
683  case "save_dist":
684  // save a copy of the distributed language file
685  $orig_file = $this->object->getLangPath() . "/ilias_" . $this->object->key . ".lang";
686  $copy_file = $this->object->getDataPath() . "/ilias_" . $this->object->key . ".lang";
687  if (@copy($orig_file, $copy_file)) {
688  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_saved_dist"), true);
689  } else {
690  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_save_dist_failed"), true);
691  }
692  break;
693 
694  // load the content of the local language file
695  case "load":
696  $lang_file = $this->object->getCustLangPath() . "/ilias_" . $this->object->key . ".lang.local";
697  if (is_file($lang_file) and is_readable($lang_file)) {
698  $this->object->importLanguageFile($lang_file, "replace");
699  $this->object->setLocal(true);
700  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_loaded_local"), true);
701  } else {
702  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_read_local"), true);
703  }
704  break;
705 
706  // revert the database to the default language file
707  case "clear":
708  $lang_file = $this->object->getLangPath() . "/ilias_" . $this->object->key . ".lang";
709  if (is_file($lang_file) and is_readable($lang_file)) {
710  $this->object->importLanguageFile($lang_file, "replace");
711  $this->object->setLocal(false);
712  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_cleared_local"), true);
713  } else {
714  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_clear_local"), true);
715  }
716  break;
717 
718  // delete local additions in the datavase (langmode only)
719  case "delete_added":
720  ilObjLanguageExt::_deleteValues($this->object->key, $this->object->getAddedValues());
721  break;
722 
723  // merge local changes back to the global language file (langmode only)
724  case "merge":
725  $orig_file = $this->object->getLangPath() . "/ilias_" . $this->object->key . ".lang";
726  $copy_file = $this->object->getCustLangPath() . "/ilias_" . $this->object->key . ".lang";
727 
728  if (is_file($orig_file) and is_writable($orig_file)) {
729  // save a copy of the global language file
730  @copy($orig_file, $copy_file);
731 
732  // modify and write the new global file
733  $global_file_obj = $this->object->getGlobalLanguageFile();
734  $global_file_obj->setAllValues($this->object->getMergedValues());
735  $global_file_obj->setAllComments($this->object->getMergedRemarks());
736  $global_file_obj->write();
737  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_merged_global"), true);
738  } else {
739  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_write_global"), true);
740  }
741  break;
742 
743  // remove the local language file (langmode only)
744  case "remove_local_file":
745  $lang_file = $this->object->getCustLangPath() . "/ilias_" . $this->object->key . ".lang.local";
746 
747  if (!is_file($lang_file)) {
748  $this->object->setLocal(false);
749  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_local_missed"), true);
750  } elseif (@unlink($lang_file)) {
751  $this->object->setLocal(false);
752  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_local_file_deleted"), true);
753  } else {
754  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_delete_local"), true);
755  }
756  break;
757  }
758 
759  $this->ctrl->redirect($this, "maintain");
760  }
761 
765  public function settingsObject(): void
766  {
767  $form = $this->initNewSettingsForm();
768  $this->tpl->setContent($form->getHTML());
769  }
770 
774  public function saveSettingsObject(): void
775  {
776  global $DIC;
777  $ilSetting = $DIC->settings();
778 
779  $translate_key = "lang_translate_" . $this->object->key;
780 
781  $post_translation = $this->http->request()->getParsedBody()['translation'] ?? "";
782  // save and get the page translation setting
783  $translate = $ilSetting->get($translate_key, '0');
784  if (!is_null($post_translation) && $post_translation != $translate) {
785  $ilSetting->set($translate_key, $post_translation);
786  $this->tpl->setOnScreenMessage('success', $this->lng->txt("settings_saved"));
787  }
788  $form = $this->initNewSettingsForm();
789 
790  $this->tpl->setContent($form->getHTML());
791  }
792 
794  {
795  global $DIC;
796  $ilSetting = $DIC->settings();
797  $translate_key = "lang_translate_" . $this->object->key;
798  $translate = (bool) $ilSetting->get($translate_key, '0');
799 
800  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
801  $form = new ilPropertyFormGUI();
802  $form->setFormAction($this->ctrl->getFormAction($this));
803  $form->setTitle($this->lng->txt("language_settings"));
804  $form->setPreventDoubleSubmission(false);
805  $form->addCommandButton('saveSettings', $this->lng->txt("language_change_settings"));
806 
807  $ci = new ilCheckboxInputGUI($this->lng->txt("language_translation_enabled"), "translation");
808  $ci->setChecked($translate);
809  $ci->setInfo($this->lng->txt("language_note_translation"));
810  $form->addItem($ci);
811 
812  return $form;
813  }
814 
818  public function statisticsObject(): void
819  {
820  $modules = ilObjLanguageExt::_getModules($this->object->key);
821 
822  $data = [];
823  $total = [];
824  foreach ($modules as $module) {
825  $row = [];
826  $row["module"] = $module;
827  $row["all"] = count($this->object->getAllValues(array($module)));
828  $row["changed"] = count($this->object->getChangedValues(array($module)));
829  $row["unchanged"] = $row["all"] - $row["changed"];
830  isset($total["all"]) ? $total["all"] += $row["all"] : $total["all"] = $row["all"];
831  isset($total["changed"]) ? $total["changed"] += $row["changed"] : $total["changed"] = $row["changed"];
832  isset($total["unchanged"]) ? $total["unchanged"] += $row["unchanged"] : $total["unchanged"] = $row["unchanged"];
833  $data[] = $row;
834  }
835  $total["module"] = "<b>" . $this->lng->txt("language_all_modules") . "</b>";
836  $total["all"] = "<b>" . $total["all"] . "</b>";
837  $total["changed"] = "<b>" . $total["changed"] . "</b>";
838  $total["unchanged"] = "<b>" . $total["unchanged"] . "</b>";
839  $data[] = $total;
840 
841  // create and configure the table object
842  include_once "Services/Table/classes/class.ilTable2GUI.php";
843  $table_gui = new ilTable2GUI($this, "statistics");
844  $table_gui->setRowTemplate("tpl.lang_statistics_row.html", "Services/Language");
845  $table_gui->setEnableTitle(false);
846  $table_gui->setEnableNumInfo(false);
847  $table_gui->setLimit(count($data));
848  $table_gui->setExportFormats(array(ilTable2GUI::EXPORT_EXCEL));
849 
850  $table_gui->addColumn(ucfirst($this->lng->txt("module")), "", "25%");
851  $table_gui->addColumn($this->lng->txt("language_scope_global"), "", "25%");
852  $table_gui->addColumn($this->lng->txt("language_scope_local"), "", "25%");
853  $table_gui->addColumn($this->lng->txt("language_scope_unchanged"), "", "25%");
854 
855  $table_gui->setData($data);
856 
857  $this->tpl->setContent($table_gui->getHTML());
858  }
859 
864  public function getAdminTabs(): void
865  {
866  global $DIC;
867  $ilCtrl = $DIC->ctrl();
868  $cmd = $ilCtrl->getCmd();
869 
871  $this->tabs_gui->setBackTarget(
872  $this->lng->txt("back"),
873  $this->ctrl->getLinkTargetByClass("ilObjLanguageFolderGUI")
874  );
875 
876  $this->tabs_gui->addTab(
877  "edit",
878  $this->lng->txt("edit"),
879  $this->ctrl->getLinkTarget($this, "view")
880  );
881 
882  $this->tabs_gui->addTab(
883  "export",
884  $this->lng->txt('export'),
885  $this->ctrl->getLinkTarget($this, "export")
886  );
887 
888  $this->tabs_gui->addTab(
889  "import",
890  $this->lng->txt("import"),
891  $this->ctrl->getLinkTarget($this, "import")
892  );
893 
894  $this->tabs_gui->addTab(
895  "maintain",
896  $this->lng->txt("language_maintain"),
897  $this->ctrl->getLinkTarget($this, "maintain")
898  );
899 
900  $this->tabs_gui->addTab(
901  "settings",
902  $this->lng->txt("settings"),
903  $this->ctrl->getLinkTarget($this, "settings")
904  );
905 
906  $this->tabs_gui->addTab(
907  "statistics",
908  $this->lng->txt("language_statistics"),
909  $this->ctrl->getLinkTarget($this, "statistics")
910  );
911 
912  switch ($cmd) {
913  case "":
914  case "view":
915  case "applyFilter":
916  case "resetFilter":
917  case "save":
918  $this->tabs_gui->activateTab("edit");
919  break;
920  default:
921  $this->tabs_gui->activateTab($cmd);
922  }
923  }
924  }
925 
930  protected function addAdminLocatorItems(bool $do_not_add_object = false): void
931  {
932  global $DIC;
933  $ilLocator = $DIC["ilLocator"];
934 
936  parent::addAdminLocatorItems(true); // #13881
937 
938  $ilLocator->addItem(
939  $this->lng->txt("languages"),
940  $this->ctrl->getLinkTargetByClass("ilobjlanguagefoldergui", "")
941  );
942 
943  $ilLocator->addItem(
944  $this->lng->txt("meta_l_" . $this->object->getTitle()),
945  $this->ctrl->getLinkTarget($this, "view")
946  );
947  }
948  }
949 
954  protected function setTitleAndDescription(): void
955  {
957  $this->tpl->setHeaderPageTitle($this->lng->txt("translation"));
958  $this->tpl->setTitle($this->lng->txt("translation") . " " . $this->lng->txt("meta_l_" . $this->object->key));
959  } else {
960  $this->tpl->setTitle($this->lng->txt("meta_l_" . $this->object->key));
961  }
962  $this->tpl->setTitleIcon(ilUtil::getImagePath("standard/icon_lngf.svg"), $this->lng->txt("obj_" . $this->object->getType()));
963  }
964 
965 
966  //
967  // new entries
968  //
969 
970  protected function buildMissingEntries(array $a_missing = null): string
971  {
972  global $DIC;
973  $ilCtrl = $DIC->ctrl();
974 
975  if (!count($a_missing)) {
976  return '';
977  }
978 
979  $res = array("<h3>" . $this->lng->txt("adm_missing_entries") . "</h3>", "<ul>");
980 
981  foreach ($a_missing as $entry) {
982  $ilCtrl->setParameter($this, "eid", $entry);
983  $res[] = '<li>' . $entry .
984  ' <a href="' . $ilCtrl->getLinkTarget($this, "addNewEntry") .
985  '">' . $this->lng->txt("adm_missing_entry_add_action") . '</a></li>';
986  $ilCtrl->setParameter($this, "eid", "");
987  }
988 
989  $res[] = "</ul>";
990 
991  return implode("\n", $res);
992  }
993 
994  public function addNewEntryObject(ilPropertyFormGUI $a_form = null): void
995  {
996  global $DIC;
997  $tpl = $DIC["tpl"];
998 
999  $id = "";
1000  if ($this->http->wrapper()->query()->has("eid")) {
1001  $id = trim($this->http->wrapper()->query()->retrieve("eid", $this->refinery->kindlyTo()->string()));
1002  }
1003  if (!$a_form) {
1004  $a_form = $this->initAddNewEntryForm($id);
1005  }
1006 
1007  $tpl->setContent($a_form->getHTML());
1008  }
1009 
1010  protected function initAddNewEntryForm(string $a_id = null): ilPropertyFormGUI
1011  {
1012  global $DIC;
1013  $ilCtrl = $DIC->ctrl();
1014 
1015  if (!$a_id) {
1016  $a_id = $this->http->request()->getParsedBody()['id'] ?? "";
1017  }
1018 
1019  if (!$a_id ||
1020  !in_array($a_id, ilObjLanguageAccess::_getSavedTopics())) {
1021  $ilCtrl->redirect($this, "view");
1022  }
1023 
1024  include_once "Services/Form/classes/class.ilPropertyFormGUI.php";
1025  $form = new ilPropertyFormGUI();
1026  $form->setFormAction($ilCtrl->getFormAction($this, "saveNewEntry"));
1027  $form->setTitle($this->lng->txt("adm_missing_entry_add"));
1028 
1030  $options = array_combine($mods, $mods);
1031 
1032  $mod = new ilSelectInputGUI(ucfirst($this->lng->txt("module")), "mod");
1033  $mod->setOptions(array("" => $this->lng->txt("please_select")) + $options);
1034  $mod->setRequired(true);
1035  $form->addItem($mod);
1036 
1037  $id = new ilTextInputGUI(ucfirst($this->lng->txt("identifier")), "id");
1038  $id->setValue($a_id);
1039  $id->setDisabled(true);
1040  $form->addItem($id);
1041 
1042  foreach ($this->lng->getInstalledLanguages() as $lang_key) {
1043  $trans = new ilTextInputGUI($this->lng->txt("meta_l_" . $lang_key), "trans_" . $lang_key);
1044  if (in_array($lang_key, array("de", "en"))) {
1045  $trans->setRequired(true);
1046  }
1047  $form->addItem($trans);
1048  }
1049 
1050  $form->addCommandButton("saveNewEntry", $this->lng->txt("save"));
1051  $form->addCommandButton("view", $this->lng->txt("cancel"));
1052 
1053  return $form;
1054  }
1055 
1056  public function saveNewEntryObject(): void
1057  {
1058  global $DIC;
1059  $ilDB = $DIC->database();
1060  $ilCtrl = $DIC->ctrl();
1061  $ilUser = $DIC->user();
1062 
1063  $form = $this->initAddNewEntryForm();
1064  if ($form->checkInput()) {
1065  $mod = $form->getInput("mod");
1066  $id = $form->getInput("id");
1067 
1068  $lang = array();
1069  foreach ($this->lng->getInstalledLanguages() as $lang_key) {
1070  $trans = trim($form->getInput("trans_" . $lang_key));
1071  if ($trans) {
1072  // add single entry
1074  $mod,
1075  $id,
1076  $lang_key,
1077  $trans,
1078  date("Y-m-d H:i:s"),
1079  $ilUser->getLogin()
1080  );
1081 
1082  // add to serialized module
1083  $set = $ilDB->query("SELECT lang_array FROM lng_modules" .
1084  " WHERE lang_key = " . $ilDB->quote($lang_key, "text") .
1085  " AND module = " . $ilDB->quote($mod, "text"));
1086  $row = $ilDB->fetchAssoc($set);
1087  $entries = unserialize($row["lang_array"], ["allowed_classes" => false]);
1088  if (is_array($entries)) {
1089  $entries[$id] = $trans;
1090  ilObjLanguage::replaceLangModule($lang_key, $mod, $entries);
1091  }
1092  }
1093  }
1094 
1095  $this->tpl->setOnScreenMessage('success', $this->lng->txt("settings_saved"), true);
1096  $ilCtrl->redirect($this, "view");
1097  }
1098 
1099  $form->setValuesByPost();
1100  $this->addNewEntryObject($form);
1101  }
1102 
1106  protected function getSuccessMessage(): string
1107  {
1108  global $DIC;
1109  $f = $DIC->ui()->factory();
1110  $renderer = $DIC->ui()->renderer();
1111 
1112  return $renderer->render($f->messageBox()->success($this->lng->txt("language_variables_saved")));
1113  }
1114 
1115  private function getSession(): array
1116  {
1117  return ilSession::get("lang_ext_maintenance") ?? [];
1118  }
1119 } // END class.ilObjLanguageExtGUI
downloadObject()
Download a language file.
static get(string $a_var)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$res
Definition: ltiservices.php:69
exit
Definition: login.php:29
assignObject()
Assign the extended language object.
const ILIAS_VERSION
getSuccessMessage()
Get success message after variables were saved.
This class represents a selection list property in a property form.
uploadObject()
Process an uploaded language file.
getUserLanguage()
Return language of user.
static _isPageTranslation()
Check if the current request is a page translation.
static _getSavedModules()
Get the stored modules from the user session.
This class represents a file property in a property form.
initAddNewEntryForm(string $a_id=null)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
getViewTable()
Get the table to view language entries.
static _lookupId(string $a_key)
Lookup the object ID for a language key.
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
cancelObject()
Cancel the current action.
loadLanguageModule(string $a_module)
Load language module.
viewObject()
viewObject container presentation for "administration -> repository, trash, permissions" ...
setVariable(string $variable, $value='')
Sets the given variable to the given value.
Class ilObjLanguageExtGUI.
static deliverData(string $a_data, string $a_filename, string $mime="application/octet-stream")
exportObject()
Show the screen to export a language file.
static _checkMaintenance()
Permission check for language maintenance (import/export)
saveSettingsObject()
Set the language settings.
global $DIC
Definition: feed.php:28
addAdminLocatorItems(bool $do_not_add_object=false)
Set the locator for admin mode (Overwritten from ilObjectGUI, called by prepareOutput) ...
ilLanguage $lng
importObject()
Show the screen to import a language file.
static _getValues(string $a_lang_key, array $a_modules=array(), array $a_topics=array(), string $a_pattern='', string $a_state='')
Get the translations of specified topics.
static http()
Fetches the global http state from ILIAS.
This class represents a property in a property form.
__construct(VocabulariesInterface $vocabularies)
ilGlobalTemplateInterface $tpl
__construct($a_data, int $a_id=0, bool $a_call_by_reference=false)
Constructor.
setContent(string $a_html)
Sets content for standard template.
Class ilObjLanguageExt.
Class ilObjectGUI Basic methods of all Output classes.
getAdminTabs()
Get tabs for admin mode (Overwritten from ilObjectGUI, called by prepareOutput)
static _getModules(string $a_lang_key)
Get all modules of a language.
string $key
Consumer key/client ID value.
Definition: System.php:193
static _deleteValues(string $a_lang_key, array $a_values=array())
Delete a set of translation in the database.
$comments
buildMissingEntries(array $a_missing=null)
statisticsObject()
Print out statistics about the language.
settingsObject()
View the language settings.
setTitleAndDescription()
Set the Title and the description (Overwritten from ilObjectGUI, called by prepareOutput) ...
static _getSavedTopics()
Get the stored topics from the user session.
setRequired(bool $a_required)
$filename
Definition: buildRTE.php:78
saveObject()
Save the changed translations.
static replaceLangEntry(string $a_module, string $a_identifier, string $a_lang_key, string $a_value, string $a_local_change=null, string $a_remarks=null)
Replace lang entry.
$lang
Definition: xapiexit.php:26
static ilTempnam(?string $a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
Class ilLanguageFile.
global $ilSetting
Definition: privfeed.php:18
static _getRemarks(string $a_lang_key, bool $a_all_changed=false)
Get all remarks of a language.
addNewEntryObject(ilPropertyFormGUI $a_form=null)
viewObject(int $changesSuccessBool=0)
Show the edit screen.
maintainObject()
Process the language maintenance.
$post
Definition: ltitoken.php:49
getId()
get the language object id (needed for filter serialization) Return language object id ...
static set(string $a_var, $a_val)
Set a value.
static _saveValues(string $a_lang_key, array $a_values=array(), array $a_remarks=array())
Save a set of translation in the database.