+<?php\r
+\r
+/**\r
+ * Represents a language and defines localizable string formatting and\r
+ * other functions, as well as the localized messages for HTML Purifier.\r
+ */\r
+class HTMLPurifier_Language\r
+{\r
+\r
+ /**\r
+ * ISO 639 language code of language. Prefers shortest possible version.\r
+ * @type string\r
+ */\r
+ public $code = 'en';\r
+\r
+ /**\r
+ * Fallback language code.\r
+ * @type bool|string\r
+ */\r
+ public $fallback = false;\r
+\r
+ /**\r
+ * Array of localizable messages.\r
+ * @type array\r
+ */\r
+ public $messages = array();\r
+\r
+ /**\r
+ * Array of localizable error codes.\r
+ * @type array\r
+ */\r
+ public $errorNames = array();\r
+\r
+ /**\r
+ * True if no message file was found for this language, so English\r
+ * is being used instead. Check this if you'd like to notify the\r
+ * user that they've used a non-supported language.\r
+ * @type bool\r
+ */\r
+ public $error = false;\r
+\r
+ /**\r
+ * Has the language object been loaded yet?\r
+ * @type bool\r
+ * @todo Make it private, fix usage in HTMLPurifier_LanguageTest\r
+ */\r
+ public $_loaded = false;\r
+\r
+ /**\r
+ * @type HTMLPurifier_Config\r
+ */\r
+ protected $config;\r
+\r
+ /**\r
+ * @type HTMLPurifier_Context\r
+ */\r
+ protected $context;\r
+\r
+ /**\r
+ * @param HTMLPurifier_Config $config\r
+ * @param HTMLPurifier_Context $context\r
+ */\r
+ public function __construct($config, $context)\r
+ {\r
+ $this->config = $config;\r
+ $this->context = $context;\r
+ }\r
+\r
+ /**\r
+ * Loads language object with necessary info from factory cache\r
+ * @note This is a lazy loader\r
+ */\r
+ public function load()\r
+ {\r
+ if ($this->_loaded) {\r
+ return;\r
+ }\r
+ $factory = HTMLPurifier_LanguageFactory::instance();\r
+ $factory->loadLanguage($this->code);\r
+ foreach ($factory->keys as $key) {\r
+ $this->$key = $factory->cache[$this->code][$key];\r
+ }\r
+ $this->_loaded = true;\r
+ }\r
+\r
+ /**\r
+ * Retrieves a localised message.\r
+ * @param string $key string identifier of message\r
+ * @return string localised message\r
+ */\r
+ public function getMessage($key)\r
+ {\r
+ if (!$this->_loaded) {\r
+ $this->load();\r
+ }\r
+ if (!isset($this->messages[$key])) {\r
+ return "[$key]";\r
+ }\r
+ return $this->messages[$key];\r
+ }\r
+\r
+ /**\r
+ * Retrieves a localised error name.\r
+ * @param int $int error number, corresponding to PHP's error reporting\r
+ * @return string localised message\r
+ */\r
+ public function getErrorName($int)\r
+ {\r
+ if (!$this->_loaded) {\r
+ $this->load();\r
+ }\r
+ if (!isset($this->errorNames[$int])) {\r
+ return "[Error: $int]";\r
+ }\r
+ return $this->errorNames[$int];\r
+ }\r
+\r
+ /**\r
+ * Converts an array list into a string readable representation\r
+ * @param array $array\r
+ * @return string\r
+ */\r
+ public function listify($array)\r
+ {\r
+ $sep = $this->getMessage('Item separator');\r
+ $sep_last = $this->getMessage('Item separator last');\r
+ $ret = '';\r
+ for ($i = 0, $c = count($array); $i < $c; $i++) {\r
+ if ($i == 0) {\r
+ } elseif ($i + 1 < $c) {\r
+ $ret .= $sep;\r
+ } else {\r
+ $ret .= $sep_last;\r
+ }\r
+ $ret .= $array[$i];\r
+ }\r
+ return $ret;\r
+ }\r
+\r
+ /**\r
+ * Formats a localised message with passed parameters\r
+ * @param string $key string identifier of message\r
+ * @param array $args Parameters to substitute in\r
+ * @return string localised message\r
+ * @todo Implement conditionals? Right now, some messages make\r
+ * reference to line numbers, but those aren't always available\r
+ */\r
+ public function formatMessage($key, $args = array())\r
+ {\r
+ if (!$this->_loaded) {\r
+ $this->load();\r
+ }\r
+ if (!isset($this->messages[$key])) {\r
+ return "[$key]";\r
+ }\r
+ $raw = $this->messages[$key];\r
+ $subst = array();\r
+ $generator = false;\r
+ foreach ($args as $i => $value) {\r
+ if (is_object($value)) {\r
+ if ($value instanceof HTMLPurifier_Token) {\r
+ // factor this out some time\r
+ if (!$generator) {\r
+ $generator = $this->context->get('Generator');\r
+ }\r
+ if (isset($value->name)) {\r
+ $subst['$'.$i.'.Name'] = $value->name;\r
+ }\r
+ if (isset($value->data)) {\r
+ $subst['$'.$i.'.Data'] = $value->data;\r
+ }\r
+ $subst['$'.$i.'.Compact'] =\r
+ $subst['$'.$i.'.Serialized'] = $generator->generateFromToken($value);\r
+ // a more complex algorithm for compact representation\r
+ // could be introduced for all types of tokens. This\r
+ // may need to be factored out into a dedicated class\r
+ if (!empty($value->attr)) {\r
+ $stripped_token = clone $value;\r
+ $stripped_token->attr = array();\r
+ $subst['$'.$i.'.Compact'] = $generator->generateFromToken($stripped_token);\r
+ }\r
+ $subst['$'.$i.'.Line'] = $value->line ? $value->line : 'unknown';\r
+ }\r
+ continue;\r
+ } elseif (is_array($value)) {\r
+ $keys = array_keys($value);\r
+ if (array_keys($keys) === $keys) {\r
+ // list\r
+ $subst['$'.$i] = $this->listify($value);\r
+ } else {\r
+ // associative array\r
+ // no $i implementation yet, sorry\r
+ $subst['$'.$i.'.Keys'] = $this->listify($keys);\r
+ $subst['$'.$i.'.Values'] = $this->listify(array_values($value));\r
+ }\r
+ continue;\r
+ }\r
+ $subst['$' . $i] = $value;\r
+ }\r
+ return strtr($raw, $subst);\r
+ }\r
+}\r
+\r
+// vim: et sw=4 sts=4\r