ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilObjLanguage.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once "./Services/Object/classes/class.ilObject.php";
5
15{
28
29 var $key;
31
32
40 function __construct($a_id = 0, $a_call_by_reference = false)
41 {
42 global $lng;
43
44 $this->type = "lng";
45 parent::__construct($a_id,$a_call_by_reference);
46
47 $this->type = "lng";
48 $this->key = $this->title;
49 $this->status = $this->desc;
50 $this->lang_default = $lng->lang_default;
51 $this->lang_user = $lng->lang_user;
52 $this->lang_path = $lng->lang_path;
53 $this->cust_lang_path = $lng->cust_lang_path;
54 $this->separator = $lng->separator;
55 $this->comment_separator = $lng->comment_separator;
56 }
57
58
63 public static function getInstalledLanguages()
64 {
65 $objects = array();
67 foreach ($languages as $lang)
68 {
69 $langObj = new ilObjLanguage($lang["obj_id"], false);
70 if ($langObj->isInstalled())
71 {
72 $objects[] = $langObj;
73 }
74 else
75 {
76 unset($langObj);
77 }
78 }
79 return $objects;
80 }
81
82
88 function getKey()
89 {
90 return $this->key;
91 }
92
98 function getStatus()
99 {
100 return $this->status;
101 }
102
107 {
108 if ($this->key == $this->lang_default)
109 return true;
110 else
111 return false;
112 }
113
117 function isUserLanguage()
118 {
119 if ($this->key == $this->lang_user)
120 {
121 return true;
122 }
123 else
124 {
125 return false;
126 }
127 }
128
129
135 function isInstalled()
136 {
137 if (substr($this->getStatus(), 0, 9) == "installed")
138 {
139 return true;
140 }
141 else
142 {
143 return false;
144 }
145 }
146
153 function isLocal()
154 {
155 if (substr($this->getStatus(), 10) == "local")
156 {
157 return true;
158 }
159 else
160 {
161 return false;
162 }
163 }
164
171 function install($scope = '')
172 {
173 if (!empty($scope))
174 {
175 if ($scope == 'global')
176 {
177 $scope = '';
178 }
179 else
180 {
181 $scopeExtension = '.' . $scope;
182 }
183 }
184
185 if (($this->isInstalled() == false) ||
186 ($this->isInstalled() == true && $this->isLocal() == false && !empty($scope)))
187 {
188 if ($this->check($scope))
189 {
190 // lang-file is ok. Flush data in db and...
191 if (empty($scope))
192 {
193 $this->flush('keep_local');
194 }
195
196 // ...re-insert data from lang-file
197 $this->insert($scope);
198
199 // update information in db-table about available/installed languages
200 if (empty($scope))
201 {
202 $newDesc = 'installed';
203 }
204 else if ($scope == 'local')
205 {
206 $newDesc = 'installed_local';
207 }
208 $this->setDescription($newDesc);
209 $this->update();
210 return $this->getKey();
211 }
212 }
213 return "";
214 }
215
216
222 function uninstall()
223 {
224 if ((substr($this->status, 0, 9) == "installed") && ($this->key != $this->lang_default) && ($this->key != $this->lang_user))
225 {
226 $this->flush('all');
227 $this->setTitle($this->key);
228 $this->setDescription("not_installed");
229 $this->update();
230 $this->resetUserLanguage($this->key);
231
232 return $this->key;
233 }
234 return "";
235 }
236
237
242 function refresh()
243 {
244 if ($this->isInstalled() == true)
245 {
246 if ($this->check())
247 {
248 $this->flush('keep_local');
249 $this->insert();
250 $this->setTitle($this->getKey());
251 $this->setDescription($this->getStatus());
252 $this->update();
253
254 if ($this->isLocal() == true)
255 {
256 if ($this->check('local'))
257 {
258 $this->insert('local');
259 $this->setTitle($this->getKey());
260 $this->setDescription($this->getStatus());
261 $this->update();
262 }
263 }
264 return true;
265 }
266 }
267 return false;
268 }
269
273 static function refreshAll()
274 {
276 $refreshed = array();
277
278 foreach ($languages as $lang)
279 {
280 $langObj = new ilObjLanguage($lang["obj_id"],false);
281 if ($langObj->refresh())
282 {
283 $refreshed[] = $langObj->getKey();
284 }
285 unset($langObj);
286 }
287
288 self::refreshPlugins($refreshed);
289 }
290
291
296 public static function refreshPlugins($a_lang_keys = null)
297 {
298 global $ilPluginAdmin;
299
300 // refresh languages of activated plugins
301 include_once("./Services/Component/classes/class.ilPluginSlot.php");
302 $slots = ilPluginSlot::getAllSlots();
303 foreach ($slots as $slot)
304 {
305 $act_plugins = $ilPluginAdmin->getActivePluginsForSlot($slot["component_type"],
306 $slot["component_name"], $slot["slot_id"]);
307 foreach ($act_plugins as $plugin)
308 {
309 include_once("./Services/Component/classes/class.ilPlugin.php");
310 $pl = ilPlugin::getPluginObject($slot["component_type"],
311 $slot["component_name"], $slot["slot_id"], $plugin);
312 if (is_object($pl))
313 {
314 $pl->updateLanguages($a_lang_keys);
315 }
316 }
317 }
318 }
319
320
326 static function _deleteLangData($a_lang_key, $a_keep_local_change = false)
327 {
328 global $ilDB;
329 if (!$a_keep_local_change)
330 {
331 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = ".
332 $ilDB->quote($a_lang_key, "text"));
333 }
334 else
335 {
336 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = ".
337 $ilDB->quote($a_lang_key, "text").
338 " AND local_change IS NULL");
339 }
340 }
341
346 function flush($a_mode = 'all')
347 {
348 global $ilDB;
349
350 ilObjLanguage::_deleteLangData($this->key, ($a_mode == 'keep_local'));
351
352 if ($a_mode == 'all')
353 {
354 $ilDB->manipulate("DELETE FROM lng_modules WHERE lang_key = ".
355 $ilDB->quote($this->key, "text"));
356 }
357 }
358
359
366 function getLocalChanges($a_min_date = "", $a_max_date = "")
367 {
368 global $ilDB;
369
370 if ($a_min_date == "")
371 {
372 $a_min_date = "1980-01-01 00:00:00";
373 }
374 if ($a_max_date == "")
375 {
376 $a_max_date = "2200-01-01 00:00:00";
377 }
378
379 $q = sprintf("SELECT * FROM lng_data WHERE lang_key = %s ".
380 "AND local_change >= %s AND local_change <= %s",
381 $ilDB->quote($this->key, "text"), $ilDB->quote($a_min_date, "timestamp"),
382 $ilDB->quote($a_max_date, "timestamp"));
383 $result = $ilDB->query($q);
384
385 $changes = array();
386 while ($row = $result->fetchRow(ilDBConstants::FETCHMODE_ASSOC))
387 {
388 $changes[$row["module"]][$row["identifier"]] = $row["value"];
389 }
390 return $changes;
391 }
392
393
399 static function _getLastLocalChange($a_key)
400 {
401 global $ilDB;
402
403 $q = sprintf("SELECT MAX(local_change) last_change FROM lng_data ".
404 "WHERE lang_key = %s AND local_change IS NOT NULL",
405 $ilDB->quote($a_key, "text"));
406 $result = $ilDB->query($q);
407
409 {
410 return $row['last_change'];
411 }
412 else
413 {
414 return "";
415 }
416 }
417
418
425 static function _getLocalChangesByModule($a_key, $a_module)
426 {
428 global $ilDB;
429
430 $changes = array();
431 $result = $ilDB->queryF("SELECT * FROM lng_data WHERE lang_key = %s AND module = %s AND local_change IS NOT NULL",
432
433 array('text', 'text'),
434 array($a_key, $a_module));
435
436 while ($row = $ilDB->fetchAssoc($result))
437 {
438 $changes[$row['identifier']] = $row['value'];
439 }
440 return $changes;
441 }
442
443
449 function insert($scope = '')
450 {
451 global $ilDB;
452
453 if (!empty($scope))
454 {
455 if ($scope == 'global')
456 {
457 $scope = '';
458 }
459 else
460 {
461 $scopeExtension = '.' . $scope;
462 }
463 }
464
466 if ($scope == "local")
467 {
468 $path = $this->cust_lang_path;
469 }
470
471 $lang_file = $path . "/ilias_" . $this->key . ".lang" . $scopeExtension;
472 if (is_file($lang_file))
473 {
474 // initialize the array for updating lng_modules below
475 $lang_array = array();
476 $lang_array["common"] = array();
477
478 // remove header first
479 if ($content = $this->cut_header(file($lang_file)))
480 {
481 if (empty($scope))
482 {
483 // reset change date for a global file
484 // get all local changes for a global file
485 $change_date = null;
486 $local_changes = $this->getLocalChanges();
487 }
488 else if ($scope == 'local')
489 {
490 // set the change date to import time for a local file
491 // get the modification date of the local file
492 // get the newer local changes for a local file
493 $change_date = date("Y-m-d H:i:s",time());
494 $min_date = date("Y-m-d H:i:s", filemtime($lang_file));
495 $local_changes = $this->getLocalChanges($min_date);
496 }
497
498 foreach ($content as $key => $val)
499 {
500 // split the line of the language file
501 // [0]: module
502 // [1]: identifier
503 // [2]: value
504 // [3]: comment (optional)
505 $separated = explode($this->separator,trim($val));
506 $pos = strpos($separated[2], $this->comment_separator);
507 if ($pos !== false)
508 {
509 $separated[3] = substr($separated[2], $pos + strlen($this->comment_separator));
510 $separated[2] = substr($separated[2] , 0 , $pos);
511 }
512
513 // check if the value has a local change
514 $local_value = $local_changes[$separated[0]][$separated[1]];
515
516 if (empty($scope))
517 {
518 // import of a global language file
519
520 if ($local_value != "" and $local_value != $separated[2])
521 {
522 // keep an existing and different local calue
523 $lang_array[$separated[0]][$separated[1]] = $local_value;
524 }
525 else
526 {
527 // check for double entries in global file
528 if ($double_checker[$separated[0]][$separated[1]][$this->key])
529 {
530 $this->ilias->raiseError("Duplicate Language Entry in $lang_file:\n$val",
531 $this->ilias->error_obj->MESSAGE);
532 }
533 $double_checker[$separated[0]][$separated[1]][$this->key] = true;
534
535 // insert a new value if no local value exists
536 // reset local change date if the values are equal
537 ilObjLanguage::replaceLangEntry($separated[0], $separated[1],
538 $this->key, $separated[2], $change_date, $separated[3]);
539
540 $lang_array[$separated[0]][$separated[1]] = $separated[2];
541 }
542 }
543 else if ($scope == 'local')
544 {
545 // import of a local language file
546
547 if ($local_value != "")
548 {
549 // keep a locally changed value that is newer than the file
550 $lang_array[$separated[0]][$separated[1]] = $local_value;
551 }
552 else
553 {
554 // insert a new value if no global value exists
555 // (local files may have additional entries for customizations)
556 // set the change date to the import date
557 ilObjLanguage::replaceLangEntry($separated[0], $separated[1],
558 $this->key, $separated[2], $change_date, $separated[3]);
559
560 $lang_array[$separated[0]][$separated[1]] = $separated[2];
561 }
562 }
563 }
564
565 $ld = "";
566 if (empty($scope))
567 {
568 $ld = "installed";
569 }
570 else if ($scope == 'local')
571 {
572 $ld = "installed_local";
573 }
574 if ($ld)
575 {
576 $query = "UPDATE object_data SET " .
577 "description = ".$ilDB->quote($ld, "text").", " .
578 "last_update = ".$ilDB->now()." " .
579 "WHERE title = ".$ilDB->quote($this->key, "text")." " .
580 "AND type = 'lng'";
581 $ilDB->manipulate($query);
582 }
583 }
584
585 foreach($lang_array as $module => $lang_arr)
586 {
587 if ($scope == "local")
588 {
589 $q = "SELECT * FROM lng_modules WHERE ".
590 " lang_key = ".$ilDB->quote($this->key, "text").
591 " AND module = ".$ilDB->quote($module, "text");
592 $set = $ilDB->query($q);
593 $row = $ilDB->fetchAssoc($set);
594 $arr2 = unserialize($row["lang_array"]);
595 if (is_array($arr2))
596 {
597 $lang_arr = array_merge($arr2, $lang_arr);
598 }
599 }
600 ilObjLanguage::replaceLangModule($this->key, $module, $lang_arr);
601 }
602 }
603 }
604
608 static final function replaceLangModule($a_key, $a_module, $a_array)
609 {
610 global $DIC;
611 $ilDB = $DIC->database();
612
613 ilGlobalCache::flushAll();
614
615 $ilDB->manipulate(sprintf("DELETE FROM lng_modules WHERE lang_key = %s AND module = %s",
616 $ilDB->quote($a_key, "text"), $ilDB->quote($a_module, "text")));
617
618 /*$ilDB->manipulate(sprintf("INSERT INTO lng_modules (lang_key, module, lang_array) VALUES ".
619 "(%s,%s,%s)", $ilDB->quote($a_key, "text"),
620 $ilDB->quote($a_module, "text"),
621 $ilDB->quote(serialize($a_array), "clob")));*/
622 $ilDB->insert("lng_modules", array(
623 "lang_key" => array("text", $a_key),
624 "module" => array("text", $a_module),
625 "lang_array" => array("clob", serialize((array) $a_array))
626 ));
627
628 // check if the module is correctly saved
629 // see mantis #20046 and #19140
630 $result = $ilDB->queryF("SELECT lang_array FROM lng_modules WHERE lang_key = %s AND module = %s",
631 array('text','text'), array($a_key, $a_module));
632 $row = $ilDB->fetchAssoc($result);
633
634 $unserialied = unserialize($row['lang_array']);
635 if (!is_array($unserialied))
636 {
638 $ilErr = $DIC['ilErr'];
639 $ilErr->raiseError("Data for module '" . $a_module . "' of language '" . $a_key . "' is not correctly saved. ".
640 "Please check the collation of your database tables lng_data and lng_modules. It must be utf8_unicode_ci.",
641 $ilErr->MESSAGE);
642 }
643 }
644
648 static final function replaceLangEntry($a_module, $a_identifier,
649 $a_lang_key, $a_value, $a_local_change = null, $a_remarks = null)
650 {
651 global $ilDB;
652
653 ilGlobalCache::flushAll();
654
655 if (isset($a_remarks))
656 {
657 $a_remarks = substr($a_remarks, 0, 250);
658 }
659 if ($a_remarks == '')
660 {
661 unset($a_remarks);
662 }
663
664 if (isset($a_value))
665 {
666 $a_value = substr($a_value, 0, 4000);
667 }
668 if ($a_value == '')
669 {
670 unset($a_value);
671 }
672
673 $ilDB->replace(
674 'lng_data',
675 array(
676 'module' => array('text',$a_module),
677 'identifier' => array('text',$a_identifier),
678 'lang_key' => array('text',$a_lang_key)
679 ),
680 array(
681 'value' => array('text',$a_value),
682 'local_change' => array('timestamp',$a_local_change),
683 'remarks' => array('text', $a_remarks)
684 )
685 );
686 return true;
687
688 /*
689 $ilDB->manipulate(sprintf("DELETE FROM lng_data WHERE module = %s AND ".
690 "identifier = %s AND lang_key = %s",
691 $ilDB->quote($a_module, "text"), $ilDB->quote($a_identifier, "text"),
692 $ilDB->quote($a_lang_key, "text")));
693
694
695 $ilDB->manipulate(sprintf("INSERT INTO lng_data " .
696 "(module, identifier, lang_key, value, local_change) " .
697 "VALUES (%s,%s,%s,%s,%s)",
698 $ilDB->quote($a_module, "text"), $ilDB->quote($a_identifier, "text"),
699 $ilDB->quote($a_lang_key, "text"), $ilDB->quote($a_value, "text"),
700 $ilDB->quote($a_local_change, "timestamp")));
701 */
702 }
703
707 static final function updateLangEntry($a_module, $a_identifier,
708 $a_lang_key, $a_value, $a_local_change = null, $a_remarks = null)
709 {
710 global $ilDB;
711
712 if (isset($a_remarks))
713 {
714 $a_remarks = substr($a_remarks, 0, 250);
715 }
716 if ($a_remarks == '')
717 {
718 unset($a_remarks);
719 }
720
721 if (isset($a_value))
722 {
723 $a_value = substr($a_value, 0, 4000);
724 }
725 if ($a_value == '')
726 {
727 unset($a_value);
728 }
729
730 $ilDB->manipulate(sprintf("UPDATE lng_data " .
731 "SET value = %s, local_change = %s, remarks = %s ".
732 "WHERE module = %s AND identifier = %s AND lang_key = %s ",
733 $ilDB->quote($a_value, "text"), $ilDB->quote($a_local_change, "timestamp"),
734 $ilDB->quote($a_remarks, "text"),
735 $ilDB->quote($a_module, "text"), $ilDB->quote($a_identifier, "text"),
736 $ilDB->quote($a_lang_key, "text")));
737 }
738
739
743 static final function deleteLangEntry($a_module, $a_identifier, $a_lang_key)
744 {
745 global $ilDB;
746
747 $ilDB->manipulate(sprintf("DELETE FROM lng_data " .
748 "WHERE module = %s AND identifier = %s AND lang_key = %s ",
749 $ilDB->quote($a_module, "text"),
750 $ilDB->quote($a_identifier, "text"),
751 $ilDB->quote($a_lang_key, "text")));
752
753 return true;
754 }
755
756
763 function resetUserLanguage($lang_key)
764 {
765 global $ilDB;
766
767 $query = "UPDATE usr_pref SET " .
768 "value = ".$ilDB->quote($this->lang_default, "text")." " .
769 "WHERE keyword = ".$ilDB->quote('language', "text")." ".
770 "AND value = ".$ilDB->quote($lang_key, "text");
771 $ilDB->manipulate($query);
772 }
773
782 static function cut_header($content)
783 {
784 foreach ($content as $key => $val)
785 {
786 if (trim($val) == "<!-- language file start -->")
787 {
788
789 return array_slice($content,$key +1);
790 }
791 }
792
793 return false;
794 }
795
802 function optimizeData()
803 {
804 // Mantis #22313: removed table optimization
805 return true;
806 }
807
817 function check($scope = '')
818 {
819 include_once("./Services/Utilities/classes/class.ilStr.php");
820
821 if (!empty($scope))
822 {
823 if ($scope == 'global')
824 {
825 $scope = '';
826 }
827 else
828 {
829 $scopeExtension = '.' . $scope;
830 }
831 }
832
834 if ($scope == "local")
835 {
836 $path = $this->cust_lang_path;
837 }
838
839 $tmpPath = getcwd();
840
841 // dir check
842 if (!is_dir($path))
843 {
844 $this->ilias->raiseError("Directory not found: ".$path, $this->ilias->error_obj->MESSAGE);
845 }
846
847 chdir($path);
848
849 // compute lang-file name format
850 $lang_file = "ilias_" . $this->key . ".lang" . $scopeExtension;
851
852 // file check
853 if (!is_file($lang_file))
854 {
855 $this->ilias->raiseError("File not found: ".$lang_file,$this->ilias->error_obj->MESSAGE);
856 }
857
858 // header check
859 $content = $this->cut_header(file($lang_file));
860 if ($content === false)
861 {
862 $this->ilias->raiseError("Wrong Header in ".$lang_file,$this->ilias->error_obj->MESSAGE);
863 }
864
865 // check (counting) elements of each lang-entry
866 $line = 0;
867 foreach ($content as $key => $val)
868 {
869 $separated = explode($this->separator, trim($val));
870 $num = count($separated);
871 ++$n;
872 if ($num != 3)
873 {
874 $line = $n + 36;
875 $this->ilias->raiseError("Wrong parameter count in ".$lang_file." in line $line (Value: $val)! Please check your language file!",$this->ilias->error_obj->MESSAGE);
876 }
877 if (!ilStr::isUtf8($separated[2]))
878 {
879 $this->ilias->raiseError("Non UTF8 character found in ".$lang_file." in line $line (Value: $val)! Please check your language file!",$this->ilias->error_obj->MESSAGE);
880 }
881 }
882
883 chdir($tmpPath);
884
885 // no error occured
886 return true;
887 }
888
892 static function countUsers($a_lang)
893 {
894 global $ilDB, $lng;
895
896 $set = $ilDB->query("SELECT COUNT(*) cnt FROM usr_data ud JOIN usr_pref up".
897 " ON ud.usr_id = up.usr_id ".
898 " WHERE up.value = ".$ilDB->quote($a_lang, "text").
899 " AND up.keyword = ".$ilDB->quote("language", "text"));
900 $rec = $ilDB->fetchAssoc($set);
901
902 // add users with no usr_pref set to default language
903 if ($a_lang == $lng->lang_default)
904 {
905 $set2 = $ilDB->query("SELECT COUNT(*) cnt FROM usr_data ud LEFT JOIN usr_pref up".
906 " ON (ud.usr_id = up.usr_id AND up.keyword = ".$ilDB->quote("language", "text").")".
907 " WHERE up.value IS NULL ");
908 $rec2 = $ilDB->fetchAssoc($set2);
909 }
910
911 return (int) $rec["cnt"] + (int) $rec2["cnt"];
912 }
913
914
915} // END class.LanguageObject
916?>
sprintf('%.4f', $callTime)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
$result
$n
Definition: RandomTest.php:80
$path
Definition: aliased.php:25
An exception for terminatinating execution or to throw for unit testing.
Class ilObjLanguage.
static refreshPlugins($a_lang_keys=null)
static _deleteLangData($a_lang_key, $a_keep_local_change=false)
Delete languge data.
static deleteLangEntry($a_module, $a_identifier, $a_lang_key)
Delete lang entry.
static refreshAll()
Refresh all installed languages.
isInstalled()
Check language object status, and return true if language is installed.
uninstall()
uninstall current language
getKey()
get language key
getStatus()
get language status
isLocal()
Check language object status, and return true if a local language file is installed.
static getInstalledLanguages()
Get the language objects of the installed languages.
static countUsers($a_lang)
Count number of users that use a language.
resetUserLanguage($lang_key)
search ILIAS for users which have selected '$lang_key' as their prefered language and reset them to d...
install($scope='')
install current language
isSystemLanguage()
check if language is system language
isUserLanguage()
check if language is system language
flush($a_mode='all')
remove language data from database
static updateLangEntry($a_module, $a_identifier, $a_lang_key, $a_value, $a_local_change=null, $a_remarks=null)
Replace lang entry.
insert($scope='')
insert language data from file into database
static cut_header($content)
remove lang-file haeder information from '$content' This function seeks for a special keyword where t...
__construct($a_id=0, $a_call_by_reference=false)
Constructor.
refresh()
refresh current language
getLocalChanges($a_min_date="", $a_max_date="")
get locally changed language entries
optimizeData()
optimizes the db-table langdata
check($scope='')
Validate the logical structure of a lang file.
static _getLastLocalChange($a_key)
get the date of the last local change
static replaceLangEntry($a_module, $a_identifier, $a_lang_key, $a_value, $a_local_change=null, $a_remarks=null)
Replace lang entry.
Class ilObject Basic functions for all objects.
update()
update object in db
static _getObjectsByType($a_obj_type="", $a_owner="")
Get objects by type.
setTitle($a_title)
set object title
setDescription($a_desc)
set object description
static getAllSlots()
Get all plugin slots.
static getPluginObject($a_ctype, $a_cname, $a_slot_id, $a_pname)
Get plugin object.
static isUtf8($a_str)
Check whether string is utf-8.
$languages
Definition: cssgen2.php:34
for($i=1; $i<=count($kw_cases_sel); $i+=1) $lang
Definition: langwiz.php:349
$ld
Definition: langwiz.php:244
redirection script todo: (a better solution should control the processing via a xml file)
global $ilErr
Definition: raiseError.php:16
global $ilDB
global $DIC