<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>apps/chippino/template/chip/node/redirect.php</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -43,7 +43,7 @@ class ChipComponent_PXHTMLNode extends PXHTMLNode {
                     $value = '&quot;'.$result[$key].'&quot;';
                 break;
                 case 'url':
-                    $value = '&quot;'.$this-&gt;route['segments'][$key].'&quot;';
+                    $value = '&quot;'.(isset($this-&gt;route['segments'][$key]) ? $this-&gt;route['segments'][$key] : '').'&quot;';
                 break;
                 case 'local':
                 default:</diff>
      <filename>apps/chippino/template/chip/node/component.php</filename>
    </modified>
    <modified>
      <diff>@@ -9,18 +9,31 @@ class TalCondition_PXHTMLNode extends PXHTMLNode {
         $attr = $node-&gt;getAttribute('tal:condition');
         $attr = str_replace(';;', ';', $attr);
         
-        $terms = preg_split('/(([\s]+and[\s]+)|([\s]+or[\s]+))/', $attr, -1, PREG_SPLIT_OFFSET_CAPTURE);
+        $conditionals = array(
+            ' lt '   =&gt; ' &lt; ',
+            ' gt '   =&gt; ' &gt; ',
+            ' or '   =&gt; ' ) || ( ',
+            ' and '  =&gt; ' ) &amp;&amp; ( ',
+            ' eq '   =&gt; ' == ',
+            ' ne '   =&gt; ' != ',
+            ' lte '  =&gt; ' &lt;= ',
+            ' gte '  =&gt; ' &gt;= ',
+        );
+        
+        $terms = preg_split('/([\s]+(and|or|lt|gt|eq|ne|lte|gte)[\s]+)/', $attr, -1, PREG_SPLIT_OFFSET_CAPTURE);
 
         $ifs = array();
         $endphps = array();
         $phps = array();
+        
+        $ifs[] = '('; // start an opening ( for grouping
         foreach ($terms as $idx =&gt; $term_info) {
             $term = $term_info[0];
             $pos = $term_info[1];
             
             // check for &quot;not&quot;. If found, wrap the segment in a not execution
             $not = FALSE;
-            if (stripos($attr, 'not:') === 0) {
+            if (stripos($attr, 'not ') === 0) {
                 $attr = trim(substr($attr, 4));
                 $not = TRUE;
             }
@@ -29,32 +42,52 @@ class TalCondition_PXHTMLNode extends PXHTMLNode {
             
             $str = 'try {';
             if ($not) {
-                $str .= $this-&gt;processTales($term, $c.' = (%s) ? FALSE : TRUE;', TRUE);
+                $str .= $this-&gt;processTales($term, $c.' = (%s);');
             }
             else {
-                $str .= $this-&gt;processTales($term, $c.' = (%s) ? TRUE : FALSE;', TRUE);
+                $str .= $this-&gt;processTales($term, $c.' = (%s);');
             }
             $str .= '} catch (Exception $e) { '.$c.' = FALSE; }';
             $phps[] = $str;
             $endphps[] = 'unset('.$c.');';
-
-            // get the closest occurance of &quot;and&quot; or &quot;or&quot;
-            $and_pos = strrpos(substr($attr, 0, $pos), ' and ');
-            $or_pos = strrpos(substr($attr, 0, $pos), ' or ');
             
-            if ($and_pos &lt; $or_pos &amp;&amp; $pos &gt; 0) { // if &quot;or&quot; is after &quot;and&quot;
-                $ifs[] = ' || '.$c;
+            $pos_list = array();
+            foreach (array_keys($conditionals) as $term) {
+                $place = strpos($attr, $term, $pos);
+                if ($place !== FALSE) {
+                    $pos_list[$term] = $place;
+                }
+            }
+            
+            asort($pos_list);
+            
+            // take the first item off the sorted stack
+            $if_key = NULL;
+            foreach ($pos_list as $pos_name =&gt; $pos_value) {
+                $if_key = $pos_name;
+                break;
+            }
+            
+            if ($not) {
+                $ifs[] = '!(';
             }
-            elseif ($or_pos &lt; $and_pos &amp;&amp; $pos &gt; 0) { // if &quot;and&quot; is after &quot;or&quot;
-                $ifs[] = ' &amp;&amp; '.$c;
+            
+            $ifs[] = $c;
+            
+            if ($not) {
+                $ifs[] = ')';
             }
-            else { // neither &quot;and&quot; nor &quot;or&quot;
-                $ifs[] = $c;
+            
+            if ($if_key !== NULL) {
+                $ifs[] = $conditionals[$if_key]; 
             }
         }
         
+        $ifs[] = ')'; // closing ) for the stack
+        
         $statement_begin = implode('', array(
             implode('', $phps),
+            // 'var_dump('.implode(');var_dump(',$cs).');',
             'if ('.implode($ifs).') {',
         ));
         </diff>
      <filename>apps/chippino/template/classes/node/tal/condition.php</filename>
    </modified>
    <modified>
      <diff>@@ -21,12 +21,12 @@ class TalDefine_PXHTMLNode extends PXHTMLNode {
             
             // are the first 5 words local? if not, global
             $local = FALSE;
-            if (strpos($attr, 'local') === 0) {
-                $attr = trim(substr($attr, 5));
+            if (strpos($attr, 'local ') === 0) {
+                $attr = trim(substr($attr, 6));
                 $local = TRUE;
             }
-            elseif (strpos($attr, 'global') === 0) {
-                $attr = trim(substr($attr, 6));
+            elseif (strpos($attr, 'global ') === 0) {
+                $attr = trim(substr($attr, 7));
             }
         
             list($var, $as) = explode(' ', $attr, 2);</diff>
      <filename>apps/chippino/template/classes/node/tal/define.php</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,7 @@ class PXHTMLTales {
         return $obj;
     }
     
-    public function process($segments, $stmt, $enable_conditionals = FALSE) {
+    public function process($segments, $stmt) {
         $segments = explode('|', $segments);
         $statements = array();
         foreach ($segments as $segment) {
@@ -32,22 +32,6 @@ class PXHTMLTales {
                 continue;
             }
             
-            // covert conditional statements with a space on either side
-            if ($enable_conditionals) {
-                $conds = array(
-                    ' lt '   =&gt; ' &lt; ',
-                    ' gt '   =&gt; ' &gt; ',
-                    ' or '   =&gt; ' || ',
-                    ' and '  =&gt; ' &amp;&amp; ',
-                    ' eq '   =&gt; ' == ',
-                    ' ne '   =&gt; ' != ',
-                    ' lte '  =&gt; ' &lt;= ',
-                    ' gte '  =&gt; ' &gt;= ',
-                );
-            
-                $segment = str_replace(array_keys($conds), array_values($conds), $segment);
-            }
-            
             $handlers = self::cfg()-&gt;getTalesHandlers();
             $handled = FALSE;
             foreach ($handlers as $handler =&gt; $obj) {
@@ -73,7 +57,7 @@ class PXHTMLTales {
             $output .= 'try { '.$statement.' } catch(Exception $e) {';
             $output_sfx .= '}';
             if ($idx == count($statements) - 1) {
-                $output .= 'throw new Exception(&quot;unresolvable paths: '.implode(' | ', $segments).'&quot;);';
+                $output .= 'throw new Exception(&quot;unresolvable paths: '.implode(' | ', str_replace('$', '$$', $segments)).'&quot;);';
             }
         }
         </diff>
      <filename>apps/chippino/template/classes/tales/tales.php</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,12 @@ class PXHTMLTemplateContext {
     }
     
     public function setRoot($key, $value) {
-        $this-&gt;stack[count($this-&gt;stack) - 1][$key] = $value;
+        if (count($this-&gt;stack)) {
+            $this-&gt;stack[count($this-&gt;stack) - 1][$key] = $value;
+        }
+        else {
+            $this-&gt;stack[0][$key] = $value; // first thing on stack
+        }
     }
     
     public function delete($key) {
@@ -37,7 +42,8 @@ class PXHTMLTemplateContext {
         }
         
         if ($base_obj === NULL &amp;&amp; count($pieces) === 0) {
-            return '';
+            throw new Exception('unseekable path');         
+            return ''; // empty top level variable
         }
         
         if ($base_obj === NULL) {</diff>
      <filename>apps/chippino/template/classes/template/context.php</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,8 @@ class PXHTMLTemplatePhpHelper {
     }
     
     protected function resolveCtxDeclarations($string) {
+        $string = str_replace('$$', '__DBLDOLLAR__', $string);
+        
         preg_match_all('/\$\{(.*?)\}/', $string, $matches);
 
         if (!$matches[0]) {
@@ -20,30 +22,34 @@ class PXHTMLTemplatePhpHelper {
         // like a TALES expression
         foreach ($matches[1] as $idx =&gt; $attr) {
             $c = $this-&gt;createLocalVariable();
-
-            if (strpos($attr, ' ') === FALSE) {
-                $str = PXHTMLTales::getInstance()-&gt;process($attr, $c.' = %s;');
-                $php_inst = '&lt;'.'?php '.$str.'echo htmlspecialchars('.$c.'); unset('.$c.');'.'?'.'&gt;';
+            
+            $structure = FALSE;
+            $dump = FALSE;
+            if (strpos($attr, 'structure ') === 0) {
+                $attr = trim(substr($attr, 10));
+                $structure = TRUE;
+            }
+            if (strpos($attr, 'dump ') === 0) {
+                $attr = trim(substr($attr, 5));
+                $dump = TRUE;
+            }
+            
+            $str = PXHTMLTales::getInstance()-&gt;process($attr, $c.' = %s;');
+            
+            if ($structure) {
+                $php_inst = '&lt;'.'?php '.$str.'echo '.$c.'; unset('.$c.');'.'?'.'&gt;';
+            }
+            elseif ($dump) {
+                $php_inst = '&lt;'.'?php '.$str.'var_dump('.$c.'); unset('.$c.');'.'?'.'&gt;';
             }
             else {
-                list($type, $attr) = explode(' ', $attr, 2);
-                if (strtolower($type) === 'structure') {
-                    $str = PXHTMLTales::getInstance()-&gt;process($attr, $c.' = %s;');
-                    $php_inst = '&lt;'.'?php '.$str.'echo '.$c.'; unset('.$c.');'.'?'.'&gt;';
-                }
-                elseif (strtolower($type) === 'dump') {
-                    $str = PXHTMLTales::getInstance()-&gt;process($attr, $c.' = %s;');
-                    $php_inst = '&lt;'.'?php '.$str.'var_dump('.$c.'); unset('.$c.');'.'?'.'&gt;';
-                }
-                else {
-                    throw new Exception ('unknown type for ${...}');
-                }
+                $php_inst = '&lt;'.'?php '.$str.'echo htmlspecialchars('.$c.'); unset('.$c.');'.'?'.'&gt;';
             }
             
             $replaces[$matches[0][$idx]] = $php_inst;
         }
 
-        return str_replace(array_keys($replaces), array_values($replaces), $string);
+        return str_replace('__DBLDOLLAR__', '$', str_replace(array_keys($replaces), array_values($replaces), $string));
     }
     
     public function createLocalVariable() {</diff>
      <filename>apps/chippino/template/classes/template/phphelper.php</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,7 @@ if (!class_exists('PXHTML')) {
     chip('#Chippino/Template/Chip/Node/Include')-&gt;with();
     chip('#Chippino/Template/Chip/Node/Inspect')-&gt;with();
     chip('#Chippino/Template/Chip/Node/Header')-&gt;with();
+    chip('#Chippino/Template/Chip/Node/Redirect')-&gt;with();
     
     chip('#Chippino/Template/Chip/Expr/Url')-&gt;with();
 }
@@ -34,7 +35,9 @@ if (file_exists($cache_file)) {
 $content = PXHTML::parse($file, $doctype);
 file_put_contents('/tmp/'.$chk.'.php', $content);
 
+ob_start();
 include '/tmp/'.$chk.'.php';
+ob_end_flush();
 // var_dump($content);
 exit;
 </diff>
      <filename>apps/chippino/template/init.php</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c04c030164f0b70ff58e9a6b43b27799ebf98bbc</id>
    </parent>
  </parents>
  <author>
    <name>Jakob Heuser</name>
    <email>jakob@felocity.org</email>
  </author>
  <url>http://github.com/Jakobo/chippino/commit/690a83a18530ff2d446df46b0a384853e3f7d99a</url>
  <id>690a83a18530ff2d446df46b0a384853e3f7d99a</id>
  <committed-date>2009-05-21T12:03:03-07:00</committed-date>
  <authored-date>2009-05-21T12:03:03-07:00</authored-date>
  <message>redirect support, and a few bug fixes discovered regarding define</message>
  <tree>ebaebb9405fc639ea565f56d3aee2c806411eb8c</tree>
  <committer>
    <name>Jakob Heuser</name>
    <email>jakob@felocity.org</email>
  </committer>
</commit>
