@@ -12,7 +12,7 @@ public static function render($template, $data, $functions = array())
1212
1313 private static function createNode ($ type , $ expression )
1414 {
15- return (object ) array ('type ' => $ type , 'expression ' => $ expression , 'children ' => array ());
15+ return (object ) array ('type ' => $ type , 'expression ' => $ expression , 'children ' => array (), ' value ' => null );
1616 }
1717
1818 private static function tokenize ($ template )
@@ -47,6 +47,9 @@ private static function createSyntaxTree(&$tokens)
4747 } elseif ($ token == 'endfor ' ) {
4848 $ type = 'endfor ' ;
4949 $ expression = false ;
50+ } elseif ($ token == 'else ' ) {
51+ $ type = 'else ' ;
52+ $ expression = false ;
5053 } elseif (substr ($ token , 0 , 3 ) == 'if: ' ) {
5154 $ type = 'if ' ;
5255 $ expression = substr ($ token , 3 );
@@ -57,15 +60,18 @@ private static function createSyntaxTree(&$tokens)
5760 $ type = 'var ' ;
5861 $ expression = $ token ;
5962 }
60- if (in_array ($ type , array ('endif ' , 'endfor ' ))) {
61- $ current = array_pop ($ stack );
62- } else {
63+ if (in_array ($ type , array ('endif ' , 'endfor ' , 'else ' ))) {
64+ if (count ($ stack )) {
65+ $ current = array_pop ($ stack );
66+ }
67+ }
68+ if (in_array ($ type , array ('if ' , 'for ' , 'var ' , 'else ' ))) {
6369 $ node = Template::createNode ($ type , $ expression );
6470 array_push ($ current ->children , $ node );
65- if ( in_array ( $ type , array ( ' if ' , ' for ' ))) {
66- array_push ( $ stack , $ current );
67- $ current = $ node ;
68- }
71+ }
72+ if ( in_array ( $ type , array ( ' if ' , ' for ' , ' else ' ))) {
73+ array_push ( $ stack , $ current ) ;
74+ $ current = $ node ;
6975 }
7076 } else {
7177 array_push ($ current ->children , Template::createNode ('lit ' , $ token ));
@@ -77,11 +83,15 @@ private static function createSyntaxTree(&$tokens)
7783 private static function renderChildren ($ node , $ data , $ functions )
7884 {
7985 $ result = '' ;
86+ $ previousChild = null ;
8087 foreach ($ node ->children as $ child ) {
8188 switch ($ child ->type ) {
8289 case 'if ' :
8390 $ result .= Template::renderIfNode ($ child , $ data , $ functions );
8491 break ;
92+ case 'else ' :
93+ $ result .= Template::renderElseNode ($ child , $ previousChild , $ data , $ functions );
94+ break ;
8595 case 'for ' :
8696 $ result .= Template::renderForNode ($ child , $ data , $ functions );
8797 break ;
@@ -92,6 +102,7 @@ private static function renderChildren($node, $data, $functions)
92102 $ result .= $ child ->expression ;
93103 break ;
94104 }
105+ $ previousChild = $ child ;
95106 }
96107 return $ result ;
97108 }
@@ -109,6 +120,19 @@ private static function renderIfNode($node, $data, $functions)
109120 $ result = '' ;
110121 if ($ value ) {
111122 $ result .= Template::renderChildren ($ node , $ data , $ functions );
123+ $ node ->value = $ value ;
124+ }
125+ return $ result ;
126+ }
127+
128+ private static function renderElseNode ($ node , $ previousNode , $ data , $ functions )
129+ {
130+ if ($ previousNode ->type != 'if ' ) {
131+ return "{{else!!could not find matching 'if'}} " ;
132+ }
133+ $ result = '' ;
134+ if (!$ previousNode ->value ) {
135+ $ result .= Template::renderChildren ($ node , $ data , $ functions );
112136 }
113137 return $ result ;
114138 }
@@ -117,11 +141,15 @@ private static function renderForNode($node, $data, $functions)
117141 {
118142 $ parts = explode ('| ' , $ node ->expression );
119143 $ path = array_shift ($ parts );
120- $ path = explode (': ' , $ path , 2 );
121- if (count ($ path ) != 2 ) {
144+ $ path = explode (': ' , $ path , 3 );
145+ if (count ($ path ) == 2 ) {
146+ list ($ var , $ path ) = $ path ;
147+ $ key = false ;
148+ } elseif (count ($ path ) == 3 ) {
149+ list ($ var , $ key , $ path ) = $ path ;
150+ } else {
122151 return '{{for: ' . $ node ->expression . '!! ' . "for must have 'for:var:array' format " . '}} ' ;
123152 }
124- list ($ var , $ path ) = $ path ;
125153 try {
126154 $ value = Template::resolvePath ($ path , $ data );
127155 $ value = Template::applyFunctions ($ value , $ parts , $ functions );
@@ -132,8 +160,8 @@ private static function renderForNode($node, $data, $functions)
132160 return '{{for: ' . $ node ->expression . '!! ' . "expression must evaluate to an array " . '}} ' ;
133161 }
134162 $ result = '' ;
135- foreach ($ value as $ v ) {
136- $ data = array_merge ($ data , [$ var => $ v ]);
163+ foreach ($ value as $ k => $ v ) {
164+ $ data = array_merge ($ data , $ key ? [ $ var => $ v , $ key => $ k ] : [$ var => $ v ]);
137165 $ result .= Template::renderChildren ($ node , $ data , $ functions );
138166 }
139167 return $ result ;
0 commit comments