Giter Site home page Giter Site logo

h2o-php's Introduction

H2O template markup

Being a martial arts fan, I borrow a quote.

H2O template

H2O is markup language for PHP that has taken a lot of inspiration from Django.

Features

  • Readable and human-friendly syntax.
  • Easy to use and maintain
  • Encourages reuse in templates by allowing template inclusion and inheritance.
  • Highly extensible through filters, tags, and template extensions.
  • Includes a rich set of filters and tags for string formatting, HTML helpers and internationalization support.

Requirement

  • PHP 5.1 +

News

  • version 0.4
    1. Breaking changes autoescape is now turned on by default
    2. Improved searchpath and file loading handling
    3. Improved handling on PHP overloaded objects
    4. Plenty of bug fixes
  • version 0.3
    1. Support internationalized templates and translation parsing toolkit
    2. Performance optimization on context lookup
    3. Fixed operator parsing

Getting started

Getting h2o

Download

With Git

git clone http://github.com/speedmax/h2o-php.git

With SVN

svn checkout http://h2o-template.googlecode.com/svn/trunk/ h2o

Installation

  1. Download and extract h2o into your project path or your php include path

    Sample file structure setup

    myawesome_app/
        index.php
        templates/
          index.html
        h2o/
    
  2. Use require 'h2o/h2o.php' in your php files to include the h2o library.

  3. Below is a basic code sample to get your project going.

  4. Check out the \example and \specs dirs to see some of h2o's more interesting features in action.

templates/index.html

<body>
    <head><title>Hello world</title></head>
    <body>
        Greetings {{ name }}
    </body>
</body>

index.php

<?php
    require 'h2o/h2o.php';
    $h2o = new h2o('templates/index.html');
    echo $h2o->render(array('name'=>'Peter Jackson'));
?>

Useful links

Syntax explanation

variable

{{ variable }}

Use dot (.) to access attributes of a variable

variable lookup order

  1. key of an associative array
  2. array-index
  3. object attribute
  4. object method call

Example

in your template

{{ person.name }} 

in php

<?php 
    $h2o = new H2o('template.tpl');
    $person =array(
            'name' => 'Peter Jackson', 'age' => 25
    );
    $h2o->render(compact('person'));
?>

Let's say that you have assigned the value Peter Jackson to a 'person' variable in your php script. The following variable tag will print out Peter Jackson.

Filters

Filters are variable modifiers that manipulate or format the value of a variable. A filter usually looks like this {{ person.name|capitalize }}, a pipe ( | ) character after a variable, plus a filter name, will cause H2O to apply the filter.

Filter chaining

filter chaining
Let me borrow the image from liquid template

You can chain multiple filters together and use a pipe ( | ) character to separate them. {{ document.body|escape|nl2br }}

Filter arguments
Filters can accept arguments. For example: {{ document.description|truncate 20 }} will display the first 20 characters of the document's description.

Moreover, there are cases where you might want to pass in multiple arguments. Use commas ( , ) to separate them: {{ person.bio|truncate 20, "..." }}

Filter named arguments
h2o uses colons ( : ) for named arguments. These allow you to build 'optional argument' arrays.

{{ '/images/logo.png' | image_tag width:450, height:250, alt:"company logo" }}

The above code translated to php will be like the below snippet, which resembles what happens internally:

<?php
    echo image_tag("/image/logo.png", array(
        'width' => 450, 
        'height' => 250, 
        'alt'=>'company logo'
    ));
?>

Note: Difference with Django, Smarty H2o does not use the colon ( : ) character to separate arguments for readability reasons, H2o uses the comma ( , ) which is more logical.

Tag

{% tag %}

Tags are very powerful, as they control the logical flow and structure of a template, There are inline tags {% inline_tag %} or tags that requires a close tag. For example: {% if condition %} ... {% endif %}

The "if" tag

if tags evaluate either a variable or a simple expression. If the result of the if expression is true, then the contents of the if block will be allowed to render.

{% if person.is_adult %}
    You are old enough.
{% else %}
    sorry, you are too young for that.
{% endif %}

The "for" tag

for tags allow iteratation over an array of items.

{% for task in tasks %}
    {{ task }}
{% endfor %}

The above snippet will print out each "task" in the "tasks" array.

Template inheritance

H2o supports template inheritance. Inheritance allows you to factor out a lot of common code that would otherwise be duplicated across most of your templates.

Template inheritance is implemented using the block and extends tags, with child templates extending their parent templates. Word of Caution:

  • H2o templates only support single inheritance (just like PHP!), and currently do not support deep inheritance chains.

Quote from the Django docs:

... a base skeleton template that contains all the common elements of your site and defines blocks that child templates can override.

Example:

base.html - defines the base structure of our pages.

<html>
 <head><title>{%block title %}This is a page title {% endblock %}</title></head>
 <body>
 <div id="content">
   {% block content%}
       <h1> Page title </h1>
       <p> H2O template inheritance is a powerful tool </p> 
   {% endblock %}
 </div>

 <div id="sidebar">
   {% block sidebar %}{% endblock %}
 </div>
 </body>
</html>

As you can see, the base template is a typical web page using a two column layout. We defined two blocks (content and sidebar) and HTML code common across all of our pages.

page.html - defines a page-specific template.

{% extends 'base.html' %}

{% block content %}
    <h1> extended page </h1>
    <p> Body of extended page </p>
{% endblock %}

{% block sidebar %}
    Sidebar contains use links.
{% endblock %}

The page.html extends base.html, allowing us to override any block previously defined in base.html.

Below is an excellent article about template inheritance in Django. If you wish to understand H2o's template-inheritance system, this would be a great spot to start, since H2o's template-inheritance system is strongly influenced by Django's.

Power of inheritance is a very good blog post explaining inheritance

Tips

  • If you have found that you have several common elements inside the same template, it may be a good idea to put that portion of the template inside a block in a base template.
  • block give you a hook, which is useful, since these can help with javascript and css too.
  • When defining a block use a short and distinctive name

Configuration

There are a range of options for configuring the template engine.

<?php
    $h2o = new H2o('template.tpl', array(
        [option_name] => [option_value]
    ));
?>

Loader

The name of the loader or an instance of H2o_Loader

Use file loader [default]

$template = new H2o('index.html', array('loader'=>'file');

Advanced setup $loader ); ?>

Use dictionary loader

If you want to load templates from resources other than files, then this will be your friend. H2o uses dict_loader() for testing.

<?php
    $loader = dict_loader(array(
        "index.html" => 'Hello {{ person }}'
    ));
    $template = new H2o('index.html', array('loader' => $loader'));
?> 

Searchpath

default: this will be the base path of your template

H2o use this path to load additional templates and extensions.

You can either explicity set the search path,

$template = new H2o('index.html', array('searchpath' => '/sites/common_templates'));

or h2o will try to find the searchpath for you.

$template = new H2o('/sites/common_templates/index.html');

Cache

You can define the type of caching engine h2o should use, if any. Set 'cache' to false to disable caching. You can read more about performance and caching in following sections

Use file cache [default]

$template = new H2o('index.html', array('cache'=>'file'));

Use apc cache:

$template = new H2o('index.html', array('cache'=>'apc'));

Use memcache cache

$template = new H2o('index.html', array('cache'=>'memcache'));

Disable caching

$template = new H2o('index.html', array('cache'=>false));

Cache_dir

When the file cache is used, you can define where you want templates to be cached.

It will put a cached template in same location as the normal template

$template = new H2o('index.html', array('cache_dir'=>'/tmp/cached_templates'));

Cache_ttl

"cache_ttl" specifies how long a cached template should be used (defaults: 1 hour) before it is recompiled. The template fragment cache that is bundled in the cache extension will use this as default ttl value.

$template = new H2o('index.html', array('cache_ttl' => 3600));

Performance and Caching

Caching can increase performance since it skips step of inefficient template parsing. H2o caches the template objects (the internal data structure of a template) and the bundled caching backends include File, APC, and Memcache.

File cache

By default h2o uses the file cache to store template objects. Change h2o option cache_dir to where you want to store template cache (ie: /tmp).

<?php
    $template = new H2o('homepage.tpl', array(
        'cache' => 'file',
        'cache_dir' => '/tmp'
    ));
?>

APC cache

APC is an op-code and object cache extension for php whose performance is generally 10-30% better than just plain file caching.

<?php
    $template = new h2o('homepage.tpl', array('cache' => 'apc'));
?>

Memcache

Currently not implemented

Extending H2o

Known issues

Yes, h2o has them. However, if you are careful, these shouldn't hinder your template development. The deep inheritance issue is a bit problematic for some template architectures, but again, if you are careful, and perhaps a bit inventive, it won't hinder you terribly much.

  • {{ block.super }} doesn't work with more than 1 level of inheritance yet, so if {{ block.super }} invokes another {{ block.super }} it won't work just yet.
  • 'if' conditions don't support multiple expressions or mathematical expressions yet, like: {% if something > 3 or something < 2 %} or {% if something + else > 12 %} These likely will not be implemented in the future unless some daring soul implements them and contributes the code back to the h2o-php project.

Contributors

  • Taylor Luk - Founder of Issue publishing
  • jlogsdon - Major refactoring (wip) and bug fixes
  • cyberklin - Added filter support for any context resolve
  • idlesign - Added if_changed tag support
  • metropolis - Improved our test coverage
  • plus many others

Credit

H2o borrows ideas and/or concepts from the following projects:

  • Django template - Django web development framework.
  • Ptemplates - Armin Ronacher's pet project for a django port in PHP.
  • Jinja - Django inspired template in Python.

Special Thanks: Armin Ronacher, since early versions of h2o were based off of his Ptemplates project.

The MIT License

Copyright (c) 2008 Taylor Luk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

h2o-php's People

Contributors

agopaul avatar ciceroverneck avatar cyberklin avatar danielchatfield avatar idlesign avatar jjjjeeffff avatar jlogsdon avatar jsilva avatar philipaconrad avatar rlaager avatar speedmax avatar vdboor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

h2o-php's Issues

relative_time doesn't work when the timestamp given is in the future.

relative_time doesn't work when the timestamp given is in the future. i've fixed it in my versions. since i don't have permissions to edit the source, i'm posting the change below..

static function relative_time($timestamp, $format = 'g:iA') {

...
if($delta < 0){
$delta = abs($delta);
$future = 1;
}
...
if($future)return "in $string";
else return "$string ago";
}

variables starting with &rsquo;or&rsquo; cause errors

echo $h2o->render(array(
’org’=>’My People’,
’job’ => ’templater’ ,
’days’ => $arr ,
));

In the above example the var named "org" fails to show and chucks up 4 warnings, below, xdebug output.

Change the var name to "porg" and all works as it should !

It is repeatable with the word "andy" as well.

Call the var "andy", it fails, "randy" it works.

However, "indy" works fine, so it not because it starts with a vowel.

Sorry I couldn’t fix it but I think you might find that a parser is sensing the words ’or’ and ’and’ as being one of the permitted tags/filters.

I couldn’t spot it though.

A very subtle bastard of a bug, lost half a day, but am gratified if it helps you.

Win32, server2003, apache 2, PHP5.2.6.

Paul

Notice: Undefined offset: 0 in C:\var\www\includes\h2o\h2o\context.php on line 92
Call Stack

Time Memory Function Location

1 1.0543 121392 {main}( ) ..\index.php:0
2 1.0999 1002640 H2o->render( ) ..\index.php:291
3 1.1005 1003872 NodeList->render( ) ..\h2o.php:133
4 1.1005 1003928 Extends_Tag->render( ) ..\nodes.php:27
5 1.1006 1004040 NodeList->render( ) ..\tags.php:200
6 1.1007 1004672 VariableNode->render( ) ..\nodes.php:27
7 1.1007 1004944 H2o_Context->resolve( ) ..\nodes.php:59

( ! ) Warning: preg_match() expects parameter 2 to be string, array given in C:\var\www\includes\h2o\h2o\context.php on line 102
Call Stack

Time Memory Function Location

1 1.0543 121392 {main}( ) ..\index.php:0
2 1.0999 1002640 H2o->render( ) ..\index.php:291
3 1.1005 1003872 NodeList->render( ) ..\h2o.php:133
4 1.1005 1003928 Extends_Tag->render( ) ..\nodes.php:27
5 1.1006 1004040 NodeList->render( ) ..\tags.php:200
6 1.1007 1004672 VariableNode->render( ) ..\nodes.php:27
7 1.1007 1004944 H2o_Context->resolve( ) ..\nodes.php:59
8 1.1047 1006256 preg_match ( ) ..\context.php:102

( ! ) Warning: preg_match() expects parameter 2 to be string, array given in C:\var\www\includes\h2o\h2o\context.php on line 106
Call Stack

Time Memory Function Location

1 1.0543 121392 {main}( ) ..\index.php:0
2 1.0999 1002640 H2o->render( ) ..\index.php:291
3 1.1005 1003872 NodeList->render( ) ..\h2o.php:133
4 1.1005 1003928 Extends_Tag->render( ) ..\nodes.php:27
5 1.1006 1004040 NodeList->render( ) ..\tags.php:200
6 1.1007 1004672 VariableNode->render( ) ..\nodes.php:27
7 1.1007 1004944 H2o_Context->resolve( ) ..\nodes.php:59
8 1.1087 1006408 preg_match ( ) ..\context.php:106

( ! ) Warning: array_shift() [function.array-shift]: The argument should be an array in C:\var\www\includes\h2o\h2o\context.php on line 164
Call Stack

Time Memory Function Location

1 1.0543 121392 {main}( ) ..\index.php:0
2 1.0999 1002640 H2o->render( ) ..\index.php:291
3 1.1005 1003872 NodeList->render( ) ..\h2o.php:133
4 1.1005 1003928 Extends_Tag->render( ) ..\nodes.php:27
5 1.1006 1004040 NodeList->render( ) ..\tags.php:200
6 1.1007 1004672 VariableNode->render( ) ..\nodes.php:27
7 1.1126 1005800 H2o_Context->applyFilters( ) ..\nodes.php:61
8 1.1127 1006928 array_shift ( ) ..\context.php:164

original LH ticket

This ticket has 0 attachment(s).

Variable access to array index

Assume the following:

$arr = array(
    array('x' => 0),
    array('x' => 1),
    array('x' => 2),
    array('x' => 3),
);

$b = array(1, 2, 3, 4);
{% for a in arr %}
    {{ b.{{ a.x }} }}

{% endfor %}

Expected output:

1
2
3
4

Actual output: unexpected character in filters : "." at 306 on line 228 in /h2o/h2o/parser.php

(edited to clarify variable tags)

Support non-standardized gettext implementations

Currently i18n only supports gettext native php extension, it is good but contains serious limitation on some deployment platform.

For instance apache1/2 caches translation mo file aggressively with no way to flush the gettext cache when apache is setup with mod_php, (php fastcgi is not affected)

Ideal gettext support

  • php-gettext php extension
  • php-gettext pure php library
  • other i18n implementation such as CakePHP I18n class

original LH ticket

This ticket has 0 attachment(s).

Extending FilterCollection complains of static functions

Trying to create customized filters:

class CustomFilters extends FilterCollection {

    function contains($haystack, $needle) {
        return strpos($haystack, $needle) !== false;
    }
}

I get this error message:

[E_STRICT] call_user_func_array() expects parameter 1 to be a valid callback, non-static method CustomFilters::contains() should not be called statically in /home/bruno/workspace/libs/h2o-php/h2o/context.php on line 197

Solved by forcing the function as static (exactly the opposite what the error reported):

class CustomFilters extends FilterCollection {

    static function contains($haystack, $needle) {
        return strpos($haystack, $needle) !== false;
    }
}

Any ideas why this weird behaviour? And, if that's the correct solution, it would be nice idea to update the Wiki documentation.

Thanks,

Why loop instead of forloop?

Since h2o is based on Django templates, why did you choose to rename some of the loop variables?

Django:

{% for item in list %}
    {{ forloop.counter0 }}
    {{ forloop.parentloop.counter0 }}
{% endfor %}

h2o:

{% for item in list %}
    {{ loop.counter0 }}
    {{ loop.parent.counter0 }}
{% endfor %}

This makes templates non-portable (or less portable)

I don't know much php but ... in loaders.php

I don't know much php but ... in loaders.php
the class H2o_File_Cache constructor may create a directory using 'tempnam' which is not done securely(as far as I know it is not secure in php :/ ).

Nested Extends don't bubble blocks to base template

'### base.html
<html>
<head><title>{% block title %}OHH NOES!{% endblock %}</title></head>
<body>
<div id="main">{% block body %}{% endblock %}</div>
</body>
</html>

'### one_col.html (notice no title block)
{% extends "base.html" %}
{% block body %}
<div id="col1">{% block content %}{% endblock %}</div>
{% endblock %}

'### report.html (notice title block)
{% extends "one_col.html" %}
{% block title %}Awesome Report{% endblock %}
{% block content %}I love H2O!{% endblock %}

'### view-source: http://www.example.com/report.html
<html>
<head><title>OHH NOES!</title></head>
<body>
<div id="main">
<div id="col1">
I love H2O!
</div>
</div>
</body>

Objects are not converted to strings (e.g. using __toString())

When a VariableNode() resolves an object, it is not printed as string.
This could be done using the __toString() method.

Where could this be implemented?
The source was a bit unclear for me, whether that needs to happen in resolve(), getVariable() or escape()

Warning thrown when a comment is added to a template

Intermittent problem which is hard to nail down, only affects single-line comments AFAICT. {* a comment *}

example:
@@@
{% extends ’gmap_layout.html’ %}

{%block title %}{{ service.title|excape }} in {{ place_name }}{% endblock %}

{% block header %}

{{ service.title|excape }} in {{ place_name }}

{% endblock %}
{* with a comment *}
{% block place %}

About {{ place_name }}

Information about your chosen place more ...
{% endblock %}
@@@

PHP Warning shown:
Warning: Missing argument 2 for H2o_Node::__construct(), called in C:\var\www\includes\h2o\h2o\parser.php on line 80 and defined in C:\var\www\includes\h2o\h2o\nodes.php on line 8
Call stack:

Time Memory Function Location

1 0.9379 129168 {main}( ) ..\index.php:0
2 1.0018 1277784 H2o->__construct( ) ..\index.php:292
3 1.0071 1280568 H2o->loadTemplate( ) ..\h2o.php:83
4 1.0071 1280568 H2o_File_Loader->read_cache( ) ..\h2o.php:87
5 1.0090 1299704 H2o_File_Loader->read( ) ..\loaders.php:59
6 1.0101 1300656 H2o->parse( ) ..\loaders.php:47
7 1.0230 1465704 H2o_Parser->parse( ) ..\h2o.php:103
8 1.0235 1467360 H2o::createTag( ) ..\parser.php:88
9 1.0236 1467928 Extends_Tag->__construct( ) ..\h2o.php:148
10 1.0238 1469568 H2o_Parser->parse( ) ..\tags.php:176
11 1.0406 1474472 H2o_Node->__construct( ) ..\parser.p

Workround:

1 hide php warnings ;-)
2 call a second template beneath it.

$footer = new h2o( &rsquo;tpl/footer.html&rsquo;);
echo $footer->render();

Win32, php 5.2.6, h20 beta 3

original LH ticket

This ticket has 0 attachment(s).

InvalidArgumentException for-loop over empty arrays

While testing the library, I noticed this error when loading the h2o-php/example/i18n/index.php page:

Fatal error: Uncaught exception 'InvalidArgumentException' with message 'The for tag cannot iterate over the value: ' in h2o-php/h2o/tags.php:137
Stack trace:
#0 h2o-php/h2o/nodes.php(27): For_Tag->render(Object(H2o_Context), Object(StreamWriter))
#1 h2o-php/h2o/tags.php(172): NodeList->render(Object(H2o_Context), Object(StreamWriter))
#2 h2o-php/h2o/nodes.php(27): For_Tag->render(Object(H2o_Context), Object(StreamWriter))
#3 h2o-php/h2o.php(136): NodeList->render(Object(H2o_Context), Object(StreamWriter))
#4 h2o-php/example/i18n/index.php(44): H2o->render(Array)
#5 {main}
  thrown in h2o-php/h2o/tags.php on line 137

The issue happens because the index.php contains an empty array() for one of the user.tasks (3rd). The error does not happen if the array is not empty.

From version:
commit 93eee9c

Whitespace arround tags

When template tags are indented with the HTML code, the HTML tags get double indention. I find this output ugly, and would like to see it differently.

I think the following would lead to much to both clean template code and clean output.

  • when the full line has a template tag, pretend the full line doesn't exist.
  • if there is other code at the line, preserve whitespace; pretend the template tag didn't exist.

I hope you agree :)

[Warning] In read_cache after calling loadTemplate

Warning: unserialize(): Function spl_autoload_call() hasn't defined the class it was called for in h2o/loaders.php on line 108

I looked into it, but don't understand how unserialize() uses spl_autoload_call() and which class should be defined. In fact, I don't get the warning at all, because unserialize() is a global function, so why is there a need to define a class?

Full stack trace below. H2o version is 0.4.1.

( ! ) Warning: unserialize(): Function spl_autoload_call() hasn't defined the class it was called for in h2o/loaders.php on line 108
Call Stack
#TimeMemoryFunctionLocation
10.0002245648{main}( )../index.php:0
20.01181005480H2o->__construct( )../index.php:9
30.01231010792H2o->loadTemplate( )../h2o.php:85
40.01231010856H2o_File_Loader->read_cache( )../h2o.php:90
50.01341024048unserialize ( )../loaders.php:108

Tags not interpreted after large number of characters.

If you create a template:

{% extends base.html %}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id consequat justo. Phasellus gravida, mi a aliquam eleifend, nisi quam elementum felis, eget congue magna lorem eget magna....
... REPEAT FOR A LONG TIME...
{% block content %}

{% endblock %}

The block and endblock tags are not interpreted but are shown in the output as raw tags. If you move the block to the top of the file the block shows correctly.

It seems like there's a maximum number of characters allowed in the templates.

methods not called for objects?

I have an object with child objects that have their own methods. According to the documentation, these should be callable via the dot notation, should they not?

Example:
{% for index, object in c.objects %}

  • {{ object.name}} | {{ object.method_name }}

  • {% endfor %}

    object.method_name returns a string, but it's not appearing in the rendered page?

    relative_date and relative_time

    Hi there...

    Cant seem to get relative_date and relative_time to work with integer timestamps.

    E.g. {{ mytime|relative_time }} where mytime is an integer timestamp always returns the current date / time.

    I can see why. In filters.php line 250:

    $timestamp = strtotime($timestamp);

    Maybe this should be:

    $timestamp = (!is_numeric($timestamp)) ? strtotime($timestamp) : $timestamp;

    And, line 278:

    $time = strtotime($time);

    Should be:

    $time = (!is_numeric($time)) ? strtotime($time) : $time;

    Cheers!

    original LH ticket

    This ticket has 0 attachment(s).

    date filter does not work with integer timestamps

    Hi there...

    If I have a variable (say "my_timestamp") containing an integer timestamp, the following {{ my_timestamp | date }} does not work (it always displays Jan 1 1970).

    The current code for this filter passes integers to strtotime, but that returns FALSE for integer input (at least on my system, php 5.3).

    static function date($time, $format = ’jS F Y H:i’) {
    if ($time instanceof DateTime)
    $time = (int) $time->format(’U’);

    return date($format, strtotime($time));
    

    }

    I would suggest this should be:

    static function date($time, $format = ’jS F Y H:i’) {
    if ($time instanceof DateTime)
    $time = (int) $time->format(’U’);

    if (!is_numeric($time)) $time = strtotime($time);
    
    return date($format, $time);
    

    }

    original LH ticket

    This ticket has 0 attachment(s).

    Recode in 5.3?

    Will we see it? I mean it has some powerful changes, and a template engine could make much use of it :)

    (Question) Method invoking on object variable?

    I can't find any example but i think it must be possible somehow.
    Also, what about array literals?

    What i am looking for is

    {{ myClass.someMethod(['a' = 'b', 2, 3, 4]) }}
    

    I assign my objects via render(). I can {% debug %} them, just not call any method.

    I thought about making "MyClass" a filter collection, but then it is still not clear if i can set arrays inside the template to use them as option hashes. And it would be bad for a couple other inheritance related reasons.

    Is this planned or already supported?

    PHP Notice in h20/loaders.php file

    The class H2o_File_Loader that extends H2o_Loader tries to use a private property from H2o_Loader, giving the alarm:

    Notice: Undefined property: H2o_File_Loader::$cache in /var/www/h2o/h2o/loaders.php on line 50

    To solve the problem, just change the line 11 of loaders.php:

    private $cache = false;
    

    to:

    protected $cache = false;
    

    This is so small issue the I figured it wasn't worth to fork your code.

    Very nicely done! I was looking for something Django alike to deal with templating... the alternatives, sad to say, suck!

    Cheers,

    i18n fails to replace empty variables in blocktrans

    I found that running a template code such as:

    {% blocktrans test=value_from_php %}This is a {{ test }}!{% endblocktrans %}

    where value_from_php is a value passed in the render() method, with empty string.

    The output of this is:

    This is a %(test)!
    

    meaning it does not replace the string within the translation text.

    Optimizing file dir info

    You should check the files and insert in top of all:
    defined('DS') or define('FILE_DIR', dirname(__FILE__));
    then change all the:

    `````` dirname(FILE).DS.to:FILE_DIR.DS.```

    Parse error in latest download

    Hi there...

    Just downloaded the latest from github (0.4)... Got this error:

    (2048) Non-static method H2O_RE::init() should not be called statically, assuming $this from incompatible context /Volumes/Work/www/sites/testsparks.com/modules/Sparks.View/ext/h2o/h2o/parser.php (185)

    Cheers...

    original LH ticket

    This ticket has 0 attachment(s).

    Problem with outputting protected class data through h2o

    Using the ORM framework found at: http://lukebaker.org/projects/activerecord-in-php/ I was unable to output data in the template because the model’s object’s "attributes" array (where it keeps its row data, accessed through a custom getter __get()) was protected.

    In the PHP file, if I have a $user object, I can do print $user->username and it will output "bob", but if I display a template, with vars "user" => $user ... and then try to {{ user.username }} in template, nothing is output.

    original LH ticket

    This ticket has 0 attachment(s).

    Typo in the "filesize" filter.

    In "filters.php" file on the line 125 it should be "MB" instead of "BM":

    'BM' => pow(2, 20), 'GB' => pow(2, 30),

    should be transformed in

    'MB' => pow(2, 20), 'GB' => pow(2, 30).

    [PATCH] parser initialization fails when invoked in PHP 5.3

    It's missing a static declaration, so here it is:

    Index: h2o/parser.php
    --- h2o/parser.php  Mo Nov 17 05:01:46 2008
    +++ h2o/parser.php  So Jun  5 00:18:47 2011
    @@ -148,7 +148,7 @@
         static  $whitespace, $seperator, $parentheses, $pipe, $filter_end, $operator,
                 $number,  $string, $i18n_string, $name, $named_args;
    
    -    function init() {
    +    static function init() {
             $r = 'strip_regex';
    
             self::$whitespace   = '/\s+/m';
    

    Variables should be able to start with underscore (_)

    Don't have time to fork and push right now, but before I forget...

    line 173 of /h2o/parser.php:

    From:

            self::$name         = '/[a-zA-Z][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/';

    To:

            self::$name         = '/[a-zA-Z_][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/';

    E_STRICT warning

    Strict standards: Non-static method CoreFilters::first() cannot be called statically in /home/tkn/public/h2o-php/h2o.php on line 211

    original LH ticket

    This ticket has 0 attachment(s).

    Invalid with tag syntax

    I cannot get the following to work with the with tag. What am I doing wrong?

    {% with dashboard.team.projectManager as pm %}

    {% endwith %}

    Filters in if Tags?

    Is it possible to use a Filter within an if tag? e.g.

    {% if people | length <= 1 %}      
        There is only one person
    {% else %}                      
       There is more than one person
    {% endif %} 
    

    strftime filter support

    I'm sorry if I'm nitpicking here, but I would like a strftime filter in addition to the date filter (I like strftime's syntax more and strftime works with locales).

    Could it be added?

    nl2br no longer works due to auto escape feature

    The nl2br filter does not work anymore, because the autoescape feature convert it to a literal
    tag.

    As current workarround, I've figured I can use:

    {{ tagname | escape | nl2br | safe }}
    

    But I find this a bit cumbersome. Would it be possible to find a better fix for this? (e.g. how django does it?)

    variables and properties should be case insensitive.

    I don't see a good reason for variables on template be case sensitive.

    A issue example:

    When get data from a database, append this data to a collection of objects (that map some database table) and then send this array of objects to h2o template, all the properties of my current object must respect the case sensitive to work properly. Unfortunately some times, change the case of table column name is necessary and it will make the h2o page brake, without either a warning or error message. The reason is because that column name (a property of object) was previously wrote with a different case.

    Issue with cache loader

    I'm getting this error (on some server setups):

    Warning: file_exists() [function.file-exists]: open_basedir restriction in effect. File(/tmp/9Z9Ngp) is not within the allowed path(s): (/home/www/web362/) in /home/www/web362/html/wordpress/wp-content/plugins/password-protect-wordpress-blog/lava/_classes/h2o/loaders.php on line 181

    Warning: realpath() [function.realpath]: open_basedir restriction in effect. File(/tmp) is not within the allowed path(s): (/home/www/web362/) in /home/www/web362/html/wordpress/wp-content/plugins/password-protect-wordpress-blog/lava/_classes/h2o/loaders.php on line 190

    Warning: file_put_contents(/h2o_0568baaca511328a453079f08744fa99) [function.file-put-contents]: failed to open stream: Permission denied in /home/www/web362/html/wordpress/wp-content/plugins/password-protect-wordpress-blog/lava/_classes/h2o/loaders.php on line 208

    Is there a way to disable the cache or tell it to store it somewhere else rather than a temp directory (which it doesn't have the permission to create). I see that cache_dir is a option but I can't see how I can pass an options array without changing your code. The function which creates and returns the file loader only takes one parameter - maybe this needs to be changed to support a second parameter ($options - which would default to a blank array).

    i18n blocktrans can not handle quotes

    I noticed that the text in blocktrans is not being properly handled due to excessive escaping.

    To reproduce the problem:

    the template file:

    {% blocktrans %}Didn't get it? <a id="resend" href="#">Resend</a> now{% endblocktrans %}
    {%blocktrans %}Reply with "{{ keyword }}" to {{ code }}{% endblocktrans %}
    

    the .mo file result:

    msgid "Didn't get it? <a id=\\\"resend\\\" href=\\\"#\\\">Resend</a> now"
    msgstr "¿No lo ha recibido? <a id=\"resend\" href=\"#\">Reenvíelo</a> ahora"
    
    msgid "Reply with \\\"%(keyword)\\\" to %(code)"
    msgstr "¡Envíe un SMS con \"%(keyword)\"  al %(code) para confirmar!"
    

    This causes the translation string to be untraceable for replacing in the original template when the page is rendered.

    With block does not work

    The with block does not seem to work.

    e.g. {% with form as f %}{% debug %}{% endwith %} produces an empty structure, while {{ form.url }} does work.

    for-tag does not keep array indexes

    Hi,
    when iterating over an array, the indexes are not kept:

    $someArray = array(3=>"Three", 1=>'One',0=>'Zero Mostel', 2=>'Two');
    

    If you're now iterating the array like this:

    {% for key,value in someArray %}
    {{key}}: {{value}}<br />
    {% endfor %}
    

    you get the following:

    0: Three
    1: One
    2: Zero Mostel
    3: Two
    

    while this is expected:

    3: Three
    1: One
    0: Zero Mostel
    2: Two
    

    Maybe using sort() instead of asort() somewhere?

    Basic HTML & Text breaking h2o templates

    I've been using h2o templates to build up a website. However, I have been building the page normally as I would do and just putting in a terms and conditions page which has a lot of text and basic html characters etc...

    However, when I reach a certain number of characters it breaks with the error logs stating

    Unclose tag, expecting endblock --- Triggered from /var/www/public_html/config/lib/h2o/parser.php:98

    If I reduce the text of the file back down it works, does anyone have any ideas of what is going on and how we can fix this issue.

    Internationalized templates example (i18n in general)

    When I try to run the i18n example (/h2o/example/i18n/) I get a whole bunch of Strict Standards errors:

    Strict Standards: Non-static method H2o_I18n::gettext() cannot be called statically in /h2o/h2o.php on line 227
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Only variables should be passed by reference in /h2o/ext/i18n.php on line 331
    Strict Standards: Non-static method H2o::getOptions() should not be called statically in /h2o/ext/i18n.php on line 361
    Strict Standards: Non-static method H2o::getOptions() should not be called statically in /h2o/ext/i18n.php on line 361
    Strict Standards: Non-static method H2o::getOptions() should not be called statically in /h2o/ext/i18n.php on line 361
    Strict Standards: Non-static method H2o_I18n::gettext() cannot be called statically in /h2o/h2o/context.php on line 199
    Strict Standards: Non-static method H2o_I18n::gettext() cannot be called statically in /h2o/h2o/context.php on line 199

    And of course the example doesn't work.

    *.mo files do get generated though.

    PHP version: 5.2.10

    For_Tag creates notice when using list()

    The following piece of code creates a notice if there is was no limit or reversed value matched. This is kind of sloppy, and is causing me trouble because it throws an ErrorException in my code.

    class For_Tag

    @list(,$this->key, $this->item, $this->iteratable, $this->limit, $this->reversed) = $match;
    

    For a quick fix I just pushed two false values onto $match before this line is called. But perhaps you could use named subpatterns with the preg_match, then do:

    if (isset($match["limit"]))
        $this->limit = (int) $match["limit"];
    else
        $this->limit = 0;
    

    Recommend Projects

    • React photo React

      A declarative, efficient, and flexible JavaScript library for building user interfaces.

    • Vue.js photo Vue.js

      🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

    • Typescript photo Typescript

      TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

    • TensorFlow photo TensorFlow

      An Open Source Machine Learning Framework for Everyone

    • Django photo Django

      The Web framework for perfectionists with deadlines.

    • D3 photo D3

      Bring data to life with SVG, Canvas and HTML. 📊📈🎉

    Recommend Topics

    • javascript

      JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

    • web

      Some thing interesting about web. New door for the world.

    • server

      A server is a program made to process requests and deliver data to clients.

    • Machine learning

      Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

    • Game

      Some thing interesting about game, make everyone happy.

    Recommend Org

    • Facebook photo Facebook

      We are working to build community through open source technology. NB: members must have two-factor auth.

    • Microsoft photo Microsoft

      Open source projects and samples from Microsoft.

    • Google photo Google

      Google ❤️ Open Source for everyone.

    • D3 photo D3

      Data-Driven Documents codes.