associative arrays as parameters

Heiko Roth <[email protected]> Tue, 05 Sep 2006 15:00:11 +0200
Newsgroups gmane.comp.php.smarty.devel
Message-ID <[email protected]>
Hello Monte,

I send you a small patch which allows associative arrays as plugin params.
An example:

{navigation id=$site->rootId var=nav
query.fields="id,name,url,order_field" query.where="type='news/entry'"}

Plugin code:
function smarty_function_navigation($params, &$smarty)
{
    $children = $nav->getChildren($params['query'], array('no_nav_hide'
=> true));
    if (!$children) return false;
    $smarty->assign($params['var'], $children);
}


without patch:
{navigation id=$site->rootId var=nav
query="array('fields'=>'id,name,url,order_field',
'where'=>'type=\'news/entry\''}

Plugin code:
function smarty_function_navigation($params, &$smarty)
{
    $params['query'] = eval($params['query']); // This is evil.
    $children = $nav->getChildren($params['query'], array('no_nav_hide'
=> true));
    if (!$children) return false;
    $smarty->assign($params['var'], $children);
}


or
{navigation id=$site->rootId var=nav
query_fields="id,name,url,order_field" query_where="type='news/entry'"}
drawback: You have to define and process every possible key.

Plugin code:
function smarty_function_navigation($params, &$smarty)
{
    $params['query'] = array();
    if (isset($params['query_order']))
    {
        $params['query']['order'] = $params['query_order'];
    }
    if (isset($params['query_fields']))
    {
        $params['query']['fields'] = $params['query_fields'];
    }
    if (isset($params['query_where']))
    {
        $params['query']['where'] = $params['query_where'];
    }
    if (isset($params['query_from']))
    {
        $params['query']['from'] = $params['query_from'];
    }
    $children = $nav->getChildren($params['query'], array('no_nav_hide'
=> true));
    if (!$children) return false;
    $smarty->assign($params['var'], $children);
}


We define Smarty plugins as an interface to our framework. With the
associative notation described above, we can extend our framework and
the extension can be used by our designers without changing the Smarty
plugin.
Another benefit is that the plugin code is much smaller.
This patch is completly compatible with all plugins. We use it for
several months now.

Please consider to bring the patch to 2.6.15  ;-) 
This patch works multidimensional, too.

Thanks,
Heiko.

Heiko Roth.

Dipl. Inform.
GeschÀftsfÌhrer
EGOTEC GmbH
Alte Neckarelzer Straße 24 D
D-74821 Mosbach

Telefon +49 (0) 6261/674318
Fax +49 (0) 6261/674329
E-Mail [email protected]
Internet www.egocms.com
PGP-ID: 0x5EA92BC7

-- 
Smarty Development Mailing List (http://smarty.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
smarty-2.6.14-associative-arrays.diff.patch (text/x-patch, 2.3 KB)
Index: Smarty_Compiler.class.php
===================================================================
--- Smarty_Compiler.class.php	(Revision 23425)
+++ Smarty_Compiler.class.php	(Revision 23427)
@@ -1529,7 +1529,7 @@
                 case 0:
                     /* If the token is a valid identifier, we set attribute name
                        and go to state 1. */
-                    if (preg_match('~^\w+$~', $token)) {
+                    if (preg_match('~^[\w\.]+$~', $token)) {
                         $attr_name = $token;
                         $state = 1;
                     } else
@@ -1562,8 +1562,19 @@
                             /* treat as a string, double-quote it escaping quotes */
                             $token = '"'.addslashes($token).'"';
                         }
-
-                        $attrs[$attr_name] = $token;
+                        if (strpos($attr_name, '.')===false)
+                        {
+                            $attrs[$attr_name] = $token;
+                        } else { // Input of associative arrays with notation test.foo="4711" test.foo2="water" becomes $params[test][foo]="4711" and $params[test][foo2]="water"
+                            $attr_name2 = explode('.', $attr_name);
+                            $attrs2 = $token;
+                            while ($attr_name3 = array_pop($attr_name2))
+                            {
+                                $attrs3 = array($attr_name3 => $attrs2);
+                                $attrs2 = $attrs3;
+                            }
+                            $attrs = array_merge_recursive($attrs, $attrs2);
+                        }
                         $state = 0;
                     } else
                         $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
@@ -1608,6 +1619,15 @@
      */
     function _parse_var_props($val)
     {
+        if (is_array($val))
+        { // Associative arrays.
+           $a = array();
+           foreach ($val as $key => $value)
+           {
+               $a[] = "'$key' => ".$this->_parse_var_props($value);
+           }
+           return 'array('.join(',', $a).')';
+        }
         $val = trim($val);
 
         if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {