HTMLPurifier 4.4.0
/home/ezyang/Dev/htmlpurifier/library/HTMLPurifier/LanguageFactory.php
Go to the documentation of this file.
00001 <?php
00002 
00010 class HTMLPurifier_LanguageFactory
00011 {
00012 
00018     public $cache;
00019 
00025     public $keys = array('fallback', 'messages', 'errorNames');
00026 
00031     protected $validator;
00032 
00038     protected $dir;
00039 
00044     protected $mergeable_keys_map = array('messages' => true, 'errorNames' => true);
00045 
00050     protected $mergeable_keys_list = array();
00051 
00057     public static function instance($prototype = null) {
00058         static $instance = null;
00059         if ($prototype !== null) {
00060             $instance = $prototype;
00061         } elseif ($instance === null || $prototype == true) {
00062             $instance = new HTMLPurifier_LanguageFactory();
00063             $instance->setup();
00064         }
00065         return $instance;
00066     }
00067 
00072     public function setup() {
00073         $this->validator = new HTMLPurifier_AttrDef_Lang();
00074         $this->dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier';
00075     }
00076 
00083     public function create($config, $context, $code = false) {
00084 
00085         // validate language code
00086         if ($code === false) {
00087             $code = $this->validator->validate(
00088               $config->get('Core.Language'), $config, $context
00089             );
00090         } else {
00091             $code = $this->validator->validate($code, $config, $context);
00092         }
00093         if ($code === false) $code = 'en'; // malformed code becomes English
00094 
00095         $pcode = str_replace('-', '_', $code); // make valid PHP classname
00096         static $depth = 0; // recursion protection
00097 
00098         if ($code == 'en') {
00099             $lang = new HTMLPurifier_Language($config, $context);
00100         } else {
00101             $class = 'HTMLPurifier_Language_' . $pcode;
00102             $file  = $this->dir . '/Language/classes/' . $code . '.php';
00103             if (file_exists($file) || class_exists($class, false)) {
00104                 $lang = new $class($config, $context);
00105             } else {
00106                 // Go fallback
00107                 $raw_fallback = $this->getFallbackFor($code);
00108                 $fallback = $raw_fallback ? $raw_fallback : 'en';
00109                 $depth++;
00110                 $lang = $this->create($config, $context, $fallback);
00111                 if (!$raw_fallback) {
00112                     $lang->error = true;
00113                 }
00114                 $depth--;
00115             }
00116         }
00117 
00118         $lang->code = $code;
00119 
00120         return $lang;
00121 
00122     }
00123 
00129     public function getFallbackFor($code) {
00130         $this->loadLanguage($code);
00131         return $this->cache[$code]['fallback'];
00132     }
00133 
00138     public function loadLanguage($code) {
00139         static $languages_seen = array(); // recursion guard
00140 
00141         // abort if we've already loaded it
00142         if (isset($this->cache[$code])) return;
00143 
00144         // generate filename
00145         $filename = $this->dir . '/Language/messages/' . $code . '.php';
00146 
00147         // default fallback : may be overwritten by the ensuing include
00148         $fallback = ($code != 'en') ? 'en' : false;
00149 
00150         // load primary localisation
00151         if (!file_exists($filename)) {
00152             // skip the include: will rely solely on fallback
00153             $filename = $this->dir . '/Language/messages/en.php';
00154             $cache = array();
00155         } else {
00156             include $filename;
00157             $cache = compact($this->keys);
00158         }
00159 
00160         // load fallback localisation
00161         if (!empty($fallback)) {
00162 
00163             // infinite recursion guard
00164             if (isset($languages_seen[$code])) {
00165                 trigger_error('Circular fallback reference in language ' .
00166                     $code, E_USER_ERROR);
00167                 $fallback = 'en';
00168             }
00169             $language_seen[$code] = true;
00170 
00171             // load the fallback recursively
00172             $this->loadLanguage($fallback);
00173             $fallback_cache = $this->cache[$fallback];
00174 
00175             // merge fallback with current language
00176             foreach ( $this->keys as $key ) {
00177                 if (isset($cache[$key]) && isset($fallback_cache[$key])) {
00178                     if (isset($this->mergeable_keys_map[$key])) {
00179                         $cache[$key] = $cache[$key] + $fallback_cache[$key];
00180                     } elseif (isset($this->mergeable_keys_list[$key])) {
00181                         $cache[$key] = array_merge( $fallback_cache[$key], $cache[$key] );
00182                     }
00183                 } else {
00184                     $cache[$key] = $fallback_cache[$key];
00185                 }
00186             }
00187 
00188         }
00189 
00190         // save to cache for later retrieval
00191         $this->cache[$code] = $cache;
00192 
00193         return;
00194     }
00195 
00196 }
00197 
00198 // vim: et sw=4 sts=4