[limb-svn] r4160 - in 3.x/packages/wact/trunk: framework/template/compiler framework/template/compiler/parser framework/template/compiler/tags tests/cases/template/compiler tests/cases/template/filters
svn at limb-project.com
svn at limb-project.com
Sun Oct 15 23:52:26 MSD 2006
Author: serega
Date: 2006-10-15 23:52:26 +0400 (Sun, 15 Oct 2006)
New Revision: 4160
Added:
3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php
3.x/packages/wact/trunk/framework/template/compiler/OutputExpression.class.php
3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php
3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php
3.x/packages/wact/trunk/framework/template/compiler/parser/
3.x/packages/wact/trunk/framework/template/compiler/parser/ParserListener.interface.php
3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserMalformedTest.class.php
3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTest.class.php
3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTruncatedTest.class.php
3.x/packages/wact/trunk/tests/cases/template/compiler/SourceFileParserTest.class.php
Removed:
3.x/packages/wact/trunk/framework/template/compiler/htmlparser.inc.php
3.x/packages/wact/trunk/framework/template/compiler/nodebuilder.inc.php
3.x/packages/wact/trunk/framework/template/compiler/outputexpression.inc.php
3.x/packages/wact/trunk/tests/cases/template/compiler/htmlparser.test.php
3.x/packages/wact/trunk/tests/cases/template/compiler/sourcefileparser.test.php
Modified:
3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php
3.x/packages/wact/trunk/framework/template/compiler/parserstate.inc.php
3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php
3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php
3.x/packages/wact/trunk/tests/cases/template/compiler/parserstate.test.php
3.x/packages/wact/trunk/tests/cases/template/filters/clip_filter.test.php
Log:
-- WACT package clean up and refactorings
Copied: 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php (from rev 4159, 3.x/packages/wact/trunk/framework/template/compiler/htmlparser.inc.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/HTMLParser.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,380 @@
+<?php
+//--------------------------------------------------------------------------------
+// Copyright 2003 Procata, Inc.
+// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
+//--------------------------------------------------------------------------------
+
+/**
+* HTML/XHTML/XML parser
+* fast parser robustly handles malformed input.
+* All events are triggered by valid markup.
+* If markup is invalid, it is treated as data event.
+* @access protected
+* @abstract
+*/
+class HTMLParser
+{
+ var $publicId;
+ var $Observer;
+ /**
+ * XML document being parsed
+ * @var string
+ * @access private
+ */
+ var $rawtext;
+ /**
+ * Position in XML document relative to start (0)
+ * @var int
+ * @access private
+ */
+ var $position;
+ /**
+ * Length of the XML document in characters
+ * @var int
+ * @access private
+ */
+ var $length;
+
+ /**
+ * @var Observer event handler
+ * @access protected
+ */
+ function HTMLParser(&$Observer) {
+ $this->Observer =& $Observer;
+ }
+
+ /*
+ * Calculates the line number from the byte index
+ * @return int the current line number
+ * @access private
+ */
+ function getLineNumber() {
+ return 1 + substr_count(substr($this->rawtext, 0, $this->position), "\n");
+ }
+
+ function getPublicId() {
+ return $this->publicId;
+ }
+
+ /*
+ * Calculates the column number from the byte index
+ * @return int the current line number
+ * @access private
+ */
+ function getColumnNumber() {
+ // Not implemented yet.
+ }
+
+ /**
+ * Moves the position forward past any whitespace characters
+ * @access protected
+ * @return void
+ */
+ function ignoreWhitespace() {
+ while ($this->position < $this->length &&
+ strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) {
+ $this->position++;
+ }
+ }
+
+ /**
+ * Begins the parsing operation, setting up any decorators, depending on
+ * parse options invoking _parse() to execute parsing
+ * @param string XML document to parse
+ * @access protected
+ * @return void
+ */
+ function parse($data, $publicId = NULL) {
+ $this->rawtext = $data;
+ $this->length = strlen($data);
+ $this->position = 0;
+ $this->publicId = $publicId;
+
+ $this->Observer->setDocumentLocator($this);
+
+ do {
+ $start = $this->position;
+ $this->position = strpos($this->rawtext, '<', $start);
+ if ($this->position === FALSE) {
+ if ($start < $this->length) {
+ $this->Observer->characters(substr($this->rawtext, $start));
+ }
+ return;
+ }
+
+ if ($this->position > $start) {
+ $this->Observer->characters(substr($this->rawtext, $start, $this->position - $start));
+ }
+
+ $this->position += 1; // ignore '<' character
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF('<');
+ return;
+ }
+
+ $element_pos = $this->position;
+ $this->position += 1;
+
+ switch($this->rawtext{$element_pos}) {
+ case '/':
+ $start = $this->position;
+ while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $tag = substr($this->rawtext, $start, $this->position - $start);
+
+ $this->Observer->endElement($tag);
+ $this->position += 1; // ignore '>' string
+ break;
+ case '?':
+ $start = $this->position;
+ while ($this->position < $this->length && strpos(" \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $target = substr($this->rawtext, $start, $this->position - $start);
+
+ $this->ignoreWhitespace();
+
+ $start = $this->position;
+ $this->position = strpos($this->rawtext, '?>', $start);
+ if ($this->position === FALSE) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $this->Observer->processingInstruction($target,
+ substr($this->rawtext, $start, $this->position - $start));
+
+ $this->position += 2; // ignore '? >' string
+ break;
+ case '%':
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $start = $this->position;
+ $this->position = strpos($this->rawtext, '%>', $start);
+ if ($this->position === FALSE) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $this->Observer->jasp(substr($this->rawtext, $start, $this->position - $start));
+
+ /* changed to multi line comment per request on list
+ http://sourceforge.net/mailarchive/forum.php?thread_id=5925242&forum_id=35579
+ ignore '%>' string
+ */
+ $this->position += 2;
+ break;
+ case '!':
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $start = $this->position;
+ if (substr($this->rawtext, $start, 2) == "--") {
+ $this->position = strpos($this->rawtext, '-->', $start);
+ if ($this->position === FALSE) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+ $this->Observer->comment(
+ substr($this->rawtext, $start + 2, $this->position - $start - 2));
+ $this->position += 3;
+ } else if (strcasecmp(substr($this->rawtext, $start, 7), 'DOCTYPE') == 0) {
+ while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+ $this->Observer->doctype(
+ substr($this->rawtext, $start, $this->position - $start));
+ $this->position += 1;
+ } else if (substr($this->rawtext, $start, 7) == '[CDATA[') {
+ $this->position = strpos($this->rawtext, ']]>', $start + 7);
+ if ($this->position === FALSE) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+ $this->Observer->cdata(
+ substr($this->rawtext, $start + 7 , $this->position - $start - 7));
+ $this->position += 3;
+ } else {
+ while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+ $this->position += 1;
+ $this->Observer->escape(
+ substr($this->rawtext, $start, $this->position - $start));
+ }
+ break;
+ default:
+ while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $tag = substr($this->rawtext, $element_pos, $this->position - $element_pos);
+ $Attributes = array();
+
+ $this->ignoreWhitespace();
+
+ while ( $this->position < $this->length &&
+ $this->rawtext{$this->position} != '/' &&
+ $this->rawtext{$this->position} != '>') {
+
+ $start = $this->position;
+ while ($this->position < $this->length && strpos("/>= \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $attributename = substr($this->rawtext, $start, $this->position - $start);
+ $attributevalue = NULL;
+
+ $this->ignoreWhitespace();
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ if ( $this->rawtext{$this->position} == '=') {
+ $this->position++;
+ $this->ignoreWhitespace();
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ $quote = $this->rawtext{$this->position};
+ if ($quote == '"' || $quote == "'") {
+ $start = $this->position + 1;
+ $this->position = strpos($this->rawtext, $quote, $start);
+ if ($this->position === FALSE) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+ $attributevalue = substr($this->rawtext, $start, $this->position - $start);
+
+ $this->position++;
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ if (strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+ $this->Observer->invalidAttributeSyntax();
+ }
+
+ } else {
+ $start = $this->position;
+ while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+ $attributevalue = substr($this->rawtext, $start, $this->position - $start);
+ }
+ }
+
+ $Attributes[$attributename] = $attributevalue;
+
+ $this->ignoreWhitespace();
+ }
+
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ if ($this->rawtext{$this->position} == '/') {
+ $this->position += 1;
+ if ($this->position >= $this->length) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $element_pos - 1));
+ return;
+ }
+
+ if ($this->rawtext{$this->position} != '>') {
+ $start = $this->position;
+ while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
+ $this->position++;
+ }
+ if ($this->position >= $this->length) {
+ $this->Observer->invalidEntitySyntax(
+ substr($this->rawtext, $element_pos - 1));
+ break;
+ }
+
+ $this->Observer->invalidEntitySyntax(
+ substr($this->rawtext, $element_pos - 1, $this->position - $element_pos + 2));
+ $this->position += 1;
+ break;
+ }
+
+ $this->Observer->emptyElement($tag, $Attributes);
+ } else {
+ $this->Observer->startElement($tag, $Attributes);
+ }
+ $this->position += 1;
+
+ /*
+ removed due to bug #1000806
+ see http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-specifying-data
+ if (strcasecmp($tag, 'script') == 0 || strcasecmp($tag, 'style') == 0) {
+ $start = $this->position;
+ $this->position = strpos($this->rawtext, '</', $start);
+ if ($this->position == FALSE) {
+ $this->Observer->unexpectedEOF(
+ substr($this->rawtext, $start));
+ return;
+ }
+
+ $this->Observer->characters(
+ substr($this->rawtext, $start, $this->position - $start));
+
+ }
+ */
+
+ break;
+ }
+ } while ($this->position < $this->length);
+ }
+
+}
+?>
Copied: 3.x/packages/wact/trunk/framework/template/compiler/OutputExpression.class.php (from rev 4159, 3.x/packages/wact/trunk/framework/template/compiler/outputexpression.inc.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/OutputExpression.class.php (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/OutputExpression.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,34 @@
+<?php
+/**
+* Outputs the result of an expression like {$var} or {$'var'}
+*/
+class OutputExpression extends CompilerComponent
+{
+ protected $expression;
+
+ function OutputExpression($expression)
+ {
+ $this->expression = new Expression($expression, $this, 'html');
+ }
+
+ function prepare()
+ {
+ $this->expression->prepare();
+ parent::prepare();
+ }
+
+ function generate($code_writer)
+ {
+ if ($this->expression->isConstant())
+ $code_writer->writeHTML($this->expression->getValue());
+ else
+ {
+ $this->expression->generatePreStatement($code_writer);
+ $code_writer->writePHP('echo ');
+ $this->expression->generateExpression($code_writer);
+ $code_writer->writePHP(';');
+ $this->expression->generatePostStatement($code_writer);
+ }
+ }
+}
+?>
\ No newline at end of file
Modified: 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/SourceFileParser.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -19,10 +19,10 @@
/**
* Includes
*/
-require_once WACT_ROOT . '/template/compiler/nodebuilder.inc.php';
+require_once WACT_ROOT . '/template/compiler/WactNodeBuilder.class.php';
require_once WACT_ROOT . '/template/compiler/WactTreeBuilder.class.php';
require_once WACT_ROOT . '/template/compiler/parserstate.inc.php';
-require_once WACT_ROOT . '/template/compiler/htmlparser.inc.php';
+require_once WACT_ROOT . '/template/compiler/HtmlParser.class.php';
//--------------------------------------------------------------------------------
/**
@@ -31,7 +31,7 @@
* @access public
* @package WACT_TEMPLATE
*/
-class SourceFileParser
+class SourceFileParser implements ParserListener
{
/**
* Path and filename of source template
@@ -118,7 +118,7 @@
* @return void
* @access protected
*/
- function parse(&$ComponentRoot)
+ function parse($ComponentRoot)
{
$TagDictionary = WactDictionaryHolder ::instance()->getTagDictionary();
@@ -128,12 +128,12 @@
$this->TreeBuilder->setCursor($ComponentRoot);
- $this->ComponentParsingState =& new WactComponentParsingState($this, $this->TreeBuilder, $NodeBuilder, $TagDictionary);
- $this->LiteralParsingState =& new WactLiteralParsingState($this, $this->TreeBuilder);
+ $this->ComponentParsingState = new WactComponentParsingState($this, $this->TreeBuilder, $NodeBuilder, $TagDictionary);
+ $this->LiteralParsingState = new WactLiteralParsingState($this, $this->TreeBuilder);
$this->changeToComponentParsingState();
$Chain =& $this->buildFilterChain($this->config->getSaxFilters());
- $parser =& new HTMLParser($Chain);
+ $parser = new HTMLParser($Chain);
$template = $this->locator->readTemplateFile($this->SourceFile);
$parser->parse($template, $this->SourceFile);
@@ -152,7 +152,7 @@
* @access public
*/
function changeToComponentParsingState() {
- $this->State =& $this->ComponentParsingState;
+ $this->State = $this->ComponentParsingState;
}
/**
@@ -162,7 +162,7 @@
* @access public
*/
function changeToLiteralParsingState($tag) {
- $this->State = & $this->LiteralParsingState;
+ $this->State = $this->LiteralParsingState;
$this->State->literalTag = $tag;
}
@@ -172,7 +172,7 @@
* @return void
* @access private
*/
- function setDocumentLocator(&$locator) {
+ function setDocumentLocator($locator) {
$this->LiteralParsingState->setDocumentLocator($locator);
$this->ComponentParsingState->setDocumentLocator($locator);
}
Copied: 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php (from rev 4159, 3.x/packages/wact/trunk/framework/template/compiler/nodebuilder.inc.php)
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactNodeBuilder.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,220 @@
+<?php
+/**
+* Responsible for building nodes of the component tree.
+* WactTreeBuilder is responsible for the tree structure.
+*/
+class WactNodeBuilder
+{
+ const BEFORE_CONTENT = 1;
+ const EXPRESSION = 2;
+ const AFTER_CONTENT = 5;
+
+ protected $variable_reference_pattern;
+
+ var $locator;
+
+ function __construct()
+ {
+ $this->variableReferencePattern =
+ // start at the beginning
+ '/^' .
+ // Pick up the portion of the string before the variable reference
+ '((?s).*?)' .
+ // Beginning of a variable reference
+ preg_quote('{$', '/') .
+ // Collect the entire variable reference into one subexpression
+ '(' .
+ // capture the contents of one or more fragments.
+ '(' .
+ // Anything thats not a quote or the end of the variable
+ // reference can be in a fragment
+ '[^"\'}]+' .
+ // OR
+ '|' .
+ // A string inside quotes is also a fragment
+ '(\'|").*?\4' .
+ ')+' .
+ ')' .
+ // end of a variable reference
+ preg_quote('}', '/') .
+ // Pick up the portion of the string after the variable reference
+ // This portion may contain additional references; we only match
+ // one at a time.
+ '((?s).*)' .
+ // Match until the end of the string
+ '$/';
+ }
+
+ function setDocumentLocator($locator)
+ {
+ $this->locator = $locator;
+ }
+
+ /**
+ * Builds a component, adding attributes
+ * @param TagInfo
+ * @param string XML tag name of component
+ * @param array attributes for tag
+ * @param boolean whether the tag has contents
+ * @return CompilerComponent
+ * @access public
+ */
+ function buildTagNode($TagInfo, $tag, $attrs, $isEmpty)
+ {
+ $component = $this->_initTagNode($TagInfo, $tag);
+ $component->emptyClosedTag = $isEmpty;
+ $this->addAttributesToComponent($component, $attrs);
+ return $component;
+ }
+
+ /**
+ * Builds content node(s), adding it (them) to the component tree.
+ * A single piece of content may actually be a mix of terminal nodes
+ * (TextNodes and Expressions)
+ * @param WactTreeBuilder
+ * @param string content of tag
+ * @return void
+ * @access public
+ */
+ function addContent(&$TreeBuilder, $text) {
+ // if there is no expression (common case), shortcut this process
+ if (strpos($text, '{$') === FALSE) {
+ $TreeBuilder->addTextNode($text);
+ return;
+ }
+
+ while (preg_match($this->variableReferencePattern, $text, $match)) {
+ if (strlen($match[self :: BEFORE_CONTENT]) > 0) {
+ $TreeBuilder->addTextNode($match[self :: BEFORE_CONTENT]);
+ }
+
+ $expression =& new OutputExpression($match[self :: EXPRESSION]);
+ $expression->SourceLocation =& new WactSourceLocation(
+ $this->locator->getPublicId(),
+ $this->locator->getLineNumber());
+
+ $TreeBuilder->addNode($expression);
+
+ $text = $match[self :: AFTER_CONTENT];
+ }
+ if (strlen($text) > 0) {
+ $TreeBuilder->addTextNode($text);
+ }
+ }
+
+ /**
+ * Builds XML processing instructions and adds them to the component tree.
+ * PHP instructions are ignored.
+ * @param WactTreeBuilder
+ * @param string target processor
+ * @param string instruction
+ * @return void
+ * @access public
+ */
+ function addProcessingInstruction(&$TreeBuilder, $target, $instruction) {
+ // we can optimize here by not loading PHP node until we need it
+ // It will probably be rarely used in templates.
+ require_once WACT_ROOT . '/template/compiler/PHPNode.class.php';
+
+ // Pass through any PI's except PHP PI's
+ $php_targets = array('php','PHP','=','');
+ if(in_array($target, $php_targets))
+ {
+ $TreeBuilder->addNode(new PHPNode($instruction));
+ }
+ else
+ {
+ $php = 'echo "<?'.$target.' '; // Whitespace assumption
+ $php.= str_replace('"','\"',$instruction);
+ $php.= '?>\n";'; // Newline assumption
+ $TreeBuilder->addNode(new PHPNode($php));
+ }
+ }
+
+ /**
+ * Create a new tag component
+ * @param TagInfo
+ * @param string XML tag name of component
+ * @return void
+ * @access private
+ */
+ protected function _initTagNode(&$TagInfo, $tag) {
+ $class = $TagInfo->TagClass;
+ $component =& new $class();
+ $component->SourceLocation =& new WactSourceLocation(
+ $this->locator->getPublicId(),
+ $this->locator->getLineNumber());
+ $component->tag = $tag;
+ $component->TagInfo =& $TagInfo;
+ $dict = WactDictionaryHolder :: instance()->getPropertyDictionary();;
+ $properties = $dict->getPropertyList($tag);
+ foreach ($properties as $property) {
+ $property->load();
+ $PropertyClass = $property->PropertyClass;
+ $component->registerProperty(
+ $property->Property, new $PropertyClass($component));
+ }
+ return $component;
+ }
+
+ /**
+ * Create AttributeNodes or ArtributeVariableReferences to a component
+ * @param CompilerCOmponent
+ * @param array attributes found in tag
+ * @return void
+ * @access private
+ */
+ function addAttributesToComponent(&$component, $attrs) {
+ foreach ( $attrs as $name => $value ) {
+ // if there is no expression (common case), shortcut this process
+ if (strpos($value, '{$') === FALSE) {
+ $attribute =& new AttributeNode($name, $value);
+ } else {
+ if (preg_match($this->variableReferencePattern, $value, $match)) {
+ if (strlen($match[self :: AFTER_CONTENT]) == 0 &&
+ strlen($match[self :: BEFORE_CONTENT]) == 0) {
+ $attribute =& new AttributeExpression(
+ $name, $match[self :: EXPRESSION], $component);
+ } else {
+ $attribute =& $this->createCompoundAttribute(
+ $component, $name, $value);
+ }
+ } else {
+ $attribute =& new AttributeNode($name, $value);
+ }
+ }
+
+ $component->addChildAttribute($attribute);
+ }
+ }
+
+ /**
+ * Creates a compound attribute
+ * @param CompilerComponent component to which the attribute belongs
+ * @param string name
+ * @param string value
+ * @return CompoundAttribute
+ * @access private
+ */
+ function &createCompoundAttribute(&$component, $name, $value) {
+ $attribute =& new CompoundAttribute($name);
+
+ while (preg_match($this->variableReferencePattern, $value, $match)) {
+ if (strlen($match[self :: BEFORE_CONTENT]) > 0) {
+ $attribute->addAttributeFragment(
+ new AttributeNode($name, $match[self :: BEFORE_CONTENT]));
+ }
+
+ $attribute->addAttributeFragment(new AttributeExpression($name,
+ $match[self :: EXPRESSION], $component));
+
+ $value = $match[self :: AFTER_CONTENT];
+ }
+ if (strlen($value) > 0) {
+ $attribute->addAttributeFragment(new AttributeNode($name, $value));
+ }
+
+ return $attribute;
+ }
+}
+?>
\ No newline at end of file
Added: 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/WactSourceLocation.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,13 @@
+<?php
+class WactSourceLocation
+{
+ public $file;
+ public $line;
+
+ function __construct($file, $line)
+ {
+ $this->file = $file;
+ $this->line = $line;
+ }
+}
+?>
\ No newline at end of file
Deleted: 3.x/packages/wact/trunk/framework/template/compiler/htmlparser.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/htmlparser.inc.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/htmlparser.inc.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -1,380 +0,0 @@
-<?php
-//--------------------------------------------------------------------------------
-// Copyright 2003 Procata, Inc.
-// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
-//--------------------------------------------------------------------------------
-
-/**
-* HTML/XHTML/XML parser
-* fast parser robustly handles malformed input.
-* All events are triggered by valid markup.
-* If markup is invalid, it is treated as data event.
-* @access protected
-* @abstract
-*/
-class HTMLParser
-{
- var $publicId;
- var $Observer;
- /**
- * XML document being parsed
- * @var string
- * @access private
- */
- var $rawtext;
- /**
- * Position in XML document relative to start (0)
- * @var int
- * @access private
- */
- var $position;
- /**
- * Length of the XML document in characters
- * @var int
- * @access private
- */
- var $length;
-
- /**
- * @var Observer event handler
- * @access protected
- */
- function HTMLParser(&$Observer) {
- $this->Observer =& $Observer;
- }
-
- /*
- * Calculates the line number from the byte index
- * @return int the current line number
- * @access private
- */
- function getLineNumber() {
- return 1 + substr_count(substr($this->rawtext, 0, $this->position), "\n");
- }
-
- function getPublicId() {
- return $this->publicId;
- }
-
- /*
- * Calculates the column number from the byte index
- * @return int the current line number
- * @access private
- */
- function getColumnNumber() {
- // Not implemented yet.
- }
-
- /**
- * Moves the position forward past any whitespace characters
- * @access protected
- * @return void
- */
- function ignoreWhitespace() {
- while ($this->position < $this->length &&
- strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) {
- $this->position++;
- }
- }
-
- /**
- * Begins the parsing operation, setting up any decorators, depending on
- * parse options invoking _parse() to execute parsing
- * @param string XML document to parse
- * @access protected
- * @return void
- */
- function parse($data, $publicId = NULL) {
- $this->rawtext = $data;
- $this->length = strlen($data);
- $this->position = 0;
- $this->publicId = $publicId;
-
- $this->Observer->setDocumentLocator($this);
-
- do {
- $start = $this->position;
- $this->position = strpos($this->rawtext, '<', $start);
- if ($this->position === FALSE) {
- if ($start < $this->length) {
- $this->Observer->characters(substr($this->rawtext, $start));
- }
- return;
- }
-
- if ($this->position > $start) {
- $this->Observer->characters(substr($this->rawtext, $start, $this->position - $start));
- }
-
- $this->position += 1; // ignore '<' character
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF('<');
- return;
- }
-
- $element_pos = $this->position;
- $this->position += 1;
-
- switch($this->rawtext{$element_pos}) {
- case '/':
- $start = $this->position;
- while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $tag = substr($this->rawtext, $start, $this->position - $start);
-
- $this->Observer->endElement($tag);
- $this->position += 1; // ignore '>' string
- break;
- case '?':
- $start = $this->position;
- while ($this->position < $this->length && strpos(" \n\r\t", $this->rawtext{$this->position}) === FALSE) {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $target = substr($this->rawtext, $start, $this->position - $start);
-
- $this->ignoreWhitespace();
-
- $start = $this->position;
- $this->position = strpos($this->rawtext, '?>', $start);
- if ($this->position === FALSE) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $this->Observer->processingInstruction($target,
- substr($this->rawtext, $start, $this->position - $start));
-
- $this->position += 2; // ignore '? >' string
- break;
- case '%':
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $start = $this->position;
- $this->position = strpos($this->rawtext, '%>', $start);
- if ($this->position === FALSE) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $this->Observer->jasp(substr($this->rawtext, $start, $this->position - $start));
-
- /* changed to multi line comment per request on list
- http://sourceforge.net/mailarchive/forum.php?thread_id=5925242&forum_id=35579
- ignore '%>' string
- */
- $this->position += 2;
- break;
- case '!':
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $start = $this->position;
- if (substr($this->rawtext, $start, 2) == "--") {
- $this->position = strpos($this->rawtext, '-->', $start);
- if ($this->position === FALSE) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
- $this->Observer->comment(
- substr($this->rawtext, $start + 2, $this->position - $start - 2));
- $this->position += 3;
- } else if (strcasecmp(substr($this->rawtext, $start, 7), 'DOCTYPE') == 0) {
- while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
- $this->Observer->doctype(
- substr($this->rawtext, $start, $this->position - $start));
- $this->position += 1;
- } else if (substr($this->rawtext, $start, 7) == '[CDATA[') {
- $this->position = strpos($this->rawtext, ']]>', $start + 7);
- if ($this->position === FALSE) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
- $this->Observer->cdata(
- substr($this->rawtext, $start + 7 , $this->position - $start - 7));
- $this->position += 3;
- } else {
- while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
- $this->position += 1;
- $this->Observer->escape(
- substr($this->rawtext, $start, $this->position - $start));
- }
- break;
- default:
- while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $tag = substr($this->rawtext, $element_pos, $this->position - $element_pos);
- $Attributes = array();
-
- $this->ignoreWhitespace();
-
- while ( $this->position < $this->length &&
- $this->rawtext{$this->position} != '/' &&
- $this->rawtext{$this->position} != '>') {
-
- $start = $this->position;
- while ($this->position < $this->length && strpos("/>= \n\r\t", $this->rawtext{$this->position}) === FALSE) {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $attributename = substr($this->rawtext, $start, $this->position - $start);
- $attributevalue = NULL;
-
- $this->ignoreWhitespace();
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- if ( $this->rawtext{$this->position} == '=') {
- $this->position++;
- $this->ignoreWhitespace();
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- $quote = $this->rawtext{$this->position};
- if ($quote == '"' || $quote == "'") {
- $start = $this->position + 1;
- $this->position = strpos($this->rawtext, $quote, $start);
- if ($this->position === FALSE) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
- $attributevalue = substr($this->rawtext, $start, $this->position - $start);
-
- $this->position++;
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- if (strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
- $this->Observer->invalidAttributeSyntax();
- }
-
- } else {
- $start = $this->position;
- while ($this->position < $this->length && strpos("/> \n\r\t", $this->rawtext{$this->position}) === FALSE) {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(substr($this->rawtext, $element_pos - 1));
- return;
- }
- $attributevalue = substr($this->rawtext, $start, $this->position - $start);
- }
- }
-
- $Attributes[$attributename] = $attributevalue;
-
- $this->ignoreWhitespace();
- }
-
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- if ($this->rawtext{$this->position} == '/') {
- $this->position += 1;
- if ($this->position >= $this->length) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $element_pos - 1));
- return;
- }
-
- if ($this->rawtext{$this->position} != '>') {
- $start = $this->position;
- while ($this->position < $this->length && $this->rawtext{$this->position} != '>') {
- $this->position++;
- }
- if ($this->position >= $this->length) {
- $this->Observer->invalidEntitySyntax(
- substr($this->rawtext, $element_pos - 1));
- break;
- }
-
- $this->Observer->invalidEntitySyntax(
- substr($this->rawtext, $element_pos - 1, $this->position - $element_pos + 2));
- $this->position += 1;
- break;
- }
-
- $this->Observer->emptyElement($tag, $Attributes);
- } else {
- $this->Observer->startElement($tag, $Attributes);
- }
- $this->position += 1;
-
- /*
- removed due to bug #1000806
- see http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-specifying-data
- if (strcasecmp($tag, 'script') == 0 || strcasecmp($tag, 'style') == 0) {
- $start = $this->position;
- $this->position = strpos($this->rawtext, '</', $start);
- if ($this->position == FALSE) {
- $this->Observer->unexpectedEOF(
- substr($this->rawtext, $start));
- return;
- }
-
- $this->Observer->characters(
- substr($this->rawtext, $start, $this->position - $start));
-
- }
- */
-
- break;
- }
- } while ($this->position < $this->length);
- }
-
-}
-?>
Deleted: 3.x/packages/wact/trunk/framework/template/compiler/nodebuilder.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/nodebuilder.inc.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/nodebuilder.inc.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -1,278 +0,0 @@
-<?php
-//------------------------------------------------------------------------------
-// Copyright 2003 Procata, Inc.
-// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
-//------------------------------------------------------------------------------
-/**
-* @package WACT_TEMPLATE
-* @version $Id: nodebuilder.inc.php,v 1.2 2005/12/30 10:35:47 ian_w_white Exp $
-*/
-//------------------------------------------------------------------------------
-
-/**#@+
- * ExpresionParser capture constants
- */
-define('WACT_EXPPARSER_BEFORE_CONTENT', 1);
-define('WACT_EXPPARSER_EXPRESSION', 2);
-define('WACT_EXPPARSER_AFTER_CONTENT', 5);
-/**#@-*/
-
-class WactSourceLocation {
-
- /**
- * Used to identify the source template file, when generating compile time
- * error messages.
- * @var string source template filename
- * @access private
- */
- var $file;
-
- /**
- * Used to indentify the line number where a compile time error occurred.
- * @var int line number
- * @access private
- */
- var $line;
-
- function WactSourceLocation($file, $line) {
- $this->file = $file;
- $this->line = $line;
- }
-
-}
-
-
-/**
-* Responsible for building nodes of the component tree.
-* WactTreeBuilder is responsible for the tree structure.
-*
-* @see http://wact.sourceforge.net/index.php/NodeBuilder
-* @access public
-* @package WACT_TEMPLATE
-*/
-class WactNodeBuilder {
-
- /**
- * Regular expression for mathcing wact variable expressions
- * @access private
- */
- var $variableReferencePattern;
-
- /**
- * Used to locate position within document
- * @access private
- */
- var $locator;
-
- /**
- * Constructs WactTreeBuilder, setting up expression parsers
- * @access public
- */
- function WactNodeBuilder() {
- $this->variableReferencePattern =
- // start at the beginning
- '/^' .
- // Pick up the portion of the string before the variable reference
- '((?s).*?)' .
- // Beginning of a variable reference
- preg_quote('{$', '/') .
- // Collect the entire variable reference into one subexpression
- '(' .
- // capture the contents of one or more fragments.
- '(' .
- // Anything thats not a quote or the end of the variable
- // reference can be in a fragment
- '[^"\'}]+' .
- // OR
- '|' .
- // A string inside quotes is also a fragment
- '(\'|").*?\4' .
- ')+' .
- ')' .
- // end of a variable reference
- preg_quote('}', '/') .
- // Pick up the portion of the string after the variable reference
- // This portion may contain additional references; we only match
- // one at a time.
- '((?s).*)' .
- // Match until the end of the string
- '$/';
- }
-
- /**
- * Sets the Document Locator
- * @param DocumentLocator
- * @return void
- * @access public
- */
- function setDocumentLocator(&$locator) {
- $this->locator =& $locator;
- }
-
- /**
- * Builds a component, adding attributes
- * @param TagInfo
- * @param string XML tag name of component
- * @param array attributes for tag
- * @param boolean whether the tag has contents
- * @return CompilerComponent
- * @access public
- */
- function &buildComponent(&$TagInfo, $tag, $attrs, $isEmpty) {
- $component =& $this->createComponent($TagInfo, $tag);
- $component->emptyClosedTag = $isEmpty;
- $this->addAttributesToComponent($component, $attrs);
- return $component;
- }
-
- /**
- * Builds content node(s), adding it (them) to the component tree.
- * A single piece of content may actually be a mix of terminal nodes
- * (TextNodes and Expressions)
- * @param WactTreeBuilder
- * @param string content of tag
- * @return void
- * @access public
- */
- function addContent(&$TreeBuilder, $text) {
- // if there is no expression (common case), shortcut this process
- if (strpos($text, '{$') === FALSE) {
- $TreeBuilder->addTextNode($text);
- return;
- }
-
- while (preg_match($this->variableReferencePattern, $text, $match)) {
- if (strlen($match[WACT_EXPPARSER_BEFORE_CONTENT]) > 0) {
- $TreeBuilder->addTextNode($match[WACT_EXPPARSER_BEFORE_CONTENT]);
- }
-
- $expression =& new OutputExpression($match[WACT_EXPPARSER_EXPRESSION]);
- $expression->SourceLocation =& new WactSourceLocation(
- $this->locator->getPublicId(),
- $this->locator->getLineNumber());
-
- $TreeBuilder->addNode($expression);
-
- $text = $match[WACT_EXPPARSER_AFTER_CONTENT];
- }
- if (strlen($text) > 0) {
- $TreeBuilder->addTextNode($text);
- }
- }
-
- /**
- * Builds XML processing instructions and adds them to the component tree.
- * PHP instructions are ignored.
- * @param WactTreeBuilder
- * @param string target processor
- * @param string instruction
- * @return void
- * @access public
- */
- function addProcessingInstruction(&$TreeBuilder, $target, $instruction) {
- // we can optimize here by not loading PHP node until we need it
- // It will probably be rarely used in templates.
- require_once WACT_ROOT . '/template/compiler/PHPNode.class.php';
-
- // Pass through any PI's except PHP PI's
- $php_targets = array('php','PHP','=','');
- if(in_array($target, $php_targets))
- {
- $TreeBuilder->addNode(new PHPNode($instruction));
- }
- else
- {
- $php = 'echo "<?'.$target.' '; // Whitespace assumption
- $php.= str_replace('"','\"',$instruction);
- $php.= '?>\n";'; // Newline assumption
- $TreeBuilder->addNode(new PHPNode($php));
- }
- }
-
- /**
- * Create a new tag component
- * @param TagInfo
- * @param string XML tag name of component
- * @return void
- * @access private
- */
- function &createComponent(&$TagInfo, $tag) {
- $class = $TagInfo->TagClass;
- $component =& new $class();
- $component->SourceLocation =& new WactSourceLocation(
- $this->locator->getPublicId(),
- $this->locator->getLineNumber());
- $component->tag = $tag;
- $component->TagInfo =& $TagInfo;
- $dict = WactDictionaryHolder :: instance()->getPropertyDictionary();;
- $properties = $dict->getPropertyList($tag);
- foreach ($properties as $property) {
- $property->load();
- $PropertyClass = $property->PropertyClass;
- $component->registerProperty(
- $property->Property, new $PropertyClass($component));
- }
- return $component;
- }
-
- /**
- * Create AttributeNodes or ArtributeVariableReferences to a component
- * @param CompilerCOmponent
- * @param array attributes found in tag
- * @return void
- * @access private
- */
- function addAttributesToComponent(&$component, $attrs) {
- foreach ( $attrs as $name => $value ) {
- // if there is no expression (common case), shortcut this process
- if (strpos($value, '{$') === FALSE) {
- $attribute =& new AttributeNode($name, $value);
- } else {
- if (preg_match($this->variableReferencePattern, $value, $match)) {
- if (strlen($match[WACT_EXPPARSER_AFTER_CONTENT]) == 0 &&
- strlen($match[WACT_EXPPARSER_BEFORE_CONTENT]) == 0) {
- $attribute =& new AttributeExpression(
- $name, $match[WACT_EXPPARSER_EXPRESSION], $component);
- } else {
- $attribute =& $this->createCompoundAttribute(
- $component, $name, $value);
- }
- } else {
- $attribute =& new AttributeNode($name, $value);
- }
- }
-
- $component->addChildAttribute($attribute);
- }
- }
-
- /**
- * Creates a compound attribute
- * @param CompilerComponent component to which the attribute belongs
- * @param string name
- * @param string value
- * @return CompoundAttribute
- * @access private
- */
- function &createCompoundAttribute(&$component, $name, $value) {
- $attribute =& new CompoundAttribute($name);
-
- while (preg_match($this->variableReferencePattern, $value, $match)) {
- if (strlen($match[WACT_EXPPARSER_BEFORE_CONTENT]) > 0) {
- $attribute->addAttributeFragment(
- new AttributeNode($name, $match[WACT_EXPPARSER_BEFORE_CONTENT]));
- }
-
- $attribute->addAttributeFragment(new AttributeExpression($name,
- $match[WACT_EXPPARSER_EXPRESSION], $component));
-
- $value = $match[WACT_EXPPARSER_AFTER_CONTENT];
- }
- if (strlen($value) > 0) {
- $attribute->addAttributeFragment(new AttributeNode($name, $value));
- }
-
- return $attribute;
- }
-}
-?>
\ No newline at end of file
Deleted: 3.x/packages/wact/trunk/framework/template/compiler/outputexpression.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/outputexpression.inc.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/outputexpression.inc.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -1,42 +0,0 @@
-<?php
-//--------------------------------------------------------------------------------
-// Copyright 2003 Procata, Inc.
-// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
-//--------------------------------------------------------------------------------
-/**
-* @package WACT_TAG
-* @version $Id: outputexpression.inc.php,v 1.4 2005/08/16 12:46:05 pachanga Exp $
-*/
-//--------------------------------------------------------------------------------
-/**
-* Outputs the resultof an expression
-* @see CoreOutputTag
-* @see http://wact.sourceforge.net/index.php/CoreOutputTag
-* @access protected
-* @package WACT_TAG
-*/
-class OutputExpression extends CompilerComponent {
- var $expression;
-
- function OutputExpression($expression) {
- $this->expression =& new Expression($expression, $this, 'html');
- }
-
- function prepare() {
- $this->expression->prepare();
- parent::prepare();
- }
-
- function generate(&$code) {
- if ($this->expression->isConstant()) {
- $code->writeHTML($this->expression->getValue());
- } else {
- $this->expression->generatePreStatement($code);
- $code->writePHP('echo ');
- $this->expression->generateExpression($code);
- $code->writePHP(';');
- $this->expression->generatePostStatement($code);
- }
- }
-}
-?>
\ No newline at end of file
Added: 3.x/packages/wact/trunk/framework/template/compiler/parser/ParserListener.interface.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parser/ParserListener.interface.php (rev 0)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parser/ParserListener.interface.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,19 @@
+<?php
+interface ParserListener
+{
+ function startElement($tag_name, $attrs);
+ function endElement($tag_name);
+ function emptyElement($tag_name, $attrs);
+ function characters($data);
+ function cdata($data);
+ function processingInstruction($type, $data);
+ function escape($data);
+ function comment($data);
+ function doctype($data);
+ function jasp($data);
+ function unexpectedEOF($data);
+ function invalidEntitySyntax($data);
+ function invalidAttributeSyntax();
+ function setDocumentLocator($locator);
+}
+?>
\ No newline at end of file
Modified: 3.x/packages/wact/trunk/framework/template/compiler/parserstate.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/parserstate.inc.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/parserstate.inc.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -1,27 +1,9 @@
<?php
-//--------------------------------------------------------------------------------
-// Copyright 2003 Procata, Inc.
-// Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
-//--------------------------------------------------------------------------------
/**
-* @package WACT_TEMPLATE
-* @version $Id: parserstate.inc.php,v 1.49 2005/12/30 10:35:47 ian_w_white Exp $
-*/
-//--------------------------------------------------------------------------------
-/**
-* Load array_change_key_case as needed
-*/
-if (!function_exists('array_change_key_case')) {
- require_once WACT_ROOT . '/util/phpcompat/array_change_key_case.php';
-}
-
-/**
* Base state handler for the SourceFileParser. Handles plain text
-* @see http://wact.sourceforge.net/index.php/BaseParsingState
-* @access public
-* @package WACT_TEMPLATE
*/
-class WactBaseParsingState {
+abstract class WactBaseParsingState
+{
/**
* Instance of SourceFileParser
* @var SourceFileParser
@@ -42,32 +24,20 @@
*/
var $TreeBuilder;
- /**
- * @param SourceFileParser
- * @access protected
- */
- function WactBaseParsingState(&$Parser, &$TreeBuilder) {
- $this->Parser = & $Parser;
- $this->TreeBuilder = & $TreeBuilder;
- $this->Locator = NULL; // to suppress 4.1.2 warnings
+ function __construct($Parser, $TreeBuilder)
+ {
+ $this->Parser = $Parser;
+ $this->TreeBuilder = $TreeBuilder;
}
- /**
- * @param Locator
- * @access protected
- */
- function setDocumentLocator(&$locator) {
- $this->Locator =& $locator;
- $this->TreeBuilder->setDocumentLocator($locator);
+ function setDocumentLocator($locator)
+ {
+ $this->Locator = $locator;
+ $this->TreeBuilder->setDocumentLocator($locator);
}
- /**
- * Builds an attribute string based on passed array of attributes
- * @param array
- * @return string
- * @access protected
- */
- function getAttributeString($attrs) {
+ function getAttributeString($attrs)
+ {
$attrib_str = '';
foreach ( $attrs as $key => $value ) {
$attrib_str .= ' ' . $key;
@@ -87,10 +57,11 @@
* @param string tag content
* @access public
*/
- function invalidAttributeSyntax() {
- throw new WactException('compiler', 'INVALID_ATTRIBUTE_SYNTAX', array(
- 'file' => $this->Locator->getPublicId(),
- 'line' => $this->Locator->getLineNumber()));
+ function invalidAttributeSyntax()
+ {
+ throw new WactException('compiler', 'INVALID_ATTRIBUTE_SYNTAX', array(
+ 'file' => $this->Locator->getPublicId(),
+ 'line' => $this->Locator->getLineNumber()));
}
}
@@ -107,7 +78,8 @@
* @access public
* @access WACT_TEMPLATE
*/
-class WactComponentParsingState extends WactBaseParsingState {
+class WactComponentParsingState extends WactBaseParsingState implements ParserListener
+{
/**
* Instance of TagDictionary
* @var TagDictionary
@@ -125,19 +97,22 @@
* @param SourceFileParser
* @access public
*/
- function WactComponentParsingState(&$Parser, &$TreeBuilder, &$NodeBuilder, &$TagDictionary) {
- parent::WactBaseParsingState($Parser, $TreeBuilder);
- $this->TagDictionary =& $TagDictionary;
- $this->NodeBuilder =& $NodeBuilder;
+ function __construct($Parser, $TreeBuilder, $NodeBuilder, $TagDictionary)
+ {
+ parent :: __construct($Parser, $TreeBuilder);
+ $this->TagDictionary =& $TagDictionary;
+ $this->NodeBuilder =& $NodeBuilder;
}
/**
* @param Locator
* @access protected
*/
- function setDocumentLocator(&$locator) {
- parent::setDocumentLocator($locator);
- $this->NodeBuilder->setDocumentLocator($locator);
+ function setDocumentLocator($locator)
+ {
+ parent::setDocumentLocator($locator);
+
+ $this->NodeBuilder->setDocumentLocator($locator);
}
/**
@@ -185,7 +160,7 @@
if ( $TagInfo->EndTag != ENDTAG_FORBIDDEN )
$this->TreeBuilder->pushExpectedTag($tag, PARSER_TAG_IS_COMPONENT, $this->_getPositionInfo());
- $component =& $this->NodeBuilder->buildComponent($TagInfo, $tag, $attrs, FALSE);
+ $component =& $this->NodeBuilder->buildTagNode($TagInfo, $tag, $attrs, FALSE);
if ( $this->TreeBuilder->pushNode($component) == PARSER_FORBID_PARSING)
$this->Parser->changeToLiteralParsingState($tag);
@@ -242,14 +217,13 @@
*/
function emptyElement($tag, $attrs)
{
-
$lower_attributes = $this->checkAttributes($attrs);
$TagInfo =& $this->TagDictionary->findComponent($tag, $lower_attributes, TRUE, $this->TreeBuilder->getCursor());
if (is_object($TagInfo)) {
$TagInfo->load();
- $component =& $this->NodeBuilder->buildComponent($TagInfo, $tag, $attrs, TRUE);
+ $component =& $this->NodeBuilder->buildTagNode($TagInfo, $tag, $attrs, TRUE);
if ( $this->TreeBuilder->pushNode($component) == PARSER_FORBID_PARSING) {
$this->Parser->changeToLiteralParsingState($tag);
}
@@ -381,28 +355,10 @@
* @access public
* @access WACT_TEMPLATE
*/
-class WactLiteralParsingState extends WactBaseParsingState {
- /**
- * Name of the literal tag
- * @var string
- * @access public
- */
+class WactLiteralParsingState extends WactBaseParsingState implements ParserListener
+{
var $literalTag;
- /**
- * @param SourceFileParser
- * @access public
- */
- function WactLiteralParsingState(&$Parser, &$TreeBuilder) {
- parent::WactBaseParsingState($Parser, $TreeBuilder);
- }
-
- /**
- * Handle opening tags
- * @param string tag name
- * @param array tag attributes
- * @access public
- */
function startElement($tag, $attrs) {
$this->TreeBuilder->addTextNode('<' . $tag . $this->getAttributeString($attrs) . '>');
}
@@ -519,6 +475,5 @@
// Ignore the error and treat the rest of the file like data
$this->TreeBuilder->addTextNode($text);
}
-
}
?>
\ No newline at end of file
Modified: 3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/tags/tagdictionary.inc.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -110,7 +110,7 @@
* @return boolean TRUE if it's a component
* @access private
*/
- function findComponent($tag, $attrs, $isEmpty, &$Component) {
+ function findComponent($tag, $attrs, $isEmpty, $Component) {
$tag = strtolower($tag);
// Does the tag have a wact:id attribute? if so, set 'runat = server'
if ( isset ( $attrs['wact:id'] ) ) {
Modified: 3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php
===================================================================
--- 3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/framework/template/compiler/templatecompiler.inc.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -31,7 +31,7 @@
require_once WACT_ROOT . '/template/compiler/TextNode.class.php';
require_once WACT_ROOT . '/template/compiler/PHPNode.class.php';
-require_once WACT_ROOT . '/template/compiler/outputexpression.inc.php';
+require_once WACT_ROOT . '/template/compiler/OutputExpression.class.php';
require_once WACT_ROOT . '/template/compiler/attribute/AttributeNode.class.php';
require_once WACT_ROOT . '/template/compiler/filter/CompilerFilter.class.php';
@@ -42,6 +42,9 @@
require_once WACT_ROOT . '/template/compiler/property/property.inc.php';
require_once WACT_ROOT . '/template/compiler/property/constant.inc.php';
+require_once WACT_ROOT . '/template/compiler/parser/ParserListener.interface.php';
+
+require_once WACT_ROOT . '/template/compiler/WactSourceLocation.class.php';
require_once WACT_ROOT . '/template/compiler/WactTreeBuilder.class.php';
require_once WACT_ROOT . '/template/compiler/SourceFileParser.class.php';
require_once WACT_ROOT . '/template/compiler/CodeWriter.class.php';
Added: 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserMalformedTest.class.php
===================================================================
--- 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserMalformedTest.class.php (rev 0)
+++ 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserMalformedTest.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,92 @@
+<?php
+require_once(WACT_TEST_CASES . '/template/compiler/HtmlParserTest.class.php');
+
+class HtmlParserMalformedTest extends UnitTestCase
+{
+ protected $parser;
+ protected $listener;
+
+ function setUp()
+ {
+ $this->listener = new MockParserListener();
+ $this->parser = new HTMLParser($this->listener);
+ }
+
+ function testMalformedJasp()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<%>'));
+ $this->listener->expectNever('jasp');
+ $this->parser->parse('stuff<%>');
+ }
+
+ function testMalformedProcessingInstruction()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<?>'));
+ $this->listener->expectNever('processingInstruction');
+ $this->parser->parse('stuff<?>');
+ }
+
+ function testMalformedProcessingInstruction2()
+ {
+ $this->listener->expectOnce('unexpectedEOF', array('<??>'));
+ $this->listener->expectNever('processingInstruction');
+ $this->listener->expectNever('characters');
+ $this->parser->parse('<??>');
+ }
+
+ function testMalformedComment()
+ {
+ $this->listener->expectOnce('unexpectedEOF', array('<!--x->'));
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('comment');
+ $this->listener->expectNever('characters');
+ $this->parser->parse('<!--x->');
+ }
+
+ function testOpenElementMalformedClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('invalidEntitySyntax', array('<tag attribute=\'value\'/morestuff'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=\'value\'/morestuff');
+ }
+
+ function testOpenElementMalformedClose2()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('invalidEntitySyntax', array('<tag attribute=\'value\'/morestuff>'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=\'value\'/morestuff>');
+ }
+
+ function testElementNestedSingleQuote()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array('attribute' => '', "'" => NULL)));
+ $this->listener->expectOnce('invalidAttributeSyntax');
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<tag attribute=\'\'\'>');
+ }
+
+ function testElementNestedDoubleQuote()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array('attribute' => '', '"' => NULL)));
+ $this->listener->expectOnce('invalidAttributeSyntax');
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<tag attribute=""">');
+ }
+
+ function testElementMalformedAttribute()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array('attribute' => 'test', 'extra' => NULL)));
+ $this->listener->expectOnce('invalidAttributeSyntax');
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<tag attribute="test"extra>');
+ }
+}
+
+?>
\ No newline at end of file
Copied: 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTest.class.php (from rev 4159, 3.x/packages/wact/trunk/tests/cases/template/compiler/htmlparser.test.php)
===================================================================
--- 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTest.class.php (rev 0)
+++ 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTest.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,299 @@
+<?php
+require_once(WACT_ROOT . '/template/compiler/templatecompiler.inc.php');
+
+Mock::generate('ParserListener', 'MockParserListener');
+
+class HtmlParserTest extends UnitTestCase
+{
+ var $parser;
+ var $listener;
+
+ function setUp()
+ {
+ $this->listener = new MockParserListener();
+ $this->parser = new HTMLParser($this->listener);
+ }
+
+ function testEmpty()
+ {
+ $this->listener->expectNever('jasp');
+ $this->listener->expectNever('processingInstruction');
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('startElement');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('');
+ }
+
+ function testSimpledata()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->parser->parse('stuff');
+ }
+
+ function testPreservingWhiteSpace()
+ {
+ $this->listener->expectOnce('characters', array(" stuff\t\r\n "));
+ $this->parser->parse(" stuff\t\r\n ");
+ }
+
+ function testEmptyElement()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array()));
+ $this->listener->expectOnce('endElement', array('tag'));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<tag></tag>');
+ }
+
+ function testEmptyElementSelfClose()
+ {
+ $this->listener->expectOnce('emptyElement', array('br', array()));
+ $this->listener->expectNever('startElement');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<br/>');
+ }
+
+ function testElementWithContent()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array()));
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('endElement', array('tag'));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<tag>stuff</tag>');
+ }
+
+ function testEmptyComment()
+ {
+ $this->listener->expectOnce('comment', array(''));
+ $this->listener->expectNever('characters');
+ $this->parser->parse('<!---->');
+ }
+
+ function testElementNestedSingleQuote()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array('attribute' => '\'')));
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('endElement');
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<tag attribute="\'">');
+ }
+
+ function testElementNestedDoubleQuote()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array('attribute' => '"')));
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('endElement');
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<tag attribute=\'"\'>');
+ }
+
+ function testEmptyDocType()
+ {
+ $this->listener->expectOnce('doctype', array('DOCTYPE'));
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('escape');
+ $this->parser->parse('<!DOCTYPE>');
+ }
+
+ function testEmptyClose()
+ {
+ $this->listener->expectOnce('endElement', array(''));
+ $this->listener->expectNever('characters');
+ $this->parser->parse('</>');
+ }
+
+ function testEmptyJasp()
+ {
+ $this->listener->expectOnce('jasp', array(''));
+ $this->listener->expectNever('characters');
+ $this->parser->parse('<%%>');
+ }
+
+ function testTargetOnlyProcessingInstruction()
+ {
+ $this->listener->expectOnce('processingInstruction', array('php', ''));
+ $this->listener->expectNever('characters');
+ $this->parser->parse('<?php ?>');
+ }
+
+ function testElementWithPreContent()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('startElement', array('br', array()));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('stuff<br>');
+ }
+
+ function testElementWithPostContent()
+ {
+ $this->listener->expectOnce('startElement', array('br', array()));
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<br>stuff');
+ }
+
+ function testExpressionAfterTag()
+ {
+ $this->listener->expectOnce('emptyElement', array('br', array()));
+ $this->listener->expectOnce('characters', array('{$str|clip:5}'));
+ $this->parser->parse('<br/>{$str|clip:5}');
+ }
+
+ function testExpressionAfterTagWithArguments()
+ {
+ $this->listener->expectOnce('emptyElement', array('core:set', array('str' => 'abcdefgh')));
+ $this->listener->expectOnce('characters', array('{$str|clip:5}'));
+ $this->parser->parse('<core:set str="abcdefgh" />{$str|clip:5}');
+ }
+
+ function testMismatchedElements()
+ {
+ $this->listener->expectArgumentsAt(0, 'startElement', array('b', array()));
+ $this->listener->expectArgumentsAt(1, 'startElement', array('i', array()));
+ $this->listener->expectArgumentsAt(0, 'endElement', array('b'));
+ $this->listener->expectArgumentsAt(1, 'endElement', array('i'));
+ $this->listener->expectCallCount('startElement', 2);
+ $this->listener->expectCallCount('endElement', 2);
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<b><i>stuff</b></i>');
+ }
+
+ function testAttributes()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array("a" => "A", "b" => "B", "c" => "C")));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<tag a="A" b=\'B\' c = "C">');
+ }
+
+ function testEmptyAttributes()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array("a" => NULL, "b" => NULL, "c" => NULL)));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<tag a b c>');
+ }
+
+ function testNastyAttributes()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array("a" => "&%$'?<>",
+ "b" => "\r\n\t\"",
+ "c" => "")));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse("<tag a=\"&%$'?<>\" b='\r\n\t\"' c = ''>");
+ }
+
+ function testAttributesPadding()
+ {
+ $this->listener->expectOnce('startElement', array('tag', array("a" => "A", "b" => "B", "c" => "C")));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse("<tag\ta=\"A\"\rb='B'\nc = \"C\"\n>");
+ }
+
+ function testAllProcessingInstruction()
+ {
+ $this->listener->expectOnce('processingInstruction', array('php', 'print "Hello"; '));
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('startElement');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<?php print "Hello"; ?>');
+ }
+
+ function testNestedProcessingInstruction()
+ {
+ $this->listener->expectOnce('processingInstruction', array('php', 'print "Hello"; '));
+ $this->listener->expectArgumentsAt(0, 'characters', array('a'));
+ $this->listener->expectArgumentsAt(1, 'characters', array('b'));
+ $this->listener->expectCallCount('characters', 2);
+ $this->listener->expectNever('startElement');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('a<?php print "Hello"; ?>b');
+ }
+
+ function testEscapeDocTypeHandler()
+ {
+ $this->listener->expectOnce('doctype', array('doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"'));
+ $this->parser->parse('<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">');
+ }
+
+ function testNestedDoctypeHandler()
+ {
+ $this->listener->expectOnce('doctype', array('doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"'));
+ $this->listener->expectArgumentsAt(0, 'characters', array('a'));
+ $this->listener->expectArgumentsAt(1, 'characters', array('b'));
+ $this->listener->expectCallCount('characters', 2);
+ $this->parser->parse('a<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">b');
+ }
+
+ function testEscapeCData()
+ {
+ $this->listener->expectOnce('cdata', array('string = \'A CDATA block\';'));
+ $this->parser->parse('<![CDATA[string = \'A CDATA block\';]]>');
+ }
+
+ function testSimpleComment()
+ {
+ $this->listener->expectOnce('comment', array(' A comment '));
+ $this->parser->parse('<!-- A comment -->');
+ }
+
+ function testNastyComment()
+ {
+ $this->listener->expectOnce('comment', array(' <tag></tag><?php ?><' . '% %> '));
+ $this->parser->parse('<tag><!-- <tag></tag><?php ?><' . '% %> --></tag>');
+ }
+
+ function testSimpleJasp()
+ {
+ $this->listener->expectOnce('jasp', array(' document.write("Hello World");'));
+ $this->listener->expectNever('processingInstruction');
+ $this->listener->expectNever('comment');
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('startElement');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<' . '% document.write("Hello World");%>');
+ }
+
+ function testNastyJasp()
+ {
+ $this->listener->expectOnce('jasp', array(' <tag a="A"><?php ?></tag><!-- comment --> '));
+ $this->listener->expectNever('processingInstruction');
+ $this->listener->expectNever('comment');
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('characters');
+ $this->listener->expectNever('startElement');
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('<' . '% <tag a="A"><?php ?></tag><!-- comment --> %>');
+ }
+
+ function testJaspInTag()
+ {
+ $this->listener->expectOnce( 'jasp', array(' document.write("Hello World");'));
+ $this->listener->expectNever('processingInstruction');
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('characters');
+ $this->listener->expectOnce('startElement');
+ $this->listener->expectOnce('endElement');
+ $this->parser->parse('<tag><' . '% document.write("Hello World");%></tag>');
+ }
+
+ /*
+// removed due to bug #1000806
+// see http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-specifying-data
+ function testScriptElement() {
+ $this->listener->expectOnce('startElement', array('script', array('language'=>'Javascript')));
+ $this->listener->expectOnce('endElement', array('script'));
+ $this->listener->expectOnce('characters', array("document.write('<B>Test<\/B>');"));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<script language="Javascript">document.write(\'<B>Test<\/B>\');</script>');
+ }
+ */
+
+ function testScriptElementEmbedComment() {
+ $this->listener->expectOnce('startElement', array('script', array('language'=>'Javascript')));
+ $this->listener->expectOnce('endElement', array('script'));
+ $this->listener->expectOnce('comment', array(" document.write('<B>Test<\/B>'); "));
+ $this->listener->expectNever('invalidAttributeSyntax');
+ $this->parser->parse('<script language="Javascript"><!-- document.write(\'<B>Test<\/B>\'); --></script>');
+ }
+}
+?>
\ No newline at end of file
Added: 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTruncatedTest.class.php
===================================================================
--- 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTruncatedTest.class.php (rev 0)
+++ 3.x/packages/wact/trunk/tests/cases/template/compiler/HtmlParserTruncatedTest.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,233 @@
+<?php
+require_once(WACT_TEST_CASES . '/template/compiler/HtmlParserTest.class.php');
+
+class HtmlParserTruncatedTest extends UnitTestCase
+{
+ var $parser;
+ var $listener;
+
+ function setUp()
+ {
+ $this->listener = new MockParserListener();
+ $this->parser = new HTMLParser($this->listener);
+ }
+
+ function testTruncatedOpen()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<');
+ }
+
+ function testTruncatedEmptyClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('</'));
+ $this->listener->expectNever('endElement');
+ $this->parser->parse('stuff</');
+ }
+
+ function testTruncatedClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('</a'));
+ $this->parser->parse('stuff</a');
+ $this->listener->expectNever('endElement');
+ }
+
+ function testTruncatedProcessingInstruction()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<?'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<?');
+ }
+
+ function testTruncatedProcessingInstructionTarget()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<?php'));
+ $this->listener->expectNever('processingInstruction');
+ $this->parser->parse('stuff<?php');
+ }
+
+ function testTruncatedProcessingInstructionNoClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<?php '));
+ $this->listener->expectNever('processingInstruction');
+ $this->parser->parse('stuff<?php ');
+ }
+
+ function testTruncatedJasp()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<%'));
+ $this->listener->expectNever('jasp');
+ $this->parser->parse('stuff<%');
+ }
+
+ function testTruncatedJaspNoClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<% more stuff'));
+ $this->listener->expectNever('jasp');
+ $this->parser->parse('stuff<% more stuff');
+ }
+
+ function testTruncatedComment()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<!--'));
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('comment');
+ $this->parser->parse('stuff<!--');
+ }
+
+ function testTruncatedCommentNoClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<!-- blah'));
+ $this->listener->expectNever('escape');
+ $this->listener->expectNever('comment');
+ $this->parser->parse('stuff<!-- blah');
+ }
+
+ function testTruncatedDocType()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<!doctype'));
+ $this->listener->expectNever('escape');
+ $this->parser->parse('stuff<!doctype');
+ }
+
+ function testTruncatedDocTypetNoClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<!doctype blah'));
+ $this->listener->expectNever('escape');
+ $this->parser->parse('stuff<!doctype blah');
+ }
+
+ function testTruncatedOpenElementChar()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<a'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<a');
+ }
+
+ function testTruncatedOpenElement()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag');
+ }
+
+ function testTruncatedOpenElementSpace()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag '));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag ');
+ }
+
+ function testTruncatedOpenElementMinimizedAttribute()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute');
+ }
+
+ function testTruncatedOpenElementMinimizedAttributeSpace()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute '));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute ');
+ }
+
+ function testTruncatedOpenElementAttribute()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute='));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=');
+ }
+
+ function testTruncatedOpenElementAttributeSpace()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute= '));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute= ');
+ }
+
+ function testTruncatedOpenElementAttributeNoQuote()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=value'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=value');
+ }
+
+ function testTruncatedOpenElementAttributeDoubleQuote()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute="'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute="');
+ }
+
+ function testTruncatedOpenElementAttributeDoubleQuoteNoClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute="value'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute="value');
+ }
+
+ function testTruncatedOpenElementAttributeDoubleQuoteValue()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute="value"'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute="value"');
+ }
+
+ function testTruncatedOpenElementAttributeSingleQuote()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\''));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=\'');
+ }
+
+ function testTruncatedOpenElementAttributeSingleQuoteNoClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\'value'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=\'value');
+ }
+
+ function testTruncatedOpenElementAttributeSingleQuoteValue()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\'value\''));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=\'value\'');
+ }
+
+ function testTruncatedOpenElementClose()
+ {
+ $this->listener->expectOnce('characters', array('stuff'));
+ $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\'value\'/'));
+ $this->listener->expectNever('startElement');
+ $this->parser->parse('stuff<tag attribute=\'value\'/');
+ }
+}
+?>
\ No newline at end of file
Copied: 3.x/packages/wact/trunk/tests/cases/template/compiler/SourceFileParserTest.class.php (from rev 4159, 3.x/packages/wact/trunk/tests/cases/template/compiler/sourcefileparser.test.php)
===================================================================
--- 3.x/packages/wact/trunk/tests/cases/template/compiler/SourceFileParserTest.class.php (rev 0)
+++ 3.x/packages/wact/trunk/tests/cases/template/compiler/SourceFileParserTest.class.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -0,0 +1,134 @@
+<?php
+require_once WACT_ROOT . '/template/compiler/templatecompiler.inc.php';
+
+Mock::generate('WactLiteralParsingState','MockLiteralParsingState');
+Mock::generate('WactComponentParsingState','MockComponentParsingState');
+Mock::generatePartial('SourceFileParser','SourceFileParserTestVersion', array('SourceFileParser'));
+
+class SourceFileParserTest extends UnitTestCase {
+
+ function setUp()
+ {
+ $this->SFP = new SourceFileParserTestVersion();
+ $this->SFP->ComponentParsingState = new MockComponentParsingState();
+ $this->SFP->LiteralParsingState = new MockLiteralParsingState();
+ $this->SFP->State = $this->SFP->ComponentParsingState;
+ }
+
+ function testBuildFilterChain() {
+ $Parser =& $this->SFP->buildFilterChain('tagstolower');
+ $this->SFP->ComponentParsingState->expectOnce('startElement', array('test', '*'));
+ $Parser->startElement('TEST', array());
+ }
+
+ function testChangeToComponentParsingState() {
+ $this->SFP->changeToComponentParsingState();
+ $this->assertIsA($this->SFP->State, 'MockComponentParsingState');
+ }
+
+ function testChangeToLiteralParsingState() {
+ $this->SFP->changeToLiteralParsingState('test');
+ $this->assertIsA($this->SFP->State,'MockLiteralParsingState');
+ $this->assertEqual($this->SFP->LiteralParsingState->literalTag, 'test');
+ }
+
+ function testChangeStates() {
+ $this->SFP->changeToComponentParsingState();
+ $this->assertIsA($this->SFP->State, 'MockComponentParsingState');
+ $this->SFP->changeToLiteralParsingState('test');
+ $this->assertIsA($this->SFP->State, 'MockLiteralParsingState');
+ $this->SFP->changeToComponentParsingState();
+ $this->assertIsA($this->SFP->State, 'MockComponentParsingState');
+ }
+
+
+ function testSetDocumentLocator() {
+ $this->SFP->ComponentParsingState->expectOnce('setDocumentLocator');
+ $this->SFP->LiteralParsingState->expectOnce('setDocumentLocator');
+ $Locator = NULL;
+
+ $this->SFP->setDocumentLocator($Locator);
+ }
+
+ function testStartElement() {
+ $tag = 'test';
+ $attributes = array('foo' => 'bar');
+ $this->SFP->State->expectOnce('startElement', array($tag, $attributes));
+ $this->SFP->startElement($tag, $attributes);
+ }
+
+ function testEndElement() {
+ $tag = 'test';
+ $this->SFP->State->expectOnce('endElement', array($tag));
+ $this->SFP->endElement($tag);
+ }
+
+ function testEmptyElement() {
+ $tag = 'test';
+ $attributes = array('foo' => 'bar');
+ $this->SFP->State->expectOnce('emptyElement', array($tag, $attributes));
+ $this->SFP->emptyElement($tag, $attributes);
+ }
+
+ function testCharacters() {
+ $data = 'test';
+ $this->SFP->State->expectOnce('characters', array($data));
+ $this->SFP->characters($data);
+ }
+
+ function testCdata() {
+ $data = 'test';
+ $this->SFP->State->expectOnce('cdata', array($data));
+ $this->SFP->cdata($data);
+ }
+
+ function testProcessingInstruction() {
+ $target = 'test';
+ $instruction = 'hi';
+ $this->SFP->State->expectOnce('processingInstruction', array($target, $instruction));
+ $this->SFP->processingInstruction($target, $instruction);
+ }
+
+ function testEscape() {
+ $text = 'test';
+ $this->SFP->State->expectOnce('escape', array($text));
+ $this->SFP->escape($text);
+ }
+
+ function testComment() {
+ $text = 'test';
+ $this->SFP->State->expectOnce('comment', array($text));
+ $this->SFP->comment($text);
+ }
+
+ function testDoctype() {
+ $text = 'test';
+ $this->SFP->State->expectOnce('doctype', array($text));
+ $this->SFP->doctype($text);
+ }
+
+ function testJasp() {
+ $text = 'test';
+ $this->SFP->State->expectOnce('jasp', array($text));
+ $this->SFP->jasp($text);
+ }
+
+ function testUnexpectedEOF() {
+ $text = 'test';
+ $this->SFP->State->expectOnce('unexpectedEOF', array($text));
+ $this->SFP->unexpectedEOF($text);
+ }
+
+ function testInvalidEntitySyntax() {
+ $text = 'test';
+ $this->SFP->State->expectOnce('invalidEntitySyntax', array($text));
+ $this->SFP->invalidEntitySyntax($text);
+ }
+
+ function testInvalidAttributeSyntax() {
+ $this->SFP->State->expectOnce('invalidAttributeSyntax', array());
+ $this->SFP->invalidAttributeSyntax();
+ }
+
+}
+?>
\ No newline at end of file
Deleted: 3.x/packages/wact/trunk/tests/cases/template/compiler/htmlparser.test.php
===================================================================
--- 3.x/packages/wact/trunk/tests/cases/template/compiler/htmlparser.test.php 2006-10-13 21:27:19 UTC (rev 4159)
+++ 3.x/packages/wact/trunk/tests/cases/template/compiler/htmlparser.test.php 2006-10-15 19:52:26 UTC (rev 4160)
@@ -1,606 +0,0 @@
-<?php
-/**
-* @package WACT_TESTS
-* @version $Id: htmlparser.test.php 3142 2006-04-24 15:47:48Z wiliam $
-*/
-
-require_once WACT_ROOT . 'template/compiler/htmlparser.inc.php';
-
-class ListenerInterface {
- function ListenerInterface() {
- }
-
- function startElement($name, $attrs) {
- }
-
- function endElement($name) {
- }
-
- function emptyElement($name, $attrs) {
- }
-
- function characters($data) {
- }
-
- function cdata($data) {
- }
-
- function processingInstruction($target, $data) {
- }
-
- function escape($data) {
- }
-
- function comment($data) {
- }
-
- function doctype($data) {
- }
-
- function jasp($data) {
- }
-
- function unexpectedEOF($data) {
- }
-
- function invalidEntitySyntax($data) {
- }
-
- function invalidAttributeSyntax() {
- }
-
- function setDocumentLocator(&$locator) {
- }
-}
-Mock::generate('ListenerInterface', 'MockListener');
-
-class HtmlParserTestCase extends UnitTestCase {
- var $parser;
- var $listener;
-
- function setUp() {
- $this->listener = new MockListener();
- $this->parser = new HTMLParser($this->listener);
- }
-
- function testEmpty() {
- $this->listener->expectNever('jasp');
- $this->listener->expectNever('processingInstruction');
- $this->listener->expectNever('escape');
- $this->listener->expectNever('characters');
- $this->listener->expectNever('startElement');
- $this->listener->expectNever('endElement');
- $this->parser->parse('');
- }
-
- function testSimpledata() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->parser->parse('stuff');
- }
-
- function testPreservingWhiteSpace() {
- $this->listener->expectOnce('characters', array(" stuff\t\r\n "));
- $this->parser->parse(" stuff\t\r\n ");
- }
-
- function testEmptyElement() {
- $this->listener->expectOnce('startElement', array('tag', array()));
- $this->listener->expectOnce('endElement', array('tag'));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<tag></tag>');
- }
-
- function testEmptyElementSelfClose() {
- $this->listener->expectOnce('emptyElement', array('br', array()));
- $this->listener->expectNever('startElement');
- $this->listener->expectNever('endElement');
- $this->parser->parse('<br/>');
- }
-
- function testElementWithContent() {
- $this->listener->expectOnce('startElement', array('tag', array()));
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('endElement', array('tag'));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<tag>stuff</tag>');
- }
-
- function testEmptyComment() {
- $this->listener->expectOnce('comment', array(''));
- $this->listener->expectNever('characters');
- $this->parser->parse('<!---->');
- }
-
- function testElementNestedSingleQuote() {
- $this->listener->expectOnce('startElement', array('tag', array('attribute' => '\'')));
- $this->listener->expectNever('characters');
- $this->listener->expectNever('endElement');
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<tag attribute="\'">');
- }
-
- function testElementNestedDoubleQuote() {
- $this->listener->expectOnce('startElement', array('tag', array('attribute' => '"')));
- $this->listener->expectNever('characters');
- $this->listener->expectNever('endElement');
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<tag attribute=\'"\'>');
- }
-
- function testEmptyDocType() {
- $this->listener->expectOnce('doctype', array('DOCTYPE'));
- $this->listener->expectNever('characters');
- $this->listener->expectNever('escape');
- $this->parser->parse('<!DOCTYPE>');
- }
-
- function testEmptyClose() {
- $this->listener->expectOnce('endElement', array(''));
- $this->listener->expectNever('characters');
- $this->parser->parse('</>');
- }
-
- function testEmptyJasp() {
- $this->listener->expectOnce('jasp', array(''));
- $this->listener->expectNever('characters');
- $this->parser->parse('<%%>');
- }
-
- function testTargetOnlyProcessingInstruction() {
- $this->listener->expectOnce('processingInstruction', array('php', ''));
- $this->listener->expectNever('characters');
- $this->parser->parse('<?php ?>');
- }
-
- function testElementWithPreContent() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('startElement', array('br', array()));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('stuff<br>');
- }
-
- function testElementWithPostContent() {
- $this->listener->expectOnce('startElement', array('br', array()));
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<br>stuff');
- }
-
- function testMismatchedElements() {
- $this->listener->expectArgumentsAt(0, 'startElement', array('b', array()));
- $this->listener->expectArgumentsAt(1, 'startElement', array('i', array()));
- $this->listener->expectArgumentsAt(0, 'endElement', array('b'));
- $this->listener->expectArgumentsAt(1, 'endElement', array('i'));
- $this->listener->expectCallCount('startElement', 2);
- $this->listener->expectCallCount('endElement', 2);
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<b><i>stuff</b></i>');
- }
-
- function testAttributes() {
- $this->listener->expectOnce(
- 'startElement',
- array('tag', array("a" => "A", "b" => "B", "c" => "C")));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<tag a="A" b=\'B\' c = "C">');
- }
-
- function testEmptyAttributes() {
- $this->listener->expectOnce(
- 'startElement',
- array('tag', array("a" => NULL, "b" => NULL, "c" => NULL)));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<tag a b c>');
- }
-
- function testNastyAttributes() {
- $this->listener->expectOnce(
- 'startElement',
- array('tag', array("a" => "&%$'?<>", "b" => "\r\n\t\"", "c" => "")));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse("<tag a=\"&%$'?<>\" b='\r\n\t\"' c = ''>");
- }
-
- function testAttributesPadding() {
- $this->listener->expectOnce(
- 'startElement',
- array('tag', array("a" => "A", "b" => "B", "c" => "C")));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse("<tag\ta=\"A\"\rb='B'\nc = \"C\"\n>");
- }
-
- function testAllprocessingInstruction() {
- $this->listener->expectOnce('processingInstruction', array('php', 'print "Hello"; '));
- $this->listener->expectNever('characters');
- $this->listener->expectNever('startElement');
- $this->listener->expectNever('endElement');
- $this->parser->parse('<?php print "Hello"; ?>');
- }
-
- function testNestedprocessingInstruction() {
- $this->listener->expectOnce('processingInstruction', array('php', 'print "Hello"; '));
- $this->listener->expectArgumentsAt(0, 'characters', array('a'));
- $this->listener->expectArgumentsAt(1, 'characters', array('b'));
- $this->listener->expectCallCount('characters', 2);
- $this->listener->expectNever('startElement');
- $this->listener->expectNever('endElement');
- $this->parser->parse('a<?php print "Hello"; ?>b');
- }
-
-
- function testEscapeDocTypeHandler() {
- $this->listener->expectOnce(
- 'doctype',
- array('doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"'));
- $this->parser->parse('<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">');
- }
-
- function testNestedDoctypeHandler() {
- $this->listener->expectOnce(
- 'doctype',
- array('doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"'));
- $this->listener->expectArgumentsAt(0, 'characters', array('a'));
- $this->listener->expectArgumentsAt(1, 'characters', array('b'));
- $this->listener->expectCallCount('characters', 2);
- $this->parser->parse('a<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">b');
- }
-
- function testEscapeCData() {
- $this->listener->expectOnce(
- 'cdata',
- array('string = \'A CDATA block\';'));
- $this->parser->parse('<![CDATA[string = \'A CDATA block\';]]>');
- }
-
- function testSimpleComment() {
- $this->listener->expectOnce('comment', array(' A comment '));
- $this->parser->parse('<!-- A comment -->');
- }
-
- function testNastyComment() {
- $this->listener->expectOnce(
- 'comment',
- array(' <tag></tag><?php ?><' . '% %> '));
- $this->parser->parse('<tag><!-- <tag></tag><?php ?><' . '% %> --></tag>');
- }
-
- function testSimpleJasp() {
- $this->listener->expectOnce(
- 'jasp',
- array(' document.write("Hello World");'));
- $this->listener->expectNever('processingInstruction');
- $this->listener->expectNever('comment');
- $this->listener->expectNever('escape');
- $this->listener->expectNever('characters');
- $this->listener->expectNever('startElement');
- $this->listener->expectNever('endElement');
- $this->parser->parse('<' . '% document.write("Hello World");%>');
- }
-
- function testNastyJasp() {
- $this->listener->expectOnce(
- 'jasp',
- array(' <tag a="A"><?php ?></tag><!-- comment --> '));
- $this->listener->expectNever('processingInstruction');
- $this->listener->expectNever('comment');
- $this->listener->expectNever('escape');
- $this->listener->expectNever('characters');
- $this->listener->expectNever('startElement');
- $this->listener->expectNever('endElement');
- $this->parser->parse('<' . '% <tag a="A"><?php ?></tag><!-- comment --> %>');
- }
-
- function testJaspInTag() {
- $this->listener->expectOnce(
- 'jasp',
- array(' document.write("Hello World");'));
- $this->listener->expectNever('processingInstruction');
- $this->listener->expectNever('escape');
- $this->listener->expectNever('characters');
- $this->listener->expectOnce('startElement');
- $this->listener->expectOnce('endElement');
- $this->parser->parse('<tag><' . '% document.write("Hello World");%></tag>');
- }
-
- /*
- removed due to bug #1000806
- see http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-specifying-data
- function testScriptElement() {
- $this->listener->expectOnce('startElement', array('script', array('language'=>'Javascript')));
- $this->listener->expectOnce('endElement', array('script'));
- $this->listener->expectOnce('characters', array("document.write('<B>Test<\/B>');"));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<script language="Javascript">document.write(\'<B>Test<\/B>\');</script>');
- }
-
- function testScriptElementEmbedComment() {
- $this->listener->expectOnce('startElement', array('script', array('language'=>'Javascript')));
- $this->listener->expectOnce('endElement', array('script'));
- $this->listener->expectOnce('characters', array("<!-- document.write('<B>Test<\/B>'); -->"));
- $this->listener->expectNever('invalidAttributeSyntax');
- $this->parser->parse('<script language="Javascript"><!-- document.write(\'<B>Test<\/B>\'); --></script>');
- }
- */
-}
-
-class HtmlParserTruncatedTestCase extends UnitTestCase {
- var $parser;
- var $listener;
-
- function setUp() {
- $this->listener = new MockListener();
- $this->parser = new HTMLParser($this->listener);
- }
-
- function testTruncatedOpen() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<');
- }
-
- function testTruncatedEmptyClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('</'));
- $this->listener->expectNever('endElement');
- $this->parser->parse('stuff</');
- }
-
- function testTruncatedClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('</a'));
- $this->parser->parse('stuff</a');
- $this->listener->expectNever('endElement');
- }
-
- function testTruncatedProcessingInstruction() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<?'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<?');
- }
-
- function testTruncatedProcessingInstructionTarget() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<?php'));
- $this->listener->expectNever('processingInstruction');
- $this->parser->parse('stuff<?php');
- }
-
- function testTruncatedProcessingInstructionNoClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<?php '));
- $this->listener->expectNever('processingInstruction');
- $this->parser->parse('stuff<?php ');
- }
-
- function testTruncatedJasp() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<%'));
- $this->listener->expectNever('jasp');
- $this->parser->parse('stuff<%');
- }
-
- function testTruncatedJaspNoClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<% more stuff'));
- $this->listener->expectNever('jasp');
- $this->parser->parse('stuff<% more stuff');
- }
-
- function testTruncatedComment() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<!--'));
- $this->listener->expectNever('escape');
- $this->listener->expectNever('comment');
- $this->parser->parse('stuff<!--');
- }
-
- function testTruncatedCommentNoClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<!-- blah'));
- $this->listener->expectNever('escape');
- $this->listener->expectNever('comment');
- $this->parser->parse('stuff<!-- blah');
- }
-
- function testTruncatedDocType() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<!doctype'));
- $this->listener->expectNever('escape');
- $this->parser->parse('stuff<!doctype');
- }
-
- function testTruncatedDocTypetNoClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<!doctype blah'));
- $this->listener->expectNever('escape');
- $this->parser->parse('stuff<!doctype blah');
- }
-
- function testTruncatedOpenElementChar() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<a'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<a');
- }
-
- function testTruncatedOpenElement() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag');
- }
-
- function testTruncatedOpenElementSpace() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag '));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag ');
- }
-
- function testTruncatedOpenElementMinimizedAttribute() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute');
- }
-
- function testTruncatedOpenElementMinimizedAttributeSpace() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute '));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute ');
- }
-
- function testTruncatedOpenElementAttribute() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute='));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute=');
- }
-
- function testTruncatedOpenElementAttributeSpace() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute= '));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute= ');
- }
-
- function testTruncatedOpenElementAttributeNoQuote() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=value'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute=value');
- }
-
- function testTruncatedOpenElementAttributeDoubleQuote() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute="'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute="');
- }
-
- function testTruncatedOpenElementAttributeDoubleQuoteNoClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute="value'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute="value');
- }
-
- function testTruncatedOpenElementAttributeDoubleQuoteValue() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute="value"'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute="value"');
- }
-
- function testTruncatedOpenElementAttributeSingleQuote() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\''));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute=\'');
- }
-
- function testTruncatedOpenElementAttributeSingleQuoteNoClose() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\'value'));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<tag attribute=\'value');
- }
-
- function testTruncatedOpenElementAttributeSingleQuoteValue() {
- $this->listener->expectOnce('characters', array('stuff'));
- $this->listener->expectOnce('unexpectedEOF', array('<tag attribute=\'value\''));
- $this->listener->expectNever('startElement');
- $this->parser->parse('stuff<