Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  
   3  /**
   4   * Represents a language and defines localizable string formatting and
   5   * other functions, as well as the localized messages for HTML Purifier.
   6   */
   7  class HTMLPurifier_Language
   8  {
   9  
  10      /**
  11       * ISO 639 language code of language. Prefers shortest possible version.
  12       * @type string
  13       */
  14      public $code = 'en';
  15  
  16      /**
  17       * Fallback language code.
  18       * @type bool|string
  19       */
  20      public $fallback = false;
  21  
  22      /**
  23       * Array of localizable messages.
  24       * @type array
  25       */
  26      public $messages = array();
  27  
  28      /**
  29       * Array of localizable error codes.
  30       * @type array
  31       */
  32      public $errorNames = array();
  33  
  34      /**
  35       * True if no message file was found for this language, so English
  36       * is being used instead. Check this if you'd like to notify the
  37       * user that they've used a non-supported language.
  38       * @type bool
  39       */
  40      public $error = false;
  41  
  42      /**
  43       * Has the language object been loaded yet?
  44       * @type bool
  45       * @todo Make it private, fix usage in HTMLPurifier_LanguageTest
  46       */
  47      public $_loaded = false;
  48  
  49      /**
  50       * @type HTMLPurifier_Config
  51       */
  52      protected $config;
  53  
  54      /**
  55       * @type HTMLPurifier_Context
  56       */
  57      protected $context;
  58  
  59      /**
  60       * @param HTMLPurifier_Config $config
  61       * @param HTMLPurifier_Context $context
  62       */
  63      public function __construct($config, $context)
  64      {
  65          $this->config  = $config;
  66          $this->context = $context;
  67      }
  68  
  69      /**
  70       * Loads language object with necessary info from factory cache
  71       * @note This is a lazy loader
  72       */
  73      public function load()
  74      {
  75          if ($this->_loaded) {
  76              return;
  77          }
  78          $factory = HTMLPurifier_LanguageFactory::instance();
  79          $factory->loadLanguage($this->code);
  80          foreach ($factory->keys as $key) {
  81              $this->$key = $factory->cache[$this->code][$key];
  82          }
  83          $this->_loaded = true;
  84      }
  85  
  86      /**
  87       * Retrieves a localised message.
  88       * @param string $key string identifier of message
  89       * @return string localised message
  90       */
  91      public function getMessage($key)
  92      {
  93          if (!$this->_loaded) {
  94              $this->load();
  95          }
  96          if (!isset($this->messages[$key])) {
  97              return "[$key]";
  98          }
  99          return $this->messages[$key];
 100      }
 101  
 102      /**
 103       * Retrieves a localised error name.
 104       * @param int $int error number, corresponding to PHP's error reporting
 105       * @return string localised message
 106       */
 107      public function getErrorName($int)
 108      {
 109          if (!$this->_loaded) {
 110              $this->load();
 111          }
 112          if (!isset($this->errorNames[$int])) {
 113              return "[Error: $int]";
 114          }
 115          return $this->errorNames[$int];
 116      }
 117  
 118      /**
 119       * Converts an array list into a string readable representation
 120       * @param array $array
 121       * @return string
 122       */
 123      public function listify($array)
 124      {
 125          $sep      = $this->getMessage('Item separator');
 126          $sep_last = $this->getMessage('Item separator last');
 127          $ret = '';
 128          for ($i = 0, $c = count($array); $i < $c; $i++) {
 129              if ($i == 0) {
 130              } elseif ($i + 1 < $c) {
 131                  $ret .= $sep;
 132              } else {
 133                  $ret .= $sep_last;
 134              }
 135              $ret .= $array[$i];
 136          }
 137          return $ret;
 138      }
 139  
 140      /**
 141       * Formats a localised message with passed parameters
 142       * @param string $key string identifier of message
 143       * @param array $args Parameters to substitute in
 144       * @return string localised message
 145       * @todo Implement conditionals? Right now, some messages make
 146       *     reference to line numbers, but those aren't always available
 147       */
 148      public function formatMessage($key, $args = array())
 149      {
 150          if (!$this->_loaded) {
 151              $this->load();
 152          }
 153          if (!isset($this->messages[$key])) {
 154              return "[$key]";
 155          }
 156          $raw = $this->messages[$key];
 157          $subst = array();
 158          $generator = false;
 159          foreach ($args as $i => $value) {
 160              if (is_object($value)) {
 161                  if ($value instanceof HTMLPurifier_Token) {
 162                      // factor this out some time
 163                      if (!$generator) {
 164                          $generator = $this->context->get('Generator');
 165                      }
 166                      if (isset($value->name)) {
 167                          $subst['$'.$i.'.Name'] = $value->name;
 168                      }
 169                      if (isset($value->data)) {
 170                          $subst['$'.$i.'.Data'] = $value->data;
 171                      }
 172                      $subst['$'.$i.'.Compact'] =
 173                      $subst['$'.$i.'.Serialized'] = $generator->generateFromToken($value);
 174                      // a more complex algorithm for compact representation
 175                      // could be introduced for all types of tokens. This
 176                      // may need to be factored out into a dedicated class
 177                      if (!empty($value->attr)) {
 178                          $stripped_token = clone $value;
 179                          $stripped_token->attr = array();
 180                          $subst['$'.$i.'.Compact'] = $generator->generateFromToken($stripped_token);
 181                      }
 182                      $subst['$'.$i.'.Line'] = $value->line ? $value->line : 'unknown';
 183                  }
 184                  continue;
 185              } elseif (is_array($value)) {
 186                  $keys = array_keys($value);
 187                  if (array_keys($keys) === $keys) {
 188                      // list
 189                      $subst['$'.$i] = $this->listify($value);
 190                  } else {
 191                      // associative array
 192                      // no $i implementation yet, sorry
 193                      $subst['$'.$i.'.Keys'] = $this->listify($keys);
 194                      $subst['$'.$i.'.Values'] = $this->listify(array_values($value));
 195                  }
 196                  continue;
 197              }
 198              $subst['$' . $i] = $value;
 199          }
 200          return strtr($raw, $subst);
 201      }
 202  }
 203  
 204  // vim: et sw=4 sts=4