Merge branch 'release/1.3'

This commit is contained in:
Jeremy Bush 2010-12-09 13:05:36 -06:00
commit a0bd4e1532
11 changed files with 375 additions and 173 deletions

View file

@ -1,198 +1,144 @@
KOstache
============
# KOstache
KOstache is a kohana module for using [Mustache](http://defunkt.github.com/mustache/) templates in your application.
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 & Simple Example
-----
## Example
View classes go in classes/view/
Did you know the pagination view in Kohana is terrible? We are going to fix it:
classes/view/example.php
### How it exists now:
<?php
<p class="pagination">
class View_Example extends Kostache
{
public $foo = 'bar';
}
<?php if ($first_page !== FALSE): ?>
<a href="<?php echo $page->url($first_page) ?>" rel="first"><?php echo __('First') ?></a>
<?php else: ?>
<?php echo __('First') ?>
<?php endif ?>
Template files go in templates/
<?php if ($previous_page !== FALSE): ?>
<a href="<?php echo $page->url($previous_page) ?>" rel="prev"><?php echo __('Previous') ?></a>
<?php else: ?>
<?php echo __('Previous') ?>
<?php endif ?>
templates/example.mustache
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
This is a {{foo}}
<?php if ($i == $current_page): ?>
<strong><?php echo $i ?></strong>
<?php else: ?>
<a href="<?php echo $page->url($i) ?>"><?php echo $i ?></a>
<?php endif ?>
In your controller, just do:
<?php endfor ?>
$view = new View_Example;
echo $view;
<?php if ($next_page !== FALSE): ?>
<a href="<?php echo $page->url($next_page) ?>" rel="next"><?php echo __('Next') ?></a>
<?php else: ?>
<?php echo __('Next') ?>
<?php endif ?>
And you get:
<?php if ($last_page !== FALSE): ?>
<a href="<?php echo $page->url($last_page) ?>" rel="last"><?php echo __('Last') ?></a>
<?php else: ?>
<?php echo __('Last') ?>
<?php endif ?>
"This is a bar"
</p><!-- .pagination -->
Complex Example
-----
Wow, look at all that login in there! How do you plan on effectively maintaining that?!?
Model (This example uses [AutoModeler](http://github.com/zombor/Auto-Modeler)):
<?php
class Model_Test extends AutoModeler
{
protected $_table_name = 'tests';
protected $_data = array(
'id' => '',
'name' => '',
'value' => '',
);
protected $_rules = array(
'name' => array('not_empty'),
'value' => array('not_empty'),
);
}
View:
<?php
class View_Example extends Kostache
{
public $title = 'Testing';
public function things()
{
return Inflector::plural(get_class(new Model_Test));
}
public function tests()
{
$tests = array();
foreach (AutoModeler::factory('test')->fetch_all() as $test)
{
$tests[] = $test->as_array();
}
return $tests;
}
}
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
<p>Here are all my {{things}}:</p>
<ul>
{{#tests}}
<li><strong>{{id}}:</strong> ({{name}}:{{value}})</li>
{{/tests}}
</ul>
</body>
</html>
Controller:
<?php
class Controller_Welcome extends Controller {
public function action_index()
{
echo new View_Example;
}
} // End Welcome
Grabbing a single model value
-----
Model (This example uses [AutoModeler](http://github.com/zombor/Auto-Modeler)):
<?php
class Model_Test extends AutoModeler
{
protected $_table_name = 'tests';
protected $_data = array(
'id' => '',
'name' => '',
'value' => '',
);
protected $_rules = array(
'name' => array('not_empty'),
'value' => array('not_empty'),
);
}
View:
<?php
class View_Singular extends Kostache
{
protected $_pragmas = array(Kostache::PRAGMA_DOT_NOTATION => TRUE);
public $thing_id = NULL;
public $title = 'Testing';
public function thing()
{
return new Model_Test($this->thing_id);
}
}
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
<p>This is just one thing:</p>
<h2>{{thing.id}}</h2>
<ul>
<li>Name: {{thing.name}}</li>
<li>Value: {{thing.value}}</li>
</ul>
</body>
</html>
Controller:
### Our new View Class (classes/view/pagination/basic.php)
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Welcome extends Controller {
class View_Pagination_Basic extends kostache {
protected $pagination;
public function action_singular($id)
{
$view = new View_Singular;
$view->thing_id = $id;
echo $view;
protected function items()
{
$items = array();
// First.
$first['title'] = 'first';
$first['name'] = __('first');
$first['url'] = ($this->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;
}
} // End Welcome
}
Using the View_Layout class
---
Yum, logic in a class, where it belongs :)
### Our mustache template (templates/pagination/basic.mustache)
<p class="pagination">
{{#items}}
{{#url}}<a href="{{url}}" {{#title}}rel="{{rel}}"{{/title}}>{{/url}}{{#num}}<strong>{{/num}}{{name}}{{#num}}</strong>{{/num}}{{#url}}</a>{{/url}}
{{/items}}
</p>
Holy cow, that's more maintainable :)
## Partials
To use a partial in your template you use the greater than sign (>) and the name, e.g. {{>header}}.
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.
protected $_partials = array(
'header' => 'header', // Loads templates/header.mustache
'footer' => 'footer/default', // Loads templates/footer/default.mustache
);
## Using the View_Layout class
KOstache comes with a View_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 View_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 {{>body}} partial defined in it.
If you have a view that extends the View_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;
}
For specific usage and documentation, see:
[PHP Mustache](http://github.com/bobthecow/mustache.php)

View file

@ -2,6 +2,8 @@
class Kohana_Kostache extends Mustache
{
const VERSION = 1.3;
protected $_partials_processed = FALSE;
/**

View file

@ -4,6 +4,8 @@ class View_Kohana_Layout extends Kostache
{
protected $_layout = 'layout';
public $render_layout = TRUE;
/**
* @var string template title
*/
@ -22,12 +24,15 @@ class View_Kohana_Layout extends Kostache
$this->_template = strtolower(implode(DIRECTORY_SEPARATOR, $foo));
}
$this->_partials+=array(
'body' => $this->_template
);
if ($this->render_layout)
{
$this->_partials+=array(
'body' => $this->_template
);
// Make the layout view the child class's template
$this->_template = $this->_layout;
// Make the layout view the child class's template
$this->_template = $this->_layout;
}
return parent::render($template, $view, $partials);
}

7
guide/kostache.about.md Normal file
View file

@ -0,0 +1,7 @@
# About KOstache
KOstache is a 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.
This module requires mustache.php and includes it as a git submodule. See [Working With Git](tutorials.git) for more information about managing submodules.

139
guide/kostache.examples.md Normal file
View file

@ -0,0 +1,139 @@
# KOstache Examples
## Complex Example
Model (This example uses [AutoModeler](http://github.com/zombor/Auto-Modeler)):
class Model_Test extends AutoModeler
{
protected $_table_name = 'tests';
protected $_data = array(
'id' => '',
'name' => '',
'value' => '',
);
protected $_rules = array(
'name' => array('not_empty'),
'value' => array('not_empty'),
);
}
View:
class View_Example extends Kostache
{
public $title = 'Testing';
public function things()
{
return Inflector::plural(get_class(new Model_Test));
}
public function tests()
{
$tests = array();
foreach (AutoModeler::factory('test')->fetch_all() as $test)
{
$tests[] = $test->as_array();
}
return $tests;
}
}
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
<p>Here are all my {{things}}:</p>
<ul>
{{#tests}}
<li><strong>{{id}}:</strong> ({{name}}:{{value}})</li>
{{/tests}}
</ul>
</body>
</html>
Controller:
class Controller_Welcome extends Controller {
public function action_index()
{
echo new View_Example;
}
} // End Welcome
## Grabbing a single model value
Model (This example uses [AutoModeler](http://github.com/zombor/Auto-Modeler)):
class Model_Test extends AutoModeler
{
protected $_table_name = 'tests';
protected $_data = array(
'id' => '',
'name' => '',
'value' => '',
);
protected $_rules = array(
'name' => array('not_empty'),
'value' => array('not_empty'),
);
}
View:
class View_Singular extends Kostache
{
protected $_pragmas = array(Kostache::PRAGMA_DOT_NOTATION => TRUE);
public $thing_id = NULL;
public $title = 'Testing';
public function thing()
{
return new Model_Test($this->thing_id);
}
}
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
<p>This is just one thing:</p>
<h2>{{thing.id}}</h2>
<ul>
<li>Name: {{thing.name}}</li>
<li>Value: {{thing.value}}</li>
</ul>
</body>
</html>
Controller:
class Controller_Welcome extends Controller {
public function action_singular($id)
{
$view = new View_Singular;
$view->thing_id = $id;
echo $view;
}
} // End Welcome

58
guide/kostache.usage.md Normal file
View file

@ -0,0 +1,58 @@
# KOstache Usage
View classes go in classes/view/
classes/view/example.php
class View_Example extends Kostache
{
public $foo = 'bar';
}
Template files go in templates/
templates/example.mustache
This is a {{foo}}
In your controller, just do:
$view = new View_Example;
echo $view;
And you get:
"This is a bar"
## Partials
To use a partial in your template you use the greater than sign (>) and the name, e.g. {{>header}}.
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.
protected $_partials = array(
'header' => 'header', // Loads templates/header.mustache
'footer' => 'footer/default', // Loads templates/footer/default.mustache
);
## Using the View_Layout class
KOstache comes with a View_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 View_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 {{>body}}; partial defined in it.
If you have a view that extends the View_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;
}
## Mustache Documentation
For specific usage and documentation, see:
[PHP Mustache](http://github.com/bobthecow/mustache.php)
[Original Mustache](http://defunkt.github.com/mustache/)

4
guide/menu.kostache.md Normal file
View file

@ -0,0 +1,4 @@
1. **KOstache**
- [About](kostache.about)
- [Usage](kostache.usage)
- [Examples](kostache.examples)

View file

@ -0,0 +1,33 @@
<select name="days" id="days">
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="08">08</option>
<option value="09">09</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>

View file

@ -0,0 +1,4 @@
<select name="months" id="months">
{{#months}}<option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{month}}</option>
{{/months}}
</select>

View file

@ -0,0 +1,4 @@
<select name="years" id="years">
{{#years}}<option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{year}}</option>
{{/years}}
</select>

2
vendor/mustache vendored

@ -1 +1 @@
Subproject commit 8b1c9c113c4e189923e4874be6fca5be715239ac
Subproject commit a448453da30c6862cad912cd3db4ac4b8751deb2