ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjLanguageExtGUI.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
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  // mantis #25237
417  // @see https://php.net/manual/en/language.variables.external.php
418  $key = str_replace(["_POSTDOT_", "_POSTSPACE_"], [".", " "], $key);
419 
420  // example key of variable: 'common#:#access'
421  // example key of comment: 'common#:#access#:#comment'
422  $keys = explode($this->lng->separator, ilUtil::stripSlashes($key));
423 
424  if (count($keys) === 2) {
425  // avoid line breaks
426  $value = preg_replace("/(\015\012)|(\015)|(\012)/", "<br />", $value);
427  $value = str_replace("<<", "«", $value);
428  $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>");
429  $save_array[$key] = $value;
430 
431  // the comment has the key of the language with the suffix
432  $remarks_array[$key] = $post[$key . $this->lng->separator . "comment"];
433  }
434  }
435 
436  // save the translations
437  ilObjLanguageExt::_saveValues($this->object->key, $save_array, $remarks_array);
438 
439  // set successful changes bool to true;
440  $changesSuccessBool = 1;
441 
442  // view the list
443  $this->viewObject($changesSuccessBool);
444  }
445 
449  public function importObject(): void
450  {
451  $form = $this->initNewImportForm();
452  $this->tpl->setContent($form->getHTML());
453  }
454 
455  protected function initNewImportForm(): ilPropertyFormGUI
456  {
457  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
458  $form = new ilPropertyFormGUI();
459  $form->setFormAction($this->ctrl->getFormAction($this));
460  $form->setTitle($this->lng->txt("language_import_file"));
461  $form->addCommandButton("upload", $this->lng->txt("upload"));
462 
463  $fu = new ilFileInputGUI($this->lng->txt("file"), "userfile");
464  $fu->setRequired(true);
465  $form->addItem($fu);
466 
467  $rg = new ilRadioGroupInputGUI($this->lng->txt("language_mode_existing"), "mode_existing");
468  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_keepall"), "keepall");
469  $ro->setInfo($this->lng->txt("language_mode_existing_keepall_info"));
470  $rg->addOption($ro);
471  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_keepnew"), "keepnew");
472  $ro->setInfo($this->lng->txt("language_mode_existing_keepnew_info"));
473  $rg->addOption($ro);
474  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_replace"), "replace");
475  $ro->setInfo($this->lng->txt("language_mode_existing_replace_info"));
476  $rg->addOption($ro);
477  $ro = new ilRadioOption($this->lng->txt("language_mode_existing_delete"), "delete");
478  $ro->setInfo($this->lng->txt("language_mode_existing_delete_info"));
479  $rg->addOption($ro);
480  $rg->setValue($this->getSession()["import"]["mode_existing"] ?? "keepall");
481  $form->addItem($rg);
482 
483  return $form;
484  }
485 
489  public function uploadObject(): void
490  {
491  global $DIC;
492 
493  $form = $this->initNewImportForm();
494  if ($form->checkInput()) {
495  $post_mode_existing = $this->http->request()->getParsedBody()['mode_existing'] ?? "";
496  // save form inputs for next display
497  $tmp["import"]["mode_existing"] = ilUtil::stripSlashes($post_mode_existing);
498  ilSession::set("lang_ext_maintenance", $tmp);
499  try {
500  $upload = $DIC->upload();
501  //mantis #41617
502  if (!$upload->hasBeenProcessed()) {
503  $upload->process();
504  }
505 
506 
507  if (!$upload->hasUploads()) {
508  throw new ilException($DIC->language()->txt("upload_error_file_not_found"));
509  }
510  $UploadResult = $upload->getResults()[$_FILES["userfile"]["tmp_name"]];
511 
512  $ProcessingStatus = $UploadResult->getStatus();
513  if ($ProcessingStatus->getCode() === ProcessingStatus::REJECTED) {
514  throw new ilException($ProcessingStatus->getMessage());
515  }
516 
517  // todo: refactor when importLanguageFile() is able to work with the new Filesystem service
518  $tempfile = ilFileUtils::ilTempnam() . ".sec";
519  $upload->moveOneFileTo($UploadResult, '', Location::TEMPORARY, basename($tempfile), true);
520  $this->object->importLanguageFile($tempfile, $post_mode_existing);
521 
522  $tempfs = $DIC->filesystem()->temp();
523  $tempfs->delete(basename($tempfile));
524  } catch (Exception $e) {
525  $this->tpl->setOnScreenMessage('failure', $e->getMessage(), true);
526  $this->ctrl->redirect($this, 'import');
527  }
528 
529  $this->tpl->setOnScreenMessage('success',
530  sprintf($this->lng->txt("language_file_imported"), $_FILES["userfile"]["name"]), true);
531  $this->ctrl->redirect($this, "import");
532  }
533 
534  $form->setValuesByPost();
535  $this->tpl->setContent($form->getHTML());
536  }
537 
541  public function exportObject(): void
542  {
543  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
544  $form = new ilPropertyFormGUI();
545  $form->setFormAction($this->ctrl->getFormAction($this));
546  $form->setTitle($this->lng->txt("language_export_file"));
547  $form->setPreventDoubleSubmission(false);
548  $form->addCommandButton("download", $this->lng->txt("download"));
549 
550  $rg = new ilRadioGroupInputGUI($this->lng->txt("language_file_scope"), "scope");
551  $ro = new ilRadioOption($this->lng->txt("language_scope_global"), "global");
552  $ro->setInfo($this->lng->txt("language_scope_global_info"));
553  $rg->addOption($ro);
554  $ro = new ilRadioOption($this->lng->txt("language_scope_local"), "local");
555  $ro->setInfo($this->lng->txt("language_scope_local_info"));
556  $rg->addOption($ro);
557  if ($this->langmode) {
558  $ro = new ilRadioOption($this->lng->txt("language_scope_added"), "added");
559  $ro->setInfo($this->lng->txt("language_scope_added_info"));
560  $rg->addOption($ro);
561  }
562  $ro = new ilRadioOption($this->lng->txt("language_scope_unchanged"), "unchanged");
563  $ro->setInfo($this->lng->txt("language_scope_unchanged_info"));
564  $rg->addOption($ro);
565  if ($this->langmode) {
566  $ro = new ilRadioOption($this->lng->txt("language_scope_merged"), "merged");
567  $ro->setInfo($this->lng->txt("language_scope_merged_info"));
568  $rg->addOption($ro);
569  }
570 
571  $rg->setValue($this->getSession()["export"]["scope"] ?? "global");
572  $form->addItem($rg);
573 
574  $this->tpl->setContent($form->getHTML());
575  }
576 
580  public function downloadObject(): void
581  {
582  $post_scope = $this->http->request()->getParsedBody()['scope'] ?? "";
583  // save the selected scope
584  $tmp["export"]["scope"] = ilUtil::stripSlashes($post_scope);
585  ilSession::set("lang_ext_maintenance", $tmp);
586 
587  $filename = "ilias_" . $this->object->key . '_'
588  . str_replace(".", "_", substr(ILIAS_VERSION, 0, strpos(ILIAS_VERSION, " ")))
589  . "-" . date("Y-m-d")
590  . ".lang." . $this->getSession()["export"]["scope"];
591 
592  $global_file_obj = $this->object->getGlobalLanguageFile();
593  $local_file_obj = new ilLanguageFile($filename, $this->object->key, $post_scope);
594 
595  if ($post_scope === "global") {
596  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
597  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
598  $local_file_obj->setAllValues($this->object->getAllValues());
599  if ($this->langmode) {
600  $local_file_obj->setAllComments($this->object->getAllRemarks());
601  }
602  } elseif ($post_scope === "local") {
603  $local_file_obj->setParam("based_on", $global_file_obj->getParam("version"));
604  $local_file_obj->setAllValues($this->object->getChangedValues());
605  if ($this->langmode) {
606  $local_file_obj->setAllComments($this->object->getAllRemarks());
607  }
608  } elseif ($post_scope === "added") { // langmode only
609  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
610  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
611  $local_file_obj->setAllValues($this->object->getAddedValues());
612  $local_file_obj->setAllComments($this->object->getAllRemarks());
613  } elseif ($post_scope === "unchanged") {
614  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
615  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
616  $local_file_obj->setAllValues($this->object->getUnchangedValues());
617  if ($this->langmode) {
618  $local_file_obj->setAllComments($this->object->getAllRemarks());
619  }
620  } elseif ($post_scope === "merged") { // langmode only
621  $local_file_obj->setParam("author", $global_file_obj->getParam("author"));
622  $local_file_obj->setParam("version", $global_file_obj->getParam("version"));
623  $local_file_obj->setAllValues($this->object->getMergedValues());
624  $local_file_obj->setAllComments($this->object->getMergedRemarks());
625  }
626 
627  ilUtil::deliverData($local_file_obj->build(), $filename);
628  }
629 
633  public function maintainObject(): void
634  {
635  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
636  $form = new ilPropertyFormGUI();
637  $form->setFormAction($this->ctrl->getFormAction($this));
638  $form->setTitle($this->lng->txt("language_maintenance"));
639  $form->setPreventDoubleSubmission(false);
640  $form->addCommandButton("maintainExecute", $this->lng->txt("language_process_maintenance"));
641 
642  $rg = new ilRadioGroupInputGUI($this->lng->txt("language_maintain_local_changes"), "maintain");
643  $ro = new ilRadioOption($this->lng->txt("language_load_local_changes"), "load");
644  $ro->setInfo(sprintf($this->lng->txt("language_load_local_changes_info"), $this->object->key));
645  $rg->addOption($ro);
646  $ro = new ilRadioOption($this->lng->txt("language_clear_local_changes"), "clear");
647  $ro->setInfo(sprintf($this->lng->txt("language_clear_local_changes_info"), $this->object->key));
648  $rg->addOption($ro);
649  if ($this->langmode) {
650  $ro = new ilRadioOption($this->lng->txt("language_delete_local_additions"), "delete_added");
651  $ro->setInfo(sprintf($this->lng->txt("language_delete_local_additions_info"), $this->object->key));
652  $rg->addOption($ro);
653  $ro = new ilRadioOption($this->lng->txt("language_remove_local_file"), "remove_local_file");
654  $ro->setInfo(sprintf($this->lng->txt("language_remove_local_file_info"), $this->object->key));
655  $rg->addOption($ro);
656  $ro = new ilRadioOption($this->lng->txt("language_merge_local_changes"), "merge");
657  $ro->setInfo(sprintf($this->lng->txt("language_merge_local_changes_info"), $this->object->key));
658  $rg->addOption($ro);
659  }
660  $ro = new ilRadioOption($this->lng->txt("language_save_dist"), "save_dist");
661  $ro->setInfo(sprintf($this->lng->txt("language_save_dist_info"), $this->object->key));
662  $rg->addOption($ro);
663  $rg->setValue($this->getSession()["maintain"] ?? "load");
664  $form->addItem($rg);
665 
666  $this->tpl->setContent($form->getHTML());
667  }
668 
669  public function maintainExecuteObject(): void
670  {
671  $post_maintain = $this->http->request()->getParsedBody()['maintain'] ?? "";
672  if (isset($post_maintain)) {
673  $tmp["maintain"] = ilUtil::stripSlashes($post_maintain);
674  ilSession::set("lang_ext_maintenance", $tmp);
675  }
676 
677  switch ($post_maintain) {
678  // save the global language file for merge after
679  case "save_dist":
680  // save a copy of the distributed language file
681  $orig_file = $this->object->getLangPath() . "/ilias_" . $this->object->key . ".lang";
682  $copy_file = $this->object->getDataPath() . "/ilias_" . $this->object->key . ".lang";
683  if (@copy($orig_file, $copy_file)) {
684  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_saved_dist"), true);
685  } else {
686  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_save_dist_failed"), true);
687  }
688  break;
689 
690  // load the content of the local language file
691  case "load":
692  $lang_file = $this->object->getCustLangPath() . "/ilias_" . $this->object->key . ".lang.local";
693  if (is_file($lang_file) and is_readable($lang_file)) {
694  $this->object->importLanguageFile($lang_file, "replace");
695  $this->object->setLocal(true);
696  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_loaded_local"), true);
697  } else {
698  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_read_local"), true);
699  }
700  break;
701 
702  // revert the database to the default language file
703  case "clear":
704  $lang_file = $this->object->getLangPath() . "/ilias_" . $this->object->key . ".lang";
705  if (is_file($lang_file) and is_readable($lang_file)) {
706  $this->object->importLanguageFile($lang_file, "replace");
707  $this->object->setLocal(false);
708  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_cleared_local"), true);
709  } else {
710  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_clear_local"), true);
711  }
712  break;
713 
714  // delete local additions in the datavase (langmode only)
715  case "delete_added":
716  ilObjLanguageExt::_deleteValues($this->object->key, $this->object->getAddedValues());
717  break;
718 
719  // merge local changes back to the global language file (langmode only)
720  case "merge":
721  $orig_file = $this->object->getLangPath() . "/ilias_" . $this->object->key . ".lang";
722  $copy_file = $this->object->getCustLangPath() . "/ilias_" . $this->object->key . ".lang";
723 
724  if (is_file($orig_file) and is_writable($orig_file)) {
725  // save a copy of the global language file
726  @copy($orig_file, $copy_file);
727 
728  // modify and write the new global file
729  $global_file_obj = $this->object->getGlobalLanguageFile();
730  $global_file_obj->setAllValues($this->object->getMergedValues());
731  $global_file_obj->setAllComments($this->object->getMergedRemarks());
732  $global_file_obj->write();
733  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_merged_global"), true);
734  } else {
735  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_write_global"), true);
736  }
737  break;
738 
739  // remove the local language file (langmode only)
740  case "remove_local_file":
741  $lang_file = $this->object->getCustLangPath() . "/ilias_" . $this->object->key . ".lang.local";
742 
743  if (!is_file($lang_file)) {
744  $this->object->setLocal(false);
745  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_local_missed"), true);
746  } elseif (@unlink($lang_file)) {
747  $this->object->setLocal(false);
748  $this->tpl->setOnScreenMessage('success', $this->lng->txt("language_local_file_deleted"), true);
749  } else {
750  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("language_error_delete_local"), true);
751  }
752  break;
753  }
754 
755  $this->ctrl->redirect($this, "maintain");
756  }
757 
761  public function settingsObject(): void
762  {
763  $form = $this->initNewSettingsForm();
764  $this->tpl->setContent($form->getHTML());
765  }
766 
770  public function saveSettingsObject(): void
771  {
772  global $DIC;
773  $ilSetting = $DIC->settings();
774 
775  $translate_key = "lang_translate_" . $this->object->key;
776 
777  $post_translation = $this->http->request()->getParsedBody()['translation'] ?? "";
778  // save and get the page translation setting
779  $translate = $ilSetting->get($translate_key, '0');
780  if (!is_null($post_translation) && $post_translation != $translate) {
781  $ilSetting->set($translate_key, $post_translation);
782  $this->tpl->setOnScreenMessage('success', $this->lng->txt("settings_saved"));
783  }
784  $form = $this->initNewSettingsForm();
785 
786  $this->tpl->setContent($form->getHTML());
787  }
788 
790  {
791  global $DIC;
792  $ilSetting = $DIC->settings();
793  $translate_key = "lang_translate_" . $this->object->key;
794  $translate = (bool) $ilSetting->get($translate_key, '0');
795 
796  require_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
797  $form = new ilPropertyFormGUI();
798  $form->setFormAction($this->ctrl->getFormAction($this));
799  $form->setTitle($this->lng->txt("language_settings"));
800  $form->setPreventDoubleSubmission(false);
801  $form->addCommandButton('saveSettings', $this->lng->txt("language_change_settings"));
802 
803  $ci = new ilCheckboxInputGUI($this->lng->txt("language_translation_enabled"), "translation");
804  $ci->setChecked($translate);
805  $ci->setInfo($this->lng->txt("language_note_translation"));
806  $form->addItem($ci);
807 
808  return $form;
809  }
810 
814  public function statisticsObject(): void
815  {
816  $modules = ilObjLanguageExt::_getModules($this->object->key);
817 
818  $data = [];
819  $total = [];
820  foreach ($modules as $module) {
821  $row = [];
822  $row["module"] = $module;
823  $row["all"] = count($this->object->getAllValues(array($module)));
824  $row["changed"] = count($this->object->getChangedValues(array($module)));
825  $row["unchanged"] = $row["all"] - $row["changed"];
826  isset($total["all"]) ? $total["all"] += $row["all"] : $total["all"] = $row["all"];
827  isset($total["changed"]) ? $total["changed"] += $row["changed"] : $total["changed"] = $row["changed"];
828  isset($total["unchanged"]) ? $total["unchanged"] += $row["unchanged"] : $total["unchanged"] = $row["unchanged"];
829  $data[] = $row;
830  }
831  $total["module"] = "<b>" . $this->lng->txt("language_all_modules") . "</b>";
832  $total["all"] = "<b>" . $total["all"] . "</b>";
833  $total["changed"] = "<b>" . $total["changed"] . "</b>";
834  $total["unchanged"] = "<b>" . $total["unchanged"] . "</b>";
835  $data[] = $total;
836 
837  // create and configure the table object
838  include_once "Services/Table/classes/class.ilTable2GUI.php";
839  $table_gui = new ilTable2GUI($this, "statistics");
840  $table_gui->setRowTemplate("tpl.lang_statistics_row.html", "Services/Language");
841  $table_gui->setEnableTitle(false);
842  $table_gui->setEnableNumInfo(false);
843  $table_gui->setLimit(count($data));
844  $table_gui->setExportFormats(array(ilTable2GUI::EXPORT_EXCEL));
845 
846  $table_gui->addColumn(ucfirst($this->lng->txt("module")), "", "25%");
847  $table_gui->addColumn($this->lng->txt("language_scope_global"), "", "25%");
848  $table_gui->addColumn($this->lng->txt("language_scope_local"), "", "25%");
849  $table_gui->addColumn($this->lng->txt("language_scope_unchanged"), "", "25%");
850 
851  $table_gui->setData($data);
852 
853  $this->tpl->setContent($table_gui->getHTML());
854  }
855 
860  public function getAdminTabs(): void
861  {
862  global $DIC;
863  $ilCtrl = $DIC->ctrl();
864  $cmd = $ilCtrl->getCmd();
865 
867  $this->tabs_gui->setBackTarget(
868  $this->lng->txt("back"),
869  $this->ctrl->getLinkTargetByClass("ilObjLanguageFolderGUI")
870  );
871 
872  $this->tabs_gui->addTab(
873  "edit",
874  $this->lng->txt("edit"),
875  $this->ctrl->getLinkTarget($this, "view")
876  );
877 
878  $this->tabs_gui->addTab(
879  "export",
880  $this->lng->txt('export'),
881  $this->ctrl->getLinkTarget($this, "export")
882  );
883 
884  $this->tabs_gui->addTab(
885  "import",
886  $this->lng->txt("import"),
887  $this->ctrl->getLinkTarget($this, "import")
888  );
889 
890  $this->tabs_gui->addTab(
891  "maintain",
892  $this->lng->txt("language_maintain"),
893  $this->ctrl->getLinkTarget($this, "maintain")
894  );
895 
896  $this->tabs_gui->addTab(
897  "settings",
898  $this->lng->txt("settings"),
899  $this->ctrl->getLinkTarget($this, "settings")
900  );
901 
902  $this->tabs_gui->addTab(
903  "statistics",
904  $this->lng->txt("language_statistics"),
905  $this->ctrl->getLinkTarget($this, "statistics")
906  );
907 
908  switch ($cmd) {
909  case "":
910  case "view":
911  case "applyFilter":
912  case "resetFilter":
913  case "save":
914  $this->tabs_gui->activateTab("edit");
915  break;
916  default:
917  $this->tabs_gui->activateTab($cmd);
918  }
919  }
920  }
921 
926  protected function addAdminLocatorItems(bool $do_not_add_object = false): void
927  {
928  global $DIC;
929  $ilLocator = $DIC["ilLocator"];
930 
932  parent::addAdminLocatorItems(true); // #13881
933 
934  $ilLocator->addItem(
935  $this->lng->txt("languages"),
936  $this->ctrl->getLinkTargetByClass("ilobjlanguagefoldergui", "")
937  );
938 
939  $ilLocator->addItem(
940  $this->lng->txt("meta_l_" . $this->object->getTitle()),
941  $this->ctrl->getLinkTarget($this, "view")
942  );
943  }
944  }
945 
950  protected function setTitleAndDescription(): void
951  {
953  $this->tpl->setHeaderPageTitle($this->lng->txt("translation"));
954  $this->tpl->setTitle($this->lng->txt("translation") . " " . $this->lng->txt("meta_l_" . $this->object->key));
955  } else {
956  $this->tpl->setTitle($this->lng->txt("meta_l_" . $this->object->key));
957  }
958  $this->tpl->setTitleIcon(ilUtil::getImagePath("icon_lngf.svg"), $this->lng->txt("obj_" . $this->object->getType()));
959  }
960 
961 
962  //
963  // new entries
964  //
965 
966  protected function buildMissingEntries(array $a_missing = null): string
967  {
968  global $DIC;
969  $ilCtrl = $DIC->ctrl();
970 
971  if (!count($a_missing)) {
972  return '';
973  }
974 
975  $res = array("<h3>" . $this->lng->txt("adm_missing_entries") . "</h3>", "<ul>");
976 
977  foreach ($a_missing as $entry) {
978  $ilCtrl->setParameter($this, "eid", $entry);
979  $res[] = '<li>' . $entry .
980  ' <a href="' . $ilCtrl->getLinkTarget($this, "addNewEntry") .
981  '">' . $this->lng->txt("adm_missing_entry_add_action") . '</a></li>';
982  $ilCtrl->setParameter($this, "eid", "");
983  }
984 
985  $res[] = "</ul>";
986 
987  return implode("\n", $res);
988  }
989 
990  public function addNewEntryObject(ilPropertyFormGUI $a_form = null): void
991  {
992  global $DIC;
993  $tpl = $DIC["tpl"];
994 
995  $id = "";
996  if ($this->http->wrapper()->query()->has("eid")) {
997  $id = trim($this->http->wrapper()->query()->retrieve("eid", $this->refinery->kindlyTo()->string()));
998  }
999  if (!$a_form) {
1000  $a_form = $this->initAddNewEntryForm($id);
1001  }
1002 
1003  $tpl->setContent($a_form->getHTML());
1004  }
1005 
1006  protected function initAddNewEntryForm(string $a_id = null): ilPropertyFormGUI
1007  {
1008  global $DIC;
1009  $ilCtrl = $DIC->ctrl();
1010 
1011  if (!$a_id) {
1012  $a_id = $this->http->request()->getParsedBody()['id'] ?? "";
1013  }
1014 
1015  if (!$a_id ||
1016  !in_array($a_id, ilObjLanguageAccess::_getSavedTopics())) {
1017  $ilCtrl->redirect($this, "view");
1018  }
1019 
1020  include_once "Services/Form/classes/class.ilPropertyFormGUI.php";
1021  $form = new ilPropertyFormGUI();
1022  $form->setFormAction($ilCtrl->getFormAction($this, "saveNewEntry"));
1023  $form->setTitle($this->lng->txt("adm_missing_entry_add"));
1024 
1026  $options = array_combine($mods, $mods);
1027 
1028  $mod = new ilSelectInputGUI(ucfirst($this->lng->txt("module")), "mod");
1029  $mod->setOptions(array("" => $this->lng->txt("please_select")) + $options);
1030  $mod->setRequired(true);
1031  $form->addItem($mod);
1032 
1033  $id = new ilTextInputGUI(ucfirst($this->lng->txt("identifier")), "id");
1034  $id->setValue($a_id);
1035  $id->setDisabled(true);
1036  $form->addItem($id);
1037 
1038  foreach ($this->lng->getInstalledLanguages() as $lang_key) {
1039  $trans = new ilTextInputGUI($this->lng->txt("meta_l_" . $lang_key), "trans_" . $lang_key);
1040  if (in_array($lang_key, array("de", "en"))) {
1041  $trans->setRequired(true);
1042  }
1043  $form->addItem($trans);
1044  }
1045 
1046  $form->addCommandButton("saveNewEntry", $this->lng->txt("save"));
1047  $form->addCommandButton("view", $this->lng->txt("cancel"));
1048 
1049  return $form;
1050  }
1051 
1052  public function saveNewEntryObject(): void
1053  {
1054  global $DIC;
1055  $ilDB = $DIC->database();
1056  $ilCtrl = $DIC->ctrl();
1057  $ilUser = $DIC->user();
1058 
1059  $form = $this->initAddNewEntryForm();
1060  if ($form->checkInput()) {
1061  $mod = $form->getInput("mod");
1062  $id = $form->getInput("id");
1063 
1064  $lang = array();
1065  foreach ($this->lng->getInstalledLanguages() as $lang_key) {
1066  $trans = trim($form->getInput("trans_" . $lang_key));
1067  if ($trans) {
1068  // add single entry
1070  $mod,
1071  $id,
1072  $lang_key,
1073  $trans,
1074  date("Y-m-d H:i:s"),
1075  $ilUser->getLogin()
1076  );
1077 
1078  // add to serialized module
1079  $set = $ilDB->query("SELECT lang_array FROM lng_modules" .
1080  " WHERE lang_key = " . $ilDB->quote($lang_key, "text") .
1081  " AND module = " . $ilDB->quote($mod, "text"));
1082  $row = $ilDB->fetchAssoc($set);
1083  $entries = unserialize($row["lang_array"], ["allowed_classes" => false]);
1084  if (is_array($entries)) {
1085  $entries[$id] = $trans;
1086  ilObjLanguage::replaceLangModule($lang_key, $mod, $entries);
1087  }
1088  }
1089  }
1090 
1091  $this->tpl->setOnScreenMessage('success', $this->lng->txt("settings_saved"), true);
1092  $ilCtrl->redirect($this, "view");
1093  }
1094 
1095  $form->setValuesByPost();
1096  $this->addNewEntryObject($form);
1097  }
1098 
1102  protected function getSuccessMessage(): string
1103  {
1104  global $DIC;
1105  $f = $DIC->ui()->factory();
1106  $renderer = $DIC->ui()->renderer();
1107 
1108  return $renderer->render($f->messageBox()->success($this->lng->txt("language_variables_saved")));
1109  }
1110 
1111  private function getSession(): array
1112  {
1113  return ilSession::get("lang_ext_maintenance") ?? [];
1114  }
1115 } // 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:28
assignObject()
Assign the extended language object.
const ILIAS_VERSION
getSuccessMessage()
Get success message after variables were saved.
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.
This class represents a checkbox property in a property form.
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.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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) ...
if($format !==null) $name
Definition: metadata.php:247
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.
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.
$keys
Definition: metadata.php:204
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:17
__construct(Container $dic, ilPlugin $plugin)
static _getRemarks(string $a_lang_key, bool $a_all_changed=false)
Get all remarks of a language.
$ilUser
Definition: imgupload.php:34
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.