PageRenderTime 28ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/admin/LangManager.php

https://code.google.com/p/enanocms/
PHP | 632 lines | 467 code | 113 blank | 52 comment | 66 complexity | 3298fe2123c88407a33a76822a6ed182 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
  4. * Copyright (C) 2006-2009 Dan Fuhry
  5. *
  6. * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  10. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  11. */
  12. function page_Admin_LangManager()
  13. {
  14. global $db, $session, $paths, $template, $plugins; // Common objects
  15. global $lang;
  16. global $cache;
  17. if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
  18. {
  19. $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
  20. echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
  21. echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
  22. return;
  23. }
  24. if ( isset($_POST['action']) )
  25. {
  26. $action =& $_POST['action'];
  27. // Parse parameters
  28. if ( strpos($action, ';') )
  29. {
  30. // Parameter section
  31. $parms = substr($action, strpos($action, ';') + 1);
  32. // Action name section
  33. $action = substr($action, 0, strpos($action, ';'));
  34. // Match all parameters
  35. preg_match_all('/([a-z0-9_]+)=(.+?)(;|$)/', $parms, $matches);
  36. $parms = array();
  37. // For each full parameter, assign $parms an associative value
  38. foreach ( $matches[0] as $i => $_ )
  39. {
  40. $parm = $matches[2][$i];
  41. // Is this parameter in the form of an integer?
  42. // (designed to ease validation later)
  43. if ( ctype_digit($parm) )
  44. // Yes, run intval(), this enabling is_int()-ish checks
  45. $parm = intval($parm);
  46. $parms[$matches[1][$i]] = $parm;
  47. }
  48. }
  49. switch ( $action )
  50. {
  51. case 'install_language':
  52. if ( defined('ENANO_DEMO_MODE') )
  53. {
  54. echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
  55. break;
  56. }
  57. $lang_list = list_available_languages();
  58. // Verify that we have this language's metadata
  59. if ( isset($lang_list[@$parms['iso639']]) )
  60. {
  61. // From here it's all downhill :-)
  62. $lang_code =& $parms['iso639'];
  63. $lang_data =& $lang_list[$lang_code];
  64. $result = install_language($lang_code, $lang_data['name_eng'], $lang_data['name']);
  65. if ( $result )
  66. {
  67. // Language installed. Import the language files.
  68. $lang_local = new Language($lang_code);
  69. if ( file_exists(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json") )
  70. {
  71. $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json");
  72. }
  73. else
  74. {
  75. foreach ( array('core', 'admin', 'tools', 'user') as $file )
  76. {
  77. $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/$file.json");
  78. }
  79. }
  80. unset($lang_local);
  81. echo '<div class="info-box">' . $lang->get('acplm_msg_lang_install_success', array('lang_name' => htmlspecialchars($lang_data['name_eng']))) . '</div>';
  82. }
  83. }
  84. break;
  85. case 'modify_language':
  86. $lang_id =& $parms['lang_id'];
  87. if ( !is_int($lang_id) )
  88. {
  89. echo 'Hacking attempt';
  90. break;
  91. }
  92. if ( isset($parms['finish']) && !empty($_POST['lang_name_native']) && !empty($_POST['lang_name_english']) && !defined('ENANO_DEMO_MODE') )
  93. {
  94. // We just did validation above, it's safe to save.
  95. $name_native = $db->escape($_POST['lang_name_native']);
  96. $name_english = $db->escape($_POST['lang_name_english']);
  97. $q = $db->sql_query('UPDATE ' . table_prefix . "language SET lang_name_native = '$name_native', lang_name_default = '$name_english' WHERE lang_id = $lang_id;");
  98. if ( !$q )
  99. $db->_die();
  100. echo '<div class="info-box">' . $lang->get('acplm_msg_basic_save_success') . '</div>';
  101. }
  102. else if ( isset($parms['finish']) && defined('ENANO_DEMO_MODE') )
  103. {
  104. echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
  105. }
  106. // Select language data
  107. $q = $db->sql_query('SELECT lang_name_native, lang_name_default, lang_code FROM ' . table_prefix . "language WHERE lang_id = $lang_id;");
  108. if ( !$q )
  109. $db->_die();
  110. list($name_native, $name_english, $lang_code) = $db->fetchrow_num();
  111. // Output properties table
  112. echo '<h3>' . $lang->get('acplm_heading_modify') . '</h3>';
  113. acp_start_form();
  114. ?>
  115. <div class="tblholder">
  116. <table border="0" cellspacing="1" cellpadding="4">
  117. <tr>
  118. <th colspan="2">
  119. <?php
  120. echo $lang->get('acplm_th_lang_basic');
  121. ?>
  122. </th>
  123. </tr>
  124. <tr>
  125. <td class="row2" style="width: 50%;">
  126. <?php
  127. echo str_replace('"', '', $lang->get('acplm_field_lang_name_native'));
  128. ?>
  129. </td>
  130. <td class="row1">
  131. <input type="text" name="lang_name_native" value="<?php echo htmlspecialchars($name_native); ?>" />
  132. </td>
  133. </tr>
  134. <tr>
  135. <td class="row2">
  136. <?php
  137. echo $lang->get('acplm_field_lang_name_english');
  138. ?>
  139. </td>
  140. <td class="row1">
  141. <input type="text" name="lang_name_english" value="<?php echo htmlspecialchars($name_english); ?>" />
  142. </td>
  143. </tr>
  144. <tr>
  145. <td class="row2">
  146. <?php
  147. echo $lang->get('acplm_field_lang_code') . '<br />'
  148. . '<small>' . $lang->get('acplm_field_lang_code_hint') . '</small>';
  149. ?>
  150. </td>
  151. <td class="row1">
  152. <?php
  153. echo $lang_code;
  154. ?>
  155. </td>
  156. </tr>
  157. <tr>
  158. <th class="subhead" colspan="2">
  159. <button name="action" value="modify_language;finish=1;lang_id=<?php echo $lang_id; ?>"><?php echo $lang->get('etc_save_changes'); ?></button>
  160. </th>
  161. </tr>
  162. </table>
  163. </div>
  164. </form>
  165. <?php
  166. acp_start_form();
  167. ?>
  168. <h3><?php echo $lang->get('acplm_heading_edit_strings_portal'); ?></h3>
  169. <p><?php echo $lang->get('acplm_msg_edit_strings_portal_intro'); ?></p>
  170. <p>
  171. <?php
  172. // Grab a Language object
  173. if ( $lang->lang_id == $lang_id )
  174. {
  175. $lang_local =& $lang;
  176. }
  177. else
  178. {
  179. $lang_local = new Language($lang_id);
  180. $lang_local->fetch();
  181. }
  182. $categories_loc = array();
  183. // Using the & here ensures that a reference is created, thus avoiding wasting memory
  184. foreach ( $lang_local->strings as $cat => &$_ )
  185. {
  186. unset($_);
  187. $categories_loc[$cat] = htmlspecialchars($lang->get("meta_$cat"));
  188. }
  189. asort($categories_loc);
  190. echo '<select name="cat_id">';
  191. foreach ( $categories_loc as $cat_id => $cat_name)
  192. {
  193. echo "<option value=\"$cat_id\">$cat_name</option>";
  194. }
  195. echo '</select>';
  196. ?>
  197. <button name="action" value="edit_strings;lang_id=<?php echo $lang_id; ?>">
  198. <?php echo $lang->get('acplm_btn_edit_strings_portal'); ?>
  199. </button>
  200. </p>
  201. <h3><?php echo $lang->get('acplm_heading_reimport_portal'); ?></h3>
  202. <p><?php echo $lang->get('acplm_msg_reimport_portal_intro'); ?></p>
  203. <p>
  204. <button name="action" value="reimport;iso639=<?php echo $lang_code; ?>;lang_id=<?php echo $lang_id; ?>">
  205. <?php echo $lang->get('acplm_btn_reimport'); ?>
  206. </button>
  207. </p>
  208. </form>
  209. <?php
  210. echo '<h3>' . $lang->get('acplm_heading_backup') . '</h3>';
  211. echo '<p>' . $lang->get('acplm_backup_intro') . '</p>';
  212. echo '<form action="' . makeUrlNS('Admin', 'LangManager') . '" method="post">';
  213. echo '<button name="action" value="backup_language;lang_id=' . $lang_id . '">' . $lang->get('acplm_btn_create_backup') . '</button>';
  214. echo '</form>';
  215. return true;
  216. case 'edit_strings':
  217. $cat_id = @$_POST['cat_id'];
  218. if ( !preg_match('/^[a-z0-9]+$/', $cat_id) || !is_int(@$parms['lang_id']) )
  219. break;
  220. $lang_id =& $parms['lang_id'];
  221. if ( isset($parms['save']) && !defined('ENANO_DEMO_MODE') )
  222. {
  223. // Grab a Language object
  224. if ( $lang->lang_id == $lang_id )
  225. {
  226. $lang_local =& $lang;
  227. }
  228. else
  229. {
  230. $lang_local = new Language($lang_id);
  231. }
  232. // Main save loop
  233. // Trying to minimize queries as much as possible here, but you know how that goes.
  234. $count_upd = 0;
  235. foreach ( $_POST['string'] as $string_id => $user_content )
  236. {
  237. $curr_content = $lang_local->get_uncensored("{$cat_id}_{$string_id}");
  238. if ( $curr_content != $user_content )
  239. {
  240. $count_upd++;
  241. $user_content = $db->escape($user_content);
  242. $string_id = $db->escape($string_id);
  243. $q = $db->sql_query('UPDATE ' . table_prefix . "language_strings SET string_content = '$user_content' WHERE lang_id = $lang_id AND string_category = '$cat_id' AND string_name = '$string_id';");
  244. if ( !$q )
  245. $db->_die();
  246. }
  247. }
  248. if ( $count_upd > 0 )
  249. {
  250. // Update the cache
  251. $lang_local->regen_caches();
  252. // Update modification time
  253. $q = $db->sql_query('UPDATE ' . table_prefix . "language SET last_changed = " . time() . " WHERE lang_id = $lang_id;");
  254. if ( !$q )
  255. $db->_die();
  256. }
  257. echo '<div class="info-box">' . $lang->get('acplm_msg_string_save_success') . '</div>';
  258. }
  259. else if ( isset($parms['save']) && defined('ENANO_DEMO_MODE') )
  260. {
  261. echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
  262. }
  263. acp_start_form();
  264. $cat_name = $lang->get("meta_$cat_id");
  265. echo '<h3>' . $lang->get('acplm_editor_heading', array('cat_name' => $cat_name)) . '</h3>';
  266. // Fetch all strings
  267. // This is more efficient than iterating through $lang->strings, I think.
  268. $q = $db->sql_query('SELECT string_id, string_name, string_content FROM ' . table_prefix . "language_strings WHERE string_category = '$cat_id' AND lang_id = $lang_id;");
  269. if ( !$q )
  270. $db->_die();
  271. ?>
  272. <div class="tblholder">
  273. <table border="0" cellspacing="1" cellpadding="4">
  274. <tr>
  275. <th style="width: 3%;"><?php echo $lang->get('acplm_editor_col_string_name'); ?></th>
  276. <th><?php echo $lang->get('acplm_editor_col_string_content'); ?></th>
  277. </tr>
  278. <?php
  279. while ( $row = $db->fetchrow_num() )
  280. {
  281. list($string_id, $string_name, $string_content) = $row;
  282. unset($row);
  283. echo '<tr>';
  284. if ( strpos($string_content, "\n") )
  285. {
  286. $editor = '<textarea rows="' . get_line_count($string_content) . '" cols="50" style="width: 99%;" ';
  287. $editor .= 'name="string[' . htmlspecialchars($string_name) . ']" ';
  288. $editor .= '>' . htmlspecialchars($string_content);
  289. $editor .= '</textarea>';
  290. }
  291. else
  292. {
  293. $editor = '<input type="text" size="50" style="width: 99%;" ';
  294. $editor .= 'name="string[' . htmlspecialchars($string_name) . ']" ';
  295. $editor .= 'value="' . htmlspecialchars($string_content) . '" ';
  296. $editor .= '/>';
  297. }
  298. echo '<td class="row2">' . htmlspecialchars($string_name) . '</td>';
  299. echo '<td class="row1">' . $editor . '</td>';
  300. echo '</tr>';
  301. echo "\n";
  302. }
  303. echo '<tr>
  304. <th class="subhead" colspan="2">';
  305. echo '<input type="hidden" name="cat_id" value="' . $cat_id . '" />';
  306. // Button: save
  307. echo '<button name="action" value="edit_strings;lang_id=' . $lang_id . ';save=1" style="font-weight: bold;">' . $lang->get('etc_save_changes') . '</button> ';
  308. // Button: revert
  309. echo '<button name="action" value="edit_strings;lang_id=' . $lang_id . '" style="font-weight: normal;">' . $lang->get('acplm_editor_btn_revert') . '</button> ';
  310. // Button: cancel
  311. echo '<button name="action" value="modify_language;lang_id=' . $lang_id . '" style="font-weight: normal;">' . $lang->get('acplm_editor_btn_cancel') . '</button>';
  312. echo ' </th>
  313. </tr>';
  314. ?>
  315. </table>
  316. </div>
  317. <?php
  318. echo '</form>';
  319. return true;
  320. case 'reimport':
  321. if ( !isset($parms['iso639']) || !is_int(@$parms['lang_id']) )
  322. break;
  323. if ( defined('ENANO_DEMO_MODE') )
  324. {
  325. echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
  326. break;
  327. }
  328. $lang_code =& $parms['iso639'];
  329. $lang_id =& $parms['lang_id'];
  330. $lang_list = list_available_languages();
  331. if ( !isset($lang_list[$lang_code]) )
  332. break;
  333. // Grab a Language object
  334. if ( $lang->lang_id == $lang_id )
  335. {
  336. $lang_local =& $lang;
  337. }
  338. else
  339. {
  340. $lang_local = new Language($lang_id);
  341. }
  342. $lang_data =& $lang_list[$lang_code];
  343. // This is the big re-import loop
  344. if ( file_exists(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json") )
  345. {
  346. $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json");
  347. }
  348. else
  349. {
  350. foreach ( array('core', 'admin', 'tools', 'user') as $file )
  351. {
  352. $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/$file.json");
  353. }
  354. }
  355. echo '<div class="info-box">' . $lang->get('acplm_msg_reimport_success') . '</div>';
  356. break;
  357. case 'backup_language':
  358. if ( !is_int(@$parms['lang_id']) )
  359. break;
  360. $lang_id =& $parms['lang_id'];
  361. // Grab a Language object
  362. if ( $lang->lang_id == $lang_id )
  363. {
  364. $lang_local =& $lang;
  365. }
  366. else
  367. {
  368. $lang_local = new Language($lang_id);
  369. }
  370. $filename = 'enano_lang_' . $lang_local->lang_code . '_' . enano_date('ymd') . '.json';
  371. // Free as much memory as possible
  372. $db->close();
  373. unset($GLOBALS['session'], $GLOBALS['paths'], $GLOBALS['template'], $GLOBALS['plugins']);
  374. // HTTP headers
  375. header('Content-type: application/json');
  376. header('Content-disposition: attachment; filename=' . $filename);
  377. // Export to JSON
  378. $lang_struct = array(
  379. 'categories' => array_keys($lang_local->strings),
  380. 'strings' => $lang_local->strings
  381. );
  382. $lang_struct = enano_json_encode($lang_struct);
  383. header('Content-length: ' . strlen($lang_struct));
  384. echo $lang_struct;
  385. exit;
  386. case 'uninstall_language':
  387. if ( !is_int(@$parms['lang_id']) )
  388. break;
  389. if ( defined('ENANO_DEMO_MODE') )
  390. {
  391. echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
  392. break;
  393. }
  394. $lang_id =& $parms['lang_id'];
  395. if ( isset($parms['confirm']) )
  396. {
  397. $lang_default = intval(getConfig('default_language'));
  398. if ( $lang_default == $lang_id )
  399. {
  400. echo '<div class="error-box">' . $lang->get('acplm_err_cant_uninstall_default') . '</div>';
  401. break;
  402. }
  403. if ( $lang_id == $lang->lang_id )
  404. {
  405. // Unload the current language since it's about to be uninstalled
  406. unset($lang, $GLOBALS['lang']);
  407. $GLOBALS['lang'] = new Language($lang_default);
  408. global $lang;
  409. }
  410. // We're clear
  411. // Remove cache files
  412. $cache_file = ENANO_ROOT . "/cache/lang_{$lang_id}.php";
  413. if ( file_exists($cache_file) )
  414. @unlink($cache_file);
  415. $cache->purge("lang_{$lang_id}");
  416. // Remove strings
  417. $q = $db->sql_query('DELETE FROM ' . table_prefix . "language_strings WHERE lang_id = $lang_id;");
  418. if ( !$q )
  419. $db->_die();
  420. // Delete the language
  421. $q = $db->sql_query('DELETE FROM ' . table_prefix . "language WHERE lang_id = $lang_id;");
  422. if ( !$q )
  423. $db->_die();
  424. echo '<div class="info-box">' . $lang->get('acplm_msg_uninstall_success') . '</div>';
  425. break;
  426. }
  427. acp_start_form();
  428. echo '<h3>' . $lang->get('acplm_uninstall_confirm_title') . '</h3>';
  429. echo '<p>' . $lang->get('acplm_uninstall_confirm_body') . '</p>';
  430. echo '<p><button name="action" style="font-weight: bold;" value="uninstall_language;lang_id=' . $lang_id . ';confirm=1">' . $lang->get('acplm_btn_uninstall_confirm') . '</button> ';
  431. echo '<button name="action" value="home">' . $lang->get('acplm_btn_uninstall_cancel') . '</button></p>';
  432. echo '</form>';
  433. return true;
  434. }
  435. }
  436. acp_start_form();
  437. // Select current languages
  438. $q = $db->sql_query('SELECT lang_code, lang_name_native, lang_name_default, lang_id FROM ' . table_prefix . "language ORDER BY lang_id ASC;");
  439. if ( !$q )
  440. $db->_die();
  441. // Language properties/edit/delete portal table
  442. echo '<h3>' . $lang->get('acplm_heading_editor_portal') . '</h3>';
  443. echo '<div class="tblholder">';
  444. echo '<table border="0" cellspacing="1" cellpadding="4">';
  445. echo '<tr>
  446. <th>' . $lang->get('acplm_col_lang_id') . '</th>
  447. <th>' . $lang->get('acplm_col_lang_code') . '</th>
  448. <th>' . $lang->get('acplm_col_lang_name') . '</th>
  449. <th>' . $lang->get('acplm_col_lang_name_eng') . '</th>
  450. <th></th>
  451. </tr>';
  452. $cls = 'row2';
  453. $btn_edit = $lang->get('acplm_portal_btn_edit');
  454. $btn_unin = $lang->get('acplm_portal_btn_unin');
  455. $rows = array();
  456. while ( $row = $db->fetchrow($q) )
  457. {
  458. $rows[] = $row;
  459. $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  460. echo '<tr>';
  461. $lang_code = htmlspecialchars($row['lang_code']);
  462. $lang_name_native = htmlspecialchars($row['lang_name_native']);
  463. $lang_name_english = htmlspecialchars($row['lang_name_default']);
  464. echo "<td class=\"$cls\" style=\"text-align: center;\">{$row['lang_id']}</td>";
  465. echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_code}</td>";
  466. echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_name_native}</td>";
  467. echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_name_english}</td>";
  468. echo "<td class=\"$cls\" style=\"text-align: center;\"><button name=\"action\" value=\"modify_language;lang_id={$row['lang_id']}\">$btn_edit</button> <button name=\"action\" value=\"uninstall_language;lang_id={$row['lang_id']}\">$btn_unin</button></td>";
  469. echo '</tr>';
  470. }
  471. echo '</table></div>';
  472. $db->free_result();
  473. // $lang_list is fetched by the posthandler sometimes
  474. if ( !isset($lang_list) )
  475. {
  476. // Build a list of languages in the languages/ directory, then
  477. // eliminate the ones that are already installed.
  478. $lang_list = list_available_languages();
  479. }
  480. foreach ( $rows as $row )
  481. {
  482. $lang_code =& $row['lang_code'];
  483. if ( isset($lang_list[$lang_code]) )
  484. {
  485. unset($lang_list[$lang_code]);
  486. unset($lang_list[$lang_code]); // PHP <5.1.4 Zend bug
  487. }
  488. }
  489. if ( count($lang_list) > 0 )
  490. {
  491. echo '<h3>' . $lang->get('acplm_heading_install') . '</h3>';
  492. echo '<div class="tblholder">
  493. <table border="0" cellspacing="1" cellpadding="4">
  494. <tr>
  495. <th>' . $lang->get('acplm_col_lang_code') . '</th>
  496. <th>' . $lang->get('acplm_col_lang_name') . '</th>
  497. <th>' . $lang->get('acplm_col_lang_name_eng') . '</th>
  498. <th></th>
  499. </tr>';
  500. $cls = 'row2';
  501. foreach ( $lang_list as $lang_code => $lang_data )
  502. {
  503. $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  504. echo '<tr>';
  505. $lang_code = htmlspecialchars($lang_code);
  506. $lang_data['name'] = htmlspecialchars($lang_data['name']);
  507. $lang_data['name_eng'] = htmlspecialchars($lang_data['name_eng']);
  508. echo "<td class=\"$cls\" style=\"text-align: center;\">$lang_code</td>";
  509. echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_data['name']}</td>";
  510. echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_data['name_eng']}</td>";
  511. echo "<td class=\"$cls\" style=\"text-align: center;\"><button name=\"action\" value=\"install_language;iso639=$lang_code\">" . $lang->get('acplm_btn_install_language') . "</button></td>";
  512. echo '</tr>';
  513. }
  514. echo ' </tr>
  515. </table>
  516. </div>';
  517. }
  518. echo '</form>';
  519. }