476dbaf0808fa73148c940d440e9b28f65cdd33e
[moodle.git] / admin / langimport.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * Fetches language packages from download.moodle.org server
20  *
21  * Language packages are available at http://download.moodle.org/langpack/
22  * in ZIP format together with a file languages.md5 containing their hashes
23  * and meta info.
24  * Locally, language packs are saved into $CFG->dataroot/lang/
25  *
26  * @package   core
27  * @copyright 2005 Yu Zhang
28  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29  */
31 require_once(dirname(dirname(__FILE__)).'/config.php');
32 require_once($CFG->libdir.'/adminlib.php');
33 require_once($CFG->libdir.'/filelib.php');
34 require_once($CFG->libdir.'/componentlib.class.php');
36 admin_externalpage_setup('langimport');
38 if (!empty($CFG->skiplangupgrade)) {
39     echo $OUTPUT->header();
40     echo $OUTPUT->box(get_string('langimportdisabled', 'admin'));
41     echo $OUTPUT->footer();
42     die;
43 }
45 $mode          = optional_param('mode', 0, PARAM_INT);              // action
46 $pack          = optional_param_array('pack', array(), PARAM_SAFEDIR);    // pack to install
47 $uninstalllang = optional_param('uninstalllang', '', PARAM_LANG);   // installed pack to uninstall
48 $confirm       = optional_param('confirm', 0, PARAM_BOOL);          // uninstallation confirmation
50 define('INSTALLATION_OF_SELECTED_LANG', 2);
51 define('DELETION_OF_SELECTED_LANG', 4);
52 define('UPDATE_ALL_LANG', 5);
54 get_string_manager()->reset_caches();
56 $notice_ok    = array();
57 $notice_error = array();
59 if (($mode == INSTALLATION_OF_SELECTED_LANG) and confirm_sesskey() and !empty($pack)) {
60     set_time_limit(0);
61     make_temp_directory('');
62     make_upload_directory('lang');
64     $installer = new lang_installer($pack);
65     $results = $installer->run();
66     foreach ($results as $langcode => $langstatus) {
67         switch ($langstatus) {
68         case lang_installer::RESULT_DOWNLOADERROR:
69             $a       = new stdClass();
70             $a->url  = $installer->lang_pack_url($langcode);
71             $a->dest = $CFG->dataroot.'/lang';
72             print_error('remotedownloaderror', 'error', 'langimport.php', $a);
73             break;
74         case lang_installer::RESULT_INSTALLED:
75             $notice_ok[] = get_string('langpackinstalled', 'admin', $langcode);
76             break;
77         case lang_installer::RESULT_UPTODATE:
78             $notice_ok[] = get_string('langpackuptodate', 'admin', $langcode);
79             break;
80         }
81     }
82 }
84 if ($mode == DELETION_OF_SELECTED_LANG and !empty($uninstalllang)) {
85     if ($uninstalllang == 'en') {
86         $notice_error[] = 'English language pack can not be uninstalled';
88     } else if (!$confirm and confirm_sesskey()) {
89         echo $OUTPUT->header();
90         echo $OUTPUT->confirm(get_string('uninstallconfirm', 'admin', $uninstalllang),
91                      'langimport.php?mode='.DELETION_OF_SELECTED_LANG.'&uninstalllang='.$uninstalllang.'&confirm=1',
92                      'langimport.php');
93         echo $OUTPUT->footer();
94         die;
96     } else if (confirm_sesskey()) {
97         $dest1 = $CFG->dataroot.'/lang/'.$uninstalllang;
98         $dest2 = $CFG->dirroot.'/lang/'.$uninstalllang;
99         $rm1 = false;
100         $rm2 = false;
101         if (file_exists($dest1)){
102             $rm1 = remove_dir($dest1);
103         }
104         if (file_exists($dest2)){
105             $rm2 = remove_dir($dest2);
106         }
107         if ($rm1 or $rm2) {
108             $notice_ok[] = get_string('langpackremoved','admin');
109         } else {    //nothing deleted, possibly due to permission error
110             $notice_error[] = 'An error has occurred, language pack is not completely uninstalled, please check file permissions';
111         }
112     }
115 if ($mode == UPDATE_ALL_LANG) {
116     set_time_limit(0);
118     $installer = new lang_installer();
120     if (!$availablelangs = $installer->get_remote_list_of_languages()) {
121         print_error('cannotdownloadlanguageupdatelist', 'error');
122     }
123     $md5array = array();    // (string)langcode => (string)md5
124     foreach ($availablelangs as $alang) {
125         $md5array[$alang[0]] = $alang[1];
126     }
128     // filter out unofficial packs
129     $currentlangs = array_keys(get_string_manager()->get_list_of_translations(true));
130     $updateablelangs = array();
131     foreach ($currentlangs as $clang) {
132         if (!array_key_exists($clang, $md5array)) {
133             $notice_ok[] = get_string('langpackupdateskipped', 'admin', $clang);
134             continue;
135         }
136         $dest1 = $CFG->dataroot.'/lang/'.$clang;
137         $dest2 = $CFG->dirroot.'/lang/'.$clang;
139         if (file_exists($dest1.'/langconfig.php') || file_exists($dest2.'/langconfig.php')){
140             $updateablelangs[] = $clang;
141         }
142     }
144     // then filter out packs that have the same md5 key
145     $neededlangs = array();   // all the packs that needs updating
146     foreach ($updateablelangs as $ulang) {
147         if (!is_installed_lang($ulang, $md5array[$ulang])) {
148             $neededlangs[] = $ulang;
149         }
150     }
152     make_temp_directory('');
153     make_upload_directory('lang');
155     // clean-up currently installed versions of the packs
156     foreach ($neededlangs as $packindex => $pack) {
157         if ($pack == 'en') {
158             continue;
159         }
161         // delete old directories
162         $dest1 = $CFG->dataroot.'/lang/'.$pack;
163         $dest2 = $CFG->dirroot.'/lang/'.$pack;
164         $rm1 = false;
165         $rm2 = false;
166         if (file_exists($dest1)) {
167             if (!remove_dir($dest1)) {
168                 $notice_error[] = 'Could not delete old directory '.$dest1.', update of '.$pack.' failed, please check permissions.';
169                 unset($neededlangs[$packindex]);
170                 continue;
171             }
172         }
173         if (file_exists($dest2)) {
174             if (!remove_dir($dest2)) {
175                 $notice_error[] = 'Could not delete old directory '.$dest2.', update of '.$pack.' failed, please check permissions.';
176                 unset($neededlangs[$packindex]);
177                 continue;
178             }
179         }
180     }
182     // install all needed language packs
183     $installer->set_queue($neededlangs);
184     $results = $installer->run();
185     $updated = false;    // any packs updated?
186     foreach ($results as $langcode => $langstatus) {
187         switch ($langstatus) {
188         case lang_installer::RESULT_DOWNLOADERROR:
189             $a       = new stdClass();
190             $a->url  = $installer->lang_pack_url($langcode);
191             $a->dest = $CFG->dataroot.'/lang';
192             print_error('remotedownloaderror', 'error', 'langimport.php', $a);
193             break;
194         case lang_installer::RESULT_INSTALLED:
195             $updated = true;
196             $notice_ok[] = get_string('langpackinstalled', 'admin', $langcode);
197             break;
198         case lang_installer::RESULT_UPTODATE:
199             $notice_ok[] = get_string('langpackuptodate', 'admin', $langcode);
200             break;
201         }
202     }
204     if ($updated) {
205         $notice_ok[] = get_string('langupdatecomplete','admin');
206     } else {
207         $notice_ok[] = get_string('nolangupdateneeded','admin');
208     }
210     unset($installer);
212 get_string_manager()->reset_caches();
214 echo $OUTPUT->header();
215 echo $OUTPUT->heading(get_string('langimport', 'admin'));
217 $installedlangs = get_string_manager()->get_list_of_translations(true);
219 $missingparents = array();
220 foreach ($installedlangs as $installedlang => $unused) {
221     $parent = get_parent_language($installedlang);
222     if (empty($parent)) {
223         continue;
224     }
225     if (!isset($installedlangs[$parent])) {
226         $missingparents[$installedlang] = $parent;
227     }
230 $installer = new lang_installer();
232 if ($availablelangs = $installer->get_remote_list_of_languages()) {
233     $remote = true;
234 } else {
235     $remote = false;
236     $availablelangs = array();
237     echo $OUTPUT->box_start();
238     print_string('remotelangnotavailable', 'admin', $CFG->dataroot.'/lang/');
239     echo $OUTPUT->box_end();
242 if ($notice_ok) {
243     $info = implode('<br />', $notice_ok);
244     echo $OUTPUT->notification($info, 'notifysuccess');
247 if ($notice_error) {
248     $info = implode('<br />', $notice_error);
249     echo $OUTPUT->notification($info, 'notifyproblem');
252 if ($missingparents) {
253     foreach ($missingparents as $l=>$parent) {
254         $a = new stdClass();
255         $a->lang   = $installedlangs[$l];
256         $a->parent = $parent;
257         foreach ($availablelangs as $alang) {
258             if ($alang[0] == $parent) {
259                 $shortlang = $alang[0];
260                 $a->parent = $alang[2].' ('.$shortlang.')';
261             }
262         }
263         $info = get_string('missinglangparent', 'admin', $a);
264         echo $OUTPUT->notification($info, 'notifyproblem');
265     }
268 echo $OUTPUT->box_start();
270 echo html_writer::start_tag('table');
271 echo html_writer::start_tag('tr');
273 // list of installed languages
274 $url = new moodle_url('/admin/langimport.php', array('mode' => DELETION_OF_SELECTED_LANG));
275 echo html_writer::start_tag('td', array('valign' => 'top'));
276 echo html_writer::start_tag('form', array('id' => 'uninstallform', 'action' => $url->out(), 'method' => 'post'));
277 echo html_writer::start_tag('fieldset');
278 echo html_writer::label(get_string('installedlangs','admin'), 'uninstalllang');
279 echo html_writer::empty_tag('br');
280 echo html_writer::select($installedlangs, 'uninstalllang', '', false, array('size' => 15));
281 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
282 echo html_writer::empty_tag('br');
283 echo html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('uninstall','admin')));
284 echo html_writer::end_tag('fieldset');
285 echo html_writer::end_tag('form');
286 if ($remote) {
287     $url = new moodle_url('/admin/langimport.php', array('mode' => UPDATE_ALL_LANG));
288     echo html_writer::start_tag('form', array('id' => 'updateform', 'action' => $url->out(), 'method' => 'post'));
289     echo html_writer::tag('fieldset', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('updatelangs','admin'))));
290     echo html_writer::end_tag('form');
292 echo html_writer::end_tag('td');
294 // list of available languages
295 $options = array();
296 foreach ($availablelangs as $alang) {
297     if (!empty($alang[0]) and trim($alang[0]) !== 'en' and !is_installed_lang($alang[0], $alang[1])) {
298         $options[$alang[0]] = $alang[2].' ('.$alang[0].')';
299     }
301 if (!empty($options)) {
302     echo html_writer::start_tag('td', array('valign' => 'top'));
303     $url = new moodle_url('/admin/langimport.php', array('mode' => INSTALLATION_OF_SELECTED_LANG));
304     echo html_writer::start_tag('form', array('id' => 'installform', 'action' => $url->out(), 'method' => 'post'));
305     echo html_writer::start_tag('fieldset');
306     echo html_writer::label(get_string('availablelangs','install'), 'pack');
307     echo html_writer::empty_tag('br');
308     echo html_writer::select($options, 'pack[]', '', false, array('size' => 15, 'multiple' => 'multiple'));
309     echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
310     echo html_writer::empty_tag('br');
311     echo html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('install','admin')));
312     echo html_writer::end_tag('fieldset');
313     echo html_writer::end_tag('form');
314     echo html_writer::end_tag('td');
317 echo html_writer::end_tag('tr');
318 echo html_writer::end_tag('table');
319 echo $OUTPUT->box_end();
320 echo $OUTPUT->footer();
321 die();
323 ////////////////////////////////////////////////////////////////////////////////
324 // Local functions /////////////////////////////////////////////////////////////
325 ////////////////////////////////////////////////////////////////////////////////
327 /**
328  * checks the md5 of the zip file, grabbed from download.moodle.org,
329  * against the md5 of the local language file from last update
330  * @param string $lang
331  * @param string $md5check
332  * @return bool
333  */
334 function is_installed_lang($lang, $md5check) {
335     global $CFG;
336     $md5file = $CFG->dataroot.'/lang/'.$lang.'/'.$lang.'.md5';
337     if (file_exists($md5file)){
338         return (file_get_contents($md5file) == $md5check);
339     }
340     return false;