ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilLanguage.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 
44 class ilLanguage
45 {
51  var $text = array();
52 
59  var $lang_default = "en";
60 
68  var $lang_path;
69 
75  var $lang_key;
76 
82  var $separator = "#:#";
83 
89  var $comment_separator = "###";
90 
100  function ilLanguage($a_lang_key)
101  {
102  $this->lang_key = ($a_lang_key) ? $a_lang_key : $this->lang_default;
103  $this->lang_path = ILIAS_ABSOLUTE_PATH."/lang";
104  $this->cust_lang_path = ILIAS_ABSOLUTE_PATH."/Customizing/global/lang";
105 
106  // set lang file...
107  $txt = file($this->lang_path."/setup_lang_sel_multi.lang");
108 
109  // ...and load langdata
110  if (is_array($txt))
111  {
112  foreach ($txt as $row)
113  {
114  if ($row[0] != "#")
115  {
116  $a = explode($this->separator,trim($row));
117  $this->text[trim($a[0])] = trim($a[1]);
118  }
119  }
120  }
121 
122  // set lang file...
123  $txt = file($this->lang_path."/setup_".$this->lang_key.".lang");
124 
125  // ...and load langdata
126  if (is_array($txt))
127  {
128  foreach ($txt as $row)
129  {
130  if ($row[0] != "#")
131  {
132  $a = explode($this->separator,trim($row));
133  $this->text[trim($a[0])] = trim($a[1]);
134  }
135  }
136 
137  return true;
138  }
139 
140  return false;
141  }
142 
151  function txt($a_topic)
152  {
153  global $log;
154 
155  if (empty($a_topic))
156  {
157  return "";
158  }
159 
160  $translation = $this->text[$a_topic];
161 
162  //get position of the comment_separator
163  $pos = strpos($translation, $this->comment_separator);
164 
165  if ($pos !== false)
166  {
167  // remove comment
168  $translation = substr($translation,0,$pos);
169  }
170 
171  if ($translation == "")
172  {
173  $log->writeLanguageLog($a_topic,$this->lang_key);
174  return "-".$a_topic."-";
175  }
176  else
177  {
178  return $translation;
179  }
180  }
181 
189  function getLanguages()
190  {
191  $d = dir($this->lang_path);
192  $tmpPath = getcwd();
193  chdir ($this->lang_path);
194 
195  // get available setup-files
196  while ($entry = $d->read())
197  {
198  if (is_file($entry) && (ereg ("(^setup_.{2}\.lang$)", $entry)))
199  {
200  $lang_key = substr($entry,6,2);
201  $languages[] = $lang_key;
202  }
203  }
204 
205  chdir($tmpPath);
206 
207  return $languages;
208  }
209 
216  function installLanguages($a_lang_keys, $a_local_keys)
217  {
218  global $ilDB;
219 
220  if (empty($a_lang_keys))
221  {
222  $a_lang_keys = array();
223  }
224 
225  if (empty($a_local_keys))
226  {
227  $a_local_keys = array();
228  }
229 
230  $err_lang = array();
231 
232  $db_langs = $this->getAvailableLanguages();
233 
234  foreach ($a_lang_keys as $lang_key)
235  {
236  if ($this->checkLanguage($lang_key))
237  {
238  $this->flushLanguage($lang_key, 'keep_local');
239  $this->insertLanguage($lang_key);
240 
241  if (in_array($lang_key, $a_local_keys))
242  {
243  if ($this->checkLanguage($lang_key, "local"))
244  {
245  $this->insertLanguage($lang_key, "local");
246  }
247  else
248  {
249  $err_lang[] = $lang_key;
250  }
251  }
252 
253  // register language first time install
254  if (!array_key_exists($lang_key,$db_langs))
255  {
256  if (in_array($lang_key, $a_local_keys))
257  {
258  $itype = 'installed_local';
259  }
260  else
261  {
262  $itype = 'installed';
263  }
264  $lid = $ilDB->nextId("object_data");
265  $query = "INSERT INTO object_data ".
266  "(obj_id,type,title,description,owner,create_date,last_update) ".
267  "VALUES ".
268  "(".
269  $ilDB->quote($lid, "integer").",".
270  $ilDB->quote("lng", "text").",".
271  $ilDB->quote($lang_key, "text").",".
272  $ilDB->quote($itype, "text").",".
273  $ilDB->quote('-1',"integer").",".
274  $ilDB->now().",".
275  $ilDB->now().
276  ")";
277  $this->db->manipulate($query);
278  }
279  }
280  else
281  {
282  $err_lang[] = $lang_key;
283  }
284  }
285 
286  foreach ($db_langs as $key => $val)
287  {
288  if (!in_array($key,$err_lang))
289  {
290  if (in_array($key,$a_lang_keys))
291  {
292  if (in_array($key, $a_local_keys))
293  {
294  $ld = 'installed_local';
295  }
296  else
297  {
298  $ld = 'installed';
299  }
300  $query = "UPDATE object_data SET " .
301  "description = ".$ilDB->quote($ld, "text").", " .
302  "last_update = ".$ilDB->now()." " .
303  "WHERE obj_id = ".$ilDB->quote($val["obj_id"], "integer")." " .
304  "AND type = ".$ilDB->quote("lng", "text");
305  $ilDB->manipulate($query);
306  }
307  else
308  {
309  $this->flushLanguage($key, "all");
310 
311  if (substr($val["status"], 0, 9) == "installed")
312  {
313  $query = "UPDATE object_data SET " .
314  "description = ".$ilDB->quote("not_installed", "text").", " .
315  "last_update = ".$ilDB->now()." " .
316  "WHERE obj_id = ".$ilDB->quote($val["obj_id"], "integer")." " .
317  "AND type = ".$ilDB->quote("lng", "text");
318  $ilDB->manipulate($query);
319  }
320  }
321  }
322  }
323 
324  return ($err_lang) ? $err_lang : true;
325  }
326 
327 
328 
335  {
336  global $ilDB;
337 
338  $arr = array();
339 
340  $query = "SELECT * FROM object_data ".
341  "WHERE type = ".$ilDB->quote("lng", "text")." ".
342  "AND ".$ilDB->like("description", "text", 'installed%');
343  $r = $ilDB->query($query);
344 
345  while ($row = $ilDB->fetchObject($r))
346  {
347  $arr[] = $row->title;
348  }
349 
350  return $arr;
351  }
352 
359  {
360  global $ilDB;
361 
362  $arr = array();
363 
364  $query = "SELECT * FROM object_data ".
365  "WHERE type = ".$ilDB->quote("lng", "text")." ".
366  "AND description = ".$ilDB->quote('installed_local', "text");
367  $r = $ilDB->query($query);
368 
369  while ($row = $ilDB->fetchObject($r))
370  {
371  $arr[] = $row->title;
372  }
373 
374  return $arr;
375  }
376 
382  {
383  global $ilDB;
384 
385  $arr = array();
386 
387  $query = "SELECT * FROM object_data ".
388  "WHERE type = ".$ilDB->quote("lng", "text");
389  $r = $ilDB->query($query);
390 
391  while ($row = $ilDB->fetchObject($r))
392  {
393  $arr[$row->title]["obj_id"] = $row->obj_id;
394  $arr[$row->title]["status"] = $row->description;
395  }
396 
397  return $arr;
398  }
399 
411  function checkLanguage($a_lang_key, $scope = '')
412  {
413  if (!empty($scope))
414  {
415  if ($scope == 'global')
416  {
417  $scope = '';
418  }
419  else
420  {
421  $scopeExtension = '.' . $scope;
422  }
423  }
424 
426  if ($scope == "local")
427  {
428  $path = $this->cust_lang_path;
429  }
430 
431  $tmpPath = getcwd();
432  chdir($path);
433 
434  // compute lang-file name format
435  $lang_file = "ilias_" . $a_lang_key . ".lang" . $scopeExtension;
436 
437  // file check
438  if (!is_file($lang_file))
439  {
440  chdir($tmpPath);
441  return false;
442  }
443 
444  // header check
445  if (!$content = $this->cut_header(file($lang_file)))
446  {
447  chdir($tmpPath);
448  return false;
449  }
450 
451  // check (counting) elements of each lang-entry
452  foreach ($content as $key => $val)
453  {
454  $separated = explode($this->separator, trim($val));
455  $num = count($separated);
456 
457  if ($num != 3)
458  {
459  chdir($tmpPath);
460  return false;
461  }
462  }
463 
464  chdir($tmpPath);
465 
466  // no error occured
467  return true;
468  }
469 
480  function cut_header($content)
481  {
482  foreach ($content as $key => $val)
483  {
484  if (trim($val) == "<!-- language file start -->")
485  {
486  return array_slice($content,$key +1);
487  }
488  }
489 
490  return false;
491  }
492 
493 
499  function flushLanguage($a_lang_key, $a_mode = 'all')
500  {
501  $ilDB = $this->db;
502 
503  ilLanguage::_deleteLangData($a_lang_key, ($a_mode == 'keep_local'));
504 
505  if ($a_mode == 'all')
506  {
507  $ilDB->manipulate("DELETE FROM lng_modules WHERE lang_key = ".
508  $ilDB->quote($a_lang_key, "text"));
509  }
510  }
511 
517  static function _deleteLangData($a_lang_key, $a_keep_local_change)
518  {
519  global $ilDB;
520 
521  if (!$a_keep_local_change)
522  {
523  $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = ".
524  $ilDB->quote($a_lang_key, "text"));
525  }
526  else
527  {
528  $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = ".
529  $ilDB->quote($a_lang_key, "text").
530  " AND local_change IS NULL");
531  }
532  }
533 
541  function getLocalChanges($a_lang_key, $a_min_date = "", $a_max_date = "")
542  {
543  $ilDB = $this->db;
544 
545  if ($a_min_date == "")
546  {
547  $a_min_date = "1980-01-01 00:00:00";
548  }
549  if ($a_max_date == "")
550  {
551  $a_max_date = "2200-01-01 00:00:00";
552  }
553 
554  $q = sprintf("SELECT * FROM lng_data WHERE lang_key = %s ".
555  "AND local_change >= %s AND local_change <= %s",
556  $ilDB->quote($a_lang_key, "text"), $ilDB->quote($a_min_date, "timestamp"),
557  $ilDB->quote($a_max_date, "timestamp"));
558  $result = $ilDB->query($q);
559 
560  $changes = array();
561  while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
562  {
563  $changes[$row["module"]][$row["identifier"]] = $row["value"];
564  }
565  return $changes;
566  }
567 
568 
569  //TODO: remove redundant checks here!
577  function insertLanguage($lang_key, $scope = '')
578  {
579  $ilDB =& $this->db;
580 
581  $lang_array = array();
582 
583  if (!empty($scope))
584  {
585  if ($scope == 'global')
586  {
587  $scope = '';
588  }
589  else
590  {
591  $scopeExtension = '.' . $scope;
592  }
593  }
594 
596  if ($scope == "local")
597  {
598  $path = $this->cust_lang_path;
599  }
600 
601  $tmpPath = getcwd();
602  chdir($path);
603 
604  $lang_file = "ilias_" . $lang_key . ".lang" . $scopeExtension;
605 
606  if ($lang_file)
607  {
608  // initialize the array for updating lng_modules below
609  $lang_array = array();
610  $lang_array["common"] = array();
611 
612  // remove header first
613  if ($content = $this->cut_header(file($lang_file)))
614  {
615  // get the local changes from the database
616  if (empty($scope))
617  {
618  $local_changes = $this->getLocalChanges($lang_key);
619  }
620  else if ($scope == 'local')
621  {
622  $change_date = date("Y-m-d H:i:s",time());
623  $min_date = date("Y-m-d H:i:s", filemtime($lang_file));
624  $local_changes = $this->getLocalChanges($lang_key, $min_date);
625  }
626 
627  foreach ($content as $key => $val)
628  {
629  $separated = explode($this->separator,trim($val));
630 
631  //get position of the comment_separator
632  $pos = strpos($separated[2], $this->comment_separator);
633 
634  if ($pos !== false)
635  {
636  //cut comment of
637  $separated[2] = substr($separated[2] , 0 , $pos);
638  }
639 
640  // check if the value has a local change
641  $local_value = $local_changes[$separated[0]][$separated[1]];
642 
643  if (empty($scope))
644  {
645  if ($local_value != "" and $local_value != $separated[2])
646  {
647  // keep the locally changed value
648  $lang_array[$separated[0]][$separated[1]] = $local_value;
649  }
650  else
651  {
652  // insert a new value if no local value exists
653  // reset local_change if the values are equal
654  ilLanguage::replaceLangEntry($separated[0], $separated[1],
655  $lang_key, $separated[2]);
656 
657  $lang_array[$separated[0]][$separated[1]] = $separated[2];
658  }
659  }
660  else if ($scope == 'local')
661  {
662  if ($local_value != "")
663  {
664  // keep a locally changed value that is newer than the local file
665  $lang_array[$separated[0]][$separated[1]] = $local_value;
666  }
667  else
668  {
669  // UPDATE because the global values have already been INSERTed
670  ilLanguage::updateLangEntry($separated[0], $separated[1],
671  $lang_key, $separated[2], $change_date);
672  $lang_array[$separated[0]][$separated[1]] = $separated[2];
673  }
674  }
675  }
676  }
677 
678  foreach($lang_array as $module => $lang_arr)
679  {
680  if ($scope == "local")
681  {
682  $q = "SELECT * FROM lng_modules WHERE ".
683  " lang_key = ".$ilDB->quote($this->key, "text").
684  " AND module = ".$ilDB->quote($module, "text");
685  $set = $ilDB->query($q);
686  $row = $ilDB->fetchAssoc($set);
687  $arr2 = unserialize($row["lang_array"]);
688  if (is_array($arr2))
689  {
690  $lang_arr = array_merge($arr2, $lang_arr);
691  }
692  }
693  ilLanguage::replaceLangModule($lang_key, $module, $lang_arr);
694  }
695  }
696 
697  chdir($tmpPath);
698  }
699 
703  static final function replaceLangModule($a_key, $a_module, $a_array)
704  {
705  global $ilDB;
706 
707  $ilDB->manipulate(sprintf("DELETE FROM lng_modules WHERE lang_key = %s AND module = %s",
708  $ilDB->quote($a_key, "text"), $ilDB->quote($a_module, "text")));
709  /*$ilDB->manipulate(sprintf("INSERT INTO lng_modules (lang_key, module, lang_array) VALUES ".
710  "(%s,%s,%s)", $ilDB->quote($a_key, "text"),
711  $ilDB->quote($a_module, "text"),
712  $ilDB->quote(serialize($a_array), "clob")));*/
713  $ilDB->insert("lng_modules", array(
714  "lang_key" => array("text", $a_key),
715  "module" => array("text", $a_module),
716  "lang_array" => array("clob", serialize($a_array))
717  ));
718  }
719 
723  static final function replaceLangEntry($a_module, $a_identifier,
724  $a_lang_key, $a_value, $a_local_change = null)
725  {
726  global $ilDB;
727 
728  $ilDB->manipulate(sprintf("DELETE FROM lng_data WHERE module = %s AND ".
729  "identifier = %s AND lang_key = %s",
730  $ilDB->quote($a_module, "text"), $ilDB->quote($a_identifier, "text"),
731  $ilDB->quote($a_lang_key, "text")));
732 
733  // insert a new value if no local value exists
734  // reset local_change if the values are equal
735  $ilDB->manipulate(sprintf("INSERT INTO lng_data " .
736  "(module, identifier, lang_key, value, local_change) " .
737  "VALUES (%s,%s,%s,%s,%s)",
738  $ilDB->quote($a_module, "text"), $ilDB->quote($a_identifier, "text"),
739  $ilDB->quote($a_lang_key, "text"), $ilDB->quote($a_value, "text"),
740  $ilDB->quote($a_local_change, "timestamp")));
741  }
742 
746  static final function updateLangEntry($a_module, $a_identifier,
747  $a_lang_key, $a_value, $a_local_change = null)
748  {
749  global $ilDB;
750 
751  $ilDB->manipulate(sprintf("UPDATE lng_data " .
752  "SET value = %s, local_change = %s ".
753  "WHERE module = %s AND identifier = %s AND lang_key = %s ",
754  $ilDB->quote($a_value, "text"), $ilDB->quote($a_local_change, "timestamp"),
755  $ilDB->quote($a_module, "text"), $ilDB->quote($a_identifier, "text"),
756  $ilDB->quote($a_lang_key, "text")));
757  }
758 
764  function getLocalLanguages()
765  {
766  $local_langs = array();
767  if (is_dir($this->cust_lang_path))
768  {
769  $d = dir($this->cust_lang_path);
770  $tmpPath = getcwd();
771  chdir ($this->cust_lang_path);
772 
773  // get available .lang.local files
774  while ($entry = $d->read())
775  {
776  if (is_file($entry) && (ereg ("(^ilias_.{2}\.lang.local$)", $entry)))
777  {
778  $lang_key = substr($entry,6,2);
779  $local_langs[] = $lang_key;
780  }
781  }
782 
783  chdir($tmpPath);
784  }
785 
786  return $local_langs;
787  }
788 
790  {
791  $setup_langs = $this->getLanguages();
792 
793  $d = dir($this->lang_path);
794  $tmpPath = getcwd();
795  chdir ($this->lang_path);
796 
797  // get available lang-files
798  while ($entry = $d->read())
799  {
800  if (is_file($entry) && (ereg ("(^ilias_.{2}\.lang$)", $entry)))
801  {
802  $lang_key = substr($entry,6,2);
803  $languages1[] = $lang_key;
804  }
805  }
806 
807  //$languages = array_intersect($languages1,$setup_langs);
808 
809  chdir($tmpPath);
810 
811  return $languages1;
812  }
813 
819  function setDbHandler($a_db_handler)
820  {
821  if (empty($a_db_handler) or !is_object($a_db_handler))
822  {
823  return false;
824  }
825 
826  $this->db =& $a_db_handler;
827 
828  return true;
829  }
830 
832  {
833  }
834 } // END class.ilLanguage
835 ?>