00001 <?php
00002
00003 class HTMLPurifier_ConfigSchema_InterchangeBuilder
00004 {
00005
00009 protected $varParser;
00010
00011 public function __construct($varParser = null) {
00012 $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
00013 }
00014
00015 public static function buildFromDirectory($dir = null) {
00016 $parser = new HTMLPurifier_StringHashParser();
00017 $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
00018 $interchange = new HTMLPurifier_ConfigSchema_Interchange();
00019
00020 if (!$dir) $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema/';
00021 $info = parse_ini_file($dir . 'info.ini');
00022 $interchange->name = $info['name'];
00023
00024 $files = array();
00025 $dh = opendir($dir);
00026 while (false !== ($file = readdir($dh))) {
00027 if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') {
00028 continue;
00029 }
00030 $files[] = $file;
00031 }
00032 closedir($dh);
00033
00034 sort($files);
00035 foreach ($files as $file) {
00036 $builder->build(
00037 $interchange,
00038 new HTMLPurifier_StringHash( $parser->parseFile($dir . $file) )
00039 );
00040 }
00041
00042 return $interchange;
00043 }
00044
00050 public function build($interchange, $hash) {
00051 if (!$hash instanceof HTMLPurifier_StringHash) {
00052 $hash = new HTMLPurifier_StringHash($hash);
00053 }
00054 if (!isset($hash['ID'])) {
00055 throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
00056 }
00057 if (strpos($hash['ID'], '.') === false) {
00058 $this->buildNamespace($interchange, $hash);
00059 } else {
00060 $this->buildDirective($interchange, $hash);
00061 }
00062 $this->_findUnused($hash);
00063 }
00064
00065 public function buildNamespace($interchange, $hash) {
00066 $namespace = new HTMLPurifier_ConfigSchema_Interchange_Namespace();
00067 $namespace->namespace = $hash->offsetGet('ID');
00068 if (isset($hash['DESCRIPTION'])) {
00069 $namespace->description = $hash->offsetGet('DESCRIPTION');
00070 }
00071 $interchange->addNamespace($namespace);
00072 }
00073
00074 public function buildDirective($interchange, $hash) {
00075 $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
00076
00077
00078 $directive->id = $this->id($hash->offsetGet('ID'));
00079 $id = $directive->id->toString();
00080
00081 if (isset($hash['TYPE'])) {
00082 $type = explode('/', $hash->offsetGet('TYPE'));
00083 if (isset($type[1])) $directive->typeAllowsNull = true;
00084 $directive->type = $type[0];
00085 } else {
00086 throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
00087 }
00088
00089 if (isset($hash['DEFAULT'])) {
00090 try {
00091 $directive->default = $this->varParser->parse($hash->offsetGet('DEFAULT'), $directive->type, $directive->typeAllowsNull);
00092 } catch (HTMLPurifier_VarParserException $e) {
00093 throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
00094 }
00095 }
00096
00097 if (isset($hash['DESCRIPTION'])) {
00098 $directive->description = $hash->offsetGet('DESCRIPTION');
00099 }
00100
00101 if (isset($hash['ALLOWED'])) {
00102 $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED')));
00103 }
00104
00105 if (isset($hash['VALUE-ALIASES'])) {
00106 $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
00107 }
00108
00109 if (isset($hash['ALIASES'])) {
00110 $raw_aliases = trim($hash->offsetGet('ALIASES'));
00111 $aliases = preg_split('/\s*,\s*/', $raw_aliases);
00112 foreach ($aliases as $alias) {
00113 $directive->aliases[] = $this->id($alias);
00114 }
00115 }
00116
00117 if (isset($hash['VERSION'])) {
00118 $directive->version = $hash->offsetGet('VERSION');
00119 }
00120
00121 if (isset($hash['DEPRECATED-USE'])) {
00122 $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE'));
00123 }
00124
00125 if (isset($hash['DEPRECATED-VERSION'])) {
00126 $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION');
00127 }
00128
00129 if (isset($hash['EXTERNAL'])) {
00130 $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL')));
00131 }
00132
00133 $interchange->addDirective($directive);
00134 }
00135
00139 protected function evalArray($contents) {
00140 return eval('return array('. $contents .');');
00141 }
00142
00146 protected function lookup($array) {
00147 $ret = array();
00148 foreach ($array as $val) $ret[$val] = true;
00149 return $ret;
00150 }
00151
00156 protected function id($id) {
00157 return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
00158 }
00159
00165 protected function _findUnused($hash) {
00166 $accessed = $hash->getAccessed();
00167 foreach ($hash as $k => $v) {
00168 if (!isset($accessed[$k])) {
00169 trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE);
00170 }
00171 }
00172 }
00173
00174 }
00175