소스 검색

Merge branch 'release/0.9.0'

Justin Hileman 14 년 전
부모
커밋
5934fd8a86
10개의 변경된 파일344개의 추가작업 그리고 3개의 파일을 삭제
  1. 2 2
      Mustache.php
  2. 85 0
      MustacheLoader.php
  3. 1 1
      README.markdown
  4. 172 0
      bin/create_example.php
  5. 20 0
      examples/i18n/I18n.php
  6. 1 0
      examples/i18n/i18n.mustache
  7. 1 0
      examples/i18n/i18n.txt
  8. 60 0
      test/MustacheLoaderTest.php
  9. 1 0
      test/fixtures/bar.mustache
  10. 1 0
      test/fixtures/foo.mustache

+ 2 - 2
Mustache.php

@@ -14,7 +14,7 @@
  */
 class Mustache {
 
-	const VERSION      = '0.8.1';
+	const VERSION      = '0.9.0';
 	const SPEC_VERSION = '1.1.2';
 
 	/**
@@ -819,7 +819,7 @@ class Mustache {
 	 * @return string
 	 */
 	protected function _getPartial($tag_name) {
-		if (is_array($this->_partials) && isset($this->_partials[$tag_name])) {
+		if ((is_array($this->_partials) || $this->_partials instanceof ArrayAccess) && isset($this->_partials[$tag_name])) {
 			return $this->_partials[$tag_name];
 		}
 

+ 85 - 0
MustacheLoader.php

@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * A Mustache Partial filesystem loader.
+ *
+ * @author Justin Hileman {@link http://justinhileman.com}
+ */
+class MustacheLoader implements ArrayAccess {
+
+	protected $baseDir;
+	protected $partialsCache = array();
+	protected $extension;
+
+	/**
+	 * MustacheLoader constructor.
+	 *
+	 * @access public
+	 * @param  string $baseDir   Base template directory.
+	 * @param  string $extension File extension for Mustache files (default: 'mustache')
+	 * @return void
+	 */
+	public function __construct($baseDir, $extension = 'mustache') {
+		if (!is_dir($baseDir)) {
+			throw new InvalidArgumentException('$baseDir must be a valid directory, ' . $baseDir . ' given.');
+		}
+
+		$this->baseDir   = $baseDir;
+		$this->extension = $extension;
+	}
+
+	/**
+	 * @param  string $offset Name of partial
+	 * @return boolean
+	 */
+	public function offsetExists($offset) {
+		return (isset($this->partialsCache[$offset]) || file_exists($this->pathName($offset)));
+	}
+	
+	/**
+	 * @throws InvalidArgumentException if the given partial doesn't exist
+	 * @param  string $offset Name of partial
+	 * @return string Partial template contents
+	 */
+	public function offsetGet($offset) {
+		if (!$this->offsetExists($offset)) {
+			throw new InvalidArgumentException('Partial does not exist: ' . $offset);
+		}
+
+		if (!isset($this->partialsCache[$offset])) {
+			$this->partialsCache[$offset] = file_get_contents($this->pathName($offset));
+		}
+
+		return $this->partialsCache[$offset];
+	}
+	
+	/**
+	 * MustacheLoader is an immutable filesystem loader. offsetSet throws a LogicException if called.
+	 *
+	 * @throws LogicException
+	 * @return void
+	 */
+	public function offsetSet($offset, $value) {
+		throw new LogicException('Unable to set offset: MustacheLoader is an immutable ArrayAccess object.');
+	}
+	
+	/**
+	 * MustacheLoader is an immutable filesystem loader. offsetUnset throws a LogicException if called.
+	 *
+	 * @throws LogicException
+	 * @return void
+	 */
+	public function offsetUnset($offset) {
+		throw new LogicException('Unable to unset offset: MustacheLoader is an immutable ArrayAccess object.');
+	}
+
+	/**
+	 * An internal helper for generating path names.
+	 * 
+	 * @param  string $file Partial name
+	 * @return string File path
+	 */
+	protected function pathName($file) {
+		return $this->baseDir . '/' . $file . '.' . $this->extension;
+	}
+}

+ 1 - 1
README.markdown

@@ -44,7 +44,7 @@ Along with the associated Mustache class:
 Render it like so:
 
     <?php
-    $c = new Chris;
+    $chris = new Chris;
     echo $chris->render($template);
     ?>
 

+ 172 - 0
bin/create_example.php

@@ -0,0 +1,172 @@
+#!/usr/bin/env php
+<?php
+
+/**
+ * A commandline script to create an example and the needed files:
+ *
+ *     $ bin/create_example.php my_new_example
+ *
+ * ... and the folder my_new_example will be created in the examples/ folder containing 3 files:
+ *
+ *     my_new_example/my_new_example.mustache
+ *     my_new_example/my_new_example.txt
+ *     my_new_example/MyNewExample.php
+ */
+
+// some constants
+define('USAGE', <<<USAGE
+USAGE: {$argv[0]} example_name
+
+This creates a new example and the corresponding files in the examples/ directory
+
+USAGE
+);
+
+define('DS', DIRECTORY_SEPARATOR);
+define('EXAMPLE_PATH', realpath(dirname(__FILE__) . DS . ".." . DS . "examples"));
+
+
+/**
+ * transform a string to lowercase using underlines.
+ * Examples:
+ * String -> string
+ * AString -> a_string
+ * SomeStrings -> some_strings
+ * AStringMore -> a_string_more
+ *
+ * @param string $name
+ * @access public
+ * @return string
+ */
+function getLowerCaseName($name) {
+	return preg_replace_callback("/([A-Z])/", create_function (
+		'$match',
+		'return "_" . strtolower($match[1]);'
+	), lcfirst($name));
+}
+
+/**
+ * transform a string to Uppercase (camelcase)
+ * Examples
+ * string -> String
+ * a_string -> AString
+ * some_strings -> SomeStrings
+ * a_string_more -> AStringMore -> a_string_more
+ *
+ * @param string $name
+ * @access public
+ * @return string
+ */
+function getUpperCaseName($name) {
+	return preg_replace_callback("/_([a-z])/", create_function (
+		'$match',
+		'return strtoupper($match{1});'
+	), ucfirst($name));
+}
+
+
+/**
+ * return the given value and echo it out appending "\n"
+ *
+ * @param mixed $value
+ * @access public
+ * @return mixed
+ */
+function out($value) {
+	echo $value . "\n";
+	return $value;
+}
+
+/**
+ * create Path for certain files in an example
+ * returns the directory name if only $directory is given.
+ * if an extension is given a complete filename is returned.
+ * the returned filename will be echoed out
+ *
+ * @param string $directory directory without / at the end
+ * @param string $filename filename without path and extension
+ * @param string $extension extension of the file without "."
+ * @access public
+ * @return string
+ */
+function buildPath($directory, $filename = null,  $extension = null) {
+	return out(EXAMPLE_PATH . DS . $directory.
+					($extension !== null && $filename !== null ? DS . $filename. "." . $extension : ""));
+}
+
+/**
+ * creates the directory for the example
+ * the script die()'s if mkdir() fails
+ *
+ * @param string $directory
+ * @access public
+ * @return void
+ */
+function createDirectory($directory) {
+	if(!@mkdir(buildPath($directory))) {
+		die("FAILED to create directory\n");
+	}
+}
+
+/**
+ * create a file for the example with the given $content
+ * the script die()'s if fopen() fails
+ *
+ * @param string $directory directory without / at the end
+ * @param string $filename filename without path and extension
+ * @param string $extension extension of the file without "."
+ * @param string $content the content of the file
+ * @access public
+ * @return void
+ */
+function createFile($directory, $filename, $extension, $content = "") {
+	$handle = @fopen(buildPath($directory, $filename, $extension), "w");
+	if($handle) {
+		fwrite($handle, $content);
+		fclose($handle);
+	} else {
+		die("FAILED to create file\n");
+	}
+}
+
+
+/**
+ * routine to create the example directory and 3 files
+ *
+ * if the $example_name is "SomeThing" the following files will be created
+ * examples/some_thing
+ * examples/some_thing/some_thing.mustache
+ * examples/some_thing/some_thing.txt
+ * examples/some_thing/SomeThing.php
+ *
+ * @param mixed $example_name
+ * @access public
+ * @return void
+ */
+function main($example_name) {
+	$lowercase = getLowerCaseName($example_name);
+	$uppercase = getUpperCaseName($example_name);
+	createDirectory($lowercase);
+	createFile($lowercase, $lowercase, "mustache");
+	createFile($lowercase, $lowercase, "txt");
+	createFile($lowercase, $uppercase, "php", <<<CONTENT
+<?php
+
+class {$uppercase} extends Mustache {
+
+}
+
+CONTENT
+	);
+}
+
+// check if enougth arguments are given
+if(count($argv) > 1) {
+	// get the name of the example
+	$example_name = $argv[1];
+
+	main($example_name);
+
+} else {
+	echo USAGE;
+}

+ 20 - 0
examples/i18n/I18n.php

@@ -0,0 +1,20 @@
+<?php
+
+class I18n extends Mustache {
+
+    // Variable to be interpolated
+    public $name = 'Bob';
+
+    // Add a {{#__}} lambda for i18n
+    public $__ = array(__CLASS__, '__trans');
+
+    // A *very* small i18n dictionary :)
+    private $dictionary = array(
+        'Hello.' => 'Hola.',
+        'My name is {{ name }}.' => 'Me llamo {{ name }}.',
+    );
+
+    public function __trans($text) {
+        return isset($this->dictionary[$text]) ? $this->dictionary[$text] : $text;
+    }
+}

+ 1 - 0
examples/i18n/i18n.mustache

@@ -0,0 +1 @@
+{{#__}}Hello.{{/__}} {{#__}}My name is {{ name }}.{{/__}}

+ 1 - 0
examples/i18n/i18n.txt

@@ -0,0 +1 @@
+Hola. Me llamo Bob.

+ 60 - 0
test/MustacheLoaderTest.php

@@ -0,0 +1,60 @@
+<?php
+
+require_once '../Mustache.php';
+require_once '../MustacheLoader.php';
+
+/**
+ * @group loader
+ */
+class MustacheLoaderTest extends PHPUnit_Framework_TestCase {
+
+	public function testTheActualFilesystemLoader() {
+		$loader = new MustacheLoader(dirname(__FILE__).'/fixtures');
+		$this->assertEquals(file_get_contents(dirname(__FILE__).'/fixtures/foo.mustache'), $loader['foo']);
+		$this->assertEquals(file_get_contents(dirname(__FILE__).'/fixtures/bar.mustache'), $loader['bar']);
+	}
+
+	public function testMustacheUsesFilesystemLoader() {
+		$template = '{{> foo }} {{> bar }}';
+		$data = array(
+			'truthy' => true,
+			'foo'    => 'FOO',
+			'bar'    => 'BAR',
+		);
+		$output = 'FOO BAR';
+		$m = new Mustache();
+		$partials = new MustacheLoader(dirname(__FILE__).'/fixtures');
+		$this->assertEquals($output, $m->render($template, $data, $partials));
+	}
+
+	public function testMustacheUsesDifferentLoadersToo() {
+		$template = '{{> foo }} {{> bar }}';
+		$data = array(
+			'truthy' => true,
+			'foo'    => 'FOO',
+			'bar'    => 'BAR',
+		);
+		$output = 'FOO BAR';
+		$m = new Mustache();
+		$partials = new DifferentMustacheLoader();
+		$this->assertEquals($output, $m->render($template, $data, $partials));
+	}
+}
+
+class DifferentMustacheLoader implements ArrayAccess {
+	protected $partials = array(
+		'foo' => '{{ foo }}',
+		'bar' => '{{# truthy }}{{ bar }}{{/ truthy }}',
+	);
+
+	public function offsetExists($offset) {
+		return isset($this->partials[$offset]);
+	}
+
+	public function offsetGet($offset) {
+		return $this->partials[$offset];
+	}
+
+	public function offsetSet($offset, $value) {}
+	public function offsetUnset($offset) {}
+}

+ 1 - 0
test/fixtures/bar.mustache

@@ -0,0 +1 @@
+{{# truthy }}{{ bar }}{{/ truthy }}

+ 1 - 0
test/fixtures/foo.mustache

@@ -0,0 +1 @@
+{{ foo }}