JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
sections are shown if value is set, more &refs
[wfpl.git] / template.php
index 85132c3..9a512a6 100644 (file)
@@ -53,7 +53,7 @@ function template_file($filename, $data) {
        return fill_template(parse_template_file($filename), $data);
 }
 
-function parse_template_file($filename) {
+function &parse_template_file($filename) {
        return parse_template(file_get_contents($filename));
 }
 
@@ -61,11 +61,10 @@ function parse_template_file($filename) {
 # A template is a hash with a name string, a pieces array, and possibly 
 # an args array.
 
-function parse_template($string) {
+function &parse_template($string) {
        $tem =& tem_push();
        $tem['pieces'] = array();
-       # note: for some reason this captures '<!--' but not '-->'.
-       $matches = preg_split("/(<!--)?(~[^~]*~)(?(1)-->)/", $string, -1, PREG_SPLIT_DELIM_CAPTURE);
+       $matches = preg_split('/(<!--)?(~[^~]*~)(?(1)-->)/', preg_replace('/<!--(~[^~]*~)-->/', '$1', $string), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
        foreach($matches as $match) {
                if($match == '~~') $match = '~';
                if(substr($match,0,1) == '~' and strlen($match) > 2) {
@@ -91,7 +90,7 @@ function parse_template($string) {
                        } else {  # value slot
                                $tem['pieces'][] = array('name' => $name, 'args' => $args);
                        }
-               } elseif($match and $match != '<!--') {  # static string
+               } else {  # static string
                        $tem['pieces'][] = $match;
                }
        }
@@ -164,7 +163,7 @@ function tem_data_as_rows($value) {
                if(array_key_exists(0, $value)) return $value;
                # key/value pairs -- expand sub-template once.
                else return array($value);
-       } elseif($value) {
+       } elseif($value || $value === 0 || $value === '0' || $value === '') {
                # value -- expand sub-template once using only parent values
                return array(array());
        } else {
@@ -234,10 +233,14 @@ function tem_encoded_data($tag, $context)
 }
 
 
-function is_sub_template($piece) {
+function is_sub_template(&$piece) {
        return is_array($piece) and $piece['pieces'];
 }
 
+function is_value_slot(&$piece) {
+       return is_array($piece) and !$piece['pieces'];
+}
+
 # Return a hash containing the top-level sub-templates of tem.
 function top_sub_templates($tem, $is_sub = 'is_sub_template') {
        function_exists($is_sub) or die("no such function '$is_sub'.");
@@ -250,22 +253,33 @@ function top_sub_templates($tem, $is_sub = 'is_sub_template') {
        return $subs;
 }
 
-# Replace top-level values in $main with top-level templates from $tem.
-function merge_templates($main, $tem) {
-       $out = array('name' => $main['name'], 'pieces' => array());
-
-       $subs = top_sub_templates($tem);
-
-       foreach($main['pieces'] as $piece) {
-               $sub = $subs[$piece['name']];
-               if(is_array($piece) and !$piece['pieces'] and $sub and $sub['args'][0] != 'hide') {
-                       $piece = $subs[$piece['name']];
+# merge $subs (sub_templates) into variables in $main (template)
+function merge_sub_templates(&$main, &$subs) {
+       foreach($main['pieces'] as &$piece) {
+               if(is_array($piece)) { # not just text
+                       if($piece['pieces']) {
+                               # a sub-template in main
+                               merge_sub_templates($piece, $subs);
+                       } else {
+                               # a value-slot in main
+                               $sub = $subs[$piece['name']];
+                               if($sub and $sub['args'][0] != 'hide') {
+                                       $piece = $subs[$piece['name']];
+                                       $piece['parent'] =& $main;
+                               }
+                       }
                }
-               $out['pieces'][] = $piece;
        }
        return $out;
 }
 
+# Replace values in $main with top-level templates from $tem.
+function merge_templates(&$main, &$tem) {
+       $subs = top_sub_templates($tem);
+
+       merge_sub_templates($main, $subs);
+}
+
 
 
 # tem_auto functions
@@ -303,11 +317,11 @@ function tem_auto_first(&$value, $key, $context) {
                return $value = true;  # show once
 }
 
-# 'show' sections will be shown unless the corresponding data value
-# is false (only false, not 0 or '' or array()).
+# 'show' sections will be shown unless the corresponding data
+# value === false
 
 function tem_auto_show(&$value) {
-       if($value !== false) $value = array(array());
+       if($value === null) $value = array(array());
        return $value;
 }
 
@@ -410,11 +424,11 @@ class tem {
        }
 
        function load_str($str) {
-               $this->template = parse_template($str);
+               $this->template =& parse_template($str);
        }
 
        function load($filename) {
-               $this->template = parse_template_file($filename);
+               $this->template =& parse_template_file($filename);
        }
 
        function run($tem = false) {
@@ -443,7 +457,14 @@ class tem {
 
                # merge the data arrays and template trees (new style)
                $this->data = array_merge($this->data, $tem->data);
-               $this->template = merge_templates($this->template, $tem->template);
+               merge_templates($this->template, $tem->template);
+       }
+
+       # see merge() above
+       function merge_file($filename) {
+               $other_tem = new tem();
+               $other_tem->load($filename);
+               $this->merge($other_tem);
        }
 
        function top_sub_names($is_sub = 'is_sub_template') {
@@ -511,6 +532,16 @@ function tem_load($filename) {
        $GLOBALS['wfpl_template']->load($filename);
 }
 
+function tem_merge($tem) {
+       tem_init();
+       $GLOBALS['wfpl_template']->merge($tem);
+}
+
+function tem_merge_file($filename) {
+       tem_init();
+       $GLOBALS['wfpl_template']->merge_file($filename);
+}
+
 function tem_output($filename = false) {
        tem_init();
        $GLOBALS['wfpl_template']->output($filename);