[limb-svn] r6385 - in 3.x/trunk/limb/macro: src src/tags tests/cases tests/cases/tags

svn at limb-project.com svn at limb-project.com
Fri Oct 5 18:12:04 MSD 2007


Author: serega
Date: 2007-10-05 18:12:03 +0400 (Fri, 05 Oct 2007)
New Revision: 6385
URL: http://fisheye.limb-project.com/changelog/limb/?cs=6385

Added:
   3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php
   3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php
   3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php
   3.x/trunk/limb/macro/src/lmbMacroExpression.class.php
   3.x/trunk/limb/macro/src/lmbMacroExpressionInterface.interface.php
   3.x/trunk/limb/macro/src/lmbMacroOutputExpressionNode.class.php
   3.x/trunk/limb/macro/src/lmbMacroTagAttribute.class.php
   3.x/trunk/limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php
   3.x/trunk/limb/macro/tests/cases/lmbBaseMacroTest.class.php
   3.x/trunk/limb/macro/tests/cases/lmbMacroOutputExpressionTest.class.php
Removed:
   3.x/trunk/limb/macro/src/tags/output.tag.php
   3.x/trunk/limb/macro/tests/cases/tags/.setup.php
   3.x/trunk/limb/macro/tests/cases/tags/lmbBaseMacroTagTest.class.php
   3.x/trunk/limb/macro/tests/cases/tags/lmbMacroOutputTagTest.class.php
Modified:
   3.x/trunk/limb/macro/src/lmbMacroNode.class.php
   3.x/trunk/limb/macro/src/lmbMacroTag.class.php
   3.x/trunk/limb/macro/src/lmbMacroTagDictionary.class.php
   3.x/trunk/limb/macro/src/lmbMacroTagParsingState.class.php
   3.x/trunk/limb/macro/src/lmbMacroTreeBuilder.class.php
   3.x/trunk/limb/macro/src/tags/include.tag.php
   3.x/trunk/limb/macro/src/tags/into.tag.php
   3.x/trunk/limb/macro/src/tags/wrap.tag.php
   3.x/trunk/limb/macro/tests/cases/.setup.php
   3.x/trunk/limb/macro/tests/cases/lmbMacroTagAcceptanceTest.class.php
   3.x/trunk/limb/macro/tests/cases/lmbMacroTagDictionaryTest.class.php
   3.x/trunk/limb/macro/tests/cases/lmbMacroTagTest.class.php
   3.x/trunk/limb/macro/tests/cases/tags/lmbMacroIncludeTagTest.class.php
   3.x/trunk/limb/macro/tests/cases/tags/lmbMacroListTagTest.class.php
   3.x/trunk/limb/macro/tests/cases/tags/lmbMacroWrapTagTest.class.php
Log:
-- MACRO changes:
  * output expression syntax is now {$var} instead of {{$var}}
  * output.tag.php removed
  * output expressions now can be used as a part of the tags attirubutes. That also means what tag attributes are now objects. Use lmbMacroTag :: getEscaped($attribute_name) is you need to output tag value into compiled template.
  * minor refactoring in tests
  

Added: 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizer.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,82 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * class lmbMacroContentAnalizer.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroBlockAnalizer
+{
+  const BEFORE_CONTENT = 1;
+  const EXPRESSION = 2;
+  const AFTER_CONTENT = 4;
+
+  protected $regexp;
+
+  function __construct()
+  {
+    $this->regexp = $this->_getRegexp();
+  }
+
+  protected function _getRegexp()
+  {
+    $regexp =
+      // start at the beginning
+      '/^' .
+      // Pick up the portion of the string before the variable reference
+      '((?s).*?)' .
+      // Beginning of a variable reference
+      preg_quote('{$', '/') .
+      // Collect the entire variable reference into one subexpression
+      '(' .
+          // capture the contents of one or more fragments.
+          '(' .
+              // Anything thats not a quote or the end of the variable
+              // reference can be in a fragment
+              '[^"\'}]+' .
+          ')+' .
+      ')' .
+      // end of a variable reference
+      preg_quote('}', '/') .
+      // Pick up the portion of the string after the variable reference
+      // This portion may contain additional references; we only match
+      // one at a time.
+      '((?s).*)' .
+      // Match until the end of the string
+      '$/';
+
+    return $regexp;
+  }
+
+  function parse($text, $observer)
+  {
+    // if there is no expression (common case), shortcut this process
+    if (strpos($text, '{$') === FALSE)
+    {
+      $observer->addLiteralFragment($text);
+      return;
+    }
+
+    while (preg_match($this->regexp, $text, $match))
+    {
+      if (strlen($match[self :: BEFORE_CONTENT]) > 0)
+        $observer->addLiteralFragment($match[self :: BEFORE_CONTENT]);
+
+      $observer->addExpressionFragment('$' . $match[self :: EXPRESSION]);
+
+      $text = $match[self :: AFTER_CONTENT];
+    }
+
+    if (strlen($text) > 0)
+      $observer->addLiteralFragment($text);
+  }
+}
+

Added: 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroBlockAnalizerListener.interface.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,21 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * interface lmbMacroBlockAnalizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+interface lmbMacroBlockAnalizerListener
+{
+  function addLiteralFragment($text);
+  function addExpressionFragment($text);
+}
+

Added: 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,42 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/macro/src/lmbMacroBlockAnalizerListener.interface.php');
+lmb_require('limb/macro/src/lmbMacroOutputExpressionNode.class.php');
+lmb_require('limb/macro/src/lmbMacroExpression.class.php');
+
+/**
+ * class lmbMacroContentBlockAnalizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroContentBlockAnalizerListener implements lmbMacroBlockAnalizerListener
+{
+  protected $tree_builder;
+  protected $location;
+
+  function __construct($tree_builder, $location)
+  {
+    $this->tree_builder = $tree_builder;
+    $this->location = $location;
+  }
+
+  function addLiteralFragment($text)
+  {
+    $this->tree_builder->addTextNode($text);
+  }
+
+  function addExpressionFragment($text)
+  {
+    $expression = new lmbMacroExpression($text);
+    $output_expression = new lmbMacroOutputExpressionNode($this->location, $expression);
+    $this->tree_builder->addNode($output_expression);
+  }
+}
+

Added: 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroExpression.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,64 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+lmb_require('limb/macro/src/lmbMacroExpressionInterface.interface.php');
+
+/**
+ * class lmbMacroExpression
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroExpression implements lmbMacroExpressionInterface
+{
+  protected $tmp;
+
+  function __construct($expression_str)
+  {
+    $this->expression_str = $expression_str;
+  }
+
+  function preGenerate($code)
+  {
+    $this->tmp = $code->getTempVarRef();
+
+    // simple case if expression is just a variable
+    if(strpos($this->expression_str, '.') === false)
+    {
+      $this->tmp = $this->expression_str;
+      return;
+    }
+
+    $expr = '';
+    $items = explode('.', $this->expression_str);
+
+    //first item is variable itself
+    $var = $items[0];
+    $code->writePHP($this->tmp . "='';");
+    for($i=1; $i<sizeof($items); $i++)
+    {
+      $item = $items[$i];
+      $expr .= 'if((is_array(' . $var . ') && isset(' . $var . '["' . $item . '"])) || ' .
+               '(is_object(' . $var . ') && ' . $this->tmp . '=' . $var . '->get("' . $item . '")))' .
+               '{if(is_array(' . $var . '))' . $this->tmp . ' = ' . $var . '["' . $item . '"];';
+      $var = $this->tmp;
+    }
+
+    //closing brackets
+    for($i=1; $i < sizeof($items); $i++)
+      $expr .= '}else{' . $this->tmp . '="";}';
+
+    $code->writePHP($expr);
+  }
+
+  function getValue()
+  {
+    return $this->tmp;
+  }
+}
+

Added: 3.x/trunk/limb/macro/src/lmbMacroExpressionInterface.interface.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroExpressionInterface.interface.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroExpressionInterface.interface.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,20 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+/**
+ * interface lmbMacroExpressionInterface
+ * @package macro
+ * @version $Id$
+ */
+interface lmbMacroExpressionInterface
+{
+  function preGenerate($code);
+  function getValue();
+}
+

Modified: 3.x/trunk/limb/macro/src/lmbMacroNode.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroNode.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/lmbMacroNode.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 lmb_require('limb/macro/src/lmbMacroException.class.php');
 lmb_require('limb/macro/src/lmbMacroSourceLocation.class.php');
@@ -17,13 +17,13 @@
  */
 class lmbMacroNode
 {
-  protected $id;  
+  protected $id;
   protected $children = array();
-  protected $parent;  
+  protected $parent;
   /**
   * @var lmbMacroSourceLocation
   */
-  protected $location;    
+  protected $location;
 
   function __construct($location = null)
   {
@@ -32,17 +32,17 @@
     else
       $this->location = new lmbMacroSourceLocation();
   }
-  
+
   function setParent($parent)
   {
     $this->parent = $parent;
   }
-  
+
   function getParent()
   {
     return $this->parent;
   }
-  
+
   function getLocationInTemplate()
   {
     return $this->location;
@@ -62,7 +62,7 @@
   {
     if($this->id)
       return $this->id;
-        
+
     $this->id = self :: generateNewId();
     return $this->id;
   }
@@ -70,21 +70,21 @@
   function setId($id)
   {
     $this->id = $id;
-  }  
-  
+  }
+
   static function generateNewId()
   {
     static $counter = 1;
     return 'id00' . $counter++;
-  }    
-  
+  }
+
   function raise($error, $vars = array())
-  {    
+  {
     $vars['file'] = $this->location->getFile();
     $vars['line'] = $this->location->getLine();
     throw new lmbMacroException($error, $vars);
-  }  
-  
+  }
+
   function addChild($child)
   {
     $child->parent = $this;
@@ -188,8 +188,8 @@
         $result[] = $child;
     }
     return $result;
-  }  
-  
+  }
+
   function findParentByClass($class)
   {
     $parent = $this->parent;
@@ -198,16 +198,16 @@
       $parent = $parent->parent;
 
     return $parent;
-  }  
-  
+  }
+
   function prepare()
   {
     foreach($this->children as $child)
       $child->prepare();
-  }  
+  }
 
   function preParse(){}
-  
+
   function generateConstructor($code_writer)
   {
     foreach($this->children as $child)
@@ -219,12 +219,18 @@
     foreach($this->children as $child)
       $child->generate($code_writer);
   }
-  
+
   function generate($code_writer)
-  {   
-    $this->generateContents($code_writer);   
-  }  
-     
+  {
+    $this->_preGenerateAttributes($code_writer);
+
+    $this->generateContents($code_writer);
+  }
+
+  protected function _preGenerateAttributes($code_writer)
+  {
+  }
+
   /**
   * Checks that each immediate child of the current component has a unique ID
   * amongst its siblings.
@@ -250,6 +256,6 @@
         $checked_children[$id] = $child;
       }
     }
-  }  
+  }
 }
 

Added: 3.x/trunk/limb/macro/src/lmbMacroOutputExpressionNode.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroOutputExpressionNode.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroOutputExpressionNode.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,35 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+lmb_require('limb/macro/src/lmbMacroNode.class.php');
+
+/**
+ * class lmbMacroTag.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroOutputExpressionNode extends lmbMacroNode
+{
+  protected $expression;
+
+  function __construct($location, $expression)
+  {
+    $this->expression = $expression;
+
+    parent :: __construct($location);
+  }
+
+  function generateContents($code)
+  {
+    $this->expression->preGenerate($code);
+    $code->writePHP('echo ' . $this->expression->getValue() .  ";\n");
+  }
+}
+

Modified: 3.x/trunk/limb/macro/src/lmbMacroTag.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroTag.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/lmbMacroTag.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,12 +2,13 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroNode.class.php');
+lmb_require('limb/macro/src/lmbMacroTagAttribute.class.php');
 
 /**
  * class lmbMacroTag.
@@ -19,15 +20,15 @@
 {
   protected $tag;
   protected $has_closing_tag = true;
-  protected $empty_closed_tag = false;  
+  protected $empty_closed_tag = false;
   protected $tag_info;
   protected $attributes = array();
-  
+
   function __construct($location, $tag, $tag_info)
   {
     $this->tag = $tag;
     $this->tag_info = $tag_info;
-    
+
     parent :: __construct($location);
   }
 
@@ -35,49 +36,70 @@
   {
     return $this->tag;
   }
-  
+
   function getHasClosingTag()
   {
     return $this->has_closing_tag;
   }
-  
+
   function setHasClosingTag($flag)
   {
     return $this->has_closing_tag = $flag;
-  }  
-  
+  }
+
   function getId()
   {
     if($this->id)
       return $this->id;
-        
+
     if($id = $this->get('id'))
       $this->id = $id;
     else
       $this->id = self :: generateNewId();
 
     return $this->id;
-  }  
-  
+  }
+
   function get($name)
   {
-    if(array_key_exists(strtolower($name), $this->attributes))
-      return $this->attributes[strtolower($name)];
-  }  
-  
+    if(!array_key_exists(strtolower($name), $this->attributes))
+      return;
+
+    return $this->attributes[strtolower($name)]->getValue();
+  }
+
+  function getEscaped($name)
+  {
+    if($value = $this->get($name))
+    {
+      if($this->isDynamic($name))
+        return $value;
+      else
+        return "'" .  $value . "'";
+    }
+  }
+
+  /**
+  * Should be used for testing purposes only since not parses $value for any output expressions
+  */
   function set($name, $value)
   {
-    $this->attributes[strtolower($name)] = $value;
+    $this->attributes[strtolower($name)] = new lmbMacroTagAttribute($name, $value);
   }
 
+  function add($attribute)
+  {
+    $this->attributes[strtolower($attribute->getName())] = $attribute;
+  }
+
   function has($name)
   {
     return array_key_exists(strtolower($name), $this->attributes);
   }
 
-  function isVariable($name)
+  function isDynamic($name)
   {
-    return $this->has($name) && strpos($this->get($name), '$') === 0;
+    return $this->has($name) && $this->attributes[strtolower($name)]->isDynamic();
   }
 
   /**
@@ -87,16 +109,19 @@
   * ATTRIBUTE (true)
   * (attribute unspecified) (default)
   */
-  function getBool($attrib, $default = false)
+  function getBool($name, $default = false)
   {
-    if(!isset($this->attributes[strtolower($attrib)]))
+    if(!isset($this->attributes[strtolower($name)]))
       return $default;
 
-    return self :: getBooleanValue($this->attributes[strtolower($attrib)]);
+    return self :: getBooleanValue($this->attributes[strtolower($name)]->getValue());
   }
 
   static function getBooleanValue($value)
   {
+    if(!$value)
+      return $value;
+
     switch(strtoupper($value))
     {
       case 'FALSE':
@@ -111,22 +136,35 @@
     }
   }
 
+  function generate($code_writer)
+  {
+    $this->_preGenerataAttributes($code_writer);
+
+    $this->generateContents($code_writer);
+  }
+
+  protected function _preGenerataAttributes($code_writer)
+  {
+    foreach($this->attributes as $attribute)
+      $attribute->preGenerate($code_writer);
+  }
+
   function remove($attrib)
   {
     unset($this->attributes[strtolower($attrib)]);
-  }  
-    
+  }
+
   function raise($error, $vars = array())
   {
     $vars['tag'] = $this->tag;
     parent :: raise($error, $vars);
-  }  
+  }
 
   function raiseRequiredAttribute($attribute_name)
   {
     $this->raise('Missing required attribute', array('attribute' => $attribute_name));
   }
-  
+
   function preParse($compiler)
   {
     foreach($this->tag_info->getRequiredAttributes() as $attr_name)
@@ -147,6 +185,6 @@
                                 array('required_parent_tag_class' => $parent_class));
 
     }
-  }  
+  }
 }
 

Added: 3.x/trunk/limb/macro/src/lmbMacroTagAttribute.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroTagAttribute.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroTagAttribute.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,78 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+lmb_require('limb/macro/src/lmbMacroExpressionInterface.interface.php');
+
+/**
+ * Used to store complex expressions like "{$var1}_my_{$var2}" found inside tag attributes
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagAttribute implements lmbMacroExpressionInterface
+{
+  protected $name;
+  protected $expressions = array();
+  protected $raw_string = '';
+
+  function __construct($name, $value = null)
+  {
+    $this->name = $name;
+
+    if($value)
+      $this->raw_string .= $value;
+  }
+
+  function getName()
+  {
+    return $this->name;
+  }
+
+  function addTextFragment($text)
+  {
+    $this->raw_string .= $text;
+  }
+
+  function addExpressionFragment($expression)
+  {
+     $this->raw_string .= '%s';
+    $this->expressions[] = $expression;
+  }
+
+  function preGenerate($code_writer)
+  {
+    foreach($this->expressions as $fragment)
+      $fragment->preGenerate($code_writer);
+  }
+
+  function isDynamic()
+  {
+    return (bool)sizeof($this->expressions) || (strpos($this->raw_string, '$') === 0);
+  }
+
+  function getValue()
+  {
+    // simple case
+    if(!sizeof($this->expressions))
+       return $this->raw_string;
+
+    $res = 'sprintf(\'' . $this->raw_string. '\',';
+
+    $separator = '';
+    foreach($this->expressions as $expressions)
+    {
+      $res .= $separator . $expressions->getValue();
+      $separator = ',';
+    }
+
+    $res .= ')';
+    return $res;
+  }
+}
+
+

Added: 3.x/trunk/limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,40 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+lmb_require('limb/macro/src/lmbMacroBlockAnalizerListener.interface.php');
+/**
+ * class lmbMacroTagAttributeBlockAnalizerListener.
+ *
+ * @package macro
+ * @version $Id$
+ */
+class lmbMacroTagAttributeBlockAnalizerListener implements lmbMacroBlockAnalizerListener
+{
+  protected $attribute;
+  protected $tag_node;
+  protected $filter_dictionary;
+
+  function __construct($attribute, $tag_node)
+  {
+    $this->attribute = $attribute;
+    $this->tag_node = $tag_node;
+  }
+
+  function addLiteralFragment($text)
+  {
+    $this->attribute->addTextFragment($text);
+  }
+
+  function addExpressionFragment($text)
+  {
+    $expression = new lmbMacroExpression($text);
+    $this->attribute->addExpressionFragment($expression);
+  }
+}
+

Modified: 3.x/trunk/limb/macro/src/lmbMacroTagDictionary.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroTagDictionary.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/lmbMacroTagDictionary.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroTagInfo.class.php');
@@ -64,30 +64,9 @@
 
   function findTagInfo($tag)
   {
-    if($this->_isOutputTag($tag))
-      return $this->_getOutputTagInfo();
-    else
-    {
-      $tag = strtolower($tag);
-      if(isset($this->info[$tag]))
-        return $this->info[$tag];
-    }
+    $tag = strtolower($tag);
+    if(isset($this->info[$tag]))
+      return $this->info[$tag];
   }
-
-  protected function _isOutputTag($tag)
-  {
-    return $tag{0} == '$';
-  }
-
-  protected function _getOutputTagInfo()
-  {
-    if($this->output_tag_info)
-      return $this->output_tag_info;
-
-    //taking first item
-    $this->output_tag_info = reset(lmbMacroTagInfo :: extractFromFile($file = dirname(__FILE__) . '/tags/output.tag.php'));
-    $this->output_tag_info->setFile($file);
-    return $this->output_tag_info;
-  }
 }
 

Modified: 3.x/trunk/limb/macro/src/lmbMacroTagParsingState.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroTagParsingState.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/lmbMacroTagParsingState.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,13 +2,15 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroTokenizerListener.interface.php');
 lmb_require('limb/macro/src/lmbMacroBaseParsingState.class.php');
+lmb_require('limb/macro/src/lmbMacroTagAttributeBlockAnalizerListener.class.php');
+lmb_require('limb/macro/src/lmbMacroBlockAnalizer.class.php');
 
 /**
  * class lmbMacroTagParsingState.
@@ -40,7 +42,7 @@
       $tag_node = $this->buildTagNode($tag_info, $tag, $attrs, $self_closed_tag = true);
       $tag_node->setHasClosingTag(false);
       $this->tree_builder->pushNode($tag_node); // for cases like {{include}} we do pushNode() and popNode() here.
-      $this->tree_builder->popNode();      
+      $this->tree_builder->popNode();
     }
     else
     {
@@ -81,7 +83,7 @@
     $this->tree_builder->pushNode($tag_node); // for cases like {{include}} we do pushNode() and popNode() here.
     $this->tree_builder->popNode();
   }
-  
+
   /**
   * Builds a component, adding attributes
   * @param lmbMacroTagInfo
@@ -96,8 +98,8 @@
     $tag_node->emptyClosedTag = $isEmpty;
     $this->_addAttributesToTagNode($tag_node, $attrs);
     return $tag_node;
-  }    
-  
+  }
+
   protected function _addAttributesToTagNode($tag_node, $attrs)
   {
     foreach($attrs as $name => $value)
@@ -111,9 +113,16 @@
                                     'tag' => $tag_node->getTag(),
                                     'attribute' => $name));
       }
-      $tag_node->set($name, $value);
+
+      $attribute = new lmbMacroTagAttribute($name);
+      $listener = new lmbMacroTagAttributeBlockAnalizerListener($attribute, $tag_node);
+
+      $analizer = new lmbMacroBlockAnalizer();
+      $analizer->parse($value, $listener);
+
+      $tag_node->add($attribute);
     }
-  }  
+  }
 
   protected function _createTagNode($tag_info, $tag)
   {
@@ -121,16 +130,16 @@
     require_once($tag_info->getFile());
     $tag_node = new $class($this->parser->getCurrentLocation(), $tag, $tag_info);
     return $tag_node;
-  }    
+  }
 
   function normalizeAttributes($attrs)
   {
-    return array_change_key_case($attrs, CASE_LOWER);    
+    return array_change_key_case($attrs, CASE_LOWER);
   }
 
   function characters($text)
   {
-    $this->tree_builder->addTextNode($text);
+    $this->tree_builder->addContent($text, $this->parser->getCurrentLocation());
   }
 
   function unexpectedEOF($text)

Modified: 3.x/trunk/limb/macro/src/lmbMacroTreeBuilder.class.php
===================================================================
--- 3.x/trunk/limb/macro/src/lmbMacroTreeBuilder.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/lmbMacroTreeBuilder.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 /**
@@ -24,6 +24,8 @@
  */
 
 lmb_require('limb/macro/src/lmbMacroTextNode.class.php');
+lmb_require('limb/macro/src/lmbMacroContentBlockAnalizerListener.class.php');
+lmb_require('limb/macro/src/lmbMacroBlockAnalizer.class.php');
 
 class lmbMacroTreeBuilder
 {
@@ -82,13 +84,20 @@
     $this->addNode(new lmbMacroTextNode(null, $text));
   }
 
+  function addContent($text, $location)
+  {
+    $listener = new lmbMacroContentBlockAnalizerListener($this, $location);
+    $analizer = new lmbMacroBlockAnalizer();
+    $analizer->parse($text, $listener);
+  }
+
   /**
   * Ends a node's build phase in relation to the tree.
   * Checks child server ids and moves the 'cursor' up the tree to the parent
   * node.
   */
   function popNode()
-  {    
+  {
     $this->node->checkChildrenIds();
     $this->setCursor($this->node->getParent());
   }
@@ -133,12 +142,12 @@
       return $this->popExpectedTag($tag, $location);
     }
 
-    $expected_tag = $expected_tag_item[0];    
+    $expected_tag = $expected_tag_item[0];
     $expected_location = $expected_tag_item[1];
 
     if(strcasecmp($expected_tag, $tag) === 0)
       return $tag;
- 
+
     throw new lmbMacroException('Unexpected closing tag',
                              array('file' => $location->getFile(),
                                   'tag' => $tag,

Modified: 3.x/trunk/limb/macro/src/tags/include.tag.php
===================================================================
--- 3.x/trunk/limb/macro/src/tags/include.tag.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/tags/include.tag.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroTag.class.php');
@@ -39,7 +39,7 @@
 
   function _isDynamic()
   {
-    return $this->isVariable('file');
+    return $this->isDynamic('file');
   }
 
   function generateContents($code)
@@ -79,10 +79,10 @@
   {
     $keys = array();
     $vals = array();
-    foreach($this->attributes as $k => $v)
+    foreach($this->attributes as $k => $attribute)
     {
       $keys[] = '$' . $k;
-      $vals[] = $this->_sanitizeValue($v);
+      $vals[] = $this->getEscaped($k);
     }
     return array($keys, $vals);
   }
@@ -90,17 +90,9 @@
   protected function _attributesIntoArray()
   {
     $arr = array();
-    foreach($this->attributes as $k => $v)
-      $arr[$k] = $this->_sanitizeValue($v);
+    foreach($this->attributes as $k => $attribute)
+      $arr[$k] = $this->getEscaped($k);
     return $arr;
   }
-
-  protected function _sanitizeValue($v)
-  {
-    if(is_numeric($v) || $v{0} == '$')
-      return $v;
-    else //make it smarter
-      return "'$v'";
-  }
 }
 

Modified: 3.x/trunk/limb/macro/src/tags/into.tag.php
===================================================================
--- 3.x/trunk/limb/macro/src/tags/into.tag.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/tags/into.tag.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroTag.class.php');
@@ -22,7 +22,7 @@
   {
     parent :: preParse($compiler);
 
-    if(!$this->parent->isDynamic())
+    if(!$this->parent->isDynamicWrap())
     {
       $tree_builder = $compiler->getTreeBuilder();
       $this->_insert($this->parent, $tree_builder, $this->get('slot'));

Deleted: 3.x/trunk/limb/macro/src/tags/output.tag.php
===================================================================
--- 3.x/trunk/limb/macro/src/tags/output.tag.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/tags/output.tag.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -1,57 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
- */
-
-lmb_require('limb/macro/src/lmbMacroTag.class.php');
-
-/**
- * class lmbMacroOutputTag.
- *
- * @tag $output
- * @endtag no
- * @package macro
- * @version $Id$
- */
-class lmbMacroOutputTag extends lmbMacroTag
-{
-  function generateContents($code)
-  {
-    $code->writePHP($this->_compileExpression($code));
-  }
-
-  protected function _compileExpression($code)
-  {
-    if(strpos($this->tag, '.') === false)
-      return 'echo ' . $this->tag . ';';
-
-    $expr = '';
-
-    $items = explode('.', $this->tag);
-
-    //first item is variable itself
-    $var = $items[0];
-    $tmp = $code->getTempVarRef();
-    $code->writePHP($tmp . "='';");
-    for($i=1; $i<sizeof($items); $i++)
-    {
-      $item = $items[$i];
-      $expr .= 'if((is_array(' . $var . ') && isset(' . $var . '["' . $item . '"])) || ' . 
-               '(is_object(' . $var . ') && ' . $tmp . '=' . $var . '->get("' . $item . '")))' .  
-               '{if(is_array(' . $var . '))' . $tmp . ' = ' . $var . '["' . $item . '"];';
-      $var = $tmp;
-    }
-
-    //closing brackets
-    for($i=1; $i<sizeof($items); $i++)
-      $expr .= '}else{' . $tmp . '="";}';
-
-    $expr .= "echo $tmp;";
-    return $expr;
-  }
-}
-

Modified: 3.x/trunk/limb/macro/src/tags/wrap.tag.php
===================================================================
--- 3.x/trunk/limb/macro/src/tags/wrap.tag.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/src/tags/wrap.tag.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroTag.class.php');
@@ -24,7 +24,7 @@
   {
     parent :: preParse($compiler);
 
-    if($this->isVariable('with'))
+    if($this->isDynamic('with'))
       $this->is_dynamic = true;
 
     if(!$this->is_dynamic)
@@ -41,11 +41,6 @@
     }
   }
 
-  function isDynamic()
-  {
-    return $this->is_dynamic;
-  }
-
   protected function _compileSourceFileName($file, $compiler)
   {
     $this->sourcefile = $compiler->getTemplateLocator()->locateSourceTemplate($file);
@@ -71,9 +66,14 @@
       $this->raise('Wrap slot not found', $params);
     }
 
-    $tree_builder->pushCursor($insertionPoint, $this->location); 
+    $tree_builder->pushCursor($insertionPoint, $this->location);
   }
 
+  function isDynamicWrap()
+  {
+    return $this->is_dynamic;
+  }
+
   protected function _collectIntos()
   {
     return $this->findImmediateChildrenByClass('lmbMacroIntoTag');
@@ -108,7 +108,7 @@
 
       $handlers_str .= ')';
 
-      $code->writePHP('$this->wrapTemplate(' . $this->get('with') . ', ' . $handlers_str . ');');
+      $code->writePHP('$this->wrapTemplate(' . $this->getEscaped('with') . ', ' . $handlers_str . ');');
     }
     else
       parent :: generateContents($code);

Modified: 3.x/trunk/limb/macro/tests/cases/.setup.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/.setup.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/.setup.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -1,3 +1,4 @@
 <?php
 require_once(dirname(__FILE__) . '/../../common.inc.php');
+require_once(dirname(__FILE__) . '/lmbBaseMacroTest.class.php');
 

Added: 3.x/trunk/limb/macro/tests/cases/lmbBaseMacroTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/lmbBaseMacroTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/tests/cases/lmbBaseMacroTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,44 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+lmb_require('limb/fs/src/lmbFs.class.php');
+lmb_require('limb/core/src/lmbObject.class.php');
+lmb_require('limb/macro/src/lmbMacroTemplate.class.php');
+lmb_require('limb/macro/src/lmbMacroTagDictionary.class.php');
+
+class lmbBaseMacroTest extends UnitTestCase
+{
+  function setUp()
+  {
+    lmbFs :: rm(LIMB_VAR_DIR . '/tpl');
+    lmbFs :: mkdir(LIMB_VAR_DIR . '/tpl/compiled');
+  }
+
+  protected function _createMacro($file)
+  {
+    $base_dir = LIMB_VAR_DIR . '/tpl';
+    $cache_dir = LIMB_VAR_DIR . '/tpl/compiled';
+    $macro = new lmbMacroTemplate($file, new lmbMacroConfig($cache_dir, true, true, array($base_dir)));
+    return $macro;
+  }
+
+  protected function _createTemplate($code, $name)
+  {
+    $file = LIMB_VAR_DIR . '/tpl/' . $name;
+    file_put_contents($file, $code);
+    return $file;
+  }
+
+  protected function _createMacroTemplate($code, $name)
+  {
+    $file = $this->_createTemplate($code, $name);
+    return $this->_createMacro($file);
+  }
+}
+

Added: 3.x/trunk/limb/macro/tests/cases/lmbMacroOutputExpressionTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/lmbMacroOutputExpressionTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/macro/tests/cases/lmbMacroOutputExpressionTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -0,0 +1,118 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+class lmbMacroOutputExpressionsTest extends lmbBaseMacroTest
+{
+  function testSimpleOutput()
+  {
+    $content = '{$#var}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', 'Foo');
+
+    $out = $macro->render();
+    $this->assertEqual($out, 'Foo');
+  }
+
+  function testSimpleChainedOutputForArray()
+  {
+    $content = '{$#var.foo.bar}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', array('foo' => array('bar' => 'Hey')));
+
+    $out = $macro->render();
+    $this->assertEqual($out, 'Hey');
+  }
+
+  function testBrokenChainOutputForArray()
+  {
+    $content = '{$#var.foo.bar.baz}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', null);
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+
+    $macro->set('var', array('foo' => null));
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+
+    $macro->set('var', array('foo' => array('bar' => null)));
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+  }
+
+  function testSimpleChainedOutputForObject()
+  {
+    $content = '{$#var.foo.bar}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', new lmbObject(array('foo' => new lmbObject(array('bar' => 'Hey')))));
+
+    $out = $macro->render();
+    $this->assertEqual($out, 'Hey');
+  }
+
+  function testBrokenChainOutputForObject()
+  {
+    $content = '{$#var.foo.bar.baz}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', null);
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+
+    $macro->set('var', new lmbObject(array('foo' => null)));
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+
+    $macro->set('var', new lmbObject(array('foo' => new lmbObject(array('bar' => null)))));
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+  }
+
+  function testChainedOutputForMixedArraysAndObjects()
+  {
+    $content = '{$#var.foo.bar}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', new lmbObject(array('foo' => array('bar' => 'Hey'))));
+
+    $out = $macro->render();
+    $this->assertEqual($out, 'Hey');
+  }
+
+  function testBrokenChainOutputForMixedArraysAndObjects()
+  {
+    $content = '{$#var.foo.bar.baz}';
+
+    $macro = $this->_createMacroTemplate($content, 'tpl.html');
+
+    $macro->set('var', new lmbObject(array('foo' => array('bar' => null))));
+    $out = $macro->render();
+    $this->assertEqual($out, '');
+  }
+
+  function testTemplateWithOutputExpression()
+  {
+    $code = '<h1>{$#bar}</h1>';
+    $tpl = $this->_createMacroTemplate($code, 'tpl.html');
+    $tpl->set('bar', "foo");
+    $out = $tpl->render();
+    $this->assertEqual($out, '<h1>foo</h1>');
+  }
+}
+

Modified: 3.x/trunk/limb/macro/tests/cases/lmbMacroTagAcceptanceTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/lmbMacroTagAcceptanceTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/lmbMacroTagAcceptanceTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/macro/src/lmbMacroTemplate.class.php');
@@ -13,7 +13,7 @@
 lmb_require('limb/macro/src/lmbMacroTag.class.php');
 lmb_require('limb/macro/src/lmbMacroTagInfo.class.php');
 lmb_require('limb/fs/src/lmbFs.class.php');
- 
+
 class MacroTagFooTest extends lmbMacroTag
 {
   function generateContents($code)
@@ -30,35 +30,39 @@
   }
 }
 
-$foo_info = new lmbMacroTagInfo('foo', 'MacroTagFooTest'); 
-$bar_info = new lmbMacroTagInfo('bar', 'MacroTagBarTest'); 
+class MacroTagZooTest extends lmbMacroTag
+{
+  function generateContents($code)
+  {
+    $code->writePHP('echo ' . $this->getEscaped('attr') . ';');
+  }
+}
 
+$foo_info = new lmbMacroTagInfo('foo', 'MacroTagFooTest');
+$bar_info = new lmbMacroTagInfo('bar', 'MacroTagBarTest');
+$zoo_info = new lmbMacroTagInfo('zoo', 'MacroTagZooTest');
+
 lmbMacroTagDictionary :: instance()->register($foo_info, __FILE__);
 lmbMacroTagDictionary :: instance()->register($bar_info, __FILE__);
+lmbMacroTagDictionary :: instance()->register($zoo_info, __FILE__);
 
-class lmbMacroTagAcceptanceTest extends UnitTestCase
+class lmbMacroTagAcceptanceTest extends lmbBaseMacroTest
 {
-  function setUp()
-  {
-    lmbFs :: rm(LIMB_VAR_DIR . '/tpl');
-    lmbFs :: mkdir(LIMB_VAR_DIR . '/tpl/compiled');
-  }
-
   function testTemplateRendering()
   {
     $code = '<h1>{{foo/}}{{bar/}}</h1>';
-    $tpl = $this->_createTemplate($code);
+    $tpl = $this->_createMacroTemplate($code, 'tpl.html');
     $out = $tpl->render();
     $this->assertEqual($out, '<h1>foo!bar</h1>');
   }
 
-  protected function _createTemplate($code)
+  function testCompositeTagAttributes()
   {
-    $file = LIMB_VAR_DIR . '/tpl/' . mt_rand() . '.html';
-    file_put_contents($file, $code);
-    $cache_dir = LIMB_VAR_DIR . '/tpl/compiled';
-    $tpl = new lmbMacroTemplate($file, new lmbMacroConfig($cache_dir));
-    return $tpl;
+    $code = '<h1>{{zoo attr="Test_{$#var}"/}}</h1>';
+    $tpl = $this->_createMacroTemplate($code, 'tpl.html');
+    $tpl->set('var', 'Result');
+    $out = $tpl->render();
+    $this->assertEqual($out, '<h1>Test_Result</h1>');
   }
 }
 

Modified: 3.x/trunk/limb/macro/tests/cases/lmbMacroTagDictionaryTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/lmbMacroTagDictionaryTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/lmbMacroTagDictionaryTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,9 +2,9 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
 lmb_require('limb/fs/src/lmbFs.class.php');
@@ -29,14 +29,6 @@
     $this->assertIsA($dictionary->findTagInfo('testtag'), 'lmbMacroTagInfo');
   }
 
-  function testFindOutputTagInfoSpecialCase()
-  {
-    $dictionary = new lmbMacroTagDictionary();
-    $info = $dictionary->findTagInfo('$var');
-    $this->assertIsA($info, 'lmbMacroTagInfo');
-    $this->assertEqual($info->getClass(), 'lmbMacroOutputTag');
-  }
-
   function testRegisterTagInfoOnceOnly()
   {
     $dictionary = new lmbMacroTagDictionary();

Modified: 3.x/trunk/limb/macro/tests/cases/lmbMacroTagTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/lmbMacroTagTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/lmbMacroTagTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,24 +2,26 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
-lmb_require('limb/macro/src/lmbMacroNode.class.php'); 
+lmb_require('limb/macro/src/lmbMacroNode.class.php');
 lmb_require('limb/macro/src/lmbMacroTag.class.php');
 lmb_require('limb/macro/src/lmbMacroTagInfo.class.php');
 lmb_require('limb/macro/src/lmbMacroSourceLocation.class.php');
-lmb_require('limb/macro/src/lmbMacroCodeWriter.class.php'); 
-lmb_require('limb/macro/src/lmbMacroCompiler.class.php'); 
- 
+lmb_require('limb/macro/src/lmbMacroCodeWriter.class.php');
+lmb_require('limb/macro/src/lmbMacroCompiler.class.php');
+lmb_require('limb/macro/src/lmbMacroTagAttribute.class.php');
+
 class MacroTagClass1CompilerTest extends lmbMacroTag{}
 class MacroTagClass2CompilerTest extends lmbMacroTag{}
 
 Mock::generate('lmbMacroNode', 'MockMacroNode');
 Mock::generate('lmbMacroCodeWriter', 'MockMacroCodeWriter');
 Mock::generate('lmbMacroCompiler', 'MockMacroCompiler');
+Mock::generate('lmbMacroTagAttribute', 'MockMacroTagAttribute');
 
 class lmbMacroTagTest extends UnitTestCase
 {
@@ -38,7 +40,7 @@
   {
     return new lmbMacroTag($this->source_location, 'my_tag', $this->tag_info);
   }
-  
+
   function testGetIdAttribute()
   {
     $this->node->setId('Test');
@@ -150,6 +152,15 @@
     $this->node->generate($code_writer);
   }
 
+  function testGenerateCallsPreGenerateForAttributes()
+  {
+    $code_writer = new MockMacroCodeWriter();
+    $attribute = new MockMacroTagAttribute();
+    $attribute->expectOnce('preGenerate');
+    $this->node->add($attribute);
+    $this->node->generate($code_writer);
+  }
+
   function testCheckIdsOk()
   {
     $root = new lmbMacroNode;
@@ -208,23 +219,23 @@
     $root->addChild($child2);
 
     $root->checkChildrenIds();
-  }  
-  
+  }
+
   function testGetIdByDefault()
   {
     $this->assertNotNull($this->node->getId());
-  }  
+  }
 
   function testGetId()
   {
     $this->node->setId('TestId');
     $this->assertEqual($this->node->getId(), 'TestId');
   }
-  
+
   function testGetAttributeUnset()
   {
     $this->assertNull($this->node->get('foo'));
-  }  
+  }
 
   function testGetAttribute()
   {
@@ -266,7 +277,7 @@
     //false cases
     $this->node->set('A', NULL);
     $this->assertFalse($this->node->getBool('A'));
-    
+
     $this->node->set('D', 'False');
     $this->assertFalse($this->node->getBool('D'));
 
@@ -360,6 +371,6 @@
       $this->assertEqual($e->getParam('file'), $this->source_location->getFile());
       $this->assertEqual($e->getParam('line'), $this->source_location->getLine());
     }
-  }  
+  }
 }
 

Deleted: 3.x/trunk/limb/macro/tests/cases/tags/.setup.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/tags/.setup.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/tags/.setup.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -1,3 +0,0 @@
-<?php
-require_once(dirname(__FILE__) . '/lmbBaseMacroTagTest.class.php');
-

Deleted: 3.x/trunk/limb/macro/tests/cases/tags/lmbBaseMacroTagTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/tags/lmbBaseMacroTagTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/tags/lmbBaseMacroTagTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -1,37 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html
- */
-
-lmb_require('limb/fs/src/lmbFs.class.php');
-lmb_require('limb/macro/src/lmbMacroTemplate.class.php');
-lmb_require('limb/macro/src/lmbMacroTagDictionary.class.php');
-
-class lmbBaseMacroTagTest extends UnitTestCase
-{
-  function setUp()
-  {
-    lmbFs :: rm(LIMB_VAR_DIR . '/tpl');
-    lmbFs :: mkdir(LIMB_VAR_DIR . '/tpl/compiled');
-  }
-
-  protected function _createMacro($file)
-  {
-    $base_dir = LIMB_VAR_DIR . '/tpl';
-    $cache_dir = LIMB_VAR_DIR . '/tpl/compiled';
-    $macro = new lmbMacroTemplate($file, new lmbMacroConfig($cache_dir, true, true, array($base_dir)));
-    return $macro;
-  }
-
-  protected function _createTemplate($code, $name)
-  {
-    $file = LIMB_VAR_DIR . '/tpl/' . $name;
-    file_put_contents($file, $code);
-    return $file;
-  }
-}
-

Modified: 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroIncludeTagTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroIncludeTagTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroIncludeTagTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,23 +2,13 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
-lmb_require('limb/macro/src/lmbMacroTemplate.class.php');
-lmb_require('limb/fs/src/lmbFs.class.php');
-lmb_require('limb/macro/src/lmbMacroTagDictionary.class.php');
-
-class lmbMacroTagIncludeTest extends UnitTestCase
+class lmbMacroTagIncludeTest extends lmbBaseMacroTest
 {
-  function setUp()
-  {
-    lmbFs :: rm(LIMB_VAR_DIR . '/tpl');
-    lmbFs :: mkdir(LIMB_VAR_DIR . '/tpl/compiled');
-  }
-
   function testSimpleStaticInclude()
   {
     $bar = '<body>{{include file="foo.html"/}}</body>';
@@ -58,11 +48,11 @@
     $foo_tpl = $this->_createTemplate($foo, 'foo.html');
 
     $macro = $this->_createMacro($bar_tpl);
-    
+
     $out = $macro->render();
     $this->assertEqual($out, '<body><p>Numbers: 1 2</p></body>');
   }
-  
+
   function testStaticIncludeMixLocalAndTemplateVariables()
   {
     $bar = '<body><?php $var2=2;?>{{include file="foo.html" var1="1" var2="$var2"/}}</body>';
@@ -72,7 +62,7 @@
     $foo_tpl = $this->_createTemplate($foo, 'foo.html');
 
     $macro = $this->_createMacro($bar_tpl);
-    
+
     $macro->set('var3', 3);
     $out = $macro->render();
     $this->assertEqual($out, '<body><p>Numbers: 1 2 3</p></body>');
@@ -88,10 +78,10 @@
 
     $macro = $this->_createMacro($bar_tpl);
     $macro->set('file', 'foo.html');
-    
+
     $out = $macro->render();
     $this->assertEqual($out, '<body><p>Hello!</p></body>');
-  } 
+  }
 
   function testDynamicIncludePassLocalVars()
   {
@@ -103,10 +93,10 @@
 
     $macro = $this->_createMacro($bar_tpl);
     $macro->set('file', 'foo.html');
-    
+
     $out = $macro->render();
     $this->assertEqual($out, '<body><p>Hello, Fred!</p></body>');
-  } 
+  }
 
   function testDynamicIncludeMixLocalAndTemplateVars()
   {
@@ -119,24 +109,9 @@
     $macro = $this->_createMacro($bar_tpl);
     $macro->set('file', 'foo.html');
     $macro->set('lastname', 'Atkins');
-    
+
     $out = $macro->render();
     $this->assertEqual($out, '<body><p>Hello, Fred Atkins!</p></body>');
-  } 
-
-  protected function _createMacro($file)
-  {
-    $base_dir = LIMB_VAR_DIR . '/tpl';
-    $cache_dir = LIMB_VAR_DIR . '/tpl/compiled';
-    $macro = new lmbMacroTemplate($file, new lmbMacroConfig($cache_dir, true, true, array($base_dir)));
-    return $macro;
   }
-
-  protected function _createTemplate($code, $name)
-  {
-    $file = LIMB_VAR_DIR . '/tpl/' . $name;
-    file_put_contents($file, $code);
-    return $file;
-  }
 }
 

Modified: 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroListTagTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroListTagTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroListTagTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -7,7 +7,7 @@
  * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
-class lmbMacroListTagTest extends lmbBaseMacroTagTest
+class lmbMacroListTagTest extends lmbBaseMacroTest
 {
   function testSimpleList()
   {
@@ -91,7 +91,7 @@
 
   function testParity()
   {
-    $list = '{{list using="$#list" as="$item" parity="$parity"}}{{list:item}}{{$parity}}-{{$item}} {{/list:item}} !{{/list}}';
+    $list = '{{list using="$#list" as="$item" parity="$parity"}}{{list:item}}{$parity}-{$item} {{/list:item}} !{{/list}}';
 
     $list_tpl = $this->_createTemplate($list, 'list.html');
 
@@ -105,7 +105,7 @@
   function testEvenAndOddTags()
   {
     $list = '{{list using="$#list" as="$item" parity="$parity"}}{{list:item}}'.
-              '{{list:odd}}Odd{{/list:odd}}{{list:even}}Even{{/list:even}}-{{$item}} {{/list:item}} !{{/list}}';
+              '{{list:odd}}Odd{{/list:odd}}{{list:even}}Even{{/list:even}}-{$item} {{/list:item}} !{{/list}}';
 
     $list_tpl = $this->_createTemplate($list, 'list.html');
 
@@ -168,11 +168,11 @@
   function testListFillTagWithRatio()
   {
     $list = '{{list using="$#list" as="$item"}}List#'.
-                '{{list:item}}{{$item}}'.
+                '{{list:item}}{$item}'.
                 '{{list:glue step="3"}}++{{/list:glue}}'.
                 '{{list:glue}}:{{/list:glue}}'.
                 '{{/list:item}}'.
-                '{{list:fill upto="3" items_left="$items_left"}}{{$items_left}}{{/list:fill}}'.
+                '{{list:fill upto="3" items_left="$items_left"}}{$items_left}{{/list:fill}}'.
                 '{{/list}}';
 
     $list_tpl = $this->_createTemplate($list, 'list.html');
@@ -186,11 +186,11 @@
   function testListFillTagWithTotalElementsLessThanRatio()
   {
     $list = '{{list using="$#list" as="$item"}}List#'.
-                '{{list:item}}{{$item}}'.
+                '{{list:item}}{$item}'.
                 '{{list:glue step="3"}}++{{/list:glue}}'.
                 '{{list:glue}}:{{/list:glue}}'.
                 '{{/list:item}}'.
-                '{{list:fill upto="3" items_left="$items_left"}}{{$items_left}}{{/list:fill}}'.
+                '{{list:fill upto="3" items_left="$items_left"}}{$items_left}{{/list:fill}}'.
                 '{{/list}}';
 
     $list_tpl = $this->_createTemplate($list, 'list.html');

Deleted: 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroOutputTagTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroOutputTagTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroOutputTagTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -1,144 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
- */
-
-lmb_require('limb/macro/src/lmbMacroTemplate.class.php');
-lmb_require('limb/core/src/lmbObject.class.php');
-lmb_require('limb/fs/src/lmbFs.class.php');
-
-class lmbMacroOutputTagTest extends UnitTestCase
-{
-  function setUp()
-  {
-    lmbFs :: rm(LIMB_VAR_DIR . '/tpl');
-    lmbFs :: mkdir(LIMB_VAR_DIR . '/tpl/compiled');
-  }
-
-  function testSimpleOutput()
-  {
-    $content = '{{$#var}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-    $macro->set('var', 'Foo');
-
-    $out = $macro->render();
-    $this->assertEqual($out, 'Foo');
-  }
-
-  function testSimpleChainedOutputForArray()
-  {
-    $content = '{{$#var.foo.bar}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-    $macro->set('var', array('foo' => array('bar' => 'Hey')));
-
-    $out = $macro->render();
-    $this->assertEqual($out, 'Hey');
-  }
-
-  function testBrokenChainOutputForArray()
-  {
-    $content = '{{$#var.foo.bar.baz}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-
-    $macro->set('var', null);
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-
-    $macro->set('var', array('foo' => null));
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-
-    $macro->set('var', array('foo' => array('bar' => null)));
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-  }
-
-  function testSimpleChainedOutputForObject()
-  {
-    $content = '{{$#var.foo.bar}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-    $macro->set('var', new lmbObject(array('foo' => new lmbObject(array('bar' => 'Hey')))));
-
-    $out = $macro->render();
-    $this->assertEqual($out, 'Hey');
-  }
-
-  function testBrokenChainOutputForObject()
-  {
-    $content = '{{$#var.foo.bar.baz}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-
-    $macro->set('var', null);
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-
-    $macro->set('var', new lmbObject(array('foo' => null)));
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-
-    $macro->set('var', new lmbObject(array('foo' => new lmbObject(array('bar' => null)))));
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-  }
-
-  function testChainedOutputForMixedArraysAndObjects()
-  {
-    $content = '{{$#var.foo.bar}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-    $macro->set('var', new lmbObject(array('foo' => array('bar' => 'Hey'))));
-
-    $out = $macro->render();
-    $this->assertEqual($out, 'Hey'); 
-  }
-
-  function testBrokenChainOutputForMixedArraysAndObjects()
-  {
-    $content = '{{$#var.foo.bar.baz}}';
-
-    $tpl = $this->_createTemplate($content, 'tpl.html');
-
-    $macro = $this->_createMacro($tpl);
-
-    $macro->set('var', new lmbObject(array('foo' => array('bar' => null))));
-    $out = $macro->render();
-    $this->assertEqual($out, '');
-  }
-
-  protected function _createMacro($file)
-  {
-    $base_dir = LIMB_VAR_DIR . '/tpl';
-    $cache_dir = LIMB_VAR_DIR . '/tpl/compiled';
-    $macro = new lmbMacroTemplate($file, new lmbMacroConfig($cache_dir, true, true, array($base_dir)));
-    return $macro;
-  }
-
-  protected function _createTemplate($code, $name)
-  {
-    $file = LIMB_VAR_DIR . '/tpl/' . $name;
-    file_put_contents($file, $code);
-    return $file;
-  }
-}
-

Modified: 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroWrapTagTest.class.php
===================================================================
--- 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroWrapTagTest.class.php	2007-10-05 11:38:27 UTC (rev 6384)
+++ 3.x/trunk/limb/macro/tests/cases/tags/lmbMacroWrapTagTest.class.php	2007-10-05 14:12:03 UTC (rev 6385)
@@ -2,23 +2,13 @@
 /*
  * Limb PHP Framework
  *
- * @link http://limb-project.com 
+ * @link http://limb-project.com
  * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 
-lmb_require('limb/fs/src/lmbFs.class.php');
-lmb_require('limb/macro/src/lmbMacroTemplate.class.php');
-lmb_require('limb/macro/src/lmbMacroTagDictionary.class.php');
-
-class lmbMacroWrapTagTest extends UnitTestCase
+class lmbMacroWrapTagTest extends lmbBaseMacroTest
 {
-  function setUp()
-  {
-    lmbFs :: rm(LIMB_VAR_DIR . '/tpl');
-    lmbFs :: mkdir(LIMB_VAR_DIR . '/tpl/compiled');
-  }
-
   function testSimpleStaticWrap()
   {
     $bar = '{{wrap with="foo.html" into="slot1"}}Bob{{/wrap}}';
@@ -80,7 +70,7 @@
   }
 
   function testSimpleDynamicWrap()
-  {    
+  {
     $bar = '{{wrap with="$this->layout" into="slot1"}}Bob{{/wrap}}';
     $foo = '<p>Hello, {{slot id="slot1"/}}</p>';
 
@@ -91,7 +81,7 @@
     $macro->set('layout', 'foo.html');
 
     $out = $macro->render();
-    $this->assertEqual($out, '<p>Hello, Bob</p>'); 
+    $this->assertEqual($out, '<p>Hello, Bob</p>');
   }
 
   function testMultiDynamicWrap()
@@ -186,7 +176,7 @@
     $macro = $this->_createMacro($bar_tpl);
 
     $out = $macro->render();
-    $this->assertEqual($out, 'Bob'); 
+    $this->assertEqual($out, 'Bob');
   }
 
   function testDynamicallyWrappedChildLocalVarsAreIsolated()
@@ -201,22 +191,7 @@
     $macro->set('layout', 'foo.html');
 
     $out = $macro->render();
-    $this->assertEqual($out, 'Bob'); 
+    $this->assertEqual($out, 'Bob');
   }
-
-  protected function _createMacro($file)
-  {
-    $base_dir = LIMB_VAR_DIR . '/tpl';
-    $cache_dir = LIMB_VAR_DIR . '/tpl/compiled';
-    $macro = new lmbMacroTemplate($file, new lmbMacroConfig($cache_dir, true, true, array($base_dir)));
-    return $macro;
-  }
-
-  protected function _createTemplate($code, $name)
-  {
-    $file = LIMB_VAR_DIR . '/tpl/' . $name;
-    file_put_contents($file, $code);
-    return $file;
-  }
 }
 



More information about the limb-svn mailing list