made a copy
[atutor.git] / include / classes / Language / LanguageEditor.class.php
1 <?php
2 /************************************************************************/
3 /* ATutor                                                                                                                               */
4 /************************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
6 /* Adaptive Technology Resource Centre / University of Toronto                  */
7 /* http://atutor.ca                                                                                                             */
8 /*                                                                                                                                              */
9 /* This program is free software. You can redistribute it and/or                */
10 /* modify it under the terms of the GNU General Public License                  */
11 /* as published by the Free Software Foundation.                                                */
12 /************************************************************************/
13 // $Id$
14
15 /**
16 * LanguageEditor
17 * Class for adding/editing language.
18 * @access       public
19 * @author       Heidi Hazelton
20 * @author       Joel Kronenberg
21 * @package      Language
22 */
23 class LanguageEditor extends Language {
24
25         var $addslashes;
26
27         // array of missing terms
28         var $missingTerms;
29
30         // array of filters ['new', 'update']
31         var $filters;
32         
33         /**
34         * Constructor.
35         * 
36         * Initializes db and parent properties.
37         */
38         function LanguageEditor($myLang) {
39                 global $db, $addslashes, $msg;
40                 
41                 global $savant;
42                 $this->msg = $msg;
43
44                 $this->addslashes = $addslashes;
45
46                 if (isset($myLang)) {
47                         $this->Language($myLang);
48                 }
49                 $this->missingTerms = array();
50         }
51
52         /**
53         * Inserts a new language def'n into the database.
54         * @access       public
55         * @param        array $row              The language def'n fields as an assoc array.
56         * @return       boolean                 Returns TRUE if the def'n was inserted correctly, 
57         *                                                       or FALSE, otherwise.
58         * call staticly only!
59         */
60     function addLanguage($row, $db) {
61                 global $addslashes;
62                 global $msg;
63                 
64                 $row['code']         = trim($row['code']);
65                 $row['locale']       = trim($row['locale']);
66                 $row['charset']      = trim($row['charset']);
67                 $row['reg_exp']      = trim($row['reg_exp']);
68                 $row['native_name']  = trim($row['native_name']);
69                 $row['english_name'] = trim($row['english_name']);
70
71                 $missing_fields = array();
72
73                 if ($row['code'] == '') {
74                         $missing_fields[] = _AT('lang_code');
75                 }
76                 if ($row['charset'] == '') {
77                         $missing_fields[] = _AT('charset');
78                 }
79                 if ($row['reg_exp'] == '') {
80                         $missing_fields[] = _AT('reg_exp');
81                 }
82                 if ($row['native_name'] == '') {
83                         $missing_fields[] = _AT('name_in_language');
84                 }
85                 if ($row['english_name'] == '') {
86                         $missing_fields[] = _AT('name_in_english');
87                 }
88                 
89                 if ($missing_fields) {
90                         $missing_fields = implode(', ', $missing_fields);
91                         $msg->addError(array('EMPTY_FIELDS', $missing_fields));
92                 }
93
94                 if (!$msg->containsErrors()) {
95                         $row['code']         = $addslashes($row['code']);
96                         $row['locale']       = $addslashes($row['locale']);
97                         $row['charset']      = $addslashes($row['charset']);
98                         $row['direction']    = $addslashes($row['direction']);
99                         $row['reg_exp']      = $addslashes($row['reg_exp']);
100                         $row['native_name']  = $addslashes($row['native_name']);
101                         $row['english_name'] = $addslashes($row['english_name']);
102
103                         if (!empty($row['locale'])) { 
104                                 $row['code'] .= AT_LANGUAGE_LOCALE_SEP . strtolower($row['locale']);
105                         }
106
107                         $sql    = "INSERT INTO ".TABLE_PREFIX."languages VALUES ('$row[code]', '$row[charset]', '$row[direction]', '$row[reg_exp]', '$row[native_name]', '$row[english_name]', 3)";
108
109                         if (mysql_query($sql, $db)) {
110                                 return TRUE;
111                         } else {
112                                 return FALSE;
113                         }
114                 }
115
116                 return FALSE;
117     }
118
119         // public
120         // $row = the language info array
121         // $new_exists whether the new code+locale exists already
122         // returns true or false, depending on success if db update
123         // can be called staticly
124     function updateLanguage($row, $new_exists) {
125                 $missing_fields = array();
126
127                 if ($row['code'] == '') {
128                         $missing_fields[] = _AT('lang_code');
129                 }
130                 if ($row['charset'] == '') {
131                         $missing_fields[] = _AT('charset');
132                 }
133                 if ($row['reg_exp'] == '') {
134                         $missing_fields[] = _AT('reg_exp');
135                 }
136                 if ($row['native_name'] == '') {
137                         $missing_fields[] = _AT('name_in_language');
138                 }
139                 if ($row['english_name'] == '') {
140                         $missing_fields[] = _AT('name_in_english');
141                 }
142                 
143                 if ($missing_fields) {
144                         $missing_fields = implode(', ', $missing_fields);
145                         $msg->addError(array('EMPTY_FIELDS', $missing_fields));
146                 }
147
148
149                 if (!$this->msg->containsErrors()) {
150                         global $addslashes;
151                         global $db;
152
153                         $row['code']         = strtolower($addslashes($row['code']));
154                         if (!empty($row['locale'])) { 
155                                 $row['code'] .= AT_LANGUAGE_LOCALE_SEP . strtolower($addslashes($row['locale']));
156                         }
157                         $row['charset']      = strtolower($addslashes($row['charset']));
158                         $row['direction']    = strtolower($addslashes($row['direction']));
159                         $row['reg_exp']      = strtolower($addslashes($row['reg_exp']));
160                         $row['native_name']  = $addslashes($row['native_name']);
161                         $row['english_name'] = $addslashes($row['english_name']);
162                         if (isset($row['status'])) {
163                                 $row['status']       = intval($row['status']);
164                                 $status_sql = ', status='.$row['status'];
165                         } else {
166                                 $status_sql = '';
167                         }
168
169                         if ($row['old_code'] == $row['code']) {
170                                 $sql    = "UPDATE ".TABLE_PREFIX."languages SET char_set='$row[charset]', direction='$row[direction]', reg_exp='$row[reg_exp]', native_name='$row[native_name]', english_name='$row[english_name]' $status_sql WHERE language_code='$row[code]'";
171                                 mysql_query($sql, $db);
172
173                                 return TRUE;
174                         } else if ($new_exists) {
175                                 $this->msg->addError('LANG_EXISTS');
176                                 return FALSE;
177                         } else {
178                                 $sql    = "UPDATE ".TABLE_PREFIX."languages SET language_code='$row[code]', char_set='$row[charset]', direction='$row[direction]', reg_exp='$row[reg_exp]', native_name='$row[native_name]', english_name='$row[english_name]' $status_sql WHERE language_code='$row[old_code]'";
179                                 mysql_query($sql, $db);
180
181                                 $sql = "UPDATE ".TABLE_PREFIX."language_text SET language_code='$row[code]' WHERE language_code='$row[old_code]'";
182                                 mysql_query($sql, $db);
183
184                                 return TRUE;
185                         }
186
187                 }
188                 return FALSE;
189     }
190
191     function deleteLanguage() {
192                 $sql = "DELETE FROM ".TABLE_PREFIX."languages WHERE language_code='$this->code'";
193                 mysql_query($sql, $this->db);
194
195                 $sql = "DELETE FROM ".TABLE_PREFIX."language_text WHERE language_code='$this->code'";
196                 mysql_query($sql, $this->db);
197
198                 $sql = "UPDATE ".TABLE_PREFIX."members SET language='".DEFAULT_LANGUAGE."', creation_date=creation_date, last_login=last_login WHERE language='$this->code'";
199                 mysql_query($sql, $this->db);
200
201                 $sql = "UPDATE ".TABLE_PREFIX."courses SET primary_language='".DEFAULT_LANGUAGE."' WHERE primary_language='$this->code'";
202                 mysql_query($sql, $this->db);
203
204                 cache_purge('system_langs', 'system_langs');
205         }
206
207         // public
208         function updateTerm($variable, $term, $text) {
209                 $addslashes = $this->addslashes;
210
211                 $variable = $addslashes($variable);
212                 $term     = $addslashes($term);
213                 $text     = $addslashes($text);
214                 $code     = $addslashes($this->getCode());
215
216                 $sql    = "UPDATE ".TABLE_PREFIX."language_text SET text='$text', revised_date=NOW() WHERE language_code='$code' AND variable='$variable' AND term='$term'";
217
218                 /*
219                 if (mysql_query($sql, $this->db)) {
220                         return TRUE;
221                 } else {
222                         debug(mysql_error($this->db));
223                         return FALSE;
224                 }
225                 */
226         }
227
228         // public
229         function insertTerm($variable, $key, $text, $context) {
230                 $addslashes = $this->addslashes;
231
232                 $variable = $addslashes($variable);
233                 $key      = $addslashes($key);
234                 $text     = $addslashes($text);
235                 $code     = $addslashes($this->getCode());
236                 $context  = $addslashes($context);
237
238                 $sql = "INSERT INTO ".TABLE_PREFIX."language_text VALUES('$code', '$variable', '$key', '$text', NOW(), '$context')";
239         }
240
241         // public
242         function showMissingTermsFrame(){
243                 global $_base_path, $addslashes;
244                 //$terms = array_slice($this->missingTerms, 0, 20);
245                 $terms = $this->missingTerms;
246                 $terms = serialize($terms);
247                 $terms = urlencode($terms);
248
249                 echo '<div align="center"><iframe src="'.$_base_path.'admin/missing_language.php?terms='.$terms.SEP.'lang='.$_SESSION['lang'].'" width="99%" height="300"></div>';
250         }
251
252         // public
253         // doesn't actually check if params is one of the possible ones.
254         // possible params should be array ('new', 'update')
255         function setFilter($params){
256                 if (!is_array($params)) {
257                         return;
258                 }
259
260                 foreach($params as $param => $garbage) {
261                         $this->filters[$param] = true;
262                 }
263         }
264
265         // private
266         function checkFilter($param) {
267                 if ($this->filters[$param]) {
268                         return true;
269                 }
270                 return false;
271         }
272
273         // public
274         function printTerms($terms){
275                 global $addslashes, $languageManager; // why won't $addslashes = $this->addslashes; work?
276
277                 $counter = 0;
278
279                 $terms = unserialize(stripslashes($addslashes($terms)));
280
281                 natcasesort($terms);
282
283                 if ($this->checkFilter('new')) {
284                         $new_check = ' checked="checked"';
285                 }
286                 if ($this->checkFilter('update')) {
287                         $update_check = ' checked="checked"';
288                 }
289
290                 $fromLanguage = $languageManager->getLanguage('en');
291
292                 echo '<form method="post" action="'.htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES).'">';
293                 echo '<table border="0" cellpadding="0" cellspacing="2">';
294                 echo '<tr>';
295                 echo '<td>Show: ';
296                 echo '<input name="filter_new" id="n" value="1" type="checkbox" '.$new_check.' /><label for="n">New Language</label>, ';
297                 echo '<input name="filter_update" id="u" value="1" type="checkbox" '.$update_check.' /><label for="u">Updated Language</label> ';
298                 echo '</td>';
299                 echo '</tr>';
300
301                 foreach($terms as $term => $garbage) {
302                         $to_term   = $this->getTerm($term);
303                         $from_term = $fromLanguage->getTerm($term);
304
305                         $is_new = false;
306                         if ($to_term === false) {
307                                 $is_new = true;
308                         }
309
310                         $is_old = false;
311                         if ($to_term['revised_date_unix'] < $from_term['revised_date_unix']) {
312                                 $is_old = true;
313                         }
314
315
316                         if ($this->checkFilter('new') && !$is_new) {
317                                 continue;
318                         }
319
320                         if ($this->checkFilter('update') && !$is_old) {
321                                 continue;
322                         }
323
324                         if (($counter % 10) == 0) {
325                                 echo '<tr>';
326                                 echo '<td align="center"><input type="submit" name="submit" value="Save Changes" class="button" /></td>';
327                                 echo '</tr>';
328                         }
329
330                         $style = '';
331                         if ($is_new) {
332                                 $style = 'style="background-color: white; border: red 2px solid;"';
333                         } else {
334                                 $style = 'style="background-color: white; border: yellow 1px solid;"';
335                         }
336
337                         echo '<tr>';
338                         echo '<td><strong>[ ' . $term . ' ] '.htmlspecialchars($from_term['text']).'</strong></td></tr>';
339                         echo '<tr><td><input type="text" name="'.$term.'" '.$style.' size="100" value="'.htmlspecialchars($to_term['text']).'" />';
340                         echo '<input type="hidden" name="old['.$term.']" '.$style.' size="100" value="'.htmlspecialchars($to_term['text']).'" /></td>';
341                         echo '</tr>';
342
343                         $counter++;
344                 }
345                 echo '</table>';
346                 echo '</form>';
347         }
348
349         // public
350         function updateTerms($terms) {
351                 global $addslashes;
352
353                 foreach($terms as $term => $text) {
354                         $text = $addslashes($text);
355                         $term = $addslashes($term);
356                 
357                         if (($text != '') && ($text != $_POST['old'][$term])) {
358                                 $sql = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ('".$this->getCode()."', '_template', '$term', '$text', NOW(), '')";
359                                 mysql_query($sql, $this->db);
360                         }
361                 }
362         }
363
364         // public
365         function addMissingTerm($term) {
366                 if (!isset($this->missingTerms[$term])) {
367                         $this->missingTerms[$term] = '';
368                 }
369         }
370
371
372         // this method should be called staticly: LanguageEditor::import()
373         // public
374         function import($language_sql_file) {
375                 // move sql import class from install/ to include/classes/
376                 // store the lang def'n in a .ini file and use insertLang 
377                 // after checking if it already exists
378
379                 // use the sql class to insert the language into the db
380
381                 // check if this language exists before calling this method
382
383                 require_once(AT_INCLUDE_PATH . 'classes/sqlutility.class.php');
384                 $sqlUtility = new SqlUtility();
385
386                 $sqlUtility->queryFromFile($language_sql_file, TABLE_PREFIX);
387         }
388
389         // sends the generated language pack to the browser
390         // public
391         function export($filename = '') {
392                 $search  = array('"', "'", "\x00", "\x0a", "\x0d", "\x1a"); //\x08\\x09, not required
393                 $replace = array('\"', "\'", '\0', '\n', '\r', '\Z');
394
395                 // use a function to generate the ini file
396                 // use a diff fn to generate the sql dump
397                 // use the zipfile class to package the ini file and the sql dump
398                 $sql_dump = "INSERT INTO `languages` VALUES ('$this->code', '$this->characterSet', '$this->direction', '$this->regularExpression', '$this->nativeName', '$this->englishName', $this->status);\r\n\r\n";
399
400                 $sql_dump .= "INSERT INTO `language_text` VALUES ";
401
402                 $sql    = "SELECT * FROM ".TABLE_PREFIX."language_text WHERE language_code='$this->code' ORDER BY variable, term";
403                 $result = mysql_query($sql, $this->db);
404                 if ($row = mysql_fetch_assoc($result)) {
405                         do {
406                                 $row['text']    = str_replace($search, $replace, $row['text']);
407                                 $row['context'] = str_replace($search, $replace, $row['context']);
408
409                                 $sql_dump .= "('$this->code', '$row[variable]', '$row[term]', '$row[text]', '$row[revised_date]', '$row[context]'),\r\n";
410                         } while ($row = mysql_fetch_assoc($result));
411                 } else {
412                         $this->msg->addError('LANG_EMPTY');
413                 }
414                 $sql_dump = substr($sql_dump, 0, -3) . ";";
415
416                 $readme = 'This is an ATutor language pack. Use the administrator Language section to import this language pack or manually import the contents of the SQL file into your [table_prefix]language_text table, where `table_prefix` should be replaced with your correct ATutor table prefix as defined in ./include/config.inc.php . Additional Language Packs can be found on http://atutor.ca .';
417
418                 require(AT_INCLUDE_PATH . 'classes/zipfile.class.php');
419                 $zipfile = new zipfile();
420
421                 $zipfile->add_file($sql_dump, 'language_text.sql');
422                 $zipfile->add_file($readme, 'readme.txt');
423                 $zipfile->add_file($this->getXML(), 'language.xml');  
424
425                 if ($filename) {
426                         $fp = fopen($filename, 'wb+');
427                         fwrite($fp, $zipfile->get_file(), $zipfile->get_size());
428                 } else {
429                         $version = str_replace('.','_',VERSION);
430
431                         $zipfile->send_file('atutor_' . $version . '_' . $this->code);
432                 }
433         }
434
435 }
436 ?>