[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 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/>. 17 18 /** 19 * This library includes all the necessary stuff to use the one-click 20 * download and install feature of Moodle, used to keep updated some 21 * items like languages, pear, enviroment... i.e, components. 22 * 23 * It has been developed harcoding some important limits that are 24 * explained below: 25 * - It only can check, download and install items under moodledata. 26 * - Every downloadeable item must be one zip file. 27 * - The zip file root content must be 1 directory, i.e, everything 28 * is stored under 1 directory. 29 * - Zip file name and root directory must have the same name (but 30 * the .zip extension, of course). 31 * - Every .zip file must be defined in one .md5 file that will be 32 * stored in the same remote directory than the .zip file. 33 * - The name of such .md5 file is free, although it's recommended 34 * to use the same name than the .zip (that's the default 35 * assumption if no specified). 36 * - Every remote .md5 file will be a comma separated (CVS) file where each 37 * line will follow this format: 38 * - Field 1: name of the zip file (without extension). Mandatory. 39 * - Field 2: md5 of the zip file. Mandatory. 40 * - Field 3: whatever you want (or need). Optional. 41 * -Every local .md5 file will: 42 * - Have the zip file name (without the extension) plus -md5 43 * - Will reside inside the expanded zip file dir 44 * - Will contain the md5 od the latest installed component 45 * With all these details present, the process will perform this tasks: 46 * - Perform security checks. Only admins are allowed to use this for now. 47 * - Read the .md5 file from source (1). 48 * - Extract the correct line for the .zip being requested. 49 * - Compare it with the local .md5 file (2). 50 * - If different: 51 * - Download the newer .zip file from source. 52 * - Calculate its md5 (3). 53 * - Compare (1) and (3). 54 * - If equal: 55 * - Delete old directory. 56 * - Uunzip the newer .zip file. 57 * - Create the new local .md5 file. 58 * - Delete the .zip file. 59 * - If different: 60 * - ERROR. Old package won't be modified. We shouldn't 61 * reach here ever. 62 * - If component download is not possible, a message text about how to do 63 * the process manually (remotedownloaderror) must be displayed to explain it. 64 * 65 * General Usage: 66 * 67 * To install one component: 68 * <code> 69 * require_once($CFG->libdir.'/componentlib.class.php'); 70 * if ($cd = new component_installer('https://download.moodle.org', 'langpack/2.0', 71 * 'es.zip', 'languages.md5', 'lang')) { 72 * $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED) 73 * switch ($status) { 74 * case COMPONENT_ERROR: 75 * if ($cd->get_error() == 'remotedownloaderror') { 76 * $a = new stdClass(); 77 * $a->url = 'https://download.moodle.org/langpack/2.0/es.zip'; 78 * $a->dest= $CFG->dataroot.'/lang'; 79 * print_error($cd->get_error(), 'error', '', $a); 80 * } else { 81 * print_error($cd->get_error(), 'error'); 82 * } 83 * break; 84 * case COMPONENT_UPTODATE: 85 * //Print error string or whatever you want to do 86 * break; 87 * case COMPONENT_INSTALLED: 88 * //Print/do whatever you want 89 * break; 90 * default: 91 * //We shouldn't reach this point 92 * } 93 * } else { 94 * //We shouldn't reach this point 95 * } 96 * </code> 97 * 98 * To switch of component (maintaining the rest of settings): 99 * <code> 100 * $status = $cd->change_zip_file('en.zip'); //returns boolean false on error 101 * </code> 102 * 103 * To retrieve all the components in one remote md5 file 104 * <code> 105 * $components = $cd->get_all_components_md5(); //returns boolean false on error, array instead 106 * </code> 107 * 108 * To check if current component needs to be updated 109 * <code> 110 * $status = $cd->need_upgrade(); //returns COMPONENT_(ERROR | UPTODATE | NEEDUPDATE) 111 * </code> 112 * 113 * To get the 3rd field of the md5 file (optional) 114 * <code> 115 * $field = $cd->get_extra_md5_field(); //returns string (empty if not exists) 116 * </code> 117 * 118 * For all the error situations the $cd->get_error() method should return always the key of the 119 * error to be retrieved by one standard get_string() call against the error.php lang file. 120 * 121 * That's all! 122 * 123 * @package core 124 * @copyright (C) 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com} 125 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 126 */ 127 128 defined('MOODLE_INTERNAL') || die(); 129 130 /** 131 * @global object $CFG 132 * @name $CFG 133 */ 134 global $CFG; 135 require_once($CFG->libdir.'/filelib.php'); 136 137 // Some needed constants 138 define('COMPONENT_ERROR', 0); 139 define('COMPONENT_UPTODATE', 1); 140 define('COMPONENT_NEEDUPDATE', 2); 141 define('COMPONENT_INSTALLED', 3); 142 143 /** 144 * This class is used to check, download and install items from 145 * download.moodle.org to the moodledata directory. 146 * 147 * It always return true/false in all their public methods to say if 148 * execution has ended succesfuly or not. If there is any problem 149 * its getError() method can be called, returning one error string 150 * to be used with the standard get/print_string() functions. 151 * 152 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 153 * @package moodlecore 154 */ 155 class component_installer { 156 /** 157 * @var string 158 */ 159 var $sourcebase; /// Full http URL, base for downloadable items 160 var $zippath; /// Relative path (from sourcebase) where the 161 /// downloadeable item resides. 162 var $zipfilename; /// Name of the .zip file to be downloaded 163 var $md5filename; /// Name of the .md5 file to be read 164 var $componentname;/// Name of the component. Must be the zip name without 165 /// the extension. And it defines a lot of things: 166 /// the md5 line to search for, the default m5 file name 167 /// and the name of the root dir stored inside the zip file 168 var $destpath; /// Relative path (from moodledata) where the .zip 169 /// file will be expanded. 170 var $errorstring; /// Latest error produced. It will contain one lang string key. 171 var $extramd5info; /// Contents of the optional third field in the .md5 file. 172 var $requisitesok; /// Flag to see if requisites check has been passed ok. 173 /** 174 * @var array 175 */ 176 var $cachedmd5components; /// Array of cached components to avoid to 177 /// download the same md5 file more than once per request. 178 179 /** 180 * Standard constructor of the class. It will initialize all attributes. 181 * without performing any check at all. 182 * 183 * @param string $sourcebase Full http URL, base for downloadeable items 184 * @param string $zippath Relative path (from sourcebase) where the 185 * downloadeable item resides 186 * @param string $zipfilename Name of the .zip file to be downloaded 187 * @param string $md5filename Name of the .md5 file to be read (default '' = same 188 * than zipfilename) 189 * @param string $destpath Relative path (from moodledata) where the .zip file will 190 * be expanded (default='' = moodledataitself) 191 * @return object 192 */ 193 function component_installer ($sourcebase, $zippath, $zipfilename, $md5filename='', $destpath='') { 194 195 $this->sourcebase = $sourcebase; 196 $this->zippath = $zippath; 197 $this->zipfilename = $zipfilename; 198 $this->md5filename = $md5filename; 199 $this->componentname= ''; 200 $this->destpath = $destpath; 201 $this->errorstring = ''; 202 $this->extramd5info = ''; 203 $this->requisitesok = false; 204 $this->cachedmd5components = array(); 205 206 $this->check_requisites(); 207 } 208 209 /** 210 * This function will check if everything is properly set to begin 211 * one installation. Also, it will check for required settings 212 * and will fill everything as needed. 213 * 214 * @global object 215 * @return boolean true/false (plus detailed error in errorstring) 216 */ 217 function check_requisites() { 218 global $CFG; 219 220 $this->requisitesok = false; 221 222 /// Check that everything we need is present 223 if (empty($this->sourcebase) || empty($this->zipfilename)) { 224 $this->errorstring='missingrequiredfield'; 225 return false; 226 } 227 /// Check for correct sourcebase (this will be out in the future) 228 if (!PHPUNIT_TEST and $this->sourcebase != 'https://download.moodle.org') { 229 $this->errorstring='wrongsourcebase'; 230 return false; 231 } 232 /// Check the zip file is a correct one (by extension) 233 if (stripos($this->zipfilename, '.zip') === false) { 234 $this->errorstring='wrongzipfilename'; 235 return false; 236 } 237 /// Check that exists under dataroot 238 if (!empty($this->destpath)) { 239 if (!file_exists($CFG->dataroot.'/'.$this->destpath)) { 240 $this->errorstring='wrongdestpath'; 241 return false; 242 } 243 } 244 /// Calculate the componentname 245 $pos = stripos($this->zipfilename, '.zip'); 246 $this->componentname = substr($this->zipfilename, 0, $pos); 247 /// Calculate md5filename if it's empty 248 if (empty($this->md5filename)) { 249 $this->md5filename = $this->componentname.'.md5'; 250 } 251 /// Set the requisites passed flag 252 $this->requisitesok = true; 253 return true; 254 } 255 256 /** 257 * This function will perform the full installation if needed, i.e. 258 * compare md5 values, download, unzip, install and regenerate 259 * local md5 file 260 * 261 * @global object 262 * @uses COMPONENT_ERROR 263 * @uses COMPONENT_UPTODATE 264 * @uses COMPONENT_ERROR 265 * @uses COMPONENT_INSTALLED 266 * @return int COMPONENT_(ERROR | UPTODATE | INSTALLED) 267 */ 268 function install() { 269 270 global $CFG; 271 272 /// Check requisites are passed 273 if (!$this->requisitesok) { 274 return COMPONENT_ERROR; 275 } 276 /// Confirm we need upgrade 277 if ($this->need_upgrade() === COMPONENT_ERROR) { 278 return COMPONENT_ERROR; 279 } else if ($this->need_upgrade() === COMPONENT_UPTODATE) { 280 $this->errorstring='componentisuptodate'; 281 return COMPONENT_UPTODATE; 282 } 283 /// Create temp directory if necesary 284 if (!make_temp_directory('', false)) { 285 $this->errorstring='cannotcreatetempdir'; 286 return COMPONENT_ERROR; 287 } 288 /// Download zip file and save it to temp 289 if ($this->zippath) { 290 $source = $this->sourcebase.'/'.$this->zippath.'/'.$this->zipfilename; 291 } else { 292 $source = $this->sourcebase.'/'.$this->zipfilename; 293 } 294 295 $zipfile= $CFG->tempdir.'/'.$this->zipfilename; 296 297 if($contents = download_file_content($source)) { 298 if ($file = fopen($zipfile, 'w')) { 299 if (!fwrite($file, $contents)) { 300 fclose($file); 301 $this->errorstring='cannotsavezipfile'; 302 return COMPONENT_ERROR; 303 } 304 } else { 305 $this->errorstring='cannotsavezipfile'; 306 return COMPONENT_ERROR; 307 } 308 fclose($file); 309 } else { 310 $this->errorstring='cannotdownloadzipfile'; 311 return COMPONENT_ERROR; 312 } 313 /// Calculate its md5 314 $new_md5 = md5($contents); 315 /// Compare it with the remote md5 to check if we have the correct zip file 316 if (!$remote_md5 = $this->get_component_md5()) { 317 return COMPONENT_ERROR; 318 } 319 if ($new_md5 != $remote_md5) { 320 $this->errorstring='downloadedfilecheckfailed'; 321 return COMPONENT_ERROR; 322 } 323 /// Move current revision to a safe place 324 $destinationdir = $CFG->dataroot.'/'.$this->destpath; 325 $destinationcomponent = $destinationdir.'/'.$this->componentname; 326 @remove_dir($destinationcomponent.'_old'); //Deleting possible old components before 327 @rename ($destinationcomponent, $destinationcomponent.'_old'); //Moving to a safe place 328 /// Unzip new version 329 if (!unzip_file($zipfile, $destinationdir, false)) { 330 /// Error so, go back to the older 331 @remove_dir($destinationcomponent); 332 @rename ($destinationcomponent.'_old', $destinationcomponent); 333 $this->errorstring='cannotunzipfile'; 334 return COMPONENT_ERROR; 335 } 336 /// Delete old component version 337 @remove_dir($destinationcomponent.'_old'); 338 /// Create local md5 339 if ($file = fopen($destinationcomponent.'/'.$this->componentname.'.md5', 'w')) { 340 if (!fwrite($file, $new_md5)) { 341 fclose($file); 342 $this->errorstring='cannotsavemd5file'; 343 return COMPONENT_ERROR; 344 } 345 } else { 346 $this->errorstring='cannotsavemd5file'; 347 return COMPONENT_ERROR; 348 } 349 fclose($file); 350 /// Delete temp zip file 351 @unlink($zipfile); 352 353 return COMPONENT_INSTALLED; 354 } 355 356 /** 357 * This function will detect if remote component needs to be installed 358 * because it's different from the local one 359 * 360 * @uses COMPONENT_ERROR 361 * @uses COMPONENT_UPTODATE 362 * @uses COMPONENT_NEEDUPDATE 363 * @return int COMPONENT_(ERROR | UPTODATE | NEEDUPDATE) 364 */ 365 function need_upgrade() { 366 367 /// Check requisites are passed 368 if (!$this->requisitesok) { 369 return COMPONENT_ERROR; 370 } 371 /// Get local md5 372 $local_md5 = $this->get_local_md5(); 373 /// Get remote md5 374 if (!$remote_md5 = $this->get_component_md5()) { 375 return COMPONENT_ERROR; 376 } 377 /// Return result 378 if ($local_md5 == $remote_md5) { 379 return COMPONENT_UPTODATE; 380 } else { 381 return COMPONENT_NEEDUPDATE; 382 } 383 } 384 385 /** 386 * This function will change the zip file to install on the fly 387 * to allow the class to process different components of the 388 * same md5 file without intantiating more objects. 389 * 390 * @param string $newzipfilename New zip filename to process 391 * @return boolean true/false 392 */ 393 function change_zip_file($newzipfilename) { 394 395 $this->zipfilename = $newzipfilename; 396 return $this->check_requisites(); 397 } 398 399 /** 400 * This function will get the local md5 value of the installed 401 * component. 402 * 403 * @global object 404 * @return bool|string md5 of the local component (false on error) 405 */ 406 function get_local_md5() { 407 global $CFG; 408 409 /// Check requisites are passed 410 if (!$this->requisitesok) { 411 return false; 412 } 413 414 $return_value = 'needtobeinstalled'; /// Fake value to force new installation 415 416 /// Calculate source to read 417 $source = $CFG->dataroot.'/'.$this->destpath.'/'.$this->componentname.'/'.$this->componentname.'.md5'; 418 /// Read md5 value stored (if exists) 419 if (file_exists($source)) { 420 if ($temp = file_get_contents($source)) { 421 $return_value = $temp; 422 } 423 } 424 return $return_value; 425 } 426 427 /** 428 * This function will download the specified md5 file, looking for the 429 * current componentname, returning its md5 field and storing extramd5info 430 * if present. Also it caches results to cachedmd5components for better 431 * performance in the same request. 432 * 433 * @return mixed md5 present in server (or false if error) 434 */ 435 function get_component_md5() { 436 437 /// Check requisites are passed 438 if (!$this->requisitesok) { 439 return false; 440 } 441 /// Get all components of md5 file 442 if (!$comp_arr = $this->get_all_components_md5()) { 443 if (empty($this->errorstring)) { 444 $this->errorstring='cannotdownloadcomponents'; 445 } 446 return false; 447 } 448 /// Search for the componentname component 449 if (empty($comp_arr[$this->componentname]) || !$component = $comp_arr[$this->componentname]) { 450 $this->errorstring='cannotfindcomponent'; 451 return false; 452 } 453 /// Check we have a valid md5 454 if (empty($component[1]) || strlen($component[1]) != 32) { 455 $this->errorstring='invalidmd5'; 456 return false; 457 } 458 /// Set the extramd5info field 459 if (!empty($component[2])) { 460 $this->extramd5info = $component[2]; 461 } 462 return $component[1]; 463 } 464 465 /** 466 * This function allows you to retrieve the complete array of components found in 467 * the md5filename 468 * 469 * @return bool|array array of components in md5 file or false if error 470 */ 471 function get_all_components_md5() { 472 473 /// Check requisites are passed 474 if (!$this->requisitesok) { 475 return false; 476 } 477 478 /// Initialize components array 479 $comp_arr = array(); 480 481 /// Define and retrieve the full md5 file 482 if ($this->zippath) { 483 $source = $this->sourcebase.'/'.$this->zippath.'/'.$this->md5filename; 484 } else { 485 $source = $this->sourcebase.'/'.$this->md5filename; 486 } 487 488 /// Check if we have downloaded the md5 file before (per request cache) 489 if (!empty($this->cachedmd5components[$source])) { 490 $comp_arr = $this->cachedmd5components[$source]; 491 } else { 492 /// Not downloaded, let's do it now 493 $availablecomponents = array(); 494 495 if ($contents = download_file_content($source)) { 496 /// Split text into lines 497 $lines=preg_split('/\r?\n/',$contents); 498 /// Each line will be one component 499 foreach($lines as $line) { 500 $availablecomponents[] = explode(',', $line); 501 } 502 /// If no components have been found, return error 503 if (empty($availablecomponents)) { 504 $this->errorstring='cannotdownloadcomponents'; 505 return false; 506 } 507 /// Build an associative array of components for easily search 508 /// applying trim to avoid linefeeds and other... 509 $comp_arr = array(); 510 foreach ($availablecomponents as $component) { 511 /// Avoid sometimes empty lines 512 if (empty($component[0])) { 513 continue; 514 } 515 $component[0]=trim($component[0]); 516 if (!empty($component[1])) { 517 $component[1]=trim($component[1]); 518 } 519 if (!empty($component[2])) { 520 $component[2]=trim($component[2]); 521 } 522 $comp_arr[$component[0]] = $component; 523 } 524 /// Cache components 525 $this->cachedmd5components[$source] = $comp_arr; 526 } else { 527 /// Return error 528 $this->errorstring='remotedownloaderror'; 529 return false; 530 } 531 } 532 /// If there is no commponents or erros found, error 533 if (!empty($this->errorstring)) { 534 return false; 535 536 } else if (empty($comp_arr)) { 537 $this->errorstring='cannotdownloadcomponents'; 538 return false; 539 } 540 return $comp_arr; 541 } 542 543 /** 544 * This function returns the errorstring 545 * 546 * @return string the error string 547 */ 548 function get_error() { 549 return $this->errorstring; 550 } 551 552 /** This function returns the extramd5 field (optional in md5 file) 553 * 554 * @return string the extramd5 field 555 */ 556 function get_extra_md5_field() { 557 return $this->extramd5info; 558 } 559 560 } /// End of component_installer class 561 562 563 /** 564 * Language packs installer 565 * 566 * This class wraps the functionality provided by {@link component_installer} 567 * and adds support for installing a set of language packs. 568 * 569 * Given an array of required language packs, this class fetches them all 570 * and installs them. It detects eventual dependencies and installs 571 * all parent languages, too. 572 * 573 * @copyright 2011 David Mudrak <[email protected]> 574 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 575 */ 576 class lang_installer { 577 578 /** lang pack was successfully downloaded and deployed */ 579 const RESULT_INSTALLED = 'installed'; 580 /** lang pack was up-to-date so no download was needed */ 581 const RESULT_UPTODATE = 'uptodate'; 582 /** there was a problem with downloading the lang pack */ 583 const RESULT_DOWNLOADERROR = 'downloaderror'; 584 585 /** @var array of languages to install */ 586 protected $queue = array(); 587 /** @var string the code of language being currently installed */ 588 protected $current; 589 /** @var array of languages already installed by this instance */ 590 protected $done = array(); 591 /** @var string this Moodle major version */ 592 protected $version; 593 594 /** 595 * Prepare the installer 596 * 597 * @param string|array $langcode a code of the language to install 598 */ 599 public function __construct($langcode = '') { 600 global $CFG; 601 602 $this->set_queue($langcode); 603 $this->version = moodle_major_version(true); 604 605 if (!empty($CFG->langotherroot) and $CFG->langotherroot !== $CFG->dataroot . '/lang') { 606 debugging('The in-built language pack installer does not support alternative location ' . 607 'of languages root directory. You are supposed to install and update your language '. 608 'packs on your own.'); 609 } 610 } 611 612 /** 613 * Sets the queue of language packs to be installed 614 * 615 * @param string|array $langcodes language code like 'cs' or a list of them 616 */ 617 public function set_queue($langcodes) { 618 if (is_array($langcodes)) { 619 $this->queue = $langcodes; 620 } else if (!empty($langcodes)) { 621 $this->queue = array($langcodes); 622 } 623 } 624 625 /** 626 * Runs the installer 627 * 628 * This method calls {@link self::install_language_pack} for every language in the 629 * queue. If a dependency is detected, the parent language is added to the queue. 630 * 631 * @return array results, array of self::RESULT_xxx constants indexed by language code 632 */ 633 public function run() { 634 635 $results = array(); 636 637 while ($this->current = array_shift($this->queue)) { 638 639 if ($this->was_processed($this->current)) { 640 // do not repeat yourself 641 continue; 642 } 643 644 if ($this->current === 'en') { 645 $this->mark_processed($this->current); 646 continue; 647 } 648 649 $results[$this->current] = $this->install_language_pack($this->current); 650 651 if (in_array($results[$this->current], array(self::RESULT_INSTALLED, self::RESULT_UPTODATE))) { 652 if ($parentlang = $this->get_parent_language($this->current)) { 653 if (!$this->is_queued($parentlang) and !$this->was_processed($parentlang)) { 654 $this->add_to_queue($parentlang); 655 } 656 } 657 } 658 659 $this->mark_processed($this->current); 660 } 661 662 return $results; 663 } 664 665 /** 666 * Returns the URL where a given language pack can be downloaded 667 * 668 * Alternatively, if the parameter is empty, returns URL of the page with the 669 * list of all available language packs. 670 * 671 * @param string $langcode language code like 'cs' or empty for unknown 672 * @return string URL 673 */ 674 public function lang_pack_url($langcode = '') { 675 676 if (empty($langcode)) { 677 return 'https://download.moodle.org/langpack/'.$this->version.'/'; 678 } else { 679 return 'https://download.moodle.org/download.php/langpack/'.$this->version.'/'.$langcode.'.zip'; 680 } 681 } 682 683 /** 684 * Returns the list of available language packs from download.moodle.org 685 * 686 * @return array|bool false if can not download 687 */ 688 public function get_remote_list_of_languages() { 689 $source = 'https://download.moodle.org/langpack/' . $this->version . '/languages.md5'; 690 $availablelangs = array(); 691 692 if ($content = download_file_content($source)) { 693 $alllines = explode("\n", $content); 694 foreach($alllines as $line) { 695 if (!empty($line)){ 696 $availablelangs[] = explode(',', $line); 697 } 698 } 699 return $availablelangs; 700 701 } else { 702 return false; 703 } 704 } 705 706 // Internal implementation ///////////////////////////////////////////////// 707 708 /** 709 * Adds a language pack (or a list of them) to the queue 710 * 711 * @param string|array $langcodes code of the language to install or a list of them 712 */ 713 protected function add_to_queue($langcodes) { 714 if (is_array($langcodes)) { 715 $this->queue = array_merge($this->queue, $langcodes); 716 } else if (!empty($langcodes)) { 717 $this->queue[] = $langcodes; 718 } 719 } 720 721 /** 722 * Checks if the given language is queued or if the queue is empty 723 * 724 * @example $installer->is_queued('es'); // is Spanish going to be installed? 725 * @example $installer->is_queued(); // is there a language queued? 726 * 727 * @param string $langcode language code or empty string for "any" 728 * @return boolean 729 */ 730 protected function is_queued($langcode = '') { 731 732 if (empty($langcode)) { 733 return !empty($this->queue); 734 735 } else { 736 return in_array($langcode, $this->queue); 737 } 738 } 739 740 /** 741 * Checks if the given language has already been processed by this instance 742 * 743 * @see self::mark_processed() 744 * @param string $langcode 745 * @return boolean 746 */ 747 protected function was_processed($langcode) { 748 return isset($this->done[$langcode]); 749 } 750 751 /** 752 * Mark the given language pack as processed 753 * 754 * @see self::was_processed() 755 * @param string $langcode 756 */ 757 protected function mark_processed($langcode) { 758 $this->done[$langcode] = 1; 759 } 760 761 /** 762 * Returns a parent language of the given installed language 763 * 764 * @param string $langcode 765 * @return string parent language's code 766 */ 767 protected function get_parent_language($langcode) { 768 return get_parent_language($langcode); 769 } 770 771 /** 772 * Perform the actual language pack installation 773 * 774 * @uses component_installer 775 * @param string $langcode 776 * @return int return status 777 */ 778 protected function install_language_pack($langcode) { 779 780 // initialise new component installer to process this language 781 $installer = new component_installer('https://download.moodle.org', 'download.php/direct/langpack/' . $this->version, 782 $langcode . '.zip', 'languages.md5', 'lang'); 783 784 if (!$installer->requisitesok) { 785 throw new lang_installer_exception('installer_requisites_check_failed'); 786 } 787 788 $status = $installer->install(); 789 790 if ($status == COMPONENT_ERROR) { 791 if ($installer->get_error() === 'remotedownloaderror') { 792 return self::RESULT_DOWNLOADERROR; 793 } else { 794 throw new lang_installer_exception($installer->get_error(), $langcode); 795 } 796 797 } else if ($status == COMPONENT_UPTODATE) { 798 return self::RESULT_UPTODATE; 799 800 } else if ($status == COMPONENT_INSTALLED) { 801 return self::RESULT_INSTALLED; 802 803 } else { 804 throw new lang_installer_exception('unexpected_installer_result', $status); 805 } 806 } 807 } 808 809 810 /** 811 * Exception thrown by {@link lang_installer} 812 * 813 * @copyright 2011 David Mudrak <[email protected]> 814 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 815 */ 816 class lang_installer_exception extends moodle_exception { 817 818 public function __construct($errorcode, $debuginfo = null) { 819 parent::__construct($errorcode, 'error', '', null, $debuginfo); 820 } 821 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |