ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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 ilObjLanguage($a_id = 0, $a_call_by_reference = false)
41 {
42 global $lng;
43
44 $this->type = "lng";
45 $this->ilObject($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
62 public static function getInstalledLanguages()
63 {
64 $objects = array();
65 $languages = ilObject::_getObjectsByType("lng");
66 foreach ($languages as $lang)
67 {
68 $langObj = new ilObjLanguage($lang["obj_id"], false);
69 if ($langObj->isInstalled())
70 {
71 $objects[] = $langObj;
72 }
73 else
74 {
75 unset($langObj);
76 }
77 }
78 return $objects;
79 }
80
81
87 function getKey()
88 {
89 return $this->key;
90 }
91
97 function getStatus()
98 {
99 return $this->status;
100 }
101
106 {
107 if ($this->key == $this->lang_default)
108 return true;
109 else
110 return false;
111 }
112
116 function isUserLanguage()
117 {
118 if ($this->key == $this->lang_user)
119 {
120 return true;
121 }
122 else
123 {
124 return false;
125 }
126 }
127
128
134 function isInstalled()
135 {
136 if (substr($this->getStatus(), 0, 9) == "installed")
137 {
138 return true;
139 }
140 else
141 {
142 return false;
143 }
144 }
145
152 function isLocal()
153 {
154 if (substr($this->getStatus(), 10) == "local")
155 {
156 return true;
157 }
158 else
159 {
160 return false;
161 }
162 }
163
170 function install($scope = '')
171 {
172 if (!empty($scope))
173 {
174 if ($scope == 'global')
175 {
176 $scope = '';
177 }
178 else
179 {
180 $scopeExtension = '.' . $scope;
181 }
182 }
183
184 if (($this->isInstalled() == false) ||
185 ($this->isInstalled() == true && $this->isLocal() == false && !empty($scope)))
186 {
187 if ($this->check($scope))
188 {
189 // lang-file is ok. Flush data in db and...
190 if (empty($scope))
191 {
192 $this->flush('keep_local');
193 }
194
195 // ...re-insert data from lang-file
196 $this->insert($scope);
197
198 // update information in db-table about available/installed languages
199 if (empty($scope))
200 {
201 $newDesc = 'installed';
202 }
203 else if ($scope == 'local')
204 {
205 $newDesc = 'installed_local';
206 }
207 $this->setDescription($newDesc);
208 $this->update();
209 $this->optimizeData();
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 $this->optimizeData();
254
255 if ($this->isLocal() == true)
256 {
257 if ($this->check('local'))
258 {
259 $this->insert('local');
260 $this->setTitle($this->getKey());
261 $this->setDescription($this->getStatus());
262 $this->update();
263 $this->optimizeData();
264 }
265 }
266 return true;
267 }
268 }
269 return false;
270 }
271
275 static function refreshAll()
276 {
277 $languages = ilObject::_getObjectsByType("lng");
278 $refreshed = array();
279
280 foreach ($languages as $lang)
281 {
282 $langObj = new ilObjLanguage($lang["obj_id"],false);
283 if ($langObj->refresh())
284 {
285 $refreshed[] = $langObj->getKey();
286 }
287 unset($langObj);
288 }
289
290 self::refreshPlugins($refreshed);
291 }
292
293
298 public static function refreshPlugins($a_lang_keys = null)
299 {
300 global $ilPluginAdmin;
301
302 // refresh languages of activated plugins
303 include_once("./Services/Component/classes/class.ilPluginSlot.php");
304 $slots = ilPluginSlot::getAllSlots();
305 foreach ($slots as $slot)
306 {
307 $act_plugins = $ilPluginAdmin->getActivePluginsForSlot($slot["component_type"],
308 $slot["component_name"], $slot["slot_id"]);
309 foreach ($act_plugins as $plugin)
310 {
311 include_once("./Services/Component/classes/class.ilPlugin.php");
312 $pl = ilPlugin::getPluginObject($slot["component_type"],
313 $slot["component_name"], $slot["slot_id"], $plugin);
314 if (is_object($pl))
315 {
316 $pl->updateLanguages($a_lang_keys);
317 }
318 }
319 }
320 }
321
322
328 static function _deleteLangData($a_lang_key, $a_keep_local_change = false)
329 {
330 global $ilDB;
331 if (!$a_keep_local_change)
332 {
333 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = ".
334 $ilDB->quote($a_lang_key, "text"));
335 }
336 else
337 {
338 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = ".
339 $ilDB->quote($a_lang_key, "text").
340 " AND local_change IS NULL");
341 }
342 }
343
348 function flush($a_mode = 'all')
349 {
350 global $ilDB;
351
352 ilObjLanguage::_deleteLangData($this->key, ($a_mode == 'keep_local'));
353
354 if ($a_mode == 'all')
355 {
356 $ilDB->manipulate("DELETE FROM lng_modules WHERE lang_key = ".
357 $ilDB->quote($this->key, "text"));
358 }
359 }
360
361
368 function getLocalChanges($a_min_date = "", $a_max_date = "")
369 {
370 global $ilDB;
371
372 if ($a_min_date == "")
373 {
374 $a_min_date = "1980-01-01 00:00:00";
375 }
376 if ($a_max_date == "")
377 {
378 $a_max_date = "2200-01-01 00:00:00";
379 }
380
381 $q = sprintf("SELECT * FROM lng_data WHERE lang_key = %s ".
382 "AND local_change >= %s AND local_change <= %s",
383 $ilDB->quote($this->key, "text"), $ilDB->quote($a_min_date, "timestamp"),
384 $ilDB->quote($a_max_date, "timestamp"));
385 $result = $ilDB->query($q);
386
387 $changes = array();
388 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
389 {
390 $changes[$row["module"]][$row["identifier"]] = $row["value"];
391 }
392 return $changes;
393 }
394
395
401 function _getLastLocalChange($a_key)
402 {
403 global $ilDB;
404
405 $q = sprintf("SELECT MAX(local_change) last_change FROM lng_data ".
406 "WHERE lang_key = %s AND local_change IS NOT NULL",
407 $ilDB->quote($a_key, "text"));
408 $result = $ilDB->query($q);
409
410 if ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
411 {
412 return $row['last_change'];
413 }
414 else
415 {
416 return "";
417 }
418 }
419
420
427 static function _getLocalChangesByModule($a_key, $a_module)
428 {
430 global $ilDB;
431
432 $changes = array();
433 $result = $ilDB->queryF("SELECT * FROM lng_data WHERE lang_key = %s AND module = %s AND local_change IS NOT NULL",
434
435 array('text', 'text'),
436 array($a_key, $a_module));
437
438 while ($row = $ilDB->fetchAssoc($result))
439 {
440 $changes[$row['identifier']] = $row['value'];
441 }
442 return $changes;
443 }
444
445
451 function insert($scope = '')
452 {
453 global $ilDB;
454
455 if (!empty($scope))
456 {
457 if ($scope == 'global')
458 {
459 $scope = '';
460 }
461 else
462 {
463 $scopeExtension = '.' . $scope;
464 }
465 }
466
468 if ($scope == "local")
469 {
470 $path = $this->cust_lang_path;
471 }
472
473 $lang_file = $path . "/ilias_" . $this->key . ".lang" . $scopeExtension;
474 if (is_file($lang_file))
475 {
476 // initialize the array for updating lng_modules below
477 $lang_array = array();
478 $lang_array["common"] = array();
479
480 // remove header first
481 if ($content = $this->cut_header(file($lang_file)))
482 {
483 if (empty($scope))
484 {
485 // reset change date for a global file
486 // get all local changes for a global file
487 $change_date = null;
488 $local_changes = $this->getLocalChanges();
489 }
490 else if ($scope == 'local')
491 {
492 // set the change date to import time for a local file
493 // get the modification date of the local file
494 // get the newer local changes for a local file
495 $change_date = date("Y-m-d H:i:s",time());
496 $min_date = date("Y-m-d H:i:s", filemtime($lang_file));
497 $local_changes = $this->getLocalChanges($min_date);
498 }
499
500 foreach ($content as $key => $val)
501 {
502 // split the line of the language file
503 // [0]: module
504 // [1]: identifier
505 // [2]: value
506 // [3]: comment (optional)
507 $separated = explode($this->separator,trim($val));
508 $pos = strpos($separated[2], $this->comment_separator);
509 if ($pos !== false)
510 {
511 $separated[3] = substr($separated[2], $pos + strlen($this->comment_separator));
512 $separated[2] = substr($separated[2] , 0 , $pos);
513 }
514
515 // check if the value has a local change
516 $local_value = $local_changes[$separated[0]][$separated[1]];
517
518 if (empty($scope))
519 {
520 // import of a global language file
521
522 if ($local_value != "" and $local_value != $separated[2])
523 {
524 // keep an existing and different local calue
525 $lang_array[$separated[0]][$separated[1]] = $local_value;
526 }
527 else
528 {
529 // check for double entries in global file
530 if ($double_checker[$separated[0]][$separated[1]][$this->key])
531 {
532 $this->ilias->raiseError("Duplicate Language Entry in $lang_file:\n$val",
533 $this->ilias->error_obj->MESSAGE);
534 }
535 $double_checker[$separated[0]][$separated[1]][$this->key] = true;
536
537 // insert a new value if no local value exists
538 // reset local change date if the values are equal
539 ilObjLanguage::replaceLangEntry($separated[0], $separated[1],
540 $this->key, $separated[2], $change_date, $separated[3]);
541
542 $lang_array[$separated[0]][$separated[1]] = $separated[2];
543 }
544 }
545 else if ($scope == 'local')
546 {
547 // import of a local language file
548
549 if ($local_value != "")
550 {
551 // keep a locally changed value that is newer than the file
552 $lang_array[$separated[0]][$separated[1]] = $local_value;
553 }
554 else
555 {
556 // insert a new value if no global value exists
557 // (local files may have additional entries for customizations)
558 // set the change date to the import date
559 ilObjLanguage::replaceLangEntry($separated[0], $separated[1],
560 $this->key, $separated[2], $change_date, $separated[3]);
561
562 $lang_array[$separated[0]][$separated[1]] = $separated[2];
563 }
564 }
565 }
566
567 $ld = "";
568 if (empty($scope))
569 {
570 $ld = "installed";
571 }
572 else if ($scope == 'local')
573 {
574 $ld = "installed_local";
575 }
576 if ($ld)
577 {
578 $query = "UPDATE object_data SET " .
579 "description = ".$ilDB->quote($ld, "text").", " .
580 "last_update = ".$ilDB->now()." " .
581 "WHERE title = ".$ilDB->quote($this->key, "text")." " .
582 "AND type = 'lng'";
583 $ilDB->manipulate($query);
584 }
585 }
586
587 foreach($lang_array as $module => $lang_arr)
588 {
589 if ($scope == "local")
590 {
591 $q = "SELECT * FROM lng_modules WHERE ".
592 " lang_key = ".$ilDB->quote($this->key, "text").
593 " AND module = ".$ilDB->quote($module, "text");
594 $set = $ilDB->query($q);
595 $row = $ilDB->fetchAssoc($set);
596 $arr2 = unserialize($row["lang_array"]);
597 if (is_array($arr2))
598 {
599 $lang_arr = array_merge($arr2, $lang_arr);
600 }
601 }
602 ilObjLanguage::replaceLangModule($this->key, $module, $lang_arr);
603 }
604 }
605 }
606
610 static final function replaceLangModule($a_key, $a_module, $a_array)
611 {
612 global $ilDB, $ilErr;
613
614 ilGlobalCache::flushAll();
615
616 $ilDB->manipulate(sprintf("DELETE FROM lng_modules WHERE lang_key = %s AND module = %s",
617 $ilDB->quote($a_key, "text"), $ilDB->quote($a_module, "text")));
618
619 /*$ilDB->manipulate(sprintf("INSERT INTO lng_modules (lang_key, module, lang_array) VALUES ".
620 "(%s,%s,%s)", $ilDB->quote($a_key, "text"),
621 $ilDB->quote($a_module, "text"),
622 $ilDB->quote(serialize($a_array), "clob")));*/
623 $ilDB->insert("lng_modules", array(
624 "lang_key" => array("text", $a_key),
625 "module" => array("text", $a_module),
626 "lang_array" => array("clob", serialize((array) $a_array))
627 ));
628
629 // check if the module is correctly saved
630 // see mantis #20046 and #19140
631 $result = $ilDB->queryF("SELECT lang_array FROM lng_modules WHERE lang_key = %s AND module = %s",
632 array('text','text'), array($a_key, $a_module));
633 $row = $ilDB->fetchAssoc($result);
634
635 $unserialied = unserialize($row['lang_array']);
636 if (!is_array($unserialied))
637 {
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 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
801 function optimizeData()
802 {
803 global $ilDB;
804
805 $ilDB->optimizeTable("lng_data");
806 return true;
807 }
808
818 function check($scope = '')
819 {
820 include_once("./Services/Utilities/classes/class.ilStr.php");
821
822 if (!empty($scope))
823 {
824 if ($scope == 'global')
825 {
826 $scope = '';
827 }
828 else
829 {
830 $scopeExtension = '.' . $scope;
831 }
832 }
833
835 if ($scope == "local")
836 {
837 $path = $this->cust_lang_path;
838 }
839
840 $tmpPath = getcwd();
841
842 // dir check
843 if (!is_dir($path))
844 {
845 $this->ilias->raiseError("Directory not found: ".$path, $this->ilias->error_obj->MESSAGE);
846 }
847
848 chdir($path);
849
850 // compute lang-file name format
851 $lang_file = "ilias_" . $this->key . ".lang" . $scopeExtension;
852
853 // file check
854 if (!is_file($lang_file))
855 {
856 $this->ilias->raiseError("File not found: ".$lang_file,$this->ilias->error_obj->MESSAGE);
857 }
858
859 // header check
860 $content = $this->cut_header(file($lang_file));
861 if ($content === false)
862 {
863 $this->ilias->raiseError("Wrong Header in ".$lang_file,$this->ilias->error_obj->MESSAGE);
864 }
865
866 // check (counting) elements of each lang-entry
867 $line = 0;
868 foreach ($content as $key => $val)
869 {
870 $separated = explode($this->separator, trim($val));
871 $num = count($separated);
872 ++$n;
873 if ($num != 3)
874 {
875 $line = $n + 36;
876 $this->ilias->raiseError("Wrong parameter count in ".$lang_file." in line $line (Value: $val)! Please check your language file!",$this->ilias->error_obj->MESSAGE);
877 }
878 if (!ilStr::isUtf8($separated[2]))
879 {
880 $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);
881 }
882 }
883
884 chdir($tmpPath);
885
886 // no error occured
887 return true;
888 }
889
893 static function countUsers($a_lang)
894 {
895 global $ilDB, $lng;
896
897 $set = $ilDB->query("SELECT COUNT(*) cnt FROM usr_data ud JOIN usr_pref up".
898 " ON ud.usr_id = up.usr_id ".
899 " WHERE up.value = ".$ilDB->quote($a_lang, "text").
900 " AND up.keyword = ".$ilDB->quote("language", "text"));
901 $rec = $ilDB->fetchAssoc($set);
902
903 // add users with no usr_pref set to default language
904 if ($a_lang == $lng->lang_default)
905 {
906 $set2 = $ilDB->query("SELECT COUNT(*) cnt FROM usr_data ud LEFT JOIN usr_pref up".
907 " ON (ud.usr_id = up.usr_id AND up.keyword = ".$ilDB->quote("language", "text").")".
908 " WHERE up.value IS NULL ");
909 $rec2 = $ilDB->fetchAssoc($set2);
910 }
911
912 return (int) $rec["cnt"] + (int) $rec2["cnt"];
913 }
914
915
916} // END class.LanguageObject
917?>
$result
$n
Definition: RandomTest.php:80
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
Class ilObjLanguage.
static refreshPlugins($a_lang_keys=null)
static _deleteLangData($a_lang_key, $a_keep_local_change=false)
Delete languge data.
ilObjLanguage($a_id=0, $a_call_by_reference=false)
Constructor.
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
cut_header($content)
remove lang-file haeder information from '$content' This function seeks for a special keyword where t...
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.
_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
ilObject($a_id=0, $a_reference=true)
Constructor @access public.
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.
redirection script todo: (a better solution should control the processing via a xml file)
$path
Definition: index.php:22
global $ilDB