├── .gitignore ├── .gitmodules ├── Lib ├── CoreExtension.php ├── Twig_Extension_Ago.php ├── Twig_Extension_Basic.php ├── Twig_Extension_I18n.php ├── Twig_Extension_Number.php ├── Twig_Node_Element.php ├── Twig_Node_Trans.php └── Twig_TokenParser_Trans.php ├── View └── TwigView.php ├── examples └── Layouts │ ├── ajax.tpl │ ├── default.tpl │ ├── email │ ├── html │ │ └── default.tpl │ └── text │ │ └── default.tpl │ ├── flash.tpl │ ├── js │ └── default.tpl │ ├── rss │ └── default.tpl │ └── xml │ └── default.tpl ├── license ├── readme.md └── tmp └── views ├── .gitignore └── empty /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Vendor/Twig"] 2 | path = Vendor/Twig 3 | url = http://github.com/fabpot/Twig.git 4 | -------------------------------------------------------------------------------- /Lib/CoreExtension.php: -------------------------------------------------------------------------------- 1 | timeAgoInWords() 7 | */ 8 | function cakeAgo($var) { 9 | $time = new TimeHelper(); 10 | return $time->timeAgoInWords($var); 11 | } 12 | 13 | /** 14 | * Time Ago in Words 15 | * Use: {{ user.User.created|ago }} 16 | * 17 | * @author Kjell Bublitz 18 | * @package TwigView 19 | * @subpackage TwigView.Lib 20 | */ 21 | class Twig_Extension_Ago extends Twig_Extension { 22 | 23 | /** 24 | * Returns a list of filters to add to the existing list. 25 | * 26 | * @return array An array of filters 27 | */ 28 | public function getFilters() { 29 | return array('ago' => new Twig_Filter_Function('cakeAgo')); 30 | } 31 | 32 | /** 33 | * Returns the name of the extension. 34 | * 35 | * @return string The extension name 36 | */ 37 | public function getName() { 38 | return 'ago'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Lib/Twig_Extension_Basic.php: -------------------------------------------------------------------------------- 1 | 12 | * @package TwigView 13 | * @subpackage TwigView.Lib 14 | */ 15 | class Twig_Extension_Basic extends Twig_Extension { 16 | 17 | /** 18 | * Returns a list of filters to add to the existing list. 19 | * 20 | * @return array An array of filters 21 | */ 22 | public function getFilters() { 23 | return array( 24 | 'debug' => new Twig_Filter_Function('debug'), 25 | 'pr' => new Twig_Filter_Function('pr'), 26 | 'low' => new Twig_Filter_Function('low'), 27 | 'up' => new Twig_Filter_Function('up'), 28 | 'env' => new Twig_Filter_Function('env'), 29 | ); 30 | } 31 | 32 | /** 33 | * Returns the name of the extension. 34 | * 35 | * @return string The extension name 36 | */ 37 | public function getName() { 38 | return 'basic'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Lib/Twig_Extension_I18n.php: -------------------------------------------------------------------------------- 1 | 9 | * @package TwigView 10 | * @subpackage TwigView.Lib 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | */ 15 | class Twig_Extension_I18n extends Twig_Extension { 16 | 17 | /** 18 | * Returns the token parser instances to add to the existing list. 19 | * 20 | * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances 21 | */ 22 | public function getTokenParsers() { 23 | return array(new Twig_TokenParser_Trans()); 24 | } 25 | 26 | /** 27 | * Returns a list of filters to add to the existing list. 28 | * 29 | * @return array An array of filters 30 | */ 31 | public function getFilters() { 32 | return array('trans' => new Twig_Filter_Function('__')); 33 | } 34 | 35 | /** 36 | * Returns the name of the extension. 37 | * 38 | * @return string The extension name 39 | */ 40 | public function getName() { 41 | return 'i18n'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Lib/Twig_Extension_Number.php: -------------------------------------------------------------------------------- 1 | 3.29 GB 9 | * Use: {{ '0.555'|p(2) }} //=> 0.56 10 | * Use: {{ '5999'|curr }} //=> $5,999.00 11 | * Use: {{ '2.3'|pct }} //=> 2.30% 12 | * 13 | * 14 | * @author Kjell Bublitz 15 | * @package TwigView 16 | * @subpackage TwigView.Lib 17 | */ 18 | class Cake_Number_Filters { 19 | 20 | /** 21 | * Wrapper to Number->toReadableSize() 22 | * 23 | * @param integer $length Size in bytes 24 | */ 25 | static function size($var) { 26 | $number = new NumberHelper(); 27 | return $number->toReadableSize($var); 28 | } 29 | 30 | /** 31 | * Wrapper to Number->toPercentage() 32 | * 33 | * @param float $number A floating point number 34 | * @param integer $precision The precision of the returned number 35 | */ 36 | static function percentage($var, $p = 2) { 37 | $number = new NumberHelper(); 38 | return $number->toPercentage($var, $p); 39 | } 40 | 41 | /** 42 | * Wrapper to Number->currency() 43 | * 44 | * @param float $number 45 | * @param string $currency Valid values are 'USD', 'EUR', 'GBP' 46 | * @param array $options f.e. 'before' and 'after' options. 47 | */ 48 | static function currency($var, $curr='USD', $opts=array()) { 49 | $number = new NumberHelper(); 50 | return $number->currency($var, $curr, $opts); 51 | } 52 | 53 | /** 54 | * Wrapper to Number->precision() 55 | * 56 | * @param float $number A floating point number 57 | * @param integer $precision The precision of the returned number 58 | */ 59 | static function precision($var, $p=2) { 60 | $number = new NumberHelper(); 61 | return $number->precision($var, $p); 62 | } 63 | } 64 | 65 | /** 66 | * Twig_Extension_Number 67 | * 68 | * Use: {{ '3535839525'|size }} //=> 3.29 GB 69 | * Use: {{ '0.555'|p(2) }} //=> 0.56 70 | * Use: {{ '5999'|curr }} //=> $5,999.00 71 | * Use: {{ '2.3'|pct }} //=> 2.30% 72 | * 73 | * @author Kjell Bublitz 74 | * @package TwigView 75 | * @subpackage TwigView.Lib 76 | */ 77 | class Twig_Extension_Number extends Twig_Extension { 78 | 79 | /** 80 | * Returns a list of filters to add to the existing list. 81 | * 82 | * @return array An array of filters 83 | */ 84 | public function getFilters() { 85 | return array( 86 | 'size' => new Twig_Filter_Function('Cake_Number_Filters::size'), 87 | 'pct' => new Twig_Filter_Function('Cake_Number_Filters::percentage'), 88 | 'curr' => new Twig_Filter_Function('Cake_Number_Filters::currency'), 89 | 'p' => new Twig_Filter_Function('Cake_Number_Filters::precision'), 90 | ); 91 | } 92 | 93 | /** 94 | * Returns the name of the extension. 95 | * 96 | * @return string The extension name 97 | */ 98 | public function getName() { 99 | return 'number'; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Lib/Twig_Node_Element.php: -------------------------------------------------------------------------------- 1 | loads: APP/views/elements/login_form.tpl 8 | */ 9 | 10 | /* 11 | * This file is part of Twig. 12 | * 13 | * (c) 2009 Fabien Potencier 14 | * (c) 2009 Armin Ronacher 15 | * 16 | * For the full copyright and license information, please view the LICENSE 17 | * file that was distributed with this source code. 18 | */ 19 | class Twig_TokenParser_Element extends Twig_TokenParser { 20 | 21 | /** 22 | * Parses a token and returns a node. 23 | * 24 | * @param Twig_Token $token A Twig_Token instance 25 | * @return Twig_NodeInterface A Twig_NodeInterface instance 26 | */ 27 | public function parse(Twig_Token $token) { 28 | $expr = $this->parser->getExpressionParser()->parseExpression(); 29 | $variables = null; 30 | if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'with')) { 31 | $this->parser->getStream()->next(); 32 | $variables = $this->parser->getExpressionParser()->parseExpression(); 33 | } 34 | 35 | $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); 36 | return new Twig_Node_Element($expr, $variables, $token->getLine(), $this->getTag()); 37 | } 38 | 39 | /** 40 | * Gets the tag name associated with this token parser. 41 | * 42 | * @param string The tag name 43 | */ 44 | public function getTag() { 45 | return 'element'; 46 | } 47 | } 48 | 49 | /** 50 | * Represents an include node. 51 | * 52 | * Modified to use CakePHP paths 53 | * @author Kjell Bublitz 54 | * 55 | * @package TwigView 56 | * @subpackage TwigView.Lib 57 | * @author Fabien Potencier 58 | * @version SVN: $Id$ 59 | */ 60 | class Twig_Node_Element extends Twig_Node { 61 | 62 | /** 63 | * Constructor 64 | * 65 | * @param Twig_Node_Expression $expr 66 | * @param Twig_Node_Expression $variables 67 | * @param bool $only 68 | * @param string $lineno 69 | * @param string $tag 70 | */ 71 | public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $lineno, $tag = null) { 72 | parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only), $lineno, $tag); 73 | } 74 | 75 | /** 76 | * Compiles the node to PHP. 77 | * 78 | * @param Twig_Compiler A Twig_Compiler instance 79 | */ 80 | public function compile(Twig_Compiler $compiler) { 81 | $compiler->addDebugInfo($this); 82 | 83 | $template = $this->getNode('expr')->getAttribute('value'); 84 | $value = 'Elements' . DS . $template . '.tpl'; 85 | $this->getNode('expr')->setAttribute('value', $value); 86 | 87 | if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) { 88 | $compiler 89 | ->write("\$this->env->loadTemplate(") 90 | ->subcompile($this->getNode('expr')) 91 | ->raw(")->display("); 92 | } else { 93 | $compiler 94 | ->write("\$template = ") 95 | ->subcompile($this->getNode('expr')) 96 | ->raw(";\n") 97 | ->write("if (!\$template") 98 | ->raw(" instanceof Twig_Template) {\n") 99 | ->indent() 100 | ->write("\$template = \$this->env->loadTemplate(\$template);\n") 101 | ->outdent() 102 | ->write("}\n") 103 | ->write('$template->display('); 104 | } 105 | 106 | if (false === $this->getAttribute('only')) { 107 | if (null === $this->getNode('variables')) { 108 | $compiler->raw('$context'); 109 | } else { 110 | $compiler 111 | ->raw('array_merge($context, ') 112 | ->subcompile($this->getNode('variables')) 113 | ->raw(')'); 114 | } 115 | } else { 116 | if (null === $this->getNode('variables')) { 117 | $compiler->raw('array()'); 118 | } else { 119 | $compiler->subcompile($this->getNode('variables')); 120 | } 121 | } 122 | 123 | $compiler->raw(");\n"); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Lib/Twig_Node_Trans.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @package twig 9 | * @author Fabien Potencier 10 | * @version SVN: $Id$ 11 | */ 12 | class Twig_Node_Trans extends Twig_Node { 13 | 14 | /** 15 | * Constructor 16 | * 17 | * @param Twig_NodeInterface $body 18 | * @param Twig_NodeInterface $plural 19 | * @param Twig_Node_Expression $count 20 | * @param string $lineno 21 | * @param string $tag 22 | */ 23 | public function __construct(Twig_NodeInterface $body, Twig_NodeInterface $plural = null, Twig_Node_Expression $count = null, $lineno, $tag = null) { 24 | parent::__construct(array('count' => $count, 'body' => $body, 'plural' => $plural), array(), $lineno, $tag); 25 | } 26 | 27 | /** 28 | * Compiles the node to PHP. 29 | * 30 | * @param Twig_Compiler A Twig_Compiler instance 31 | */ 32 | public function compile(Twig_Compiler $compiler) { 33 | $compiler->addDebugInfo($this); 34 | list($msg, $vars) = $this->compileString($this->nodes['body']); 35 | 36 | if (null !== $this->nodes['plural']) { 37 | list($msg1, $vars1) = $this->compileString($this->nodes['plural']); 38 | $vars = array_merge($vars, $vars1); 39 | } 40 | 41 | $function = null === $this->nodes['plural'] ? '__' : '__n'; 42 | 43 | if ($vars) { 44 | $compiler 45 | ->write('echo strtr('.$function.'(') 46 | ->subcompile($msg); 47 | 48 | if (null !== $this->nodes['plural']) { 49 | $compiler 50 | ->raw(', ') 51 | ->subcompile($msg1) 52 | ->raw(', abs(') 53 | ->subcompile($this->nodes['count']) 54 | ->raw(')'); 55 | } 56 | 57 | $compiler->raw(', true), array('); // modified: cakephp $return flag 58 | 59 | foreach ($vars as $var) { 60 | if ('count' === $var->getAttribute('name')) { 61 | $compiler 62 | ->string('%count%') 63 | ->raw(' => abs(') 64 | ->subcompile($this->nodes['count']) 65 | ->raw('), '); 66 | } else { 67 | $compiler 68 | ->string('%'.$var->getAttribute('name').'%') 69 | ->raw(' => ') 70 | ->subcompile($var) 71 | ->raw(', '); 72 | } 73 | } 74 | 75 | $compiler->raw("));\n"); 76 | } else { 77 | $compiler 78 | ->write('echo '.$function.'(') 79 | ->subcompile($msg); 80 | 81 | if (null !== $this->nodes['plural']) { 82 | $compiler 83 | ->raw(', ') 84 | ->subcompile($msg1) 85 | ->raw(', abs(') 86 | ->subcompile($this->nodes['count']) 87 | ->raw(')'); 88 | } 89 | 90 | $compiler->raw(', true);'); // modified: cakephp $return flag 91 | } 92 | } 93 | 94 | /** 95 | * Compile String 96 | * 97 | * @param string $body 98 | * @return void 99 | */ 100 | protected function compileString($body) { 101 | if ($body instanceof Twig_Node_Expression_Name || $body instanceof Twig_Node_Expression_Constant) { 102 | return array($body, array()); 103 | } 104 | 105 | $msg = ''; 106 | $vars = array(); 107 | 108 | if ($body instanceof Twig_Node_Text) { 109 | $node = $body; 110 | $msg = $node->getAttribute('data'); 111 | } else { 112 | foreach ($body->nodes as $node) { 113 | if ($node instanceof Twig_Node_Print) { 114 | $n = $node->getNode('expr'); 115 | while ($n instanceof Twig_Node_Expression_Filter) { 116 | $n = $n->getNode('node'); 117 | } 118 | $msg .= sprintf('%%%s%%', $n->getAttribute('name')); 119 | $vars[] = new Twig_Node_Expression_Name($n->getAttribute('name'), $n->getLine()); 120 | } else { 121 | $msg .= $node->getAttribute('data'); 122 | } 123 | } 124 | } 125 | 126 | return array(new Twig_Node(array(new Twig_Node_Expression_Constant(trim($msg), $node->getLine()))), $vars); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Lib/Twig_TokenParser_Trans.php: -------------------------------------------------------------------------------- 1 | getLine(); 21 | $stream = $this->parser->getStream(); 22 | $count = null; 23 | $plural = null; 24 | 25 | if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { 26 | $body = $this->parser->getExpressionParser()->parseExpression(); 27 | } else { 28 | $stream->expect(Twig_Token::BLOCK_END_TYPE); 29 | $body = $this->parser->subparse(array($this, 'decideForFork')); 30 | if ('plural' === $stream->next()->getValue()) { 31 | $count = $this->parser->getExpressionParser()->parseExpression(); 32 | $stream->expect(Twig_Token::BLOCK_END_TYPE); 33 | $plural = $this->parser->subparse(array($this, 'decideForEnd'), true); 34 | } 35 | } 36 | 37 | $stream->expect(Twig_Token::BLOCK_END_TYPE); 38 | $this->checkTransString($body, $lineno); 39 | return new Twig_Node_Trans($body, $plural, $count, $lineno, $this->getTag()); 40 | } 41 | 42 | /** 43 | * Decide For Fork 44 | * 45 | * @param string $token 46 | * @return void 47 | */ 48 | public function decideForFork($token) { 49 | return $token->test(array('plural', 'endtrans')); 50 | } 51 | 52 | /** 53 | * Decide For End 54 | * 55 | * @param string $token 56 | * @return void 57 | */ 58 | public function decideForEnd($token) { 59 | return $token->test('endtrans'); 60 | } 61 | 62 | /** 63 | * Gets the tag name associated with this token parser. 64 | * 65 | * @param string The tag name 66 | * @return string 67 | */ 68 | public function getTag() { 69 | return 'trans'; 70 | } 71 | 72 | /** 73 | * Check Trans String 74 | * 75 | * @param Twig_NodeInterface $body 76 | * @param string $lineno 77 | * @return void 78 | */ 79 | protected function checkTransString(Twig_NodeInterface $body, $lineno) { 80 | foreach ($body as $i => $node) { 81 | if ($node instanceof Twig_Node_Text || ($node instanceof Twig_Node_Print && $node->getNode('expr') instanceof Twig_Node_Expression_Name)) { 82 | continue; 83 | } 84 | throw new Twig_Error_Syntax(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /View/TwigView.php: -------------------------------------------------------------------------------- 1 | 12 | * @link http://github.com/m3nt0r My GitHub 13 | * @link http://twitter.com/m3nt0r My Twitter 14 | * @author Graham Weldon (http://grahamweldon.com) 15 | * @license The MIT License (http://www.opensource.org/licenses/mit-license.php) 16 | */ 17 | if (!defined('TWIG_VIEW_CACHE')) { 18 | define('TWIG_VIEW_CACHE', CakePlugin::path('TwigView') . 'tmp' . DS . 'views'); 19 | } 20 | 21 | $twigPath = CakePlugin::path('TwigView'); 22 | 23 | // Load Twig Lib and start auto loader 24 | require_once($twigPath . 'Vendor' . DS . 'Twig' . DS . 'lib' . DS . 'Twig' . DS . 'Autoloader.php'); 25 | Twig_Autoloader::register(); 26 | 27 | // overwrite twig classes (thanks to autoload, no problem) 28 | require_once($twigPath . 'Lib' . DS . 'Twig_Node_Element.php'); 29 | require_once($twigPath . 'Lib' . DS . 'Twig_Node_Trans.php'); 30 | require_once($twigPath . 'Lib' . DS . 'Twig_TokenParser_Trans.php'); 31 | 32 | // my custom cake extensions 33 | require_once($twigPath . 'Lib' . DS . 'Twig_Extension_I18n.php'); 34 | require_once($twigPath . 'Lib' . DS . 'Twig_Extension_Ago.php'); 35 | require_once($twigPath . 'Lib' . DS . 'Twig_Extension_Basic.php'); 36 | require_once($twigPath . 'Lib' . DS . 'Twig_Extension_Number.php'); 37 | 38 | // get twig core extension (overwrite trans block) 39 | require_once($twigPath . 'Lib' . DS . 'CoreExtension.php'); 40 | 41 | /** 42 | * TwigView for CakePHP 43 | * 44 | * @version 0.5 45 | * @author Kjell Bublitz 46 | * @link http://github.com/m3nt0r/cakephp-twig-view GitHub 47 | * @package app.views 48 | * @subpackage app.views.twig 49 | */ 50 | class TwigView extends View { 51 | 52 | /** 53 | * File extension 54 | * 55 | * @var string 56 | */ 57 | public $ext = '.tpl'; 58 | 59 | /** 60 | * Twig Environment Instance 61 | * 62 | * @var Twig_Environment 63 | */ 64 | public $Twig; 65 | 66 | /** 67 | * Collection of paths. 68 | * These are stripped from $___viewFn. 69 | * 70 | * @todo overwrite getFilename() 71 | * @var array 72 | */ 73 | public $templatePaths = array(); 74 | 75 | /** 76 | * Constructor 77 | * Overridden to provide Twig loading 78 | * 79 | * @param Controller $Controller Controller 80 | */ 81 | public function __construct(Controller $Controller = null) { 82 | $this->templatePaths = App::path('View'); 83 | $loader = new Twig_Loader_Filesystem($this->templatePaths[0]); 84 | $this->Twig = new Twig_Environment($loader, array( 85 | 'cache' => TWIG_VIEW_CACHE, 86 | 'charset' => strtolower(Configure::read('App.encoding')), 87 | 'auto_reload' => Configure::read('debug') > 0, 88 | 'autoescape' => false, 89 | 'debug' => Configure::read('debug') > 0 90 | ));; 91 | 92 | $this->Twig->addExtension(new CoreExtension); 93 | $this->Twig->addExtension(new Twig_Extension_I18n); 94 | $this->Twig->addExtension(new Twig_Extension_Ago); 95 | $this->Twig->addExtension(new Twig_Extension_Basic); 96 | $this->Twig->addExtension(new Twig_Extension_Number); 97 | 98 | parent::__construct($Controller); 99 | 100 | if (isset($Controller->theme)) { 101 | $this->theme = $Controller->theme; 102 | } 103 | } 104 | 105 | /** 106 | * Render the view 107 | * 108 | * @param string $_viewFn 109 | * @param string $_dataForView 110 | * @return void 111 | */ 112 | protected function _render($_viewFn, $_dataForView = array()) { 113 | $isCtpFile = (substr($_viewFn, -3) === 'ctp'); 114 | 115 | if (empty($_dataForView)) { 116 | $_dataForView = $this->viewVars; 117 | } 118 | 119 | if ($isCtpFile) { 120 | return parent::_render($_viewFn, $_dataForView); 121 | } 122 | 123 | ob_start(); 124 | // Setup the helpers from the new Helper Collection 125 | $helpers = array(); 126 | $loaded_helpers = $this->Helpers->attached(); 127 | foreach($loaded_helpers as $helper) { 128 | $name = Inflector::variable($helper); 129 | $helpers[$name] = $this->loadHelper($helper); 130 | } 131 | 132 | if (!isset($_dataForView['cakeDebug'])) { 133 | $_dataForView['cakeDebug'] = null; 134 | } 135 | $data = array_merge($_dataForView, $helpers); 136 | $data['_view'] = $this; 137 | 138 | $relativeFn = str_replace($this->templatePaths, '', $_viewFn); 139 | $template = $this->Twig->loadTemplate($relativeFn); 140 | echo $template->render($data); 141 | return ob_get_clean(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /examples/Layouts/ajax.tpl: -------------------------------------------------------------------------------- 1 | {{ content_for_layout }} -------------------------------------------------------------------------------- /examples/Layouts/default.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ html.charset() }} 5 | {{ 'CakePHP: the rapid development php framework'|trans }}: {{ title_for_layout }} 6 | {{ html.meta('icon') }} 7 | {{ html.css('cake.generic') }} 8 | {{ scripts_for_layout }} 9 | 10 | 11 |
12 | 17 |
18 | {{ session.flash() }} 19 | {{ content_for_layout }} 20 |
21 | 29 |
30 | 31 | -------------------------------------------------------------------------------- /examples/Layouts/email/html/default.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title_for_layout }} 5 | 6 | 7 | {{ content_for_layout }} 8 | 9 |

This email was sent using the CakePHP Framework

10 | 11 | -------------------------------------------------------------------------------- /examples/Layouts/email/text/default.tpl: -------------------------------------------------------------------------------- 1 | {{ content_for_layout }} -------------------------------------------------------------------------------- /examples/Layouts/flash.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ html.charset() }} 5 | {{ page_title }} 6 | 7 | 8 | 9 |

{{ message }}

10 | 11 | -------------------------------------------------------------------------------- /examples/Layouts/js/default.tpl: -------------------------------------------------------------------------------- 1 | {{ scripts_for_layout }} 2 | -------------------------------------------------------------------------------- /examples/Layouts/rss/default.tpl: -------------------------------------------------------------------------------- 1 | {# do all the normal $channel stuff in controller... #} 2 | {# the below is untested, but should work. #} 3 | {{ rss.header() }} 4 | {{ rss.document(rss.channel([], channel, content_for_layout)) }} -------------------------------------------------------------------------------- /examples/Layouts/xml/default.tpl: -------------------------------------------------------------------------------- 1 | {{ xml.header() }} 2 | {{ content_for_layout }} -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2011 by Kjell Bublitz 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # TwigView plugin for CakePHP # 2 | 3 | This plugin for the [CakePHP Framework](http://cakephp.org) allows you to use the [Twig Templating Language](http://twig.sensiolabs.org) for your views. 4 | 5 | In addition to enabling the use of most of Twig's features, the plugin is tightly integrated with the CakePHP view renderer giving you full access to helpers, objects and elements. 6 | 7 | ## Installation ## 8 | 9 | Download the repository, create a folder called `TwigView` in your `plugins` folder. Extract. 10 | 11 | Alternatively: Just clone the repository directly into your app. 12 | 13 | $ cd app/Plugin 14 | $ git clone git://github.com/predominant/TwigView.git TwigView 15 | 16 | Or, add it as a submodule. 17 | 18 | $ git submodule add git://github.com/predominant/TwigView.git app/Plugin/TwigView 19 | 20 | ### Vendor Files ### 21 | 22 | Download the [Twig Library](http://www.twig-project.org/) and move `(archive)/*` to `APP/Plugin/TwigView/Vendor/Twig`. 23 | 24 | Alternatively: Just init the submodules of this repository. This will grab the latest version. 25 | 26 | $ git submodule update --init 27 | 28 | ### Cache Permissions ### 29 | 30 | Make the default view-cache folder writeable. 31 | 32 | APP/Plugin/TwigView/tmp/views 33 | 34 | Alternatively: Set where you want cache files to be stored. 35 | 36 | define('TWIG_VIEW_CACHE', APP . 'tmp'); 37 | 38 | ## Using the View Class ## 39 | 40 | To make CakePHP aware of TwigView edit your `APP/Controller/AppController.php` file and add the following: 41 | 42 | class AppController extends Controller { 43 | public $viewClass = 'TwigView.Twig'; 44 | } 45 | 46 | Be sure to load the TwigView plugin in your bootstrap.php file with: 47 | 48 | CakePlugin::load('TwigView'); 49 | 50 | or: 51 | 52 | CakePlugin::loadAll(); 53 | 54 | Now start creating view files using the `.tpl` extension. 55 | 56 | ## Default Layouts ## 57 | 58 | This plugin comes with all default layouts converted to Twig. Examples can be found in: 59 | 60 | APP/Plugin/TwigView/examples 61 | 62 | ## Themes ## 63 | 64 | The plugin has support for themes and works just like the `Theme` view. Simply add the `$theme` property to your controller and you're set. 65 | 66 | class AppController extends Controller { 67 | public $viewClass = 'TwigView.Twig'; 68 | public $theme = 'Rockstar'; 69 | } 70 | 71 | This will cause the view to also look in the `Themed` folder for templates. In the above example templates in the following directory are favored over their non-themed version. 72 | 73 | APP/View/Themed/Rockstar/ 74 | 75 | If you, for example, want to overwrite the `Layouts/default.tpl` file in the `Rockstar` theme, then create this file: 76 | 77 | APP/View/Themed/Rockstar/Layouts/default.tpl 78 | 79 | ## Using Helpers inside Templates ## 80 | 81 | All helper objects are available inside a view and can be used like any other variable inside Twig. 82 | 83 | {{ time.nice(user.created) }} 84 | 85 | ... where ... 86 | 87 | {{ time.nice(user.created) }} 88 | ^ ^ ^ ^____key 89 | | | |____array (from $this->set() or loop) 90 | | |_____ method 91 | |______ helper 92 | 93 | Which is the equivalent of writing: 94 | 95 | Time->nice($user['created']); ?> 96 | 97 | A more complex example, FormHelper inputs: 98 | 99 | {{ 100 | form.input('message', { 101 | 'label': 'Your message', 102 | 'error': { 103 | 'notempty': 'Please enter a message' 104 | } 105 | }) 106 | }} 107 | 108 | ## Referencing View Elements ## 109 | 110 | Elements must be `.tpl` files and are parsed as Twig templates. Using `.ctp` is not possible. 111 | 112 | In exchange for this limitation you can import elements as easy as this: 113 | 114 | {% element 'sidebar/about' %} 115 | 116 | ## Translating Strings ## 117 | 118 | The `trans` filter can be used on any string and simply takes the preceding string and passes it through the `__()` function. 119 | 120 | {{ 121 | form.input('email', { 122 | 'label': 'Your E-Mail Address'| trans 123 | }) 124 | }} 125 | 126 | This is the equivalent of writing: 127 | 128 | Form->input('email', array( 129 | 'label' => __("Your E-Mail Address") 130 | )); ?> 131 | 132 | ## Translating multiple lines ## 133 | 134 | The trans-block element will help you with that. This is especially useful when writing email templates using Twig. 135 | 136 | {% trans %} 137 | Hello! 138 | 139 | This is my mail body and i can translate it in X languages now. 140 | We love it! 141 | {% endtrans %} 142 | 143 | ## TwigView Custom Filters ## 144 | 145 | This plugin comes with a couple of handy filters, just like 'trans', piping some core CakePHP functions into Twig templates. 146 | 147 | ### `ago` ### 148 | 149 | Shortcut to TimeHelper::timeAgoInWords 150 | 151 | {{ user.created|ago }} 152 | 153 | ### `low` ### 154 | 155 | Convert a string to lower case 156 | 157 | {{ 'FOO'|low }} 158 | 159 | ### `up` ### 160 | 161 | Convert a string to upper case 162 | 163 | {{ 'foo'|up }} 164 | 165 | ### `debug` ### 166 | 167 | Display the debug (pre+print_r) output 168 | 169 | {{ user|debug }} 170 | 171 | ### `pr` ### 172 | 173 | Display just the print_r output 174 | 175 | {{ user|pr }} 176 | 177 | ### `env` ### 178 | 179 | Display the value from a environment variable 180 | 181 | {{ 'HTTP_HOST'|env }} 182 | 183 | ### `size` ### 184 | 185 | Convert byte integer to a human readable size 186 | 187 | {{ '3535839525'|size }} //=> 3.29 GB 188 | 189 | ### `p` ### 190 | 191 | Formats a number with a level of precision. 192 | 193 | {{ '0.555'|p(2) }} //=> 0.56 194 | 195 | ### `curr` ### 196 | 197 | Display floating point value as currency value. USD, GBP and EUR only 198 | 199 | {{ '5999'|curr }} // default, $5,999.00 200 | {{ '5999'|curr('GBP') }} // £5,999.00 201 | {{ '5999'|curr('EUR') }} // €5.999,00 202 | 203 | ### `pct` ### 204 | 205 | Formats a number into a percentage string. 206 | 207 | {{ '2.3'|pct }} //=> 2.30% 208 | 209 | ## Twig Built-In Filters ## 210 | 211 | For a list of available filters please refer to the [Twig Manual](http://www.twig-project.org/doc/templates.html#list-of-built-in-filters) 212 | 213 | ## Accessing View Instance ## 214 | 215 | In some cases it is useful to access `$this`, for example to build a DOM id from the current controller and action name. 216 | 217 | The object is accessible through `_view`. 218 | 219 |
220 | -------------------------------------------------------------------------------- /tmp/views/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.php -------------------------------------------------------------------------------- /tmp/views/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/predominant/TwigView/9b22ff50151e66fe0cc182548e9b917292a42f18/tmp/views/empty --------------------------------------------------------------------------------