JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
silenced warning when evenodd called with no data
[wfpl.git] / template.php
index 7783a07..44db726 100644 (file)
@@ -234,12 +234,16 @@ function tem_encoded_data($tag, $context)
 }
 
 
+function is_sub_template($piece) {
+       return is_array($piece) and $piece['pieces'];
+}
 
 # Return a hash containing the top-level sub-templates of tem.
-function top_sub_templates($tem) {
+function top_sub_templates($tem, $is_sub = 'is_sub_template') {
+       function_exists($is_sub) or die("no such function '$is_sub'.");
        $subs = array();
        foreach($tem['pieces'] as $piece) {
-               if(is_array($piece) and $piece['pieces']) {
+               if($is_sub($piece)) {
                        $subs[$piece['name']] = $piece;
                }
        }
@@ -253,7 +257,8 @@ function merge_templates($main, $tem) {
        $subs = top_sub_templates($tem);
 
        foreach($main['pieces'] as $piece) {
-               if(is_array($piece) and !$piece['pieces'] and $subs[$piece['name']]) {
+               $sub = $subs[$piece['name']];
+               if(is_array($piece) and !$piece['pieces'] and $sub and $sub['args'][0] != 'hide') {
                        $piece = $subs[$piece['name']];
                }
                $out['pieces'][] = $piece;
@@ -274,7 +279,7 @@ function merge_templates($main, $tem) {
 #      <!--~rows {~-->
 #              <!--~row {~-->
 #                      row content...
-#                      <!--~separator sep {~--><hr><!--~}"-->
+#                      <!--~separator sep {~--><hr><!--~}~-->
 #              <!--~}~-->
 #      <!--~}~-->
 #
@@ -285,7 +290,7 @@ function tem_auto_sep(&$value, $key, $context) {
 }
 
 # 'show' sections will be shown unless the corresponding data value
-# is false.  We check only for false; 0 or '' will not work.
+# is false (only false, not 0 or '' or array()).
 
 function tem_auto_show(&$value) {
        if($value !== false) $value = array(array());
@@ -296,8 +301,8 @@ function tem_auto_show(&$value) {
 # alternates between 'even' and 'odd'.
 
 function tem_auto_evenodd(&$values) {
-       $even = false;
-       foreach($values as &$value) {
+       $even = true;
+       if($values) foreach($values as &$value) {
                $value['evenodd'] = $even ? 'even' : 'odd';
                $even = !$even;
        }
@@ -311,6 +316,14 @@ function tem_auto_evenodd(&$values) {
 # Backward Compatibility
 # ----------------------
 
+function is_shown($piece) {
+       return $piece['args'][0] == 'hide';
+}
+
+function is_shown_sub_template($piece) {
+       return is_sub_template($piece) and is_shown($piece);
+}
+
 # Old-style templates don't show unless explicitly requested.
 function tem_auto_hide(&$value, $key, $context) {
        unset($context['data'][$key]);
@@ -321,19 +334,22 @@ function tem_auto_hide(&$value, $key, $context) {
 # so hide it and insert a value slot for its expansion(s).
 function &tem_is_old_sub($name, &$template) {
        foreach($template['pieces'] as $key => &$piece) {
-               if(is_array($piece) and $piece['pieces']) {
+               if(is_sub_template($piece)) {
                        if($piece['name'] == $name) {
-                               if($piece['args'][0] != 'hide') {  # if we haven't already
+                               if(!is_shown($piece)) {
+                                       # hide template unless explicitly show()n.
                                        $piece['args'] = array('hide');
+                                       # insert a value slot with the same name (for the expansion).
                                        $var = array('name' => $name, 'args' => array());
                                        array_splice($template['pieces'], $key, 0, array($var));
                                }
                                return $piece;
                        }
-                       $tem = tem_old_sub($name, $piece);
+                       $tem = tem_is_old_sub($name, $piece);
                        if($tem) return $tem;
                }
        }
+       return false;
 }
 
 class tem {
@@ -341,7 +357,7 @@ class tem {
        var $data; 
 
        function tem() {
-               $this->template = array();
+               $this->template = array('pieces' => array());
                $this->data = array();
        }
        
@@ -367,7 +383,9 @@ class tem {
 
        function show($name) {
                $tem = tem_is_old_sub($name, $this->template);
-               $this->data[$name] .= fill_template($tem, $this->data);
+               if($tem) {
+                       $this->data[$name] .= fill_template($tem, $this->data);
+               }
        }
 
        function show_separated($name) {
@@ -398,13 +416,29 @@ class tem {
                print($this->run($tem));
        }
 
-       function top_sub_names() {
-               return array_keys(top_sub_templates($this->template));
+       # merge top-level sub-templates of $tem (object) into $this,
+       # supporting both new and old semantics.
+       function merge($tem) {
+               # append expansions to $this->data (old style)
+
+               $subs = $tem->top_subs('is_shown_sub_template');
+               if($subs) foreach($subs as $name => $val) {
+                       $this->append($name, $val);
+                       unset($tem->data[$name]);  # so array_merge() won't overwrite things
+               }
+
+               # 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);
+       }
+
+       function top_sub_names($is_sub = 'is_sub_template') {
+               return array_keys(top_sub_templates($this->template, $is_sub));
        }
 
-       function top_subs() {
+       function top_subs($is_sub = 'is_sub_template') {
                $ret = array();
-               $names = $this->top_sub_names();
+               $names = $this->top_sub_names($is_sub);
                foreach($names as $name) {
                        $ret[$name] = $this->get($name);
                }