Просмотр исходного кода

2x faster. Who needs a Buffer instance, anyway?

Justin Hileman 13 лет назад
Родитель
Сommit
367013f01c

+ 0 - 138
src/Mustache/Buffer.php

@@ -1,138 +0,0 @@
-<?php
-
-/*
- * This file is part of Mustache.php.
- *
- * (c) 2012 Justin Hileman
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Mustache;
-
-/**
- * Mustache output Buffer class.
- *
- * Buffer instances are used by Mustache Templates for collecting output during rendering
- */
-class Buffer {
-	private $buffer  = '';
-	private $indent  = '';
-	private $charset = 'UTF-8';
-
-	/**
-	 * Mustache Buffer constructor.
-	 *
-	 * @param string $indent  Initial indent level for all lines of this buffer (default: '')
-	 * @param string $charset Override the character set used by `htmlspecialchars()` (default: 'UTF-8')
-	 */
-	public function __construct($indent = null, $charset = null) {
-		if ($indent !== null) {
-			$this->setIndent($indent);
-		}
-
-		if ($charset !== null) {
-			$this->charset = $charset;
-		}
-	}
-
-	/**
-	 * Get the current indent level.
-	 *
-	 * @return string
-	 */
-	public function getIndent() {
-		return $this->indent;
-	}
-
-	/**
-	 * Set the buffer indent level.
-	 *
-	 * Each line output by this buffer will be prefixed by this whitespace. This is used when rendering
-	 * partials and Lambda sections.
-	 *
-	 * @param string $indent
-	 */
-	public function setIndent($indent) {
-		$this->indent = $indent;
-	}
-
-	/**
-	 * Get the character set used when escaping values.
-	 *
-	 * @return string
-	 */
-	public function getCharset() {
-		return $this->charset;
-	}
-
-	/**
-	 * Write a newline to the Buffer.
-	 */
-	public function writeLine() {
-		$this->buffer .= "\n";
-	}
-
-	/**
-	 * Output text to the Buffer.
-	 *
-	 * @see \Mustache\Buffer::write
-	 *
-	 * @param string $text
-	 * @param bool   $escape Escape this text with `htmlspecialchars()`? (default: false)
-	 */
-	public function writeText($text, $escape = false) {
-		$this->write($text, true, $escape);
-	}
-
-	/**
-	 * Add output to the Buffer.
-	 *
-	 * @param string $text
-	 * @param bool   $indent Indent this line? (default: false)
-	 * @param bool   $escape Escape this text with `htmlspecialchars()`? (default: false)
-	 */
-	public function write($text, $indent = false, $escape = false) {
-		$text = (string) $text;
-
-		if ($escape) {
-			$text = $this->escape($text);
-		}
-
-		if ($indent) {
-			$this->buffer .= $this->indent . $text;
-		} else {
-			$this->buffer .= $text;
-		}
-	}
-
-	/**
-	 * Flush the contents of the Buffer.
-	 *
-	 * Resets the buffer and returns the current contents.
-	 *
-	 * @return string
-	 */
-	public function flush() {
-		$buffer = $this->buffer;
-		$this->buffer = '';
-
-		return $buffer;
-	}
-
-	/**
-	 * Helper function to escape text.
-	 *
-	 * Uses the Buffer's character set (default 'UTF-8', passed as the second argument to `__construct`).
-	 *
-	 * @see htmlspecialchars
-	 *
-	 * @param string $text
-	 *
-	 * @return string Escaped text
-	 */
-	private function escape($text) {
-		return htmlspecialchars($text, ENT_COMPAT, $this->charset);
-	}
-}

+ 22 - 16
src/Mustache/Compiler.php

@@ -109,11 +109,15 @@ class Compiler {
 	const KLASS = '<?php
 
 		class %s extends \Mustache\Template {
-			public function renderInternal(\Mustache\Context $context, $indent = \'\') {
-				$buffer = new \Mustache\Buffer($indent, $this->mustache->getCharset());
+			public function renderInternal(\Mustache\Context $context, $indent = \'\', $escape = false) {
+				$buffer = \'\';
 		%s
 
-				return $buffer->flush();
+				if ($escape) {
+					return htmlspecialchars($buffer, ENT_COMPAT, $this->mustache->getCharset());
+				}
+
+				return $buffer;
 			}
 		%s
 		}';
@@ -135,18 +139,17 @@ class Compiler {
 
 	const SECTION_CALL = '
 		// %s section
-		$this->section%s($buffer, $context, $context->%s(%s));
+		$buffer .= $this->section%s($context, $indent, $context->%s(%s));
 	';
 
 	const SECTION = '
-		private function section%s(\Mustache\Buffer $buffer, \Mustache\Context $context, $value) {
+		private function section%s(\Mustache\Context $context, $indent, $value) {
+			$buffer = \'\';
 			if (!is_string($value) && is_callable($value)) {
 				$source = %s;
-				$buffer->write(
-					$this->mustache
-						->loadLambda((string) call_user_func($value, $source)%s)
-						->renderInternal($context, $buffer->getIndent())
-				);
+				$buffer .= $this->mustache
+					->loadLambda((string) call_user_func($value, $source)%s)
+					->renderInternal($context, $indent);
 			} elseif (!empty($value)) {
 				$values = $this->isIterable($value) ? $value : array($value);
 				foreach ($values as $value) {
@@ -154,6 +157,8 @@ class Compiler {
 					$context->pop();
 				}
 			}
+
+			return $buffer;
 		}';
 
 	/**
@@ -212,7 +217,7 @@ class Compiler {
 		return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $this->walk($nodes, $level));
 	}
 
-	const PARTIAL = '$buffer->write($this->mustache->loadPartial(%s)->renderInternal($context, %s));';
+	const PARTIAL = '$buffer .= $this->mustache->loadPartial(%s)->renderInternal($context, %s);';
 
 	/**
 	 * Generate Mustache Template partial call PHP source.
@@ -236,10 +241,11 @@ class Compiler {
 		if (!is_string($value) && is_callable($value)) {
 			$value = $this->mustache
 				->loadLambda((string) call_user_func($value))
-				->renderInternal($context, $buffer->getIndent());
+				->renderInternal($context, $indent);
 		}
-		$buffer->writeText($value, %s);
+		$buffer .= $indent . %s;
 	';
+	const VARIABLE_ESCAPED = 'htmlspecialchars($value, ENT_COMPAT, $this->mustache->getCharset())';
 
 	/**
 	 * Generate Mustache Template variable interpolation PHP source.
@@ -253,13 +259,13 @@ class Compiler {
 	private function variable($id, $escape, $level) {
 		$method = $this->getFindMethod($id);
 		$id     = ($method !== 'last') ? var_export($id, true) : '';
-		$escape = $escape ? 'true' : 'false';
+		$escape = $escape ? self::VARIABLE_ESCAPED : '$value';
 
 		return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $escape);
 	}
 
-	const LINE = '$buffer->writeLine();';
-	const TEXT = '$buffer->writeText(%s);';
+	const LINE = '$buffer .= "\n";';
+	const TEXT = '$buffer .= $indent . %s;';
 
 	/**
 	 * Generate Mustache Template output Buffer call PHP source.

+ 1 - 1
src/Mustache/Template.php

@@ -71,7 +71,7 @@ abstract class Template {
 	 *
 	 * @return string Rendered template
 	 */
-	abstract public function renderInternal(Context $context);
+	abstract public function renderInternal(Context $context, $indent = '', $escape = false);
 
 	/**
 	 * Tests whether a value should be iterated over (e.g. in a section context).

+ 0 - 99
test/Mustache/Test/BufferTest.php

@@ -1,99 +0,0 @@
-<?php
-
-/*
- * This file is part of Mustache.php.
- *
- * (c) 2012 Justin Hileman
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Mustache\Test;
-
-use Mustache\Mustache;
-use Mustache\Buffer;
-
-/**
- * @group unit
- */
-class BufferTest extends \PHPUnit_Framework_TestCase {
-
-	/**
-	 * @dataProvider getConstructorArgs
-	 */
-	public function testConstructor($indent, $charset) {
-		$buffer = new Buffer($indent, $charset);
-		$this->assertEquals($indent, $buffer->getIndent());
-		$this->assertEquals($charset, $buffer->getCharset());
-	}
-
-	public function getConstructorArgs() {
-		return array(
-			array('',       'UTF-8'),
-			array('    ',   'ISO-8859-1'),
-			array("\t\t\t", 'Shift_JIS'),
-		);
-	}
-
-	public function testWrite() {
-		$buffer = new Buffer;
-		$this->assertEquals('', $buffer->flush());
-
-		$buffer->writeLine();
-		$buffer->writeLine();
-		$buffer->writeLine();
-		$this->assertEquals("\n\n\n", $buffer->flush());
-		$this->assertEquals('', $buffer->flush());
-
-		$buffer->write('foo');
-		$buffer->write('bar');
-		$buffer->writeLine();
-		$buffer->write('baz');
-		$this->assertEquals("foobar\nbaz", $buffer->flush());
-		$this->assertEquals('', $buffer->flush());
-
-		$indent = "\t\t";
-		$buffer->setIndent($indent);
-		$buffer->writeText('foo');
-		$buffer->writeLine();
-		$buffer->writeText('bar');
-		$this->assertEquals("\t\tfoo\n\t\tbar", $buffer->flush());
-		$this->assertEquals('', $buffer->flush());
-	}
-
-	/**
-	 * @dataProvider getEscapeAndIndent
-	 */
-	public function testEscapingAndIndenting($text, $escape, $indent, $whitespace, $expected) {
-		$buffer = new Buffer;
-		$buffer->setIndent($whitespace);
-
-		$buffer->write($text, $indent, $escape);
-		$this->assertEquals($expected, $buffer->flush());
-	}
-
-	public function getEscapeAndIndent() {
-		return array(
-			array('> "fun & games" <', false, false, "\t", '> "fun & games" <'),
-			array('> "fun & games" <', true,  false, "\t", '&gt; &quot;fun &amp; games&quot; &lt;'),
-			array('> "fun & games" <', true,  true,  "\t", "\t&gt; &quot;fun &amp; games&quot; &lt;"),
-			array('> "fun & games" <', false, true,  "\t", "\t> \"fun & games\" <"),
-		);
-	}
-
-	public function testChangeIndent() {
-		$indent = "\t\t";
-		$buffer = new Buffer($indent);
-		$this->assertEquals($indent, $buffer->getIndent());
-
-		$indent = "";
-		$buffer->setIndent($indent);
-		$this->assertEquals($indent, $buffer->getIndent());
-
-		$indent = " ";
-		$buffer->setIndent($indent);
-		$this->assertEquals($indent, $buffer->getIndent());
-	}
-
-}

+ 8 - 8
test/Mustache/Test/CompilerTest.php

@@ -35,13 +35,13 @@ class CompilerTest extends \PHPUnit_Framework_TestCase {
 		return array(
 			array('', array(), 'Banana', array(
 				"\nclass Banana extends \Mustache\Template",
-				'$buffer->flush();',
+				'return $buffer;',
 			)),
 
 			array('', array('TEXT'), 'Monkey', array(
 				"\nclass Monkey extends \Mustache\Template",
-				'$buffer->writeText(\'TEXT\');',
-				'$buffer->flush();',
+				'$buffer .= $indent . \'TEXT\';',
+				'return $buffer;',
 			)),
 
 			array(
@@ -62,13 +62,13 @@ class CompilerTest extends \PHPUnit_Framework_TestCase {
 				'Monkey',
 				array(
 					"\nclass Monkey extends \Mustache\Template",
-					'$buffer->writeText(\'foo\');',
-					'$buffer->writeLine();',
+					'$buffer .= $indent . \'foo\'',
+					'$buffer .= "\n"',
 					'$value = $context->find(\'name\');',
-					'$buffer->writeText($value, true);',
+					'$buffer .= $indent . htmlspecialchars($value, ENT_COMPAT, $this->mustache->getCharset());',
 					'$value = $context->last();',
-					'$buffer->writeText(\'\\\'bar\\\'\');',
-					'$buffer->flush();',
+					'$buffer .= $indent . \'\\\'bar\\\'\';',
+					'return $buffer;',
 				)
 			),
 		);

+ 1 - 1
test/Mustache/Test/TemplateTest.php

@@ -46,7 +46,7 @@ class TemplateStub extends Template {
 		return $this->mustache;
 	}
 
-	public function renderInternal(Context $context) {
+	public function renderInternal(Context $context, $indent = '', $escape = false) {
 		return $this->rendered;
 	}
 }