Merge branch 'release/2.6.1'

This commit is contained in:
Justin Hileman
2014-06-20 12:34:49 -07:00
17 changed files with 171 additions and 61 deletions
+9 -9
View File
@@ -20,13 +20,13 @@
* containing all Mustache library classes. This file can then be included in * containing all Mustache library classes. This file can then be included in
* your project, rather than requiring the Mustache Autoloader. * your project, rather than requiring the Mustache Autoloader.
*/ */
$baseDir = realpath(dirname(__FILE__).'/..'); $baseDir = realpath(dirname(__FILE__) . '/..');
require $baseDir.'/src/Mustache/Autoloader.php'; require $baseDir . '/src/Mustache/Autoloader.php';
Mustache_Autoloader::register(); Mustache_Autoloader::register();
// delete the old file // delete the old file
$file = $baseDir.'/mustache.php'; $file = $baseDir . '/mustache.php';
if (file_exists($file)) { if (file_exists($file)) {
unlink($file); unlink($file);
} }
@@ -77,7 +77,7 @@ SymfonyClassCollectionLoader::load(array(
*/ */
class SymfonyClassCollectionLoader class SymfonyClassCollectionLoader
{ {
static private $loaded; private static $loaded;
const HEADER = <<<EOS const HEADER = <<<EOS
<?php <?php
@@ -102,7 +102,7 @@ EOS;
* *
* @throws InvalidArgumentException When class can't be loaded * @throws InvalidArgumentException When class can't be loaded
*/ */
static public function load(array $classes, $cacheDir, $name, $extension = '.php') public static function load(array $classes, $cacheDir, $name, $extension = '.php')
{ {
// each $name can only be loaded once per PHP process // each $name can only be loaded once per PHP process
if (isset(self::$loaded[$name])) { if (isset(self::$loaded[$name])) {
@@ -121,9 +121,9 @@ EOS;
$content .= preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName())); $content .= preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
} }
$cache = $cacheDir.'/'.$name.$extension; $cache = $cacheDir . '/' . $name . $extension;
$header = sprintf(self::HEADER, strftime('%Y')); $header = sprintf(self::HEADER, strftime('%Y'));
self::writeCacheFile($cache, $header . substr(self::stripComments('<?php '.$content), 5)); self::writeCacheFile($cache, $header . substr(self::stripComments('<?php ' . $content), 5));
} }
/** /**
@@ -134,7 +134,7 @@ EOS;
* *
* @throws RuntimeException when a cache file cannot be written * @throws RuntimeException when a cache file cannot be written
*/ */
static private function writeCacheFile($file, $content) private static function writeCacheFile($file, $content)
{ {
$tmpFile = tempnam(dirname($file), basename($file)); $tmpFile = tempnam(dirname($file), basename($file));
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
@@ -156,7 +156,7 @@ EOS;
* *
* @return string The PHP string with the comments removed * @return string The PHP string with the comments removed
*/ */
static private function stripComments($source) private static function stripComments($source)
{ {
if (!function_exists('token_get_all')) { if (!function_exists('token_get_all')) {
return $source; return $source;
+18 -13
View File
@@ -24,7 +24,6 @@ USAGE
define('EXAMPLE_PATH', realpath(dirname(__FILE__) . '/../test/fixtures/examples')); define('EXAMPLE_PATH', realpath(dirname(__FILE__) . '/../test/fixtures/examples'));
/** /**
* transform a string to lowercase using underlines. * transform a string to lowercase using underlines.
* Examples: * Examples:
@@ -37,7 +36,8 @@ define('EXAMPLE_PATH', realpath(dirname(__FILE__) . '/../test/fixtures/examples'
* @access public * @access public
* @return string * @return string
*/ */
function getLowerCaseName($name) { function getLowerCaseName($name)
{
return preg_replace_callback("/([A-Z])/", create_function ( return preg_replace_callback("/([A-Z])/", create_function (
'$match', '$match',
'return "_" . strtolower($match[1]);' 'return "_" . strtolower($match[1]);'
@@ -56,14 +56,14 @@ function getLowerCaseName($name) {
* @access public * @access public
* @return string * @return string
*/ */
function getUpperCaseName($name) { function getUpperCaseName($name)
{
return preg_replace_callback("/_([a-z])/", create_function ( return preg_replace_callback("/_([a-z])/", create_function (
'$match', '$match',
'return strtoupper($match{1});' 'return strtoupper($match{1});'
), ucfirst($name)); ), ucfirst($name));
} }
/** /**
* return the given value and echo it out appending "\n" * return the given value and echo it out appending "\n"
* *
@@ -71,8 +71,10 @@ function getUpperCaseName($name) {
* @access public * @access public
* @return mixed * @return mixed
*/ */
function out($value) { function out($value)
{
echo $value . "\n"; echo $value . "\n";
return $value; return $value;
} }
@@ -88,7 +90,8 @@ function out($value) {
* @access public * @access public
* @return string * @return string
*/ */
function buildPath($directory, $filename = null, $extension = null) { function buildPath($directory, $filename = null, $extension = null)
{
return out(EXAMPLE_PATH . '/' . $directory. return out(EXAMPLE_PATH . '/' . $directory.
($extension !== null && $filename !== null ? '/' . $filename. "." . $extension : "")); ($extension !== null && $filename !== null ? '/' . $filename. "." . $extension : ""));
} }
@@ -101,8 +104,9 @@ function buildPath($directory, $filename = null, $extension = null) {
* @access public * @access public
* @return void * @return void
*/ */
function createDirectory($directory) { function createDirectory($directory)
if(!@mkdir(buildPath($directory))) { {
if (!@mkdir(buildPath($directory))) {
die("FAILED to create directory\n"); die("FAILED to create directory\n");
} }
} }
@@ -118,9 +122,10 @@ function createDirectory($directory) {
* @access public * @access public
* @return void * @return void
*/ */
function createFile($directory, $filename, $extension, $content = "") { function createFile($directory, $filename, $extension, $content = "")
{
$handle = @fopen(buildPath($directory, $filename, $extension), "w"); $handle = @fopen(buildPath($directory, $filename, $extension), "w");
if($handle) { if ($handle) {
fwrite($handle, $content); fwrite($handle, $content);
fclose($handle); fclose($handle);
} else { } else {
@@ -128,7 +133,6 @@ function createFile($directory, $filename, $extension, $content = "") {
} }
} }
/** /**
* routine to create the example directory and 3 files * routine to create the example directory and 3 files
* *
@@ -142,7 +146,8 @@ function createFile($directory, $filename, $extension, $content = "") {
* @access public * @access public
* @return void * @return void
*/ */
function main($example_name) { function main($example_name)
{
$lowercase = getLowerCaseName($example_name); $lowercase = getLowerCaseName($example_name);
$uppercase = getUpperCaseName($example_name); $uppercase = getUpperCaseName($example_name);
createDirectory($lowercase); createDirectory($lowercase);
@@ -160,7 +165,7 @@ CONTENT
} }
// check if enougth arguments are given // check if enougth arguments are given
if(count($argv) > 1) { if (count($argv) > 1) {
// get the name of the example // get the name of the example
$example_name = $argv[1]; $example_name = $argv[1];
-1
View File
@@ -14,7 +14,6 @@
*/ */
class Mustache_Autoloader class Mustache_Autoloader
{ {
private $baseDir; private $baseDir;
/** /**
-1
View File
@@ -16,7 +16,6 @@
*/ */
class Mustache_Compiler class Mustache_Compiler
{ {
private $sections; private $sections;
private $source; private $source;
private $indentNextLine; private $indentNextLine;
+3
View File
@@ -134,6 +134,9 @@ class Mustache_Context
{ {
for ($i = count($stack) - 1; $i >= 0; $i--) { for ($i = count($stack) - 1; $i >= 0; $i--) {
if (is_object($stack[$i]) && !($stack[$i] instanceof Closure)) { if (is_object($stack[$i]) && !($stack[$i] instanceof Closure)) {
// Note that is_callable() *will not work here*
// See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods
if (method_exists($stack[$i], $id)) { if (method_exists($stack[$i], $id)) {
return $stack[$i]->$id(); return $stack[$i]->$id();
} elseif (isset($stack[$i]->$id)) { } elseif (isset($stack[$i]->$id)) {
+2 -2
View File
@@ -23,7 +23,7 @@
*/ */
class Mustache_Engine class Mustache_Engine
{ {
const VERSION = '2.6.0'; const VERSION = '2.6.1';
const SPEC_VERSION = '1.1.2'; const SPEC_VERSION = '1.1.2';
const PRAGMA_FILTERS = 'FILTERS'; const PRAGMA_FILTERS = 'FILTERS';
@@ -213,7 +213,7 @@ class Mustache_Engine
*/ */
public function getEntityFlags() public function getEntityFlags()
{ {
return $this->entityFlags; return $this->entityFlags;
} }
/** /**
+9 -7
View File
@@ -27,14 +27,16 @@ class Mustache_HelperCollection
*/ */
public function __construct($helpers = null) public function __construct($helpers = null)
{ {
if ($helpers !== null) { if ($helpers === null) {
if (!is_array($helpers) && !$helpers instanceof Traversable) { return;
throw new Mustache_Exception_InvalidArgumentException('HelperCollection constructor expects an array of helpers'); }
}
foreach ($helpers as $name => $helper) { if (!is_array($helpers) && !$helpers instanceof Traversable) {
$this->add($name, $helper); throw new Mustache_Exception_InvalidArgumentException('HelperCollection constructor expects an array of helpers');
} }
foreach ($helpers as $name => $helper) {
$this->add($name, $helper);
} }
} }
-1
View File
@@ -14,7 +14,6 @@
*/ */
interface Mustache_Loader interface Mustache_Loader
{ {
/** /**
* Load a Template by name. * Load a Template by name.
* *
-1
View File
@@ -14,7 +14,6 @@
*/ */
interface Mustache_Loader_MutableLoader interface Mustache_Loader_MutableLoader
{ {
/** /**
* Set an associative array of Template sources for this loader. * Set an associative array of Template sources for this loader.
* *
-1
View File
@@ -25,7 +25,6 @@
*/ */
class Mustache_Loader_StringLoader implements Mustache_Loader class Mustache_Loader_StringLoader implements Mustache_Loader
{ {
/** /**
* Load a Template by source. * Load a Template by source.
* *
-1
View File
@@ -16,7 +16,6 @@
*/ */
abstract class Mustache_Template abstract class Mustache_Template
{ {
/** /**
* @var Mustache_Engine * @var Mustache_Engine
*/ */
+36 -15
View File
@@ -16,7 +16,6 @@
*/ */
class Mustache_Tokenizer class Mustache_Tokenizer
{ {
// Finite state machine states // Finite state machine states
const IN_TEXT = 0; const IN_TEXT = 0;
const IN_TAG_TYPE = 1; const IN_TAG_TYPE = 1;
@@ -85,6 +84,8 @@ class Mustache_Tokenizer
/** /**
* Scan and tokenize template source. * Scan and tokenize template source.
* *
* @throws Mustache_Exception_SyntaxException when mismatched section tags are encountered.
*
* @param string $text Mustache template source to tokenize * @param string $text Mustache template source to tokenize
* @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null) * @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null)
* *
@@ -117,7 +118,7 @@ class Mustache_Tokenizer
} else { } else {
$char = $text[$i]; $char = $text[$i];
$this->buffer .= $char; $this->buffer .= $char;
if ($char == "\n") { if ($char === "\n") {
$this->flushBuffer(); $this->flushBuffer();
$this->line++; $this->line++;
} }
@@ -152,29 +153,49 @@ class Mustache_Tokenizer
default: default:
if ($this->tagChange($this->ctag, $this->ctagLen, $text, $i)) { if ($this->tagChange($this->ctag, $this->ctagLen, $text, $i)) {
$this->tokens[] = array( $token = array(
self::TYPE => $this->tagType, self::TYPE => $this->tagType,
self::NAME => trim($this->buffer), self::NAME => trim($this->buffer),
self::OTAG => $this->otag, self::OTAG => $this->otag,
self::CTAG => $this->ctag, self::CTAG => $this->ctag,
self::LINE => $this->line, self::LINE => $this->line,
self::INDEX => ($this->tagType == self::T_END_SECTION) ? $this->seenTag - $this->otagLen : $i + $this->ctagLen self::INDEX => ($this->tagType === self::T_END_SECTION) ? $this->seenTag - $this->otagLen : $i + $this->ctagLen
); );
if ($this->tagType === self::T_UNESCAPED) {
// Clean up `{{{ tripleStache }}}` style tokens.
if ($this->ctag === '}}') {
if (($i + 2 < $len) && $text[$i + 2] === '}') {
$i++;
} else {
$msg = sprintf(
'Mismatched tag delimiters: %s on line %d',
$token[self::NAME],
$token[self::LINE]
);
throw new Mustache_Exception_SyntaxException($msg, $token);
}
} else {
$lastName = $token[self::NAME];
if (substr($lastName, -1) === '}') {
$token[self::NAME] = trim(substr($lastName, 0, -1));
} else {
$msg = sprintf(
'Mismatched tag delimiters: %s on line %d',
$token[self::NAME],
$token[self::LINE]
);
throw new Mustache_Exception_SyntaxException($msg, $token);
}
}
}
$this->buffer = ''; $this->buffer = '';
$i += $this->ctagLen - 1; $i += $this->ctagLen - 1;
$this->state = self::IN_TEXT; $this->state = self::IN_TEXT;
if ($this->tagType == self::T_UNESCAPED) { $this->tokens[] = $token;
if ($this->ctag == '}}') {
$i++;
} else {
// Clean up `{{{ tripleStache }}}` style tokens.
$lastName = $this->tokens[count($this->tokens) - 1][self::NAME];
if (substr($lastName, -1) === '}') {
$this->tokens[count($this->tokens) - 1][self::NAME] = trim(substr($lastName, 0, -1));
}
}
}
} else { } else {
$this->buffer .= $text[$i]; $this->buffer .= $text[$i];
} }
@@ -17,7 +17,7 @@ class Mustache_Test_Cache_FilesystemCacheTest extends Mustache_Test_FunctionalTe
public function testCacheGetNone() public function testCacheGetNone()
{ {
$key = 'some key'; $key = 'some key';
$cache = new Mustache_Cache_FilesystemCache(self::$tempDir);; $cache = new Mustache_Cache_FilesystemCache(self::$tempDir);
$loaded = $cache->load($key); $loaded = $cache->load($key);
$this->assertFalse($loaded); $this->assertFalse($loaded);
@@ -27,7 +27,7 @@ class Mustache_Test_Cache_FilesystemCacheTest extends Mustache_Test_FunctionalTe
{ {
$key = 'some key'; $key = 'some key';
$value = '<?php /* some value */'; $value = '<?php /* some value */';
$cache = new Mustache_Cache_FilesystemCache(self::$tempDir);; $cache = new Mustache_Cache_FilesystemCache(self::$tempDir);
$cache->cache($key, $value); $cache->cache($key, $value);
$loaded = $cache->load($key); $loaded = $cache->load($key);
@@ -46,7 +46,7 @@ class Mustache_Test_FiveThree_Functional_FiltersTest extends PHPUnit_Framework_T
array( array(
'{{% FILTERS }}{{ date | longdate }}', '{{% FILTERS }}{{ date | longdate }}',
$helpers, $helpers,
(object) array('date' => new DateTime('1/1/2000')), (object) array('date' => new DateTime('1/1/2000', new DateTimeZone("UTC"))),
'2000-01-01 12:01:00' '2000-01-01 12:01:00'
), ),
@@ -72,7 +72,7 @@ class Mustache_Test_FiveThree_Functional_FiltersTest extends PHPUnit_Framework_T
}); });
$foo = new \StdClass; $foo = new \StdClass;
$foo->date = new DateTime('1/1/2000'); $foo->date = new DateTime('1/1/2000', new DateTimeZone("UTC"));
$this->assertEquals('[[2000-01-01 12:01:00]]', $tpl->render($foo)); $this->assertEquals('[[2000-01-01 12:01:00]]', $tpl->render($foo));
} }
@@ -42,12 +42,12 @@ EOS;
$tpl = $m->loadTemplate($src); $tpl = $m->loadTemplate($src);
$data = new Mustache_Test_Functional_ClassWithLambda(); $data = new Mustache_Test_FiveThree_Functional_ClassWithLambda();
$this->assertEquals($expected, $tpl->render($data)); $this->assertEquals($expected, $tpl->render($data));
} }
} }
class Mustache_Test_Functional_ClassWithLambda class Mustache_Test_FiveThree_Functional_ClassWithLambda
{ {
public function _t() public function _t()
{ {
+85
View File
@@ -24,6 +24,28 @@ class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
$this->assertSame($expected, $tokenizer->scan($text, $delimiters)); $this->assertSame($expected, $tokenizer->scan($text, $delimiters));
} }
/**
* @expectedException Mustache_Exception_SyntaxException
*/
public function testUnevenBracesThrowExceptions()
{
$tokenizer = new Mustache_Tokenizer;
$text = "{{{ name }}";
$tokenizer->scan($text, null);
}
/**
* @expectedException Mustache_Exception_SyntaxException
*/
public function testUnevenBracesWithCustomDelimiterThrowExceptions()
{
$tokenizer = new Mustache_Tokenizer;
$text = "<%{ name %>";
$tokenizer->scan($text, "<% %>");
}
public function getTokens() public function getTokens()
{ {
return array( return array(
@@ -188,6 +210,69 @@ class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
), ),
) )
), ),
// custom delimiters don't swallow the next character, even if it is a }, }}}, or the same delimiter
array(
"<% a %>} <% b %>%> <% c %>}}}",
"<% %>",
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'a',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 7,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::VALUE => "} ",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'b',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 16,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::VALUE => "%> ",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'c',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 26,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::VALUE => "}}}",
),
)
),
// unescaped custom delimiters are properly parsed
array(
"<%{ a }%>",
"<% %>",
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_UNESCAPED,
Mustache_Tokenizer::NAME => 'a',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 9,
)
)
),
); );
} }
} }
+3 -3
View File
@@ -9,8 +9,8 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
require dirname(__FILE__).'/../src/Mustache/Autoloader.php'; require dirname(__FILE__) . '/../src/Mustache/Autoloader.php';
Mustache_Autoloader::register(); Mustache_Autoloader::register();
Mustache_Autoloader::register(dirname(__FILE__).'/../test'); Mustache_Autoloader::register(dirname(__FILE__) . '/../test');
require dirname(__FILE__).'/../vendor/yaml/lib/sfYamlParser.php'; require dirname(__FILE__) . '/../vendor/yaml/lib/sfYamlParser.php';