diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1377554
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.swp
diff --git a/README.markdown b/README.markdown
index 4b5a9e9..fe144b7 100644
--- a/README.markdown
+++ b/README.markdown
@@ -2,147 +2,56 @@
Kostache is a [Kohana 3](https://github.com/kohana/kohana) module for using [Mustache](http://defunkt.github.com/mustache/) templates in your application.
-Mustache is a logic-less template class. It is impossible to embed logic into mustache files.
+## Usage
-## Example
+To use, simply create a POPO (Plain Old PHP Object) like so:
-Did you know the pagination view in Kohana is terrible? We are going to fix it:
+```php
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Wow, look at all that logic in there! How do you plan on effectively maintaining that?!?
-
-### Our new View Class (classes/view/pagination/basic.php)
-
- pagination->first_page !== FALSE) ? $this->pagination->url($this->pagination->first_page) : FALSE;
- $items[] = $first;
-
- // Prev.
- $prev['title'] = 'prev';
- $prev['name'] = __('previous');
- $prev['url'] = ($this->pagination->previous_page !== FALSE) ? $this->pagination->url($this->pagination->previous_page) : FALSE;
- $items[] = $prev;
-
- // Numbers.
- for ($i=1; $i<=$this->pagination->total_pages; $i++)
- {
- $item = array();
-
- $item['num'] = TRUE;
- $item['name'] = $i;
- $item['url'] = ($i != $this->pagination->current_page) ? $this->pagination->url($i) : FALSE;
-
- $items[] = $item;
- }
-
- // Next.
- $next['title'] = 'next';
- $next['name'] = __('next');
- $next['url'] = ($this->pagination->next_page !== FALSE) ? $this->pagination->url($this->pagination->next_page) : FALSE;
- $items[] = $next;
-
- // Last.
- $last['title'] = 'last';
- $last['name'] = __('last');
- $last['url'] = ($this->pagination->last_page !== FALSE) ? $this->pagination->url($this->pagination->last_page) : FALSE;
- $items[] = $last;
-
- return $items;
- }
+ public function testing()
+ {
+ return 'foobar';
}
+}
+```
-Yum, logic in a class, where it belongs :)
+And create a mustache renderer. The parameter to the engine method is the template name to use.
-### Our mustache template (templates/pagination/basic.mustache)
+```php
+
- {{#items}}
- {{#url}}{{/url}}
- {{#num}}{{/num}}{{name}}{{#num}}{{/num}}
- {{#url}}{{/url}}
- {{/items}}
-
+$renderer = Kostache::factory();
+```
-Holy cow, that's more maintainable :)
+And render it:
+
+```php
+response->body($renderer->render(new View_Test));
+```
+
+## Templates
+
+Templates should go in the `templates/` directory in your cascading file system. They should have a .mustache extension.
## Partials
-To use a partial in your template you use the greater than sign (>) and the name, e.g. {{>header}}.
+Partials are loaded automatically based on the name used in the template. So if you reference `{{>foobar}}` in your template, it will look for that partial in `templates/partials/foobar.mustache`.
-You must define partials within the $_partials array in your view class. The key is the name that you use in your template and the value is a path to your partial file.
+# Layouts
- protected $_partials = array(
- 'header' => 'header', // Loads templates/header.mustache
- 'footer' => 'footer/default', // Loads templates/footer/default.mustache
- );
+KOstache supports layouts. To use, just add a `templates/layout.mustache` file (a simple one is already provided), and use `Kostache_Layout` for your renderer instead of `Kostache`. You'll probably want to put a `$title` property in your view class. The layout should include a `{{>content}}` partial to render the body of the page.
-## Using the Kostache_Layout class
-
-Kostache comes with a Kostache_Layout class instead of a template controller. This allows your layouts to be more OOP and self contained, and they do not rely on your controllers so much.
-
-To use it, have your view extend the Kostache_Layout class. You can then specify your own layout file by placing it in templates/layout.mustache. At a minimum, it needs to have a {{>content}} partial defined in it.
-
-If you have a view that extends the Kostache_Layout class, but wish to render only the template and not the entire layout, you can set the public $render_layout property to FALSE. This is useful if you want to use the same view class for external requests and HMVC requests.
-
- $view = new View_Post_List;
- if ($this->request !== Request::instance) // Is internal request
- {
- $view->render_layout = FALSE;
- }
+# Additional Information
For specific usage and documentation, see:
[PHP Mustache](http://github.com/bobthecow/mustache.php)
-[Original Mustache](http://defunkt.github.com/mustache/)
\ No newline at end of file
+[Original Mustache](http://defunkt.github.com/mustache/)
diff --git a/classes/Kohana/Kostache.php b/classes/Kohana/Kostache.php
index cc35b7f..bacb1b0 100644
--- a/classes/Kohana/Kostache.php
+++ b/classes/Kohana/Kostache.php
@@ -5,267 +5,46 @@
* @package Kostache
* @category Base
* @author Jeremy Bush
- * @author Woody Gilk
* @copyright (c) 2010-2012 Jeremy Bush
- * @copyright (c) 2011-2012 Woody Gilk
* @license MIT
*/
-abstract class Kohana_Kostache {
+class Kohana_Kostache {
- const VERSION = '3.0.0';
+ const VERSION = '4.0.0';
- /**
- * Factory method for Kostache views. Accepts a template path and an
- * optional array of partial paths.
- *
- * @param string template path
- * @param array partial paths
- * @return Kostache
- * @throws Kohana_Exception if the view class does not exist
- */
- public static function factory($path, array $partials = NULL)
+ protected $_engine;
+
+ public static function factory()
{
- $class = 'View_'.str_replace('/', '_', $path);
+ $m = new Mustache_Engine(
+ array(
+ 'loader' => new Mustache_Loader_Kohana(),
+ 'partials_loader' => new Mustache_Loader_Kohana('templates/partials'),
+ 'escape' => function($value) {
+ return html::chars($value);
+ },
+ 'cache' => APPPATH.'cache/mustache',
+ )
+ );
- if ( ! class_exists($class))
- {
- throw new Kohana_Exception('View class does not exist: :class', array(
- ':class' => $class,
- ));
- }
-
- return new $class(NULL, $partials);
+ $class = get_called_class();
+ return new $class($m);
}
- /**
- * @var string Mustache template
- */
- protected $_template;
-
- /**
- * @var array Mustache partials
- */
- protected $_partials = array();
-
- /**
- * Loads the template and partial paths.
- *
- * @param string template path
- * @param array partial paths
- * @return void
- * @uses Kostache::template
- * @uses Kostache::partial
- */
- public function __construct($template = NULL, array $partials = NULL)
+ public function __construct($engine)
{
- if ( ! $template)
- {
- if ($this->_template)
- {
- // Load the template defined in the view
- $template = $this->_template;
- }
- else
- {
- // Detect the template for this class
- $template = $this->_detect_template();
- }
- }
-
- // Load the template
- $this->template($template);
-
- if ($this->_partials)
- {
- foreach ($this->_partials as $name => $path)
- {
- // Load the partials defined in the view
- $this->partial($name, $path);
- }
- }
-
- if ($partials)
- {
- foreach ($partials as $name => $path)
- {
- // Load the partial
- $this->partial($name, $path);
- }
- }
+ $this->_engine = $engine;
}
- /**
- * Magic method, returns the output of [Kostache::render].
- *
- * @return string
- * @uses Kostache::render
- */
- public function __toString()
+ public function render($class, $template = NULL)
{
- try
+ if ($template == NULL)
{
- return $this->render();
- }
- catch (Exception $e)
- {
- ob_start();
-
- // Render the exception
- Kohana_Exception::handler($e);
-
- return (string) ob_get_clean();
- }
- }
-
- /**
- * Loads a new template from a path.
- *
- * @return Kostache
- */
- public function template($path)
- {
- $this->_template = $this->_load($path);
-
- return $this;
- }
-
- /**
- * Loads a new partial from a path. If the path is empty, the partial will
- * be removed.
- *
- * @param string partial name
- * @param mixed partial path, FALSE to remove the partial
- * @return Kostache
- */
- public function partial($name, $path)
- {
- if ( ! $path)
- {
- unset($this->_partials[$name]);
- }
- else
- {
- $this->_partials[$name] = $this->_load($path);
+ $template = explode('_', get_class($class));
+ array_shift($template);
+ $template = implode('/', $template);
}
- return $this;
+ return $this->_engine->loadTemplate($template)->render($class);
}
-
- /**
- * Assigns a variable by name.
- *
- * // This value can be accessed as {{foo}} within the template
- * $view->set('foo', 'my value');
- *
- * You can also use an array to set several values at once:
- *
- * // Create the values {{food}} and {{beverage}} in the template
- * $view->set(array('food' => 'bread', 'beverage' => 'water'));
- *
- * @param string variable name or an array of variables
- * @param mixed value
- * @return $this
- */
- public function set($key, $value = NULL)
- {
- if (is_array($key))
- {
- foreach ($key as $name => $value)
- {
- $this->{$name} = $value;
- }
- }
- else
- {
- $this->{$key} = $value;
- }
-
- return $this;
- }
-
- /**
- * Assigns a value by reference. The benefit of binding is that values can
- * be altered without re-setting them. It is also possible to bind variables
- * before they have values. Assigned values will be available as a
- * variable within the template file:
- *
- * // This reference can be accessed as {{ref}} within the template
- * $view->bind('ref', $bar);
- *
- * @param string variable name
- * @param mixed referenced variable
- * @return $this
- */
- public function bind($key, & $value)
- {
- $this->{$key} =& $value;
-
- return $this;
- }
-
- /**
- * Renders the template using the current view.
- *
- * @return string
- */
- public function render()
- {
- return $this->_stash($this->_template, $this, $this->_partials)->render();
- }
-
- /**
- * Return a new Mustache for the given template, view, and partials.
- *
- * @param string template
- * @param Kostache view object
- * @param array partial templates
- * @return Mustache
- */
- protected function _stash($template, Kostache $view, array $partials)
- {
- return new Kohana_Mustache($template, $view, $partials, array(
- 'charset' => Kohana::$charset,
- ));
- }
-
- /**
- * Load a template and return it.
- *
- * @param string template path
- * @return string
- * @throws Kohana_Exception if the template does not exist
- */
- protected function _load($path)
- {
- $file = Kohana::find_file('templates', $path, 'mustache');
-
- if ( ! $file)
- {
- throw new Kohana_Exception('Template file does not exist: :path', array(
- ':path' => 'templates/'.$path,
- ));
- }
-
- return file_get_contents($file);
- }
-
- /**
- * Detect the template name from the class name.
- *
- * @return string
- */
- protected function _detect_template()
- {
- // Start creating the template path from the class name
- $template = explode('_', get_class($this));
-
- // Remove "View" prefix
- array_shift($template);
-
- // Convert name parts into a path
- $template = strtolower(implode('/', $template));
-
- return $template;
- }
-
}
diff --git a/classes/Kohana/Kostache/Layout.php b/classes/Kohana/Kostache/Layout.php
index 1b8a7d2..1f85dc1 100644
--- a/classes/Kohana/Kostache/Layout.php
+++ b/classes/Kohana/Kostache/Layout.php
@@ -5,42 +5,42 @@
* @package Kostache
* @category Base
* @author Jeremy Bush
- * @author Woody Gilk
* @copyright (c) 2010-2012 Jeremy Bush
- * @copyright (c) 2011-2012 Woody Gilk
* @license MIT
*/
-abstract class Kohana_Kostache_Layout extends Kostache {
+class Kohana_Kostache_Layout extends Kohana_Kostache {
/**
* @var string partial name for content
*/
const CONTENT_PARTIAL = 'content';
- /**
- * @var boolean render template in layout?
- */
- public $render_layout = TRUE;
-
/**
* @var string layout path
*/
protected $_layout = 'layout';
- public function render()
+ public static function factory($layout = 'layout')
{
- if ( ! $this->render_layout)
- {
- return parent::render();
- }
+ $k = parent::factory();
+ $k->set_layout($layout);
+ return $k;
+ }
- $partials = $this->_partials;
+ public function set_layout($layout)
+ {
+ $this->_layout = (string) $layout;
+ }
- $partials[Kostache_Layout::CONTENT_PARTIAL] = $this->_template;
+ public function render($class, $template = NULL)
+ {
+ $this->_engine->setPartials(
+ array(
+ Kostache_Layout::CONTENT_PARTIAL => parent::render($class, $template)
+ )
+ );
- $template = $this->_load($this->_layout);
-
- return $this->_stash($template, $this, $partials)->render();
+ return $this->_engine->loadTemplate($this->_layout)->render($class);
}
}
diff --git a/classes/Kostache.php b/classes/Kostache.php
index 9566dc3..2595419 100644
--- a/classes/Kostache.php
+++ b/classes/Kostache.php
@@ -1,3 +1,3 @@
_base_dir = $base_dir;
+
+ if (isset($options['extension']))
+ {
+ $this->_extension = '.' . ltrim($options['extension'], '.');
+ }
+ }
+
+ public function load($name)
+ {
+ if (!isset($this->_templates[$name]))
+ {
+ $this->_templates[$name] = $this->_load_file($name);
+ }
+
+ return $this->_templates[$name];
+ }
+
+ protected function _load_file($name)
+ {
+ $filename = Kohana::find_file($this->_base_dir, $name, $this->_extension);
+ return file_get_contents($filename);
+ }
+
+ /**
+ * Set an associative array of Template sources for this loader.
+ *
+ * @param array $templates
+ */
+ public function setTemplates(array $templates)
+ {
+ $this->_templates = array_merge($this->_templates, $templates);
+ }
+
+ /**
+ * Set a Template source by name.
+ *
+ * @param string $name
+ * @param string $template Mustache Template source
+ */
+ public function setTemplate($name, $template)
+ {
+ $this->_templates[$name] = $template;
+ }
+}
diff --git a/init.php b/init.php
index 22b0b8b..b6a24da 100644
--- a/init.php
+++ b/init.php
@@ -1,4 +1,5 @@