Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/componentlib.class.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00128 defined('MOODLE_INTERNAL') || die();
00129 
00134 global $CFG;
00135 require_once($CFG->libdir.'/filelib.php');
00136 
00137 // Some needed constants
00138 define('COMPONENT_ERROR',           0);
00139 define('COMPONENT_UPTODATE',        1);
00140 define('COMPONENT_NEEDUPDATE',      2);
00141 define('COMPONENT_INSTALLED',       3);
00142 
00155 class component_installer {
00159     var $sourcebase;   
00160     var $zippath;      
00161 
00162     var $zipfilename;  
00163     var $md5filename;  
00164     var $componentname;
00165 
00166 
00167 
00168     var $destpath;     
00169 
00170     var $errorstring;  
00171     var $extramd5info; 
00172     var $requisitesok; 
00173 
00176     var $cachedmd5components; 
00177 
00178 
00193     function component_installer ($sourcebase, $zippath, $zipfilename, $md5filename='', $destpath='') {
00194 
00195         $this->sourcebase   = $sourcebase;
00196         $this->zippath      = $zippath;
00197         $this->zipfilename  = $zipfilename;
00198         $this->md5filename  = $md5filename;
00199         $this->componentname= '';
00200         $this->destpath     = $destpath;
00201         $this->errorstring  = '';
00202         $this->extramd5info = '';
00203         $this->requisitesok = false;
00204         $this->cachedmd5components = array();
00205 
00206         $this->check_requisites();
00207     }
00208 
00217     function check_requisites() {
00218         global $CFG;
00219 
00220         $this->requisitesok = false;
00221 
00223         if (empty($this->sourcebase) || empty($this->zippath) || empty($this->zipfilename)) {
00224             $this->errorstring='missingrequiredfield';
00225             return false;
00226         }
00228         if ($this->sourcebase != 'http://download.moodle.org') {
00229             $this->errorstring='wrongsourcebase';
00230             return false;
00231         }
00233         if (stripos($this->zipfilename, '.zip') === false) {
00234             $this->errorstring='wrongzipfilename';
00235             return false;
00236         }
00238         if (!empty($this->destpath)) {
00239             if (!file_exists($CFG->dataroot.'/'.$this->destpath)) {
00240                 $this->errorstring='wrongdestpath';
00241                 return false;
00242             }
00243         }
00245         $pos = stripos($this->zipfilename, '.zip');
00246         $this->componentname = substr($this->zipfilename, 0, $pos);
00248         if (empty($this->md5filename)) {
00249             $this->md5filename = $this->componentname.'.md5';
00250         }
00252         $this->requisitesok = true;
00253         return true;
00254     }
00255 
00268     function install() {
00269 
00270         global $CFG;
00271 
00273         if (!$this->requisitesok) {
00274             return COMPONENT_ERROR;
00275         }
00277         if ($this->need_upgrade() === COMPONENT_ERROR) {
00278             return COMPONENT_ERROR;
00279         } else if ($this->need_upgrade() === COMPONENT_UPTODATE) {
00280             $this->errorstring='componentisuptodate';
00281             return COMPONENT_UPTODATE;
00282         }
00284         if (!make_temp_directory('', false)) {
00285              $this->errorstring='cannotcreatetempdir';
00286              return COMPONENT_ERROR;
00287         }
00289         $source = $this->sourcebase.'/'.$this->zippath.'/'.$this->zipfilename;
00290         $zipfile= $CFG->tempdir.'/'.$this->zipfilename;
00291 
00292         if($contents = download_file_content($source)) {
00293             if ($file = fopen($zipfile, 'w')) {
00294                 if (!fwrite($file, $contents)) {
00295                     fclose($file);
00296                     $this->errorstring='cannotsavezipfile';
00297                     return COMPONENT_ERROR;
00298                 }
00299             } else {
00300                 $this->errorstring='cannotsavezipfile';
00301                 return COMPONENT_ERROR;
00302             }
00303             fclose($file);
00304         } else {
00305             $this->errorstring='cannotdownloadzipfile';
00306             return COMPONENT_ERROR;
00307         }
00309         $new_md5 = md5($contents);
00311         if (!$remote_md5 = $this->get_component_md5()) {
00312             return COMPONENT_ERROR;
00313         }
00314         if ($new_md5 != $remote_md5) {
00315             $this->errorstring='downloadedfilecheckfailed';
00316             return COMPONENT_ERROR;
00317         }
00319         $destinationdir = $CFG->dataroot.'/'.$this->destpath;
00320         $destinationcomponent = $destinationdir.'/'.$this->componentname;
00321         @remove_dir($destinationcomponent.'_old');     //Deleting possible old components before
00322         @rename ($destinationcomponent, $destinationcomponent.'_old');  //Moving to a safe place
00324         if (!unzip_file($zipfile, $destinationdir, false)) {
00326             @remove_dir($destinationcomponent);
00327             @rename ($destinationcomponent.'_old', $destinationcomponent);
00328             $this->errorstring='cannotunzipfile';
00329             return COMPONENT_ERROR;
00330         }
00332         @remove_dir($destinationcomponent.'_old');
00334         if ($file = fopen($destinationcomponent.'/'.$this->componentname.'.md5', 'w')) {
00335             if (!fwrite($file, $new_md5)) {
00336                 fclose($file);
00337                 $this->errorstring='cannotsavemd5file';
00338                 return COMPONENT_ERROR;
00339             }
00340         } else  {
00341             $this->errorstring='cannotsavemd5file';
00342             return COMPONENT_ERROR;
00343         }
00344         fclose($file);
00346         @unlink($zipfile);
00347 
00348         return COMPONENT_INSTALLED;
00349     }
00350 
00360     function need_upgrade() {
00361 
00363         if (!$this->requisitesok) {
00364             return COMPONENT_ERROR;
00365         }
00367         $local_md5 = $this->get_local_md5();
00369         if (!$remote_md5 = $this->get_component_md5()) {
00370             return COMPONENT_ERROR;
00371         }
00373        if ($local_md5 == $remote_md5) {
00374            return COMPONENT_UPTODATE;
00375        } else {
00376            return COMPONENT_NEEDUPDATE;
00377        }
00378     }
00379 
00388     function change_zip_file($newzipfilename) {
00389 
00390         $this->zipfilename = $newzipfilename;
00391         return $this->check_requisites();
00392     }
00393 
00401     function get_local_md5() {
00402         global $CFG;
00403 
00405         if (!$this->requisitesok) {
00406             return false;
00407         }
00408 
00409         $return_value = 'needtobeinstalled';   
00410 
00412        $source = $CFG->dataroot.'/'.$this->destpath.'/'.$this->componentname.'/'.$this->componentname.'.md5';
00414        if (file_exists($source)) {
00415            if ($temp = file_get_contents($source)) {
00416                $return_value = $temp;
00417            }
00418         }
00419         return $return_value;
00420     }
00421 
00430     function get_component_md5() {
00431 
00433         if (!$this->requisitesok) {
00434             return false;
00435         }
00437         if (!$comp_arr = $this->get_all_components_md5()) {
00438             if (empty($this->errorstring)) {
00439                 $this->errorstring='cannotdownloadcomponents';
00440             }
00441             return false;
00442         }
00444         if (empty($comp_arr[$this->componentname]) || !$component = $comp_arr[$this->componentname]) {
00445              $this->errorstring='cannotfindcomponent';
00446              return false;
00447         }
00449         if (empty($component[1]) || strlen($component[1]) != 32) {
00450             $this->errorstring='invalidmd5';
00451             return false;
00452         }
00454         if (!empty($component[2])) {
00455             $this->extramd5info = $component[2];
00456         }
00457         return $component[1];
00458     }
00459 
00466     function get_all_components_md5() {
00467 
00469         if (!$this->requisitesok) {
00470             return false;
00471         }
00472 
00474         $comp_arr = array();
00475 
00477         $source = $this->sourcebase.'/'.$this->zippath.'/'.$this->md5filename;
00478 
00480         if (!empty($this->cachedmd5components[$source])) {
00481             $comp_arr = $this->cachedmd5components[$source];
00482         } else {
00484             $availablecomponents = array();
00485 
00486             if ($contents = download_file_content($source)) {
00488                 $lines=preg_split('/\r?\n/',$contents);
00490                 foreach($lines as $line) {
00491                     $availablecomponents[] = explode(',', $line);
00492                 }
00494                 if (empty($availablecomponents)) {
00495                     $this->errorstring='cannotdownloadcomponents';
00496                     return false;
00497                 }
00500                 $comp_arr = array();
00501                 foreach ($availablecomponents as $component) {
00503                     if (empty($component[0])) {
00504                         continue;
00505                     }
00506                     $component[0]=trim($component[0]);
00507                     if (!empty($component[1])) {
00508                         $component[1]=trim($component[1]);
00509                     }
00510                     if (!empty($component[2])) {
00511                         $component[2]=trim($component[2]);
00512                     }
00513                     $comp_arr[$component[0]] = $component;
00514                 }
00516                 $this->cachedmd5components[$source] = $comp_arr;
00517             } else {
00519                 $this->errorstring='remotedownloaderror';
00520                 return false;
00521             }
00522         }
00524         if (!empty($this->errorstring)) {
00525              return false;
00526 
00527         } else if (empty($comp_arr)) {
00528              $this->errorstring='cannotdownloadcomponents';
00529              return false;
00530         }
00531         return $comp_arr;
00532     }
00533 
00539     function get_error() {
00540         return $this->errorstring;
00541     }
00542 
00547     function get_extra_md5_field() {
00548         return $this->extramd5info;
00549     }
00550 
00551 } 
00552 
00553 
00567 class lang_installer {
00568 
00570     const RESULT_INSTALLED      = 'installed';
00572     const RESULT_UPTODATE       = 'uptodate';
00574     const RESULT_DOWNLOADERROR  = 'downloaderror';
00575 
00577     protected $queue = array();
00579     protected $current;
00581     protected $done = array();
00583     protected $version;
00584 
00591     public function __construct($langcode = '') {
00592         global $CFG;
00593 
00594         $this->set_queue($langcode);
00595         $this->version = '2.2';
00596 
00597         if (!empty($CFG->langotherroot) and $CFG->langotherroot !== $CFG->dataroot . '/lang') {
00598             debugging('The in-built language pack installer does not support alternative location ' .
00599                 'of languages root directory. You are supposed to install and update your language '.
00600                 'packs on your own.');
00601         }
00602     }
00603 
00609     public function set_queue($langcodes) {
00610         if (is_array($langcodes)) {
00611             $this->queue = $langcodes;
00612         } else if (!empty($langcodes)) {
00613             $this->queue = array($langcodes);
00614         }
00615     }
00616 
00625     public function run() {
00626 
00627         $results = array();
00628 
00629         while ($this->current = array_shift($this->queue)) {
00630 
00631             if ($this->was_processed($this->current)) {
00632                 // do not repeat yourself
00633                 continue;
00634             }
00635 
00636             if ($this->current === 'en') {
00637                 $this->mark_processed($this->current);
00638                 continue;
00639             }
00640 
00641             $results[$this->current] = $this->install_language_pack($this->current);
00642 
00643             if (in_array($results[$this->current], array(self::RESULT_INSTALLED, self::RESULT_UPTODATE))) {
00644                 if ($parentlang = $this->get_parent_language($this->current)) {
00645                     if (!$this->is_queued($parentlang) and !$this->was_processed($parentlang)) {
00646                         $this->add_to_queue($parentlang);
00647                     }
00648                 }
00649             }
00650 
00651             $this->mark_processed($this->current);
00652         }
00653 
00654         return $results;
00655     }
00656 
00666     public function lang_pack_url($langcode = '') {
00667 
00668         if (empty($langcode)) {
00669             return 'http://download.moodle.org/langpack/'.$this->version.'/';
00670         } else {
00671             return 'http://download.moodle.org/download.php/langpack/'.$this->version.'/'.$langcode.'.zip';
00672         }
00673     }
00674 
00680     public function get_remote_list_of_languages() {
00681         $source = 'http://download.moodle.org/langpack/' . $this->version . '/languages.md5';
00682         $availablelangs = array();
00683 
00684         if ($content = download_file_content($source)) {
00685             $alllines = explode("\n", $content);
00686             foreach($alllines as $line) {
00687                 if (!empty($line)){
00688                     $availablelangs[] = explode(',', $line);
00689                 }
00690             }
00691             return $availablelangs;
00692 
00693         } else {
00694             return false;
00695         }
00696     }
00697 
00698     // Internal implementation /////////////////////////////////////////////////
00699 
00705     protected function add_to_queue($langcodes) {
00706         if (is_array($langcodes)) {
00707             $this->queue = array_merge($this->queue, $langcodes);
00708         } else if (!empty($langcodes)) {
00709             $this->queue[] = $langcodes;
00710         }
00711     }
00712 
00722     protected function is_queued($langcode = '') {
00723 
00724         if (empty($langcode)) {
00725             return !empty($this->queue);
00726 
00727         } else {
00728             return in_array($langcode, $this->queue);
00729         }
00730     }
00731 
00739     protected function was_processed($langcode) {
00740         return isset($this->done[$langcode]);
00741     }
00742 
00749     protected function mark_processed($langcode) {
00750         $this->done[$langcode] = 1;
00751     }
00752 
00759     protected function get_parent_language($langcode) {
00760         return get_parent_language($langcode);
00761     }
00762 
00770     protected function install_language_pack($langcode) {
00771 
00772         // initialise new component installer to process this language
00773         $installer = new component_installer('http://download.moodle.org', 'download.php/direct/langpack/' . $this->version,
00774             $langcode . '.zip', 'languages.md5', 'lang');
00775 
00776         if (!$installer->requisitesok) {
00777             throw new lang_installer_exception('installer_requisites_check_failed');
00778         }
00779 
00780         $status = $installer->install();
00781 
00782         if ($status == COMPONENT_ERROR) {
00783             if ($installer->get_error() === 'remotedownloaderror') {
00784                 return self::RESULT_DOWNLOADERROR;
00785             } else {
00786                 throw new lang_installer_exception($installer->get_error(), $langcode);
00787             }
00788 
00789         } else if ($status == COMPONENT_UPTODATE) {
00790             return self::RESULT_UPTODATE;
00791 
00792         } else if ($status == COMPONENT_INSTALLED) {
00793             return self::RESULT_INSTALLED;
00794 
00795         } else {
00796             throw new lang_installer_exception('unexpected_installer_result', $status);
00797         }
00798     }
00799 }
00800 
00801 
00808 class lang_installer_exception extends moodle_exception {
00809 
00810     public function __construct($errorcode, $debuginfo = null) {
00811         parent::__construct($errorcode, 'error', '', null, $debuginfo);
00812     }
00813 }
 All Data Structures Namespaces Files Functions Variables Enumerations