Added readme and code
This commit is contained in:
10
DemoTemplates/helloworld.php
Normal file
10
DemoTemplates/helloworld.php
Normal file
@@ -0,0 +1,10 @@
|
||||
{% $context['title'] = 'Hello World -- Demo' %}
|
||||
{%t SetMaster('master') %}
|
||||
|
||||
{%t StartSection('content') %}
|
||||
<!-- some head here -->
|
||||
{%t EndSection() %}
|
||||
|
||||
{%t StartSection('content') %}
|
||||
Hello {{$world}}
|
||||
{%t EndSection() %}
|
||||
10
DemoTemplates/master.php
Normal file
10
DemoTemplates/master.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{$title}}</title>
|
||||
{{t GetSection('head') }}
|
||||
</head>
|
||||
<body>
|
||||
{{t GetSection('content') }}
|
||||
</body>
|
||||
</html>
|
||||
82
README.md
82
README.md
@@ -2,3 +2,85 @@ YAPTE
|
||||
=====
|
||||
|
||||
Yet Another PHP Template Engine
|
||||
|
||||
Useful little (<150 lines) templater that doesn't get in the way.
|
||||
|
||||
Supports parent-child/master templates with sections (think TWIG).
|
||||
|
||||
PHP 5.3+ Recommended.
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
The core of the templater is focused on some simple reg-ex replcements. As Below.
|
||||
|
||||
* __Output / Logic__
|
||||
* {{ $hello }} --> <?php echo $hello ;?>
|
||||
* {% if(true): %}True!{% endif %} --> <?php if(true): ;?>True!<?php endif ;?>
|
||||
* __Templater Shortcuts__
|
||||
* {{t Render('menu') }} --> <?php echo $this->Render('menu') ;?>
|
||||
* {%t StartSection('content') %} --> <?php $this->StartSection('content') ;?>
|
||||
|
||||
The theme here is that double brackets output and bracket-percent performs actions/does logic.
|
||||
|
||||
You are of course free to use normal php tags where you see fit, these are there to help but are not required.
|
||||
|
||||
Compiled Templates
|
||||
------------------
|
||||
|
||||
The templates can be compiled to skip the step of reg-exing them, the configuration is explained below.
|
||||
|
||||
The compiled templates can be cleared at run-time by calling `Template::ClearCompiled()`
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The configuration is done via constants, as this is simpler than some sort of config system (except where one already exists).
|
||||
|
||||
* DIR_TEMPLATES -- The template directory.
|
||||
* DIR_TEMPLATES_COMPILED - The compiled templates directory.
|
||||
If not defined or false compiled templates are not used.
|
||||
This is not relative to the template directory.
|
||||
|
||||
Both can be either absolute paths or relative based on what `file_get_contents` can find.
|
||||
|
||||
Master Template Example
|
||||
-----------------------
|
||||
|
||||
Child Template `hello.php`:
|
||||
|
||||
{%t SetMaster('master') %}
|
||||
|
||||
{%t StartSection('content') %}
|
||||
Hello {{$world}}
|
||||
{%t EndSection() %}
|
||||
|
||||
Any text/content outside the sections will be lost but executed (ie not output).
|
||||
|
||||
When evaluated the master template will be rendered and the content of the sections will be available to output.
|
||||
|
||||
Parent Template `master.php`:
|
||||
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{$title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{t GetSection('content') }}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
`$this->sections` may be used for the available sections.
|
||||
|
||||
Context
|
||||
-------
|
||||
|
||||
The context is the data initially provided to the template engine and is available via `$this->context`; these variables are extracted as references for use.
|
||||
|
||||
A new context is created for each recursive call (ie master template, menu, etc) which contains the 'upper' context. modification is one way a higher context may affect lower contexts but not vice versa.
|
||||
|
||||
For instance, if a child template were to set the title in the current context this will be available in context when the master template is rendered.
|
||||
IE. `{%t context['title'] = 'Hello!' }%`. The master can then use `{{$title}}` to display 'Hello!'
|
||||
|
||||
Due to the nature of `extract` some variables cannot be used in render data, these include `context`, `this`, `file` among others.
|
||||
136
Template.php
Normal file
136
Template.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Template renderer
|
||||
*
|
||||
* @author Sam Stevens <sam@xnet.tk>
|
||||
* @license http://opensource.org/licenses/MIT MIT License
|
||||
*/
|
||||
|
||||
if (!defined('DIR_TEMPLATES_COMPILED'))
|
||||
define('DIR_TEMPLATES_COMPILED', False);
|
||||
|
||||
class Template
|
||||
{
|
||||
private static $currentTemplater = false;
|
||||
/**
|
||||
* @return Template
|
||||
*/
|
||||
public static function GetInstance()
|
||||
{
|
||||
if (self::$currentTemplater != false)
|
||||
return self::$currentTemplater;
|
||||
return new self();
|
||||
}
|
||||
public static function ClearCompiled()
|
||||
{
|
||||
$files = glob(DIR_TEMPLATES_COMPILED.'/*.template.php');
|
||||
foreach($files as $file)
|
||||
{
|
||||
if (is_file($file))
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
private $context = array();
|
||||
|
||||
private $level = 0;
|
||||
|
||||
private $sections = array();
|
||||
private $currentSection = false;
|
||||
private $master = false;
|
||||
|
||||
private function __construct() {
|
||||
}
|
||||
|
||||
private function GetCompiledFilename($tFile) {
|
||||
if (DIR_TEMPLATES_COMPILED == false) {
|
||||
return false;
|
||||
}
|
||||
$tFileSafe = preg_replace(array('%^'.preg_quote(DIR_TEMPLATES).'/%','/[^a-z0-9_\.]/i'), array('','_'), $tFile);
|
||||
return DIR_TEMPLATES_COMPILED.DS.$tFileSafe.'-'.md5($tFile).'.template.php';
|
||||
}
|
||||
private function GetCompiled($tFile) {
|
||||
$compiledFile = $this->GetCompiledFilename($tFile);
|
||||
if ($compiledFile === false) {
|
||||
return false;
|
||||
}
|
||||
if (file_exists($compiledFile) && filemtime($tFile) > filemtime($compiledFile)) {
|
||||
unlink($compiledFile);
|
||||
return False;
|
||||
}
|
||||
if (file_exists($compiledFile)) {
|
||||
return $compiledFile;
|
||||
}
|
||||
}
|
||||
private function SaveCompiled($tFile, $contents) {
|
||||
$compiledFile = $this->GetCompiledFilename($tFile);
|
||||
if ($compiledFile === false) {
|
||||
return false;
|
||||
}
|
||||
file_put_contents($compiledFile, '<?php if(!defined("DIR_TEMPLATES")) {echo "This file cannot be accessed directly";exit();} ?>'.$contents);
|
||||
}
|
||||
|
||||
public function Render($file, array $context = array()) {
|
||||
self::$currentTemplater = $this;
|
||||
|
||||
$tFile = str_replace('.', DS, $file);
|
||||
$tFile = DIR_TEMPLATES.DS.$tFile.'.php';
|
||||
if (!is_file($tFile))
|
||||
throw new Exception("Unknown Template ".$file);
|
||||
|
||||
if (isset($this->context[$this->level]))
|
||||
$context = array_replace($this->context[$this->level], $context);
|
||||
$this->level++;
|
||||
$this->context[$this->level] = &$context;
|
||||
|
||||
extract($this->context[$this->level], EXTR_REFS | EXTR_SKIP);
|
||||
|
||||
$this->master = false;
|
||||
|
||||
$compiledTemplate = $this->GetCompiled($tFile);
|
||||
if ($compiledTemplate == false) {
|
||||
$templateContents = file_get_contents($tFile);
|
||||
$templateContents = preg_replace(
|
||||
array('%{{t\s((?!}}).*?)\}}%', '%{{((?!}}).*?)}}%', '%{\%t\s((?!}}).*?)\%}%', '%{\%((?!}}).*?)\%}%'),
|
||||
array('<?php echo $this->$1 ;?>', '<?php echo $1 ;?>', '<?php $this->$1 ;?>', '<?php $1 ;?>'),
|
||||
$templateContents);
|
||||
$this->SaveCompiled($tFile, $templateContents);
|
||||
$result = eval('?>'.$templateContents);
|
||||
} else {
|
||||
ob_start();
|
||||
include($compiledTemplate);
|
||||
$result = ob_get_clean();
|
||||
}
|
||||
|
||||
self::$currentTemplater = false;
|
||||
if ($this->currentSection != False)
|
||||
$this->EndSection();
|
||||
|
||||
if ($this->master != false) {
|
||||
return $this->Render($this->master);
|
||||
}
|
||||
|
||||
unset($this->context[$this->level]);
|
||||
$this->level--;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function SetMaster($file) {
|
||||
$this->master = $file;
|
||||
}
|
||||
private function StartSection($name) {
|
||||
$this->currentSection = $name;
|
||||
ob_start();
|
||||
}
|
||||
private function EndSection() {
|
||||
$this->sections[$this->currentSection] = ob_get_clean();
|
||||
$this->currentSection = false;
|
||||
}
|
||||
private function GetSection($name) {
|
||||
if (isset($this->sections[$name]))
|
||||
return $this->sections[$name];
|
||||
return '';
|
||||
}
|
||||
}
|
||||
18
demo.php
Normal file
18
demo.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', True);
|
||||
error_reporting(E_ALL);
|
||||
date_default_timezone_set('Europe/London');
|
||||
|
||||
define('DIR_TEMPLATES', dirname(__FILE__).DIRECTORY_SEPARATOR.'DemoTemplates');
|
||||
define('DIR_TEMPLATES_COMPILED', false);
|
||||
|
||||
require('Template.php');
|
||||
|
||||
$t = Template::GetInstance();
|
||||
|
||||
$data = array(
|
||||
'world' => 'You!'
|
||||
);
|
||||
|
||||
echo $t->Render('helloworld',$data);
|
||||
Reference in New Issue
Block a user