1<?php
2  /**************************************************************************\
3  * phpGroupWare - Translation Editor                                        *
4  * http://www.phpgroupware.org                                              *
5  * --------------------------------------------                             *
6  *  This program is free software; you can redistribute it and/or modify it *
7  *  under the terms of the GNU General Public License as published by the   *
8  *  Free Software Foundation; either version 2 of the License, or (at your  *
9  *  option) any later version.                                              *
10  \**************************************************************************/
11
12  /* $Id: class.solangfile.inc.php 16054 2005-08-12 13:50:23Z skwashd $ */
13
14	class solangfile
15	{
16		var $total;
17		var $debug = False;
18
19		var $langarray;   // Currently loaded translations
20		// array of missing phrases.
21		var $missingarray;
22		var $src_file;
23		var $tgt_file;
24		var $loaded_apps = array(); // Loaded app langs
25
26		var $functions = array(		// functions containing phrases to translate and param#
27			'lang'                => array(1),
28			'create_input_box'    => array(1,3),
29			'create_check_box'    => array(1,3),
30			'create_select_box'   => array(1,4),
31			'create_text_area'    => array(1,5),
32			'create_notify'       => array(1,5),
33			'create_password_box' => array(1,3)
34		);
35		var $files = array(
36			'config.tpl' => 'config',
37			'hook_admin.inc.php' => 'file_admin',
38			'hook_preferences.inc.php' => 'file_preferences',
39			'hook_sidebox_menu.inc.php' => 'file',
40			'hook_acl_manager.inc.php' => 'acl_manager'
41		);
42
43		var $public_functions = array(
44			'index' => True
45		);
46
47		function solangfile()
48		{
49			$this->db = $GLOBALS['phpgw']->db;
50		}
51
52		function fetch_keys($app,$arr)
53		{
54			if (!is_array($arr))
55			{
56				return;
57			}
58			foreach($arr as $key => $val)
59			{
60				$this->plist[$key] = $app;
61			}
62		}
63
64		function config_file($app,$fname)
65		{
66			//echo "<p>solangfile::config_file(app='$app',fname='$fname')</p>\n";
67			$lines = file($fname);
68
69			if ($app != 'setup')
70			{
71				$app = 'admin';
72			}
73			foreach($lines as $n => $line)
74			{
75				while (ereg('\{lang_([^}]+)\}(.*)',$line,$found))
76				{
77					$lang = str_replace('_',' ',$found[1]);
78					$this->plist[$lang] = $app;
79
80					$line = $found[2];
81				}
82			}
83		}
84
85		function special_file($app,$fname,$langs_in)
86		{
87			//echo "<p>solangfile::special_file(app='$app',fname='$fname',langs_in='$langs_in')</p>\n";
88			switch ($langs_in)
89			{
90			 	case 'config':
91					$this->config_file($app,$fname);
92					return;
93				case 'file_admin':
94				case 'file_preferences':
95					$app = substr($langs_in,5);
96					break;
97				case 'phpgwapi':
98					$app = 'common';
99					break;
100			}
101			if (!function_exists('display_sidebox'))
102			{
103				function display_sidebox($appname,$menu_title,$file)	// hook_sidebox_menu
104				{
105					unset($file['_NewLine_']);
106					$GLOBALS['file'] += $file;
107				}
108				function display_section($appname,$file,$file2='')		// hook_preferences, hook_admin
109				{
110					if (is_array($file2))
111					{
112						$file = $file2;
113					}
114					$GLOBALS['file'] += $file;
115				}
116			}
117			$GLOBALS['file'] = array();
118			unset($GLOBALS['acl_manager']);
119			include($fname);
120
121			if (isset($GLOBALS['acl_manager']))	// hook_acl_manager
122			{
123				foreach($GLOBALS['acl_manager'] as $app => $data)
124				{
125					foreach ($data as $item => $arr)
126					{
127						foreach ($arr as $key => $val)
128						{
129							switch ($key)
130							{
131								case 'name':
132									$this->plist[$val] = $app;
133									break;
134								case 'rights':
135									foreach($val as $lang => $right)
136									{
137										$this->plist[$lang] = $app;
138									}
139									break;
140							}
141						}
142					}
143				}
144			}
145			if (count($GLOBALS['file']))	// hook_{admin|preferences|sidebox_menu}
146			{
147				foreach ($GLOBALS['file'] as $lang => $link)
148				{
149					$this->plist[$lang] = $app;
150				}
151			}
152		}
153
154		function parse_php_app($app,$fd)
155		{
156			$reg_expr = '('.implode('|',array_keys($this->functions)).")[ \t]*\([ \t]*(.*)$";
157			define('SEP',filesystem_separator());
158			$d=dir($fd);
159			while ($fn=$d->read())
160			{
161				if (@is_dir($fd.$fn.SEP))
162				{
163					if ( ($fn!='.')&&($fn!='..') && ($fn!='CVS') && ($fn!='.svn') )
164					{
165						$this->parse_php_app($app,$fd.$fn.SEP);
166					}
167				}
168				elseif (is_readable($fd.$fn))
169				{
170					if (isset($this->files[$fn]))
171					{
172						$this->special_file($app,$fd.$fn,$this->files[$fn]);
173					}
174					if (strpos($fn,'.php') === False)
175					{
176						continue;
177					}
178					$lines = file($fd.$fn);
179
180					foreach($lines as $n => $line)
181					{
182						//echo "line='$line', lines[1+$n]='".$lines[1+$n]."'<br>\n";
183						while (eregi($reg_expr,$line,$parts))
184						{
185							//echo "***func='$parts[1]', rest='$parts[2]'<br>\n";
186							$args = $this->functions[$parts[1]];
187							$rest = $parts[2];
188							for($i = 1; $i <= $args[0]; ++$i)
189							{
190								$next = 1;
191								if (!$rest || strpos($rest,$del,1) === False)
192								{
193									$rest .= trim($lines[++$n]);
194								}
195								$del = $rest[0];
196								if ($del == '"' || $del == "'")
197								{
198									//echo "rest='$rest'<br>\n";
199									while (($next = strpos($rest,$del,$next)) !== False && $rest[$next-1] == '\\')
200									{
201										$rest = substr($rest,0,$next-1).substr($rest,$next);
202									}
203									if ($next === False)
204									{
205										break;
206									}
207									$phrase = str_replace('\\\\','\\',substr($rest,1,$next-1));
208									//echo "next2=$next, phrase='$phrase'<br>\n";
209									if ($args[0] == $i)
210									{
211										//if (!isset($this->plist[$phrase])) echo ">>>$phrase<<<<br>\n";
212										$this->plist[$phrase] = $app;
213										array_shift($args);
214										if (!count($args))
215										{
216											break;	// no more args needed
217										}
218									}
219									$rest = substr($rest,$next+1);
220								}
221								if(!ereg("[ \t\n]*,[ \t\n]*(.*)$",$rest,$parts))
222								{
223									break;	// nothing found
224								}
225								$rest = $parts[1];
226							}
227							$line = $rest;
228						}
229					}
230				}
231			}
232			$d->close();
233		}
234
235		function missing_app($app,$userlang=en)
236		{
237			$cur_lang=$this->load_app($app,$userlang);
238			define('SEP',filesystem_separator());
239			$fd = PHPGW_SERVER_ROOT . SEP . $app . SEP;
240			$this->plist = array();
241			$this->parse_php_app($app == 'phpgwapi' ? 'common' : $app,$fd);
242
243			reset($this->plist);
244			return($this->plist);
245		}
246
247		/*!
248		@function add_app
249		@abstract loads all app phrases into langarray
250		@param $lang	user lang variable (defaults to en)
251		*/
252		function add_app($app,$userlang='en')
253		{
254			define('SEP',filesystem_separator());
255
256			$fd = PHPGW_SERVER_ROOT . SEP . $app . SEP . ($app == 'setup' ? 'lang' : 'setup');
257			$fn = $fd . SEP . 'phpgw_' . $userlang . '.lang';
258			if (@is_writeable($fn) || is_writeable($fd))
259			{
260				$wr = True;
261			}
262			$this->src_apps = array($app => $app);
263
264			if (file_exists($fn))
265			{
266				$this->src_file = $fn;
267				$fp = fopen($fn,'rb');
268				while ($data = fgets($fp,8000))
269				{
270					list($message_id,$app_name,$null,$content) = explode("\t",$data);
271					if(!$message_id)
272					{
273						continue;
274					}
275					//echo '<br>add_app(): adding phrase: $this->langarray["'.$message_id.'"]=' . trim($content);
276					$_mess_id = strtolower(trim($message_id));
277					$app_name = trim($app_name);
278					$this->langarray[$_mess_id]['message_id'] = $_mess_id;
279					$this->langarray[$_mess_id]['app_name']   = $app_name;
280					$this->langarray[$_mess_id]['content']    = trim($content);
281					$this->src_apps[$app_name] = $app_name;
282				}
283				fclose($fp);
284			}
285			else
286			{
287				$this->src_file = lang('no file');
288			}
289			// stuff class array listing apps that are included already
290			$this->loaded_apps[$userlang]['filename']  = $fn;
291			$this->loaded_apps[$userlang]['writeable'] = $wr;
292
293			if($this->debug) { _debug_array($this->langarray); }
294			@ksort($this->langarray);
295			return $this->langarray;
296		}
297
298		/*!
299		@function load_app
300		@abstract loads all app phrases into langarray
301		@param $lang user lang variable (defaults to en)
302		*/
303		function load_app($app,$userlang='en')
304		{
305			define('SEP',filesystem_separator());
306
307			$langarray = array();
308			$fd = PHPGW_SERVER_ROOT . SEP . $app . SEP . ($app == 'setup' ? 'lang' : 'setup');
309			$fn = $fd . SEP . 'phpgw_' . $userlang . '.lang';
310			if (@is_writeable($fn) || is_writeable($fd))
311			{
312				$wr = True;
313			}
314
315			if (file_exists($fn))
316			{
317				$this->tgt_file = $fn;
318				if ($fp = @fopen($fn,'rb'))
319				{
320				   while ($data = fgets($fp,8000))
321				   {
322					   list($message_id,$app_name,$null,$content) = explode("\t",$data);
323					   if(!$message_id)
324					   {
325						   continue;
326					   }
327					   //echo '<br>add_app(): adding phrase: $this->langarray["'.$message_id.'"]=' . trim($content);
328					   $_mess_id = strtolower(trim($message_id));
329					   $langarray[$_mess_id]['message_id'] = $_mess_id;
330					   $langarray[$_mess_id]['app_name']   = trim($app_name);
331					   $langarray[$_mess_id]['content']    = trim($content);
332				   }
333				   fclose($fp);
334				}
335			}
336			else
337			{
338				$this->tgt_file = lang('no file');
339			}
340			// stuff class array listing apps that are included already
341			$this->loaded_apps[$userlang]['filename']  = $fn;
342			$this->loaded_apps[$userlang]['writeable'] = $wr;
343			if($this->debug) { _debug_array($langarray); }
344			@ksort($langarray);
345			return $langarray;
346		}
347
348		function list_langs()
349		{
350			$this->db->query("SELECT DISTINCT lang FROM phpgw_lang");
351			while($this->db->next_record())
352			{
353				$lang = $this->db->f('lang');
354				$installed[] = $lang;
355			}
356			$installed = "('".implode("','",$installed)."')";
357
358			// this shows first the installed, then the available and then the rest
359			$this->db->query("SELECT lang_id,lang_name,lang_id IN $installed as installed FROM phpgw_languages ORDER BY installed DESC,available DESC,lang_name");
360			$i = 0;
361			while ($this->db->next_record())
362			{
363				$languages[$i]['lang_id']   = $this->db->f('lang_id');
364				$languages[$i]['lang_name'] = $this->db->f('lang_name');
365				$i++;
366			}
367			@reset($languages);
368			if($this->debug) { _debug_array($languages); }
369			return $languages;
370		}
371
372		function write_file($app_name,$langarray,$userlang)
373		{
374			$fn = PHPGW_SERVER_ROOT . SEP . $app_name . SEP . ($app_name == 'setup' ? 'lang' : 'setup') . SEP . 'phpgw_' . $userlang . '.lang';
375			if (file_exists($fn))
376			{
377				$backup = $fn . '.old';
378				@unlink($backup);
379				@rename($fn,$backup);
380			}
381			$fp = fopen($fn,'wb');
382			while(list($mess_id,$data) = @each($langarray))
383			{
384				fwrite($fp,$mess_id . "\t" . $data['app_name'] . "\t" . $userlang . "\t" . $data['content'] . "\n");
385			}
386			fclose($fp);
387			return;
388		}
389
390		function loaddb($app_name,$userlang)
391		{
392			$langarray = $this->load_app($app_name,$userlang);
393			if (!is_array($langarray))
394			{
395				return False;
396			}
397
398			$this->db->transaction_begin();
399
400			$userlang = $this->db->db_addslashes($userlang);
401			foreach($langarray as $x => $data)
402			{
403				$message_id = $this->db->db_addslashes(trim(substr($data['message_id'],0,MAX_MESSAGE_ID_LENGTH)));
404				$app = $this->db->db_addslashes($data['app_name']);
405				$content = $this->db->db_addslashes($data['content']);
406
407				$addit = False;
408				/*echo '<br><br><pre> checking ' . $data['message_id'] . "\t" . $data['app_name'] . "\t" . $userlang . "\t" . $data['content'];*/
409				$this->db->query("SELECT COUNT(*) FROM phpgw_lang"
410					."  WHERE message_id='$message_id' AND lang='$userlang' AND app_name='$app'",__LINE__,__FILE__);
411				$this->db->next_record();
412
413				if ($this->db->f(0) == 0)
414				{
415					$addit = True;
416					/* echo '... no</pre>'; */
417				}
418				else
419				{
420					/* echo '... yes</pre>'; */
421				}
422
423				if ($addit)
424				{
425					if($data['message_id'] && $data['content'])
426					{
427						/* echo "<br>adding - insert into lang values ('" . $data['message_id'] . "','$app_name','$userlang','" . $data['content'] . "')"; */
428						$this->db->query("INSERT into phpgw_lang VALUES ('$message_id','$app','$userlang','$content')",__LINE__,__FILE__);
429					}
430				}
431				else
432				{
433					if($data['message_id'] && $data['content'])
434					{
435						$this->db->query("UPDATE phpgw_lang SET content='$content'"
436							. " WHERE message_id='$message_id'"
437							. " AND app_name='$app' AND lang='$userlang'",__LINE__,__FILE__);
438						if ($this->db->affected_rows() > 0)
439						{
440/*
441							echo "<br>changing - update lang set content='". $data['content'] . "'"
442								. " where message_id='" . $data['message_id'] ."'"
443								. " and app_name='$app_name' and lang='$userlang'";
444*/
445						}
446					}
447				}
448			}
449			$this->db->transaction_commit();
450			return lang('done');
451		}
452	}
453?>
454