From ff60e09780075d0ae609e055fb70a03ed2d5d04f Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Wed, 5 Mar 2008 04:41:45 +0000 Subject: [PATCH] Refactor VarParser and VarParser_Flexible to use template method, factoring out common functionality. git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1603 48356398-32a2-884e-a903-53898d9a118a --- library/HTMLPurifier/VarParser.php | 81 +++++++++++++++++++++++++++-- library/HTMLPurifier/VarParser/Flexible.php | 19 ++----- 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/library/HTMLPurifier/VarParser.php b/library/HTMLPurifier/VarParser.php index 1d07329a..bb0313f1 100644 --- a/library/HTMLPurifier/VarParser.php +++ b/library/HTMLPurifier/VarParser.php @@ -2,9 +2,9 @@ /** * Parses string representations into their corresponding native PHP - * variable type. + * variable type. The base implementation does a simple type-check. */ -abstract class HTMLPurifier_VarParser +class HTMLPurifier_VarParser { /** @@ -34,6 +34,81 @@ abstract class HTMLPurifier_VarParser * @param $allow_null Whether or not to permit null as a value * @return Validated and type-coerced variable */ - abstract public function parse($var, $type, $allow_null = false); + final public function parse($var, $type, $allow_null = false) { + if (!isset(HTMLPurifier_VarParser::$types[$type])) { + throw new HTMLPurifier_VarParserException("Invalid type $type"); + } + $var = $this->parseImplementation($var, $type, $allow_null); + if ($allow_null && $var === null) return null; + // These are basic checks, to make sure nothing horribly wrong + // happened in our implementations. + switch ($type) { + case 'string': + case 'istring': + case 'text': + case 'itext': + if (!is_string($var)) break; + if ($type[0] == 'i') $var = strtolower($var); + return $var; + case 'int': + if (!is_int($var)) break; + return $var; + case 'float': + if (!is_float($var)) break; + return $var; + case 'bool': + if (!is_bool($var)) break; + return $var; + case 'lookup': + case 'list': + case 'hash': + if (!is_array($var)) break; + if ($type === 'lookup') { + foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true'); + } elseif ($type === 'list') { + $keys = array_keys($var); + if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform'); + } + return $var; + case 'mixed': + return $var; + default: + $this->errorInconsistent(__CLASS__, $type); + } + $this->errorGeneric($var, $type); + } + + /** + * Actually implements the parsing. Base implementation is to not + * do anything to $var. Subclasses should overload this! + */ + protected function parseImplementation($var, $type, $allow_null) { + return $var; + } + + /** + * Throws an exception. + */ + protected function error($msg) { + throw new HTMLPurifier_VarParserException($msg); + } + + /** + * Throws an inconsistency exception. + * @note This should not ever be called. It would be called if we + * extend the allowed values of HTMLPurifier_VarParser without + * updating subclasses. + */ + protected function errorInconsistent($class, $type) { + throw new HTMLPurifier_Exception("Inconsistency in $class: $type not implemented"); + } + + /** + * Generic error for if a type didn't work. + */ + protected function errorGeneric($var, $type) { + $vtype = gettype($var); + $this->error("Expected type $type, got $vtype"); + } } diff --git a/library/HTMLPurifier/VarParser/Flexible.php b/library/HTMLPurifier/VarParser/Flexible.php index fcec974b..1c5ddcb7 100644 --- a/library/HTMLPurifier/VarParser/Flexible.php +++ b/library/HTMLPurifier/VarParser/Flexible.php @@ -8,31 +8,23 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser { - public function parse($var, $type, $allow_null = false) { - if (!isset(HTMLPurifier_VarParser::$types[$type])) { - throw new HTMLPurifier_VarParserException("Invalid type $type"); - } + protected function parseImplementation($var, $type, $allow_null) { if ($allow_null && $var === null) return null; switch ($type) { // Note: if code "breaks" from the switch, it triggers a generic // exception to be thrown. Specific errors can be specifically // done here. case 'mixed': - return $var; case 'istring': case 'string': - case 'text': // no difference, just is longer/multiple line string + case 'text': case 'itext': - if (!is_string($var)) break; - if ($type === 'istring' || $type === 'itext') $var = strtolower($var); return $var; case 'int': if (is_string($var) && ctype_digit($var)) $var = (int) $var; - elseif (!is_int($var)) break; return $var; case 'float': if (is_string($var) && is_numeric($var)) $var = (float) $var; - elseif (!is_float($var)) break; return $var; case 'bool': if (is_int($var) && ($var === 0 || $var === 1)) { @@ -45,7 +37,7 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser } else { throw new HTMLPurifier_VarParserException("Unrecognized value '$var' for $type"); } - } elseif (!is_bool($var)) break; + } return $var; case 'list': case 'hash': @@ -94,10 +86,9 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser } return $var; default: - // This should not happen! - throw new HTMLPurifier_Exception("Inconsistency in HTMLPurifier_VarParser_Flexible: $type is not implemented"); + $this->errorInconsistent(__CLASS__, $type); } - throw new HTMLPurifier_VarParserException("Invalid input for type $type"); + $this->errorGeneric($var, $type); } } -- 2.11.4.GIT