<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>specs/runner.php</filename>
    </added>
    <added>
      <filename>specs/templates/emails/base.html</filename>
    </added>
    <added>
      <filename>specs/templates/emails/campaign1.html</filename>
    </added>
    <added>
      <filename>specs/templates/emails/campaign2.html</filename>
    </added>
    <added>
      <filename>specs/templates/emails/campaign3.html</filename>
    </added>
    <added>
      <filename>specs/templates/shared/terms_and_conditions.html</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -14,12 +14,26 @@ H2O is markup language for PHP that taken a lot of inspiration from django.
  * Bundled rich set of filters and tags for string formatting, HTML helpers and 
    internationalization. 
 
+
 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 pasing
+
 Getting started
 ------------------------
 
@@ -66,7 +80,7 @@ With SVN
 
     &lt;?php
         require 'h2o/h2o.php';
-        $h2o = new h2o('index.html');
+        $h2o = new h2o('templates/index.html');
         echo $h2o-&gt;render(array('name'=&gt;'Peter Jackson'));
     ?&gt;
 </diff>
      <filename>README.md</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,6 @@
 require '../../h2o.php';
 
 $template = new H2o('index.html', array(
-    'cache' =&gt; false,
     'cache_dir' =&gt; dirname(__FILE__)
 ));
 </diff>
      <filename>example/simple/index.php</filename>
    </modified>
    <modified>
      <diff>@@ -34,7 +34,8 @@ class H2o {
             'cache_prefix'      =&gt;      'h2o_',
             'cache_ttl'         =&gt;      3600,     // file | apc | memcache
             'searchpath'        =&gt;      false,
-  
+            'autoescape'        =&gt;      true,
+        
             // Enviroment setting
             'BLOCK_START'       =&gt;      '{%',
             'BLOCK_END'         =&gt;      '%}',
@@ -66,7 +67,7 @@ class H2o {
                 $this-&gt;searchpath = realpath($options['searchpath']).DS;
             else
                 $this-&gt;searchpath = dirname(realpath($file)).DS;
-            $this-&gt;loader = new $loaderClass($this-&gt;searchpath, $this-&gt;options);
+            $this-&gt;loader = new $loaderClass($this-&gt;searchpath, $this-&gt;options);        
         }
         
         if (isset($options['i18n'])) {
@@ -134,8 +135,8 @@ class H2o {
         return $this-&gt;stream-&gt;close();
     }
 
-    static function parseString($source) {
-        $instance = new H2o(null, array('loader' =&gt; false));
+    static function parseString($source, $options = array()) {
+        $instance = new H2o(null, array_merge($options, array('loader' =&gt; false)));
         $instance-&gt;nodelist = $instance-&gt;parse($source);
         return $instance;
     }
@@ -253,9 +254,9 @@ function h2o($name, $options = array()) {
     $is_file = '/([^\s]*?)(\.[^.\s]*$)/';
     
     if (!preg_match($is_file, $name)) {
-        return H2o::parseString($name); 
+        return H2o::parseString($name, $options); 
     }
-    
+
     $instance = new H2o($name, $options);
     return $instance;
 }</diff>
      <filename>h2o.php</filename>
    </modified>
    <modified>
      <diff>@@ -5,10 +5,11 @@
  *  encapsulate context, resolve name
  */
 class H2o_Context implements ArrayAccess {
-    var $safeClass = array('stdClass', 'BlockContext');
-    var $scopes;
-    var $options;
-    var $autoescape = true;
+    public $safeClass = array('stdClass', 'BlockContext');
+    public $scopes;
+    public $options;
+    public $autoescape = true;
+    
     private $arrayMethods = array('first'=&gt; 0, 'last'=&gt; 1, 'length'=&gt; 2, 'size'=&gt; 3);
     static $lookupTable = array();
     
@@ -20,6 +21,9 @@ class H2o_Context implements ArrayAccess {
         if (isset($options['safeClass'])) 
             $this-&gt;safeClass = array_merge($this-&gt;safeClass, $options['safeClass']);
             
+        if (isset($options['autoescape'])) 
+            $this-&gt;autoescape = $options['autoescape'];
+            
         $this-&gt;options = $options;
     }
 </diff>
      <filename>h2o/context.php</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,4 @@
 &lt;?php
-
 /**
  * 
  * @author taylor.luk
@@ -7,21 +6,21 @@
  */
 class H2o_Loader {
     public $parser;
+    public $runtime;
+    public $cached = false;
+    private $cache = false;
+    public $searchpath = false;
+    
     function read($filename) {}
     function cache_read($file, $object, $ttl = 3600) {}
 }
 
 class H2o_File_Loader extends H2o_Loader {
-    public $parser;
-    public $runtime;
-    private $cache = false;
-    public $searchpath;
-    
+
     function __construct($searchpath, $options = array()) {
         if (is_file($searchpath)) {
             $searthpath = dirname($searchpath).DS;
         }
-        
         if (!is_dir($searchpath))
             throw new TemplateNotFound($filename);
 
@@ -36,28 +35,30 @@ class H2o_File_Loader extends H2o_Loader {
     }
     
     function read($filename) {
-        
-       if (!file_exists($filename))
-        $filename = $this-&gt;searchpath . $filename;
-       
-       if (!file_exists($filename))
-           throw new TemplateNotFound($filename);
+        if (!is_file($filename))
+            $filename = $this-&gt;searchpath . $filename;
 
-       $source = file_get_contents($filename);
-       return $this-&gt;runtime-&gt;parse($source);
+        if (is_file($filename)) {
+            $source = file_get_contents($filename);
+            return $this-&gt;runtime-&gt;parse($source);
+        } else {
+            throw new TemplateNotFound($filename);
+        }
     }
 
     function read_cache($filename) {
         if (!$this-&gt;cache)
              return $this-&gt;read($filename);
+
         if (!is_file($filename))
-            $file_path = $this-&gt;searchpath . $filename;
+            $filename = $this-&gt;searchpath . $filename;
+
         $filename = realpath($filename);
-        
         $cache = md5($filename);
         $object = $this-&gt;cache-&gt;read($cache);
+        $this-&gt;cached = $object &amp;&amp; !$this-&gt;expired($object);
         
-        if (!$object || $object &amp;&amp; $this-&gt;expired($object)) {
+        if (!$this-&gt;cached) {
             $nodelist = $this-&gt;read($filename);
             $object = (object) array(
                 'filename' =&gt; $filename,
@@ -69,7 +70,7 @@ class H2o_File_Loader extends H2o_Loader {
             $this-&gt;cache-&gt;write($cache, $object);
         } else {
             foreach($object-&gt;included as $ext =&gt; $file) {
-                include_once(h2o::$extensions[$ext] = $file);
+                include_once (h2o::$extensions[$ext] = $file);
             }
         }
         return unserialize($object-&gt;content);
@@ -80,9 +81,14 @@ class H2o_File_Loader extends H2o_Loader {
     }
 
     function expired($object) {
+        if (!$object) return false;
+        
         $files = array_merge(array($object-&gt;filename), $object-&gt;templates);
         foreach ($files as $file) {
-            if (filemtime($this-&gt;searchpath.$file) &gt; $object-&gt;created)
+            if (!is_file($file))
+                $file = $this-&gt;searchpath.$file;
+            
+            if ($object-&gt;created &lt; filemtime($file))
                 return true;
         }
         return false;
@@ -94,10 +100,7 @@ function file_loader($file) {
 }
 
 class H2o_Hash_Loader {
-    public $parser;
-    public $runtime;
-    public $searchpath = false;
-    
+
     function __construct($scope, $options = array()) {
         $this-&gt;scope = $scope;
     }
@@ -119,12 +122,10 @@ function hash_loader($hash = array()) {
     return new H2o_Hash_Loader($hash);
 }
 
-
 /**
  * Cache subsystem
  *
  */
-
 function h2o_cache($options = array()) {
     $type = $options['cache'];
     $className = &quot;H2o_&quot;.ucwords($type).&quot;_Cache&quot;;
@@ -144,9 +145,9 @@ class H2o_File_Cache {
             $path = $options['cache_dir'];
         } else {
             $path = dirname($tmp = tempnam(uniqid(rand(), true), ''));
+
             if (file_exists($tmp)) unlink($tmp);
         }
-        
         if (isset($options['cache_ttl'])) {
             $this-&gt;ttl = $options['cache_ttl'];
         }</diff>
      <filename>h2o/loaders.php</filename>
    </modified>
    <modified>
      <diff>@@ -40,7 +40,7 @@ class NodeList extends H2o_Node implements IteratorAggregate  {
         return count($this-&gt;list);
     }
     
-    public function getIterator() {
+    function getIterator() {
         return new ArrayIterator( $this-&gt;list );
     }
 }</diff>
      <filename>h2o/nodes.php</filename>
    </modified>
    <modified>
      <diff>@@ -79,6 +79,13 @@ class Describe_context_lookup_basic_data_types extends SimpleSpec {
         expects(h2o('{{ a }}')-&gt;render($c))-&gt;should_be('&amp;lt;script&amp;gt;danger&amp;lt;/script&amp;gt;');
         expects(h2o('{{ b|safe }}')-&gt;render($c))-&gt;should_be('&lt;h1&gt;Welcome&lt;/h1&gt;');
         
+        # disable autoescape as option
+        expects(h2o('{{ a }}', array('autoescape' =&gt; false))-&gt;render(compact('a','b')))-&gt;should_be($a);
+        
+        # disable autoescape on context object
+        $c-&gt;autoescape = false;
+        expects(h2o('{{ a }}')-&gt;render($c))-&gt;should_be($a);
+        
     }
 }
 </diff>
      <filename>specs/context_spec.php</filename>
    </modified>
    <modified>
      <diff>@@ -2,18 +2,67 @@
 require_once 'spec_helper.php';
 
 class Describe_file_loader extends SimpleSpec {
-    function prepare() {
+
+    function should_be_able_to_read_template() {
+        chdir(dirname(__FILE__));
+        
+        $h2o = h2o('templates/a.html');
+        expects($h2o-&gt;nodelist)-&gt;should_be_a('Nodelist');
+        
+        $h2o = h2o('templates/b.html');
+        expects($h2o-&gt;nodelist)-&gt;should_be_a('Nodelist');
+        
+        $h2o = h2o('templates/emails/base.html');
+        expects($h2o-&gt;nodelist)-&gt;should_be_a('Nodelist');
     }
     
-    function should_be_able_to_read_template() {}
+    function should_read_from_alternitive_working_path() {
+        $h2o = h2o('emails/base.html', array(
+            'searchpath' =&gt; dirname(__FILE__).DS.'templates'
+        ));
+        expects($h2o-&gt;render())-&gt;should_match('/Dear Customer/');
+    }
     
-    function should_load_subtemplate_upon_extends_tag() {}
+    function should_load_subtemplate_upon_extends_tag() {
+        $h2o = h2o('emails/campaign1.html', array(
+            'searchpath' =&gt; dirname(__FILE__).DS.'templates'
+        ));
+        expects($h2o-&gt;render())-&gt;should_match('/Dear Customer/');
+
+        $h2o-&gt;loadTemplate('emails/campaign2.html');
+        expects($h2o-&gt;render())-&gt;should_match('/Hello Customer/');
+    }
     
-    function should_load_subtemplate_upon_include_tag() {}
+    function should_load_subtemplate_upon_include_tag() {
+        $h2o = h2o('emails/campaign3.html', array(
+            'searchpath' =&gt; dirname(__FILE__).DS.'templates'
+        ));
+        expects($h2o-&gt;render())-&gt;should_match('/abcWidgets Logo are registered trademarks/');
+    }
     
-    function shouble_cache_main_template() {}
+    function shouble_cache_main_template() {
+        $h2o = h2o('templates/a.html', array('cache' =&gt; false));
+        expects($h2o-&gt;cached)-&gt;should_be(false);
+        
+        $h2o = h2o('template/a.html', array('cache'=&gt;true));
+        expects($h2o-&gt;cached)-&gt;should_be(true);
+    }
     
     function should_invalidate_cache_if_any_subtemplates_has_updated() {
+        $opt = array('searchpath' =&gt; dirname(__FILE__).DS.'templates');
+        
+        # Load template twice to make sure its cached
+        $h2o = h2o('emails/campaign1.html', $opt);
+        $h2o-&gt;loadTemplate('emails/campaign1.html');
+        expects($h2o-&gt;loader-&gt;cached)-&gt;should_be(true);
+        
+        # Touch parent template
+        sleep(1);
+        touch(dirname(__FILE__).DS.'templates/emails/base.html');
+
+        $h2o-&gt;loadTemplate('emails/campaign1.html');
+        expects($h2o-&gt;loader-&gt;cached)-&gt;should_be(false);
+        $h2o-&gt;loader-&gt;flush_cache();
     }
 }
 </diff>
      <filename>specs/loader_spec.php</filename>
    </modified>
    <modified>
      <diff>@@ -37,7 +37,7 @@
  * @license Free for all  
  */
 
-class SimpleSpec extends UnitTestCase implements ArrayAccess {
+class SimpleSpec extends UnitTestCase {
     public $target;
     private $negate;
     private $matcher;
@@ -139,17 +139,6 @@ function expects($subject) {
     return $object-&gt;expect($subject);
 }
 
-class SpecProxy {
-    function __construct($class) {
-        $this-&gt;object = new $class;
-    }
-    
-    function __call($method, $args) {
-        return user_call_func_array(array($this-&gt;object, $method), $args);
-    }
-}
-
-
 class Have_Matcher {
     function __construct($subject, $count, $runtime) {
         $this-&gt;subject = $subject;</diff>
      <filename>specs/spec.php</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,10 @@
 &lt;?php
+
 function_exists('simpletest_autorun') or require 'simpletest/autorun.php';
 class_exists('H2o') or require dirname(dirname(__FILE__)).'/h2o.php';
 class_exists('SimpleSpec') or require dirname(__FILE__).'/spec.php';
 
 require 'Krumo/class.krumo.php';
 
-function n($name) {
-    return array('name'=&gt;$name);
-}
 
 ?&gt;
\ No newline at end of file</diff>
      <filename>specs/spec_helper.php</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e8a4845e08bbe6e5680de620c2d84dcecdf51513</id>
    </parent>
  </parents>
  <author>
    <name>speedmax</name>
    <email>subjective@gmail.com</email>
  </author>
  <url>http://github.com/speedmax/h2o-php/commit/194310e970f98df15d82c281af06e7aa2218ad5c</url>
  <id>194310e970f98df15d82c281af06e7aa2218ad5c</id>
  <committed-date>2009-04-15T01:03:52-07:00</committed-date>
  <authored-date>2009-04-15T01:03:52-07:00</authored-date>
  <message>preparing for version 0.4 release
 - Improve searchpath and file loading when h2o is used on non current path, or customized searchpath
 - Improve test coverage on file loading
 - Adding autoescape as initialize option
 - Refactor cache invalidation</message>
  <tree>93304007070adde4ac848aee1fed11b0fc5f099c</tree>
  <committer>
    <name>speedmax</name>
    <email>subjective@gmail.com</email>
  </committer>
</commit>
