Skip to content

Commit

Permalink
Merge branch 'master' into develop
Browse files Browse the repository at this point in the history
Conflicts:
	lib/Haanga/Compiler/Parser.php
	tests/assert_templates/trans.php
  • Loading branch information
crodas committed Jun 14, 2012
2 parents f9e5c25 + dca7626 commit f06c2db
Show file tree
Hide file tree
Showing 34 changed files with 822 additions and 585 deletions.
11 changes: 11 additions & 0 deletions .travis.yml
@@ -0,0 +1,11 @@
language: php
script: cd tests/; phpunit TestSuite.php

php:
- 5.3
- 5.4

before_script:
- curl -s http://getcomposer.org/installer | php
- php composer.phar install

2 changes: 1 addition & 1 deletion LICENSE
@@ -1,4 +1,4 @@
Copyright (c) 2010, César D. Rodas <crodas@php.net> and Menéame Comunicacions S.L.
Copyright (c) 2011, César D. Rodas <crodas@php.net> and Menéame Comunicacions S.L.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
13 changes: 13 additions & 0 deletions composer.json
@@ -0,0 +1,13 @@
{
"name": "crodas/Haanga",
"description": "Template compiler for PHP, Django-style (as much as possible). Pretty efficent by avoiding to have anything at run-time.",
"authors": [
{
"name": "César D. Rodas",
"email": "crodas@php.net"
}
],
"require": {

}
}
22 changes: 1 addition & 21 deletions lib/Haanga.php
Expand Up @@ -70,26 +70,6 @@ private function __construct()
/* The class can't be instanced */
}

final public static function AutoLoad($class)
{
static $loaded = array();
static $path;

if (!isset($loaded[$class]) && substr($class, 0, 6) === 'Haanga' && !class_exists($class, false)) {
if ($path === NULL) {
$path = dirname(__FILE__);
}
$file = $path.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
if (is_file($file)) {
require $file;
}
$loaded[$class] = TRUE;
return;
}

return FALSE;
}

public static function getTemplateDir()
{
return self::$templates_dir;
Expand Down Expand Up @@ -225,7 +205,7 @@ protected static function getCompiler($checkdir=TRUE)

/* load compiler (done just once) */
if (self::$use_autoload) {
spl_autoload_register(array(__CLASS__, 'AutoLoad'));
require_once "{$dir}/Haanga/Loader.php";
}

$compiler = new Haanga_Compiler_Runtime;
Expand Down
1,093 changes: 545 additions & 548 deletions lib/Haanga/Compiler/Parser.php

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions lib/Haanga/Compiler/Parser.y
Expand Up @@ -385,21 +385,25 @@ expr(A) ::= fvar_or_string(B). { A = B; }
/* Variable name */

varname(A) ::= varpart(B). { A = current($this->compiler->generate_variable_name(B, false)); }
varpart(A) ::= varname(B) T_OBJ|T_DOT T_ALPHA|T_CUSTOM_TAG|T_CUSTOM_BLOCK(C). {

varpart(A) ::= varpart(B) T_OBJ|T_DOT varpart_single(C). {
if (!is_array(B)) { A = array(B); }
else { A = B; } A[]=array('object' => C);
}
varpart(A) ::= varname(B) T_CLASS T_ALPHA|T_CUSTOM_TAG|T_CUSTOM_BLOCK(C). {

varpart(A) ::= varpart(B) T_CLASS varpart_single(C). {
if (!is_array(B)) { A = array(B); }
else { A = B; } A[]=array('class' => '$'.C);
}
varpart(A) ::= varname(B) T_BRACKETS_OPEN var_or_string(C) T_BRACKETS_CLOSE. {

varpart(A) ::= varpart(B) T_BRACKETS_OPEN var_or_string(C) T_BRACKETS_CLOSE. {
if (!is_array(B)) { A = array(B); }
else { A = B; } A[]=C;
}
varpart(A) ::= T_ALPHA(B). { A = B; }
varpart(A) ::= varpart_single(B). { A = B; }

/* T_BLOCK|T_CUSTOM|T_CUSTOM_BLOCK are also T_ALPHA */
varpart(A) ::= T_BLOCK|T_CUSTOM_TAG|T_CUSTOM_BLOCK(B). { A = B; }
varpart_single(A) ::= T_ALPHA|T_BLOCK|T_CUSTOM_TAG|T_CUSTOM_END|T_CUSTOM_BLOCK(B). { A = B; }

range(A) ::= numvar(B) T_DOTDOT numvar(C). { A = array(B, C); }

Expand Down
2 changes: 1 addition & 1 deletion lib/Haanga/Extension/Filter/Count.php
@@ -1,6 +1,6 @@
<?php

class Haanga_Extension_Filter_Length
class Haanga_Extension_Filter_Count
{
public $php_alias = "count";
public $is_safe = TRUE; /* a number if safe */
Expand Down
7 changes: 7 additions & 0 deletions lib/Haanga/Extension/Filter/Isarray.php
@@ -0,0 +1,7 @@
<?php

class Haanga_Extension_Filter_IsArray
{
public $php_alias = "is_array";
public $is_safe = TRUE; /* boolean if safe */
}
6 changes: 6 additions & 0 deletions lib/Haanga/Extension/Filter/Null.php
@@ -0,0 +1,6 @@
<?php

class Haanga_Extension_Filter_Null
{
public $php_alias = 'is_null';
}
16 changes: 16 additions & 0 deletions lib/Haanga/Extension/Filter/Slugify.php
@@ -0,0 +1,16 @@
<?php

class Haanga_Extension_Filter_Slugify
{
static function generator($compiler, $args)
{
if (count($args) != 1) {
$compiler->Error("slugify filter only needs one parameter");
}

$arg = hexec('strtolower', $args[0]);
$arg = hexec('str_replace'," ","-",$arg);
$arg = hexec('preg_replace',"/[^\d\w-_]/",'',$arg);
return $arg;
}
}
16 changes: 16 additions & 0 deletions lib/Haanga/Extension/Filter/Truncatechars.php
@@ -0,0 +1,16 @@
<?php

class Haanga_Extension_Filter_Truncatechars
{
static function main($text, $limit)
{
if(strlen($text) <= $limit)
return $text;
$trunctext = substr($text, 0, $limit);
$trunctext[$limit-3] = '.';
$trunctext[$limit-2] = '.';
$trunctext[$limit-1] = '.';
return $trunctext;
}
}

3 changes: 3 additions & 0 deletions lib/Haanga/Extension/Tag/Exec.php
Expand Up @@ -37,6 +37,9 @@ static function generator($cmp, $args, $assign=NULL)
$exec->end();
if ($assign) {
$code->decl($assign, $exec);

// make it global
$code->decl($cmp->getScopeVariable($assign), hvar($assign));
} else {
$cmp->do_print($code, $exec);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Haanga/Generator/PHP.php
Expand Up @@ -333,7 +333,7 @@ protected function php_foreach($op)
{
$op['array'] = $this->php_get_varname($op['array']);
$op['value'] = $this->php_get_varname($op['value']);
$code = "foreach ({$op['array']} as ";
$code = "foreach ((array) {$op['array']} as ";
if (!isset($op['key'])) {
$code .= " {$op['value']}";
} else {
Expand Down
117 changes: 117 additions & 0 deletions lib/Haanga/Loader.php
@@ -0,0 +1,117 @@
<?php

spl_autoload_register(function ($class) {
/*
This array has a map of (class => file)
*/

// classes {{{
static $classes = array (
'haanga' => '/../Haanga.php',
'haanga_ast' => '/AST.php',
'haanga_extension_filter' => '/Extension/Filter.php',
'haanga_extension' => '/Extension.php',
'haanga_extension_tag_spaceless' => '/Extension/Tag/Spaceless.php',
'haanga_extension_tag_exec' => '/Extension/Tag/Exec.php',
'haanga_extension_tag_inline' => '/Extension/Tag/Inline.php',
'haanga_extension_tag_upper' => '/Extension/Tag/Upper.php',
'haanga_extension_tag_trans' => '/Extension/Tag/Trans.php',
'haanga_extension_tag_templatetag' => '/Extension/Tag/Templatetag.php',
'haanga_extension_tag_tryinclude' => '/Extension/Tag/Tryinclude.php',
'haanga_extension_tag_setsafe' => '/Extension/Tag/Setsafe.php',
'haanga_extension_tag_dictsort' => '/Extension/Tag/Dictsort.php',
'haanga_extension_tag_min' => '/Extension/Tag/Min.php',
'haanga_extension_tag_lower' => '/Extension/Tag/Lower.php',
'haanga_extension_tag_currenttime' => '/Extension/Tag/Currenttime.php',
'haanga_extension_tag_firstof' => '/Extension/Tag/Firstof.php',
'haanga_extension_tag_buffer' => '/Extension/Tag/Buffer.php',
'haanga_extension_tag_cycle' => '/Extension/Tag/Cycle.php',
'haanga_extension_filter_urlencode' => '/Extension/Filter/Urlencode.php',
'haanga_extension_filter_default' => '/Extension/Filter/Default.php',
'haanga_extension_filter_length' => '/Extension/Filter/Length.php',
'haanga_extension_filter_truncatechars' => '/Extension/Filter/Truncatechars.php',
'haanga_extension_filter_intval' => '/Extension/Filter/Intval.php',
'haanga_extension_filter_translation' => '/Extension/Filter/Translation.php',
'haanga_extension_filter_trans' => '/Extension/Filter/Trans.php',
'haanga_extension_filter_stringformat' => '/Extension/Filter/Stringformat.php',
'haanga_extension_filter_capfirst' => '/Extension/Filter/Capfirst.php',
'haanga_extension_filter_reverse' => '/Extension/Filter/Reverse.php',
'haanga_extension_filter_substr' => '/Extension/Filter/Substr.php',
'haanga_extension_filter_upper' => '/Extension/Filter/Upper.php',
'haanga_extension_filter_isarray' => '/Extension/Filter/Isarray.php',
'haanga_extension_filter_empty' => '/Extension/Filter/Empty.php',
'haanga_extension_filter_trim' => '/Extension/Filter/Trim.php',
'haanga_extension_filter_hostname' => '/Extension/Filter/Hostname.php',
'haanga_extension_filter_count' => '/Extension/Filter/Count.php',
'haanga_extension_filter_truncatewords' => '/Extension/Filter/Truncatewords.php',
'haanga_extension_filter_dictsort' => '/Extension/Filter/Dictsort.php',
'haanga_extension_filter_exists' => '/Extension/Filter/Exists.php',
'haanga_extension_filter_title' => '/Extension/Filter/Title.php',
'haanga_extension_filter_cut' => '/Extension/Filter/Cut.php',
'haanga_extension_filter_date' => '/Extension/Filter/Date.php',
'haanga_extension_filter_lower' => '/Extension/Filter/Lower.php',
'haanga_extension_filter_slugify' => '/Extension/Filter/Slugify.php',
'haanga_extension_filter_join' => '/Extension/Filter/Join.php',
'haanga_extension_filter_escape' => '/Extension/Filter/Escape.php',
'haanga_extension_filter_pluralize' => '/Extension/Filter/Pluralize.php',
'haanga_extension_filter_safe' => '/Extension/Filter/Safe.php',
'haanga_extension_filter_null' => '/Extension/Filter/Null.php',
'haanga_extension_tag' => '/Extension/Tag.php',
'hg_parser' => '/Compiler/Tokenizer.php',
'haanga_compiler_parser' => '/Compiler/Parser.php',
'haanga_compiler_tokenizer' => '/Compiler/Tokenizer.php',
'haanga_yytoken' => '/Compiler/Parser.php',
'haanga_yystackentry' => '/Compiler/Parser.php',
'haanga_compiler_exception' => '/Compiler/Exception.php',
'haanga_compiler_runtime' => '/Compiler/Runtime.php',
'haanga_compiler' => '/Compiler.php',
'haanga_exception' => '/Exception.php',
'haanga_generator_php' => '/Generator/PHP.php',
);
// }}}

// deps {{{
static $deps = array (
'haanga_extension_filter' =>
array (
0 => 'haanga_extension',
),
'haanga_extension_filter_translation' =>
array (
0 => 'haanga_extension_filter_trans',
),
'haanga_extension_tag' =>
array (
0 => 'haanga_extension',
),
'hg_parser' =>
array (
0 => 'haanga_compiler_parser',
),
'haanga_compiler_runtime' =>
array (
0 => 'haanga_compiler',
),
);
// }}}

$class = strtolower($class);
if (isset($classes[$class])) {
if (!empty($deps[$class])) {
foreach ($deps[$class] as $zclass) {
if (!class_exists($zclass, false) && !interface_exists($zclass, false)) {
require __DIR__ . $classes[$zclass];
}
}
}

if (!class_exists($class, false) && !interface_exists($class, false)) {
require __DIR__ . $classes[$class];
}
return true;
}

return false;
});


1 change: 1 addition & 0 deletions tests/TestSuite.php
Expand Up @@ -21,6 +21,7 @@ public static function Init()
{
$config = array(
'cache_dir' => 'tmp/',
'autoload' => true,
'template_dir' => '.',
'debug' => TRUE,
'use_hash_filename' => FALSE,
Expand Down
1 change: 1 addition & 0 deletions tests/assert_templates/bug_#14.html
@@ -0,0 +1 @@
5
5 changes: 5 additions & 0 deletions tests/assert_templates/bug_#14.php
@@ -0,0 +1,5 @@
<?php

$data = array(
'endsomething' => array('endbar' => 5),
);
1 change: 1 addition & 0 deletions tests/assert_templates/bug_#14.tpl
@@ -0,0 +1 @@
{{ endsomething.endbar }}
1 change: 1 addition & 0 deletions tests/assert_templates/exec-inc.tpl
@@ -0,0 +1 @@
{{ foo }}
4 changes: 4 additions & 0 deletions tests/assert_templates/exec.html.php
@@ -1,2 +1,6 @@
<?php echo php_uname();?>


<?php echo php_uname();?>


2 changes: 2 additions & 0 deletions tests/assert_templates/exec.tpl
@@ -1 +1,3 @@
{% exec php_uname %}
{% exec php_uname as foo %}
{% include "assert_templates/exec-inc.tpl" %}
3 changes: 3 additions & 0 deletions tests/assert_templates/expr.html
@@ -0,0 +1,3 @@

hola

8 changes: 8 additions & 0 deletions tests/assert_templates/expr.php
@@ -0,0 +1,8 @@
<?php
$data = array(
'self' => array(
'status' => true,
'tiene_negativos' => true,
'nsfw' => false,
)
);
3 changes: 3 additions & 0 deletions tests/assert_templates/expr.tpl
@@ -0,0 +1,3 @@
{% if self.status == 'published' AND self.tiene_negativos AND !self.nsfw %}
hola
{% endif %}
2 changes: 2 additions & 0 deletions tests/assert_templates/is_array.html
@@ -0,0 +1,2 @@
true

3 changes: 3 additions & 0 deletions tests/assert_templates/is_array.php
@@ -0,0 +1,3 @@
<?php

$data = array('zfoo' => new stdclass, 'foo' => array());
2 changes: 2 additions & 0 deletions tests/assert_templates/is_array.tpl
@@ -0,0 +1,2 @@
{%if foo|isarray %} true {% endif %}
{%if zfoo|isarray %} true {% endif %}
Binary file not shown.
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-08-03 23:34-0400\n"
"POT-Creation-Date: 2006-07-03 16:17+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down
13 changes: 13 additions & 0 deletions tests/assert_templates/null.html
@@ -0,0 +1,13 @@


foo is null



bar is not null



foobar is not null


8 changes: 8 additions & 0 deletions tests/assert_templates/null.php
@@ -0,0 +1,8 @@
<?php

$data = array(
'obj' => array(
'foo' => NULL,
'bar' => false,
'foobar' => 0,
));
7 changes: 7 additions & 0 deletions tests/assert_templates/null.tpl
@@ -0,0 +1,7 @@
{% for k,val in obj %}
{% if val|null %}
{{ k }} is null
{% else %}
{{ k }} is not null
{% endif %}
{% endfor %}

0 comments on commit f06c2db

Please sign in to comment.