ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjLanguageDBAccess.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 {
23  protected ilDBInterface $ilDB;
24  protected string $key;
25  protected array $content;
26  protected string $scope;
27  protected array $local_changes;
28  protected ?string $change_date = null;
29  protected string $separator;
30  protected string $comment_separator;
31 
32  public function __construct(ilDBInterface $ilDB, string $key, array $content, array $local_changes, string $scope = "", string $separator = "#:#", string $comment_separator = "###")
33  {
34  $this->ilDB = $ilDB;
35  $this->key = $key;
36  $this->content = $content;
37  $this->local_changes = $local_changes;
38  $this->scope = $scope;
39  if ($scope === "local") {
40  $this->change_date = date("Y-m-d H:i:s", time());
41  }
42  $this->separator = $separator;
43  $this->comment_separator = $comment_separator;
44  }
45 
46  public function insertLangEntries(string $lang_file): array
47  {
48  // initialize the array for updating lng_modules below
49  $lang_array = array();
50  $lang_array["common"] = array();
51 
52  $double_checker = [];
53  $query_check = false;
54  $query = "INSERT INTO lng_data (module,identifier,lang_key,value,local_change,remarks) VALUES ";
55  foreach ($this->content as $val) {
56  // split the line of the language file
57  // [0]: module
58  // [1]: identifier
59  // [2]: value
60  // [3]: comment (optional)
61  $separated = explode($this->separator, trim($val));
62  $pos = strpos($separated[2], $this->comment_separator);
63  if ($pos !== false) {
64  $separated[3] = substr($separated[2], $pos + strlen($this->comment_separator));
65  $separated[2] = substr($separated[2], 0, $pos);
66  }
67 
68  // check if the value has a local change
69  $local_value = $this->local_changes[$separated[0]][$separated[1]] ?? "";
70 
71  if (empty($this->scope)) {
72  // import of a global language file
73  if ($local_value !== "" && $local_value !== $separated[2]) {
74  // keep an existing and different local value
75  $lang_array[$separated[0]][$separated[1]] = $local_value;
76  continue;
77  }
78  } elseif ($this->scope === "local") {
79  // import of a local language file
80  if ($local_value !== "") {
81  // keep a locally changed value that is newer than the file
82  $lang_array[$separated[0]][$separated[1]] = $local_value;
83  continue;
84  }
85  }
86  if ($double_checker[$separated[0]][$separated[1]][$this->key] ?? false) {
87  global $DIC;
88  $DIC->ui()->mainTemplate()->setOnScreenMessage(
89  'failure',
90  "Duplicate Language Entry in $lang_file:\n$val",
91  true
92  );
93  $DIC->ctrl()->redirectByClass(ilobjlanguagefoldergui::class, 'view');
94  }
95  $double_checker[$separated[0]][$separated[1]][$this->key] = true;
96 
97  $query .= sprintf(
98  "(%s,%s,%s,%s,%s,%s),",
99  $this->ilDB->quote($separated[0], "text"),
100  $this->ilDB->quote($separated[1], "text"),
101  $this->ilDB->quote($this->key, "text"),
102  $this->ilDB->quote($separated[2], "text"),
103  $this->ilDB->quote($this->change_date, "timestamp"),
104  $this->ilDB->quote($separated[3] ?? null, "text")
105  );
106  $query_check = true;
107  $lang_array[$separated[0]][$separated[1]] = $separated[2];
108  }
109  $query = rtrim($query, ",") . " ON DUPLICATE KEY UPDATE value=VALUES(value),local_change=VALUES(local_change),remarks=VALUES(remarks);";
110  if ($query_check) {
111  $this->ilDB->manipulate($query);
112  }
113 
114  return $lang_array;
115  }
116 
117  public function replaceLangModules(array $lang_array): void
118  {
119  // avoid flushing the whole cache (see mantis #28818)
120  ilCachedLanguage::getInstance($this->key)->deleteInCache();
121 
122  $query = "INSERT INTO lng_modules (module, lang_key, lang_array) VALUES ";
123  $modules_to_delete = [];
124  foreach ($lang_array as $module => $lang_arr) {
125  if ($this->scope === "local") {
126  $q = "SELECT * FROM lng_modules WHERE " .
127  " lang_key = " . $this->ilDB->quote($this->key, "text") .
128  " AND module = " . $this->ilDB->quote($module, "text");
129  $set = $this->ilDB->query($q);
130  $row = $this->ilDB->fetchAssoc($set);
131  $arr2 = unserialize($row["lang_array"], ["allowed_classes" => false]);
132  if (is_array($arr2)) {
133  $lang_arr = array_merge($arr2, $lang_arr);
134  }
135  }
136  $query .= sprintf(
137  "(%s,%s,%s),",
138  $this->ilDB->quote($module, "text"),
139  $this->ilDB->quote($this->key, "text"),
140  $this->ilDB->quote(serialize($lang_arr), "clob"),
141  );
142  $modules_to_delete[] = $module;
143  }
144 
145  $inModulesToDelete = $this->ilDB->in('module', $modules_to_delete, false, 'text');
146  $this->ilDB->manipulate(sprintf(
147  "DELETE FROM lng_modules WHERE lang_key = %s AND $inModulesToDelete",
148  $this->ilDB->quote($this->key, "text")
149  ));
150 
151  $query = rtrim($query, ",") . ";";
152  $this->ilDB->manipulate($query);
153 
154  // check if the module is correctly saved
155  // see mantis #20046 and #19140
156  $this->checkModules();
157  }
158 
159  protected function checkModules(): void
160  {
161  $result = $this->ilDB->queryF(
162  "SELECT module, lang_array FROM lng_modules WHERE lang_key = %s",
163  array("text"),
164  array($this->key)
165  );
166 
167  foreach ($this->ilDB->fetchAll($result) as $module) {
168  $unserialied = unserialize($module["lang_array"], ["allowed_classes" => false]);
169  if (!is_array($unserialied)) {
170  global $DIC;
171  $DIC->ui()->mainTemplate()->setOnScreenMessage(
172  'failure',
173  "Data for module '" . $module["module"] . "' of language '" . $this->key . "' is not correctly saved. " .
174  "Please check the collation of your database tables lng_data and lng_modules. It must be utf8_unicode_ci.",
175  true
176  );
177  $DIC->ctrl()->redirectByClass(ilobjlanguagefoldergui::class, 'view');
178  }
179  }
180  }
181 }
global $DIC
Definition: feed.php:28
$q
Definition: shib_logout.php:21
__construct(ilDBInterface $ilDB, string $key, array $content, array $local_changes, string $scope="", string $separator="#:#", string $comment_separator="###")