ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilSetupLanguage.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2009 ILIAS open source, University of Cologne |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 +-----------------------------------------------------------------------------+
22*/
23
24
25
48{
54 public $text = array();
55
62 public $lang_default = "en";
63
71 public $lang_path;
72
78 public $lang_key;
79
85 public $separator = "#:#";
86
92 public $comment_separator = "###";
93
103 public function __construct($a_lang_key)
104 {
105 $this->lang_key = ($a_lang_key) ? $a_lang_key : $this->lang_default;
106
107 $il_absolute_path = realpath(dirname(__FILE__) . '/../../../../');
108 $this->lang_path = $il_absolute_path . "/lang";
109 $this->cust_lang_path = $il_absolute_path . "/Customizing/global/lang";
110
111 // set lang file...
112 $txt = file($this->lang_path . "/setup_lang_sel_multi.lang");
113
114 // ...and load langdata
115 if (is_array($txt)) {
116 foreach ($txt as $row) {
117 if ($row[0] != "#") {
118 $a = explode($this->separator, trim($row));
119 if (count($a) == 2) {
120 $this->text[trim($a[0])] = trim($a[1]);
121 }
122 }
123 }
124 }
125
126 // set lang file...
127 $txt = file($this->lang_path . "/setup_" . $this->lang_key . ".lang");
128
129 // ...and load langdata
130 if (is_array($txt)) {
131 foreach ($txt as $row) {
132 if ($row[0] != "#") {
133 $a = explode($this->separator, trim($row));
134 if (count($a) == 2) {
135 $this->text[trim($a[0])] = trim($a[1]);
136 }
137 }
138 }
139
140 return true;
141 }
142
143 return false;
144 }
145
154 public function txt($a_topic, $a_default_lang_fallback_mod = '')
155 {
156 global $log;
157
158 if (empty($a_topic)) {
159 return "";
160 }
161
162 $translation = $this->text[$a_topic];
163
164 //get position of the comment_separator
165 $pos = strpos($translation, $this->comment_separator);
166
167 if ($pos !== false) {
168 // remove comment
169 $translation = substr($translation, 0, $pos);
170 }
171
172 if ($translation == "") {
173 $log->writeLanguageLog($a_topic, $this->lang_key);
174 return "-" . $a_topic . "-";
175 } else {
176 return $translation;
177 }
178 }
179
187 public function getLanguages()
188 {
189 $d = dir($this->lang_path);
190 $tmpPath = getcwd();
191 chdir($this->lang_path);
192
193 // get available setup-files
194 while ($entry = $d->read()) {
195 if (is_file($entry) && (preg_match('/(^setup_.{2}\.lang$)/', $entry))) {
196 $lang_key = substr($entry, 6, 2);
197 $languages[] = $lang_key;
198 }
199 }
200
201 chdir($tmpPath);
202
203 return $languages;
204 }
205
212 public function installLanguages($a_lang_keys, $a_local_keys)
213 {
214 global $ilDB;
215
216 if (empty($a_lang_keys)) {
217 $a_lang_keys = array();
218 }
219
220 if (empty($a_local_keys)) {
221 $a_local_keys = array();
222 }
223
224 $err_lang = array();
225
226 $db_langs = $this->getAvailableLanguages();
227
228 foreach ($a_lang_keys as $lang_key) {
229 if ($this->checkLanguage($lang_key)) {
230 $this->flushLanguage($lang_key, 'keep_local');
231 $this->insertLanguage($lang_key);
232
233 if (in_array($lang_key, $a_local_keys) && is_dir($this->cust_lang_path)) {
234 if ($this->checkLanguage($lang_key, "local")) {
235 $this->insertLanguage($lang_key, "local");
236 } else {
237 $err_lang[] = $lang_key;
238 }
239 }
240
241 // register language first time install
242 if (!array_key_exists($lang_key, $db_langs)) {
243 if (in_array($lang_key, $a_local_keys)) {
244 $itype = 'installed_local';
245 } else {
246 $itype = 'installed';
247 }
248 $lid = $ilDB->nextId("object_data");
249 $query = "INSERT INTO object_data " .
250 "(obj_id,type,title,description,owner,create_date,last_update) " .
251 "VALUES " .
252 "(" .
253 $ilDB->quote($lid, "integer") . "," .
254 $ilDB->quote("lng", "text") . "," .
255 $ilDB->quote($lang_key, "text") . "," .
256 $ilDB->quote($itype, "text") . "," .
257 $ilDB->quote('-1', "integer") . "," .
258 $ilDB->now() . "," .
259 $ilDB->now() .
260 ")";
261 $this->db->manipulate($query);
262 }
263 } else {
264 $err_lang[] = $lang_key;
265 }
266 }
267
268 foreach ($db_langs as $key => $val) {
269 if (!in_array($key, $err_lang)) {
270 if (in_array($key, $a_lang_keys)) {
271 if (in_array($key, $a_local_keys)) {
272 $ld = 'installed_local';
273 } else {
274 $ld = 'installed';
275 }
276 $query = "UPDATE object_data SET " .
277 "description = " . $ilDB->quote($ld, "text") . ", " .
278 "last_update = " . $ilDB->now() . " " .
279 "WHERE obj_id = " . $ilDB->quote($val["obj_id"], "integer") . " " .
280 "AND type = " . $ilDB->quote("lng", "text");
281 $ilDB->manipulate($query);
282 } else {
283 $this->flushLanguage($key, "all");
284
285 if (substr($val["status"], 0, 9) == "installed") {
286 $query = "UPDATE object_data SET " .
287 "description = " . $ilDB->quote("not_installed", "text") . ", " .
288 "last_update = " . $ilDB->now() . " " .
289 "WHERE obj_id = " . $ilDB->quote($val["obj_id"], "integer") . " " .
290 "AND type = " . $ilDB->quote("lng", "text");
291 $ilDB->manipulate($query);
292 }
293 }
294 }
295 }
296
297 return ($err_lang) ? $err_lang : true;
298 }
299
300
301
307 public function getInstalledLanguages()
308 {
309 global $ilDB;
310
311 $arr = array();
312
313 $query = "SELECT * FROM object_data " .
314 "WHERE type = " . $ilDB->quote("lng", "text") . " " .
315 "AND " . $ilDB->like("description", "text", 'installed%');
316 $r = $ilDB->query($query);
317
318 while ($row = $ilDB->fetchObject($r)) {
319 $arr[] = $row->title;
320 }
321
322 return $arr;
323 }
324
331 {
332 global $ilDB;
333
334 $arr = array();
335
336 $query = "SELECT * FROM object_data " .
337 "WHERE type = " . $ilDB->quote("lng", "text") . " " .
338 "AND description = " . $ilDB->quote('installed_local', "text");
339 $r = $ilDB->query($query);
340
341 while ($row = $ilDB->fetchObject($r)) {
342 $arr[] = $row->title;
343 }
344
345 return $arr;
346 }
347
352 protected function getAvailableLanguages()
353 {
354 global $ilDB;
355
356 $arr = array();
357
358 $query = "SELECT * FROM object_data " .
359 "WHERE type = " . $ilDB->quote("lng", "text");
360 $r = $ilDB->query($query);
361
362 while ($row = $ilDB->fetchObject($r)) {
363 $arr[$row->title]["obj_id"] = $row->obj_id;
364 $arr[$row->title]["status"] = $row->description;
365 }
366
367 return $arr;
368 }
369
381 protected function checkLanguage($a_lang_key, $scope = '')
382 {
383 $scopeExtension = "";
384 if (!empty($scope)) {
385 if ($scope == 'global') {
386 $scope = '';
387 } else {
388 $scopeExtension = '.' . $scope;
389 }
390 }
391
392 $path = $this->lang_path;
393 if ($scope == "local") {
394 $path = $this->cust_lang_path;
395 }
396
397 $tmpPath = getcwd();
398 chdir($path);
399
400 // compute lang-file name format
401 $lang_file = "ilias_" . $a_lang_key . ".lang" . $scopeExtension;
402
403 // file check
404 if (!is_file($lang_file)) {
405 chdir($tmpPath);
406 return false;
407 }
408
409 // header check
410 if (!$content = $this->cut_header(file($lang_file))) {
411 chdir($tmpPath);
412 return false;
413 }
414
415 // check (counting) elements of each lang-entry
416 foreach ($content as $key => $val) {
417 $separated = explode($this->separator, trim($val));
418 $num = count($separated);
419
420 if ($num != 3) {
421 chdir($tmpPath);
422 return false;
423 }
424 }
425
426 chdir($tmpPath);
427
428 // no error occured
429 return true;
430 }
431
442 protected function cut_header($content)
443 {
444 foreach ($content as $key => $val) {
445 if (trim($val) == "<!-- language file start -->") {
446 return array_slice($content, $key + 1);
447 }
448 }
449
450 return false;
451 }
452
453
459 protected function flushLanguage($a_lang_key, $a_mode = 'all')
460 {
461 $ilDB = $this->db;
462
463 ilSetupLanguage::_deleteLangData($a_lang_key, ($a_mode == 'keep_local'));
464
465 if ($a_mode == 'all') {
466 $ilDB->manipulate("DELETE FROM lng_modules WHERE lang_key = " .
467 $ilDB->quote($a_lang_key, "text"));
468 }
469 }
470
476 public static function _deleteLangData($a_lang_key, $a_keep_local_change)
477 {
478 global $ilDB;
479
480 if (!$a_keep_local_change) {
481 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = " .
482 $ilDB->quote($a_lang_key, "text"));
483 } else {
484 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = " .
485 $ilDB->quote($a_lang_key, "text") .
486 " AND local_change IS NULL");
487 }
488 }
489
497 protected function getLocalChanges($a_lang_key, $a_min_date = "", $a_max_date = "")
498 {
499 $ilDB = $this->db;
500
501 if ($a_min_date == "") {
502 $a_min_date = "1980-01-01 00:00:00";
503 }
504 if ($a_max_date == "") {
505 $a_max_date = "2200-01-01 00:00:00";
506 }
507
508 $q = sprintf(
509 "SELECT * FROM lng_data WHERE lang_key = %s " .
510 "AND local_change >= %s AND local_change <= %s",
511 $ilDB->quote($a_lang_key, "text"),
512 $ilDB->quote($a_min_date, "timestamp"),
513 $ilDB->quote($a_max_date, "timestamp")
514 );
515 $result = $ilDB->query($q);
516
517 $changes = array();
518 while ($row = $result->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
519 $changes[$row["module"]][$row["identifier"]] = $row["value"];
520 }
521 return $changes;
522 }
523
524
525 //TODO: remove redundant checks here!
533 protected function insertLanguage($lang_key, $scope = '')
534 {
535 $ilDB = &$this->db;
536
537 $lang_array = array();
538
539 $scopeExtension = "";
540 if (!empty($scope)) {
541 if ($scope == 'global') {
542 $scope = '';
543 } else {
544 $scopeExtension = '.' . $scope;
545 }
546 }
547
548 $path = $this->lang_path;
549 if ($scope == "local") {
550 $path = $this->cust_lang_path;
551 }
552
553 $tmpPath = getcwd();
554 chdir($path);
555
556 $lang_file = "ilias_" . $lang_key . ".lang" . $scopeExtension;
557
558 if (is_file($lang_file)) {
559 // initialize the array for updating lng_modules below
560 $lang_array = array();
561 $lang_array["common"] = array();
562
563 // remove header first
564 if ($content = $this->cut_header(file($lang_file))) {
565 // get the local changes from the database
566 if (empty($scope)) {
567 $local_changes = $this->getLocalChanges($lang_key);
568 } elseif ($scope == 'local') {
569 // set the change date to import time for a local file
570 // get the modification date of the local file
571 // get the newer local changes for a local file
572 $change_date = date("Y-m-d H:i:s", time());
573 $min_date = date("Y-m-d H:i:s", filemtime($lang_file));
574 $local_changes = $this->getLocalChanges($lang_key, $min_date);
575 }
576
577 foreach ($content as $key => $val) {
578 // split the line of the language file
579 // [0]: module
580 // [1]: identifier
581 // [2]: value
582 // [3]: comment (optional)
583 $separated = explode($this->separator, trim($val));
584
585 //get position of the comment_separator
586 $pos = strpos($separated[2], $this->comment_separator);
587
588 if ($pos !== false) {
589 //cut comment of
590 $separated[2] = substr($separated[2], 0, $pos);
591 }
592
593 // check if the value has a local change
594 if (isset($local_changes[$separated[0]])) {
595 $local_value = $local_changes[$separated[0]][$separated[1]];
596 } else {
597 $local_value = null;
598 }
599
600 if (empty($scope)) {
601 if ($local_value != "" and $local_value != $separated[2]) {
602 // keep the locally changed value
603 $lang_array[$separated[0]][$separated[1]] = $local_value;
604 } else {
605 // insert a new value if no local value exists
606 // reset local_change if the values are equal
608 $separated[0],
609 $separated[1],
610 $lang_key,
611 $separated[2]
612 );
613
614 $lang_array[$separated[0]][$separated[1]] = $separated[2];
615 }
616 } elseif ($scope == 'local') {
617 if ($local_value != "") {
618 // keep a locally changed value that is newer than the local file
619 $lang_array[$separated[0]][$separated[1]] = $local_value;
620 } else {
621 // UPDATE because the global values have already been INSERTed
623 $separated[0],
624 $separated[1],
625 $lang_key,
626 $separated[2],
627 $change_date
628 );
629 $lang_array[$separated[0]][$separated[1]] = $separated[2];
630 }
631 }
632 }
633 }
634
635 foreach ($lang_array as $module => $lang_arr) {
636 if ($scope == "local") {
637 $q = "SELECT * FROM lng_modules WHERE " .
638 " lang_key = " . $ilDB->quote($lang_key, "text") .
639 " AND module = " . $ilDB->quote($module, "text");
640 $set = $ilDB->query($q);
641 $row = $ilDB->fetchAssoc($set);
642 $arr2 = unserialize($row["lang_array"]);
643 if (is_array($arr2)) {
644 $lang_arr = array_merge($arr2, $lang_arr);
645 }
646 }
648 }
649 }
650
651 chdir($tmpPath);
652 }
653
657 final public static function replaceLangModule($a_key, $a_module, $a_array)
658 {
659 global $ilDB;
660
661 $ilDB->manipulate(sprintf(
662 "DELETE FROM lng_modules WHERE lang_key = %s AND module = %s",
663 $ilDB->quote($a_key, "text"),
664 $ilDB->quote($a_module, "text")
665 ));
666 /*$ilDB->manipulate(sprintf("INSERT INTO lng_modules (lang_key, module, lang_array) VALUES ".
667 "(%s,%s,%s)", $ilDB->quote($a_key, "text"),
668 $ilDB->quote($a_module, "text"),
669 $ilDB->quote(serialize($a_array), "clob")));*/
670 $ilDB->insert("lng_modules", array(
671 "lang_key" => array("text", $a_key),
672 "module" => array("text", $a_module),
673 "lang_array" => array("clob", serialize($a_array))
674 ));
675 }
676
680 final public static function replaceLangEntry(
681 $a_module,
682 $a_identifier,
683 $a_lang_key,
684 $a_value,
685 $a_local_change = null
686 ) {
687 global $ilDB;
688
689 $ilDB->manipulate(sprintf(
690 "DELETE FROM lng_data WHERE module = %s AND " .
691 "identifier = %s AND lang_key = %s",
692 $ilDB->quote($a_module, "text"),
693 $ilDB->quote($a_identifier, "text"),
694 $ilDB->quote($a_lang_key, "text")
695 ));
696
697 // insert a new value if no local value exists
698 // reset local_change if the values are equal
699 $ilDB->manipulate(sprintf(
700 "INSERT INTO lng_data " .
701 "(module, identifier, lang_key, value, local_change) " .
702 "VALUES (%s,%s,%s,%s,%s)",
703 $ilDB->quote($a_module, "text"),
704 $ilDB->quote($a_identifier, "text"),
705 $ilDB->quote($a_lang_key, "text"),
706 $ilDB->quote($a_value, "text"),
707 $ilDB->quote($a_local_change, "timestamp")
708 ));
709 }
710
714 final public static function updateLangEntry(
715 $a_module,
716 $a_identifier,
717 $a_lang_key,
718 $a_value,
719 $a_local_change = null
720 ) {
721 global $ilDB;
722
723 $ilDB->manipulate(sprintf(
724 "UPDATE lng_data " .
725 "SET value = %s, local_change = %s " .
726 "WHERE module = %s AND identifier = %s AND lang_key = %s ",
727 $ilDB->quote($a_value, "text"),
728 $ilDB->quote($a_local_change, "timestamp"),
729 $ilDB->quote($a_module, "text"),
730 $ilDB->quote($a_identifier, "text"),
731 $ilDB->quote($a_lang_key, "text")
732 ));
733 }
734
740 public function getLocalLanguages()
741 {
742 $local_langs = array();
743 if (is_dir($this->cust_lang_path)) {
744 $d = dir($this->cust_lang_path);
745 $tmpPath = getcwd();
746 chdir($this->cust_lang_path);
747
748 // get available .lang.local files
749 while ($entry = $d->read()) {
750 if (is_file($entry) && (preg_match("~(^ilias_.{2}\.lang.local$)~", $entry))) {
751 $lang_key = substr($entry, 6, 2);
752 $local_langs[] = $lang_key;
753 }
754 }
755
756 chdir($tmpPath);
757 }
758
759 return $local_langs;
760 }
761
762 public function getInstallableLanguages()
763 {
764 $setup_langs = $this->getLanguages();
765
766 $d = dir($this->lang_path);
767 $tmpPath = getcwd();
768 chdir($this->lang_path);
769
770 // get available lang-files
771 while ($entry = $d->read()) {
772 if (is_file($entry) && (preg_match("~(^ilias_.{2}\.lang$)~", $entry))) {
773 $lang_key = substr($entry, 6, 2);
774 $languages1[] = $lang_key;
775 }
776 }
777
778 //$languages = array_intersect($languages1,$setup_langs);
779
780 chdir($tmpPath);
781
782 return $languages1;
783 }
784
790 public function setDbHandler($a_db_handler)
791 {
792 if (empty($a_db_handler) or !is_object($a_db_handler)) {
793 return false;
794 }
795
796 $this->db = &$a_db_handler;
797
798 return true;
799 }
800
801 public function loadLanguageModule($a_module)
802 {
803 }
804} // END class.ilSetupLanguage
$result
An exception for terminatinating execution or to throw for unit testing.
language handling
language handling for setup
__construct($a_lang_key)
Constructor read the single-language file and put this in an array text.
cut_header($content)
Remove *.lang header information from '$content'.
static replaceLangModule($a_key, $a_module, $a_array)
Replace language module array.
flushLanguage($a_lang_key, $a_mode='all')
remove language data from database
txt($a_topic, $a_default_lang_fallback_mod='')
gets the text for a given topic
static _deleteLangData($a_lang_key, $a_keep_local_change)
Delete languge data.
insertLanguage($lang_key, $scope='')
insert language data from file in database
getInstalledLanguages()
get already installed languages (in db)
getAvailableLanguages()
get already registered languages (in db)
getInstalledLocalLanguages()
get already installed local languages (in db)
static updateLangEntry( $a_module, $a_identifier, $a_lang_key, $a_value, $a_local_change=null)
Update lang entry.
getLocalLanguages()
Searches for the existence of *.lang.local files.
getLocalChanges($a_lang_key, $a_min_date="", $a_max_date="")
get locally changed language entries
installLanguages($a_lang_keys, $a_local_keys)
install languages
setDbHandler($a_db_handler)
set db handler object @string object db handler
getLanguages()
get all setup languages in the system
static replaceLangEntry( $a_module, $a_identifier, $a_lang_key, $a_value, $a_local_change=null)
Replace lang entry.
checkLanguage($a_lang_key, $scope='')
validate the logical structure of a lang-file
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
$txt
Definition: error.php:13
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$query
$log
Definition: result.php:15
global $ilDB