Passed
Push — master ( 101b9a...e7ce0a )
by David
04:07 queued 11s
created
lib/Dwoo/Compiler.php 5 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
     /**
278 278
      * Returns the left and right template delimiters.
279 279
      *
280
-     * @return array containing the left and the right delimiters
280
+     * @return string[] containing the left and the right delimiters
281 281
      */
282 282
     public function getDelimiters()
283 283
     {
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
      * Adds a preprocessor to the compiler, it will be called
363 363
      * before the template is compiled.
364 364
      *
365
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
365
+     * @param string $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
366 366
      *                        true
367 367
      * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else
368 368
      *                        you must provide a valid callback
@@ -1321,7 +1321,7 @@  discard block
 block discarded – undo
1321 1321
      *
1322 1322
      * @param array $params parameter array
1323 1323
      *
1324
-     * @return array tokens
1324
+     * @return Compiler tokens
1325 1325
      */
1326 1326
     public function getParamTokens(array $params)
1327 1327
     {
Please login to merge, or discard this patch.
Switch Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -769,13 +769,13 @@  discard block
 block discarded – undo
769 769
                         $search = array('{<\?.*?\?>}', '{<%.*?%>}');
770 770
                     }
771 771
                     switch ($this->securityPolicy->getPhpHandling()) {
772
-                        case SecurityPolicy::PHP_ALLOW:
773
-                            break;
774
-                        case SecurityPolicy::PHP_ENCODE:
775
-                            $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
-                            break;
777
-                        case SecurityPolicy::PHP_REMOVE:
778
-                            $tpl = preg_replace($search, '', $tpl);
772
+                    case SecurityPolicy::PHP_ALLOW:
773
+                        break;
774
+                    case SecurityPolicy::PHP_ENCODE:
775
+                        $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
+                        break;
777
+                    case SecurityPolicy::PHP_REMOVE:
778
+                        $tpl = preg_replace($search, '', $tpl);
779 779
                     }
780 780
                 }
781 781
             }
@@ -875,51 +875,51 @@  discard block
 block discarded – undo
875 875
             }
876 876
 
877 877
             switch ($type) {
878
-                case Core::CLASS_PLUGIN:
879
-                case Core::CLASS_PLUGIN + Core::BLOCK_PLUGIN:
880
-                    if (class_exists('Plugin' . $plugin) !== false) {
881
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
-                    } else {
884
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
-                    }
887
-                    break;
888
-                case Core::CLASS_PLUGIN + Core::FUNC_PLUGIN:
889
-                    if (class_exists('Plugin' . $plugin) !== false) {
890
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
891
-                            "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
-                    } else {
893
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
-                            "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
-                    }
896
-                    break;
897
-                case Core::FUNC_PLUGIN:
898
-                    if (function_exists('Plugin' . $plugin) !== false) {
899
-                        $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
878
+            case Core::CLASS_PLUGIN:
879
+            case Core::CLASS_PLUGIN + Core::BLOCK_PLUGIN:
880
+                if (class_exists('Plugin' . $plugin) !== false) {
881
+                    $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
+                } else {
884
+                    $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
+                }
887
+                break;
888
+            case Core::CLASS_PLUGIN + Core::FUNC_PLUGIN:
889
+                if (class_exists('Plugin' . $plugin) !== false) {
890
+                    $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
900 891
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
901
-                    } else {
902
-                        $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
892
+                } else {
893
+                    $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
903 894
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
904
-                    }
905
-                    break;
906
-                case Core::SMARTY_MODIFIER:
907
-                    $output .= "if (function_exists('smarty_modifier_$plugin')===false)".
908
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
909
-                    break;
910
-                case Core::SMARTY_FUNCTION:
911
-                    $output .= "if (function_exists('smarty_function_$plugin')===false)".
912
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
913
-                    break;
914
-                case Core::SMARTY_BLOCK:
915
-                    $output .= "if (function_exists('smarty_block_$plugin')===false)".
916
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
917
-                    break;
918
-                case Core::PROXY_PLUGIN:
919
-                    $output .= $this->getCore()->getPluginProxy()->getLoader($plugin);
920
-                    break;
921
-                default:
922
-                    throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
895
+                }
896
+                break;
897
+            case Core::FUNC_PLUGIN:
898
+                if (function_exists('Plugin' . $plugin) !== false) {
899
+                    $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
900
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
901
+                } else {
902
+                    $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
903
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
904
+                }
905
+                break;
906
+            case Core::SMARTY_MODIFIER:
907
+                $output .= "if (function_exists('smarty_modifier_$plugin')===false)".
908
+                "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
909
+                break;
910
+            case Core::SMARTY_FUNCTION:
911
+                $output .= "if (function_exists('smarty_function_$plugin')===false)".
912
+                "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
913
+                break;
914
+            case Core::SMARTY_BLOCK:
915
+                $output .= "if (function_exists('smarty_block_$plugin')===false)".
916
+                "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
917
+                break;
918
+            case Core::PROXY_PLUGIN:
919
+                $output .= $this->getCore()->getPluginProxy()->getLoader($plugin);
920
+                break;
921
+            default:
922
+                throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
923 923
             }
924 924
         }
925 925
 
Please login to merge, or discard this patch.
Braces   +3 added lines, -6 removed lines patch added patch discarded remove patch
@@ -478,8 +478,7 @@  discard block
 block discarded – undo
478 478
         if (!class_exists($class) && !function_exists($class)) {
479 479
             try {
480 480
                 $this->getCore()->getLoader()->loadPlugin($name);
481
-            }
482
-            catch (Exception $e) {
481
+            } catch (Exception $e) {
483 482
                 throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
484 483
             }
485 484
         }
@@ -1632,8 +1631,7 @@  discard block
 block discarded – undo
1632 1631
                     // load if plugin
1633 1632
                     try {
1634 1633
                         $this->getPluginType('if');
1635
-                    }
1636
-                    catch (Exception $e) {
1634
+                    } catch (Exception $e) {
1637 1635
                         throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1638 1636
                     }
1639 1637
 
@@ -3454,8 +3452,7 @@  discard block
 block discarded – undo
3454 3452
                 if ($pluginType === - 1) {
3455 3453
                     try {
3456 3454
                         $this->getCore()->getLoader()->loadPlugin('Plugin' . Core::toCamelCase($name));
3457
-                    }
3458
-                    catch (Exception $e) {
3455
+                    } catch (Exception $e) {
3459 3456
                         if (isset($phpFunc)) {
3460 3457
                             $pluginType = Core::NATIVE_PLUGIN;
3461 3458
                         } elseif (is_object($this->getCore()->getPluginProxy()) && $this->getCore()->getPluginProxy()->handles($name)) {
Please login to merge, or discard this patch.
Spacing   +384 added lines, -386 removed lines patch added patch discarded remove patch
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
      */
295 295
     public function setNestedCommentsHandling($allow = true)
296 296
     {
297
-        $this->allowNestedComments = (bool)$allow;
297
+        $this->allowNestedComments = (bool) $allow;
298 298
     }
299 299
 
300 300
     /**
@@ -319,7 +319,7 @@  discard block
 block discarded – undo
319 319
      */
320 320
     public function setLooseOpeningHandling($allow = false)
321 321
     {
322
-        $this->allowLooseOpenings = (bool)$allow;
322
+        $this->allowLooseOpenings = (bool) $allow;
323 323
     }
324 324
 
325 325
     /**
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
      */
345 345
     public function setAutoEscape($enabled)
346 346
     {
347
-        $this->autoEscape = (bool)$enabled;
347
+        $this->autoEscape = (bool) $enabled;
348 348
     }
349 349
 
350 350
     /**
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
     {
372 372
         if ($autoload) {
373 373
             $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', Core::toCamelCase($callback));
374
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . $name;
374
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.$name;
375 375
 
376 376
             if (class_exists($class)) {
377 377
                 $callback = array(new $class($this), 'process');
@@ -396,12 +396,12 @@  discard block
 block discarded – undo
396 396
     {
397 397
         if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
398 398
             unset($this->processors['pre'][$index]);
399
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
399
+        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
400 400
                     $callback),
401 401
                 $this->processors['pre'], true)) !== false) {
402 402
             unset($this->processors['pre'][$index]);
403 403
         } else {
404
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
404
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
405 405
             foreach ($this->processors['pre'] as $index => $proc) {
406 406
                 if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
407 407
                     unset($this->processors['pre'][$index]);
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
     {
425 425
         if ($autoload) {
426 426
             $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
427
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . Core::toCamelCase($name);
427
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.Core::toCamelCase($name);
428 428
 
429 429
             if (class_exists($class)) {
430 430
                 $callback = array(new $class($this), 'process');
@@ -449,12 +449,12 @@  discard block
 block discarded – undo
449 449
     {
450 450
         if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
451 451
             unset($this->processors['post'][$index]);
452
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
452
+        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
453 453
                     $callback),
454 454
                 $this->processors['post'], true)) !== false) {
455 455
             unset($this->processors['post'][$index]);
456 456
         } else {
457
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
457
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
458 458
             foreach ($this->processors['post'] as $index => $proc) {
459 459
                 if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
460 460
                     unset($this->processors['post'][$index]);
@@ -480,7 +480,7 @@  discard block
 block discarded – undo
480 480
                 $this->getCore()->getLoader()->loadPlugin($name);
481 481
             }
482 482
             catch (Exception $e) {
483
-                throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
483
+                throw new Exception('Processor '.$name.' could not be found in your plugin directories, please ensure it is in a file named '.$name.'.php in the plugin directory');
484 484
             }
485 485
         }
486 486
 
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
     public function setTemplateSource($newSource, $fromPointer = false)
667 667
     {
668 668
         if ($fromPointer === true) {
669
-            $this->templateSource = substr($this->templateSource, 0, $this->pointer) . $newSource;
669
+            $this->templateSource = substr($this->templateSource, 0, $this->pointer).$newSource;
670 670
         } else {
671 671
             $this->templateSource = $newSource;
672 672
         }
@@ -737,11 +737,11 @@  discard block
 block discarded – undo
737 737
 
738 738
                 if ($this->debug) {
739 739
                     echo "\n";
740
-                    echo 'COMPILER INIT' . "\n";
740
+                    echo 'COMPILER INIT'."\n";
741 741
                 }
742 742
 
743 743
                 if ($this->debug) {
744
-                    echo 'PROCESSING PREPROCESSORS (' . count($this->processors['pre']) . ')' . "\n";
744
+                    echo 'PROCESSING PREPROCESSORS ('.count($this->processors['pre']).')'."\n";
745 745
                 }
746 746
 
747 747
                 // runs preprocessors
@@ -785,23 +785,23 @@  discard block
 block discarded – undo
785 785
             if ($pos === false) {
786 786
                 $this->push(substr($tpl, $ptr), 0);
787 787
                 break;
788
-            } elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
789
-                $this->push(substr($tpl, $ptr, $pos - $ptr - 1) . $this->ld);
790
-                $ptr = $pos + strlen($this->ld);
791
-            } elseif (preg_match('/^' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . 'literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', substr($tpl, $pos), $litOpen)) {
792
-                if (!preg_match('/' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . '\/literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
788
+            } elseif (substr($tpl, $pos-1, 1) === '\\' && substr($tpl, $pos-2, 1) !== '\\') {
789
+                $this->push(substr($tpl, $ptr, $pos-$ptr-1).$this->ld);
790
+                $ptr = $pos+strlen($this->ld);
791
+            } elseif (preg_match('/^'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', substr($tpl, $pos), $litOpen)) {
792
+                if (!preg_match('/'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'\/literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
793 793
                     throw new CompilationException($this, 'The {literal} blocks must be closed explicitly with {/literal}');
794 794
                 }
795 795
                 $endpos = $litClose[0][1];
796
-                $this->push(substr($tpl, $ptr, $pos - $ptr) . substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
797
-                $ptr = $endpos + strlen($litClose[0][0]);
796
+                $this->push(substr($tpl, $ptr, $pos-$ptr).substr($tpl, $pos+strlen($litOpen[0]), $endpos-$pos-strlen($litOpen[0])));
797
+                $ptr = $endpos+strlen($litClose[0][0]);
798 798
             } else {
799
-                if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
800
-                    $this->push(substr($tpl, $ptr, $pos - $ptr - 1));
799
+                if (substr($tpl, $pos-2, 1) === '\\' && substr($tpl, $pos-1, 1) === '\\') {
800
+                    $this->push(substr($tpl, $ptr, $pos-$ptr-1));
801 801
                     $ptr = $pos;
802 802
                 }
803 803
 
804
-                $this->push(substr($tpl, $ptr, $pos - $ptr));
804
+                $this->push(substr($tpl, $ptr, $pos-$ptr));
805 805
                 $ptr = $pos;
806 806
 
807 807
                 $pos += strlen($this->ld);
@@ -819,7 +819,7 @@  discard block
 block discarded – undo
819 819
 
820 820
                 // check that there is an end tag present
821 821
                 if (strpos($tpl, $this->rd, $pos) === false) {
822
-                    throw new CompilationException($this, 'A template tag was not closed, started with "' . substr($tpl, $ptr, 30) . '"');
822
+                    throw new CompilationException($this, 'A template tag was not closed, started with "'.substr($tpl, $ptr, 30).'"');
823 823
                 }
824 824
 
825 825
                 $ptr += strlen($this->ld);
@@ -833,7 +833,7 @@  discard block
 block discarded – undo
833 833
                         continue 2;
834 834
                     }
835 835
 
836
-                    $len = $subptr - $ptr;
836
+                    $len = $subptr-$ptr;
837 837
                     $this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
838 838
                     $ptr += $len;
839 839
 
@@ -847,7 +847,7 @@  discard block
 block discarded – undo
847 847
         $compiled .= $this->removeBlock('TopLevelBlock');
848 848
 
849 849
         if ($this->debug) {
850
-            echo 'PROCESSING POSTPROCESSORS' . "\n";
850
+            echo 'PROCESSING POSTPROCESSORS'."\n";
851 851
         }
852 852
 
853 853
         foreach ($this->processors['post'] as $postProc) {
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
         unset($postProc);
864 864
 
865 865
         if ($this->debug) {
866
-            echo 'COMPILATION COMPLETE : MEM USAGE : ' . memory_get_usage() . "\n";
866
+            echo 'COMPILATION COMPLETE : MEM USAGE : '.memory_get_usage()."\n";
867 867
         }
868 868
 
869 869
         $output = "<?php\n/* template head */\n";
@@ -876,30 +876,30 @@  discard block
 block discarded – undo
876 876
 
877 877
             switch ($type) {
878 878
                 case Core::CLASS_PLUGIN:
879
-                case Core::CLASS_PLUGIN + Core::BLOCK_PLUGIN:
880
-                    if (class_exists('Plugin' . $plugin) !== false) {
881
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
879
+                case Core::CLASS_PLUGIN+Core::BLOCK_PLUGIN:
880
+                    if (class_exists('Plugin'.$plugin) !== false) {
881
+                        $output .= "if (class_exists('"."Plugin".$plugin."')===false)".
882 882
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883 883
                     } else {
884
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
884
+                        $output .= "if (class_exists('".Core::NAMESPACE_PLUGINS_BLOCKS."Plugin".$plugin."')===false)".
885 885
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886 886
                     }
887 887
                     break;
888
-                case Core::CLASS_PLUGIN + Core::FUNC_PLUGIN:
889
-                    if (class_exists('Plugin' . $plugin) !== false) {
890
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
888
+                case Core::CLASS_PLUGIN+Core::FUNC_PLUGIN:
889
+                    if (class_exists('Plugin'.$plugin) !== false) {
890
+                        $output .= "if (class_exists('"."Plugin".$plugin."')===false)".
891 891
                             "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892 892
                     } else {
893
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
893
+                        $output .= "if (class_exists('".Core::NAMESPACE_PLUGINS_FUNCTIONS."Plugin".$plugin."')===false)".
894 894
                             "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895 895
                     }
896 896
                     break;
897 897
                 case Core::FUNC_PLUGIN:
898
-                    if (function_exists('Plugin' . $plugin) !== false) {
899
-                        $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
898
+                    if (function_exists('Plugin'.$plugin) !== false) {
899
+                        $output .= "if (function_exists('"."Plugin".$plugin."')===false)".
900 900
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
901 901
                     } else {
902
-                        $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
902
+                        $output .= "if (function_exists('".Core::NAMESPACE_PLUGINS_FUNCTIONS."Plugin".$plugin."')===false)".
903 903
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
904 904
                     }
905 905
                     break;
@@ -919,7 +919,7 @@  discard block
 block discarded – undo
919 919
                     $output .= $this->getCore()->getPluginProxy()->getLoader($plugin);
920 920
                     break;
921 921
                 default:
922
-                    throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
922
+                    throw new CompilationException($this, 'Type error for '.$plugin.' with type'.$type);
923 923
             }
924 924
         }
925 925
 
@@ -930,30 +930,30 @@  discard block
 block discarded – undo
930 930
         }
931 931
         foreach ($this->templatePlugins as $function) {
932 932
             if (isset($function['called']) && $function['called'] === true) {
933
-                $output .= $function['body'] . PHP_EOL;
933
+                $output .= $function['body'].PHP_EOL;
934 934
             }
935 935
         }
936 936
 
937
-        $output .= $compiled . "\n?>";
937
+        $output .= $compiled."\n?>";
938 938
 
939
-        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*' . preg_quote(self::PHP_CLOSE, '/') . preg_quote(self::PHP_OPEN, '/') . ')/', ";\n", $output);
940
-        $output = str_replace(self::PHP_CLOSE . self::PHP_OPEN, "\n", $output);
939
+        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*'.preg_quote(self::PHP_CLOSE, '/').preg_quote(self::PHP_OPEN, '/').')/', ";\n", $output);
940
+        $output = str_replace(self::PHP_CLOSE.self::PHP_OPEN, "\n", $output);
941 941
 
942 942
         // handle <?xml tag at the beginning
943 943
         $output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
944 944
 
945 945
         // add another line break after PHP closing tags that have a line break following,
946 946
         // as we do not know whether it's intended, and PHP will strip it otherwise
947
-        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0' . "\n", $output);
947
+        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0'."\n", $output);
948 948
 
949 949
         if ($this->debug) {
950
-            echo '=============================================================================================' . "\n";
950
+            echo '============================================================================================='."\n";
951 951
             $lines = preg_split('{\r\n|\n|<br />}', $output);
952 952
             array_shift($lines);
953 953
             foreach ($lines as $i => $line) {
954
-                echo ($i + 1) . '. ' . $line . "\r\n";
954
+                echo ($i+1).'. '.$line."\r\n";
955 955
             }
956
-            echo '=============================================================================================' . "\n";
956
+            echo '============================================================================================='."\n";
957 957
         }
958 958
 
959 959
         $this->template = $this->dwoo = null;
@@ -970,13 +970,13 @@  discard block
 block discarded – undo
970 970
     protected function resolveSubTemplateDependencies($function)
971 971
     {
972 972
         if ($this->debug) {
973
-            echo 'Compiler::' . __FUNCTION__ . "\n";
973
+            echo 'Compiler::'.__FUNCTION__."\n";
974 974
         }
975 975
 
976 976
         $body = $this->templatePlugins[$function]['body'];
977 977
         foreach ($this->templatePlugins as $func => $attr) {
978
-            if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS .
979
-            'Plugin' . Core::toCamelCase($func)) !== false) {
978
+            if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS.
979
+            'Plugin'.Core::toCamelCase($func)) !== false) {
980 980
                 $this->templatePlugins[$func]['called'] = true;
981 981
                 $this->resolveSubTemplateDependencies($func);
982 982
             }
@@ -1000,14 +1000,14 @@  discard block
 block discarded – undo
1000 1000
 
1001 1001
         if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
1002 1002
             // buffer is not initialized yet (the block has just been created)
1003
-            $this->stack[count($this->stack) - 2]['buffer'] .= (string)$content;
1003
+            $this->stack[count($this->stack)-2]['buffer'] .= (string) $content;
1004 1004
             $this->curBlock['buffer'] = '';
1005 1005
         } else {
1006 1006
             if (!isset($this->curBlock['buffer'])) {
1007 1007
                 throw new CompilationException($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
1008 1008
             }
1009 1009
             // append current content to current block's buffer
1010
-            $this->curBlock['buffer'] .= (string)$content;
1010
+            $this->curBlock['buffer'] .= (string) $content;
1011 1011
         }
1012 1012
         $this->line += $lineCount;
1013 1013
     }
@@ -1077,26 +1077,26 @@  discard block
 block discarded – undo
1077 1077
     public function addBlock($type, array $params, $paramtype)
1078 1078
     {
1079 1079
         if ($this->debug) {
1080
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1080
+            echo 'Compiler::'.__FUNCTION__."\n";
1081 1081
         }
1082 1082
 
1083 1083
         $class = current(array_filter([
1084
-            'Plugin' . Core::toCamelCase($type),
1085
-            Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type)
1084
+            'Plugin'.Core::toCamelCase($type),
1085
+            Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($type)
1086 1086
         ], 'class_exists'));
1087 1087
         if (false === $class) {
1088 1088
             $this->getCore()->getLoader()->loadPlugin($type);
1089 1089
         }
1090 1090
         $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1091 1091
 
1092
-        $this->stack[]  = array(
1092
+        $this->stack[] = array(
1093 1093
             'type'   => $type,
1094 1094
             'params' => $params,
1095 1095
             'custom' => false,
1096 1096
             'class'  => $class,
1097 1097
             'buffer' => null
1098 1098
         );
1099
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1099
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1100 1100
 
1101 1101
         return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1102 1102
     }
@@ -1121,14 +1121,14 @@  discard block
 block discarded – undo
1121 1121
 
1122 1122
         $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1123 1123
 
1124
-        $this->stack[]  = array(
1124
+        $this->stack[] = array(
1125 1125
             'type'   => $type,
1126 1126
             'params' => $params,
1127 1127
             'custom' => true,
1128 1128
             'class'  => $class,
1129 1129
             'buffer' => null
1130 1130
         );
1131
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1131
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1132 1132
 
1133 1133
         return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1134 1134
     }
@@ -1143,21 +1143,21 @@  discard block
 block discarded – undo
1143 1143
     public function injectBlock($type, array $params)
1144 1144
     {
1145 1145
         if ($this->debug) {
1146
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1146
+            echo 'Compiler::'.__FUNCTION__."\n";
1147 1147
         }
1148 1148
 
1149
-        $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1149
+        $class = Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($type);
1150 1150
         if (class_exists($class) === false) {
1151 1151
             $this->getCore()->getLoader()->loadPlugin($type);
1152 1152
         }
1153
-        $this->stack[]  = array(
1153
+        $this->stack[] = array(
1154 1154
             'type'   => $type,
1155 1155
             'params' => $params,
1156 1156
             'custom' => false,
1157 1157
             'class'  => $class,
1158 1158
             'buffer' => null
1159 1159
         );
1160
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1160
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1161 1161
     }
1162 1162
 
1163 1163
     /**
@@ -1172,7 +1172,7 @@  discard block
 block discarded – undo
1172 1172
     public function removeBlock($type)
1173 1173
     {
1174 1174
         if ($this->debug) {
1175
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1175
+            echo 'Compiler::'.__FUNCTION__."\n";
1176 1176
         }
1177 1177
 
1178 1178
         $output = '';
@@ -1187,12 +1187,12 @@  discard block
 block discarded – undo
1187 1187
                     $class = $top['class'];
1188 1188
                 } else {
1189 1189
                     $class = current(array_filter([
1190
-                        'Plugin' . Core::toCamelCase($top['type']),
1191
-                        Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($top['type'])
1190
+                        'Plugin'.Core::toCamelCase($top['type']),
1191
+                        Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($top['type'])
1192 1192
                     ], 'class_exists'));
1193 1193
                 }
1194 1194
                 if (count($this->stack)) {
1195
-                    $this->curBlock = &$this->stack[count($this->stack) - 1];
1195
+                    $this->curBlock = &$this->stack[count($this->stack)-1];
1196 1196
                     $this->push(call_user_func(array(
1197 1197
                         $class,
1198 1198
                         'postProcessing'
@@ -1213,7 +1213,7 @@  discard block
 block discarded – undo
1213 1213
                 }
1214 1214
             }
1215 1215
 
1216
-            throw new CompilationException($this, 'Syntax malformation, a block of type "' . $type . '" was closed but was not opened');
1216
+            throw new CompilationException($this, 'Syntax malformation, a block of type "'.$type.'" was closed but was not opened');
1217 1217
         }
1218 1218
 
1219 1219
         return $output;
@@ -1251,7 +1251,7 @@  discard block
 block discarded – undo
1251 1251
             }
1252 1252
         }
1253 1253
 
1254
-        throw new CompilationException($this, 'A parent block of type "' . $type . '" is required and can not be found');
1254
+        throw new CompilationException($this, 'A parent block of type "'.$type.'" is required and can not be found');
1255 1255
     }
1256 1256
 
1257 1257
     /**
@@ -1274,7 +1274,7 @@  discard block
 block discarded – undo
1274 1274
     public function removeTopBlock()
1275 1275
     {
1276 1276
         if ($this->debug) {
1277
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1277
+            echo 'Compiler::'.__FUNCTION__."\n";
1278 1278
         }
1279 1279
 
1280 1280
         $o = array_pop($this->stack);
@@ -1284,10 +1284,10 @@  discard block
 block discarded – undo
1284 1284
         if ($o['custom']) {
1285 1285
             $class = $o['class'];
1286 1286
         } else {
1287
-            $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($o['type']);
1287
+            $class = Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($o['type']);
1288 1288
         }
1289 1289
 
1290
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1290
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1291 1291
 
1292 1292
         return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1293 1293
     }
@@ -1366,7 +1366,7 @@  discard block
 block discarded – undo
1366 1366
     protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1367 1367
     {
1368 1368
         if ($this->debug) {
1369
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1369
+            echo 'Compiler::'.__FUNCTION__."\n";
1370 1370
         }
1371 1371
 
1372 1372
         if ($to === null) {
@@ -1383,14 +1383,14 @@  discard block
 block discarded – undo
1383 1383
                 // end template tag
1384 1384
                 $pointer += strlen($this->rd);
1385 1385
                 if ($this->debug) {
1386
-                    echo 'TEMPLATE PARSING ENDED' . "\n";
1386
+                    echo 'TEMPLATE PARSING ENDED'."\n";
1387 1387
                 }
1388 1388
 
1389 1389
                 return false;
1390 1390
             }
1391
-            ++ $from;
1391
+            ++$from;
1392 1392
             if ($pointer !== null) {
1393
-                ++ $pointer;
1393
+                ++$pointer;
1394 1394
             }
1395 1395
             if ($from >= $to) {
1396 1396
                 if (is_array($parsingParams)) {
@@ -1402,22 +1402,22 @@  discard block
 block discarded – undo
1402 1402
             $first = $in[$from];
1403 1403
         }
1404 1404
 
1405
-        $substr = substr($in, $from, $to - $from);
1405
+        $substr = substr($in, $from, $to-$from);
1406 1406
 
1407 1407
         if ($this->debug) {
1408
-            echo 'PARSE CALL : PARSING "' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . '" @ ' . $from . ':' . $to . ' in ' . $curBlock . ' : pointer=' . $pointer . "\n";
1408
+            echo 'PARSE CALL : PARSING "'.htmlentities(substr($in, $from, min($to-$from, 50))).(($to-$from) > 50 ? '...' : '').'" @ '.$from.':'.$to.' in '.$curBlock.' : pointer='.$pointer."\n";
1409 1409
         }
1410 1410
         $parsed = '';
1411 1411
 
1412 1412
         if ($curBlock === 'root' && $first === '*') {
1413 1413
             $src      = $this->getTemplateSource();
1414
-            $startpos = $this->getPointer() - strlen($this->ld);
1414
+            $startpos = $this->getPointer()-strlen($this->ld);
1415 1415
             if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1416 1416
                 if ($startpos > 0) {
1417 1417
                     do {
1418 1418
                         $char = substr($src, -- $startpos, 1);
1419 1419
                         if ($char == "\n") {
1420
-                            ++ $startpos;
1420
+                            ++$startpos;
1421 1421
                             $whitespaceStart = true;
1422 1422
                             break;
1423 1423
                         }
@@ -1428,12 +1428,12 @@  discard block
 block discarded – undo
1428 1428
                 if (!isset($whitespaceStart)) {
1429 1429
                     $startpos = $this->getPointer();
1430 1430
                 } else {
1431
-                    $pointer -= $this->getPointer() - $startpos;
1431
+                    $pointer -= $this->getPointer()-$startpos;
1432 1432
                 }
1433 1433
 
1434
-                if ($this->allowNestedComments && strpos($src, $this->ld . '*', $this->getPointer()) !== false) {
1435
-                    $comOpen  = $this->ld . '*';
1436
-                    $comClose = '*' . $this->rd;
1434
+                if ($this->allowNestedComments && strpos($src, $this->ld.'*', $this->getPointer()) !== false) {
1435
+                    $comOpen  = $this->ld.'*';
1436
+                    $comClose = '*'.$this->rd;
1437 1437
                     $level    = 1;
1438 1438
                     $ptr      = $this->getPointer();
1439 1439
 
@@ -1443,33 +1443,33 @@  discard block
 block discarded – undo
1443 1443
 
1444 1444
                         if ($open !== false && $close !== false) {
1445 1445
                             if ($open < $close) {
1446
-                                $ptr = $open + strlen($comOpen);
1447
-                                ++ $level;
1446
+                                $ptr = $open+strlen($comOpen);
1447
+                                ++$level;
1448 1448
                             } else {
1449
-                                $ptr = $close + strlen($comClose);
1450
-                                -- $level;
1449
+                                $ptr = $close+strlen($comClose);
1450
+                                --$level;
1451 1451
                             }
1452 1452
                         } elseif ($open !== false) {
1453
-                            $ptr = $open + strlen($comOpen);
1454
-                            ++ $level;
1453
+                            $ptr = $open+strlen($comOpen);
1454
+                            ++$level;
1455 1455
                         } elseif ($close !== false) {
1456
-                            $ptr = $close + strlen($comClose);
1457
-                            -- $level;
1456
+                            $ptr = $close+strlen($comClose);
1457
+                            --$level;
1458 1458
                         } else {
1459 1459
                             $ptr = strlen($src);
1460 1460
                         }
1461 1461
                     }
1462
-                    $endpos = $ptr - strlen('*' . $this->rd);
1462
+                    $endpos = $ptr-strlen('*'.$this->rd);
1463 1463
                 } else {
1464
-                    $endpos = strpos($src, '*' . $this->rd, $startpos);
1464
+                    $endpos = strpos($src, '*'.$this->rd, $startpos);
1465 1465
                     if ($endpos == false) {
1466 1466
                         throw new CompilationException($this, 'Un-ended comment');
1467 1467
                     }
1468 1468
                 }
1469
-                $pointer += $endpos - $startpos + strlen('*' . $this->rd);
1470
-                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*' . $this->rd)), $m)) {
1469
+                $pointer += $endpos-$startpos+strlen('*'.$this->rd);
1470
+                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos+strlen('*'.$this->rd)), $m)) {
1471 1471
                     $pointer += strlen($m[0]);
1472
-                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1472
+                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer'])-($this->getPointer()-$startpos-strlen($this->ld)));
1473 1473
                 }
1474 1474
 
1475 1475
                 return false;
@@ -1486,20 +1486,20 @@  discard block
 block discarded – undo
1486 1486
         } elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1487 1487
             // string
1488 1488
             $out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1489
-        } elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?(' . (is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|') . '\s*\(|\s*' . $this->rdr . '|\s*;)/i', $substr)) {
1489
+        } elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?('.(is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|').'\s*\(|\s*'.$this->rdr.'|\s*;)/i', $substr)) {
1490 1490
             // func
1491 1491
             $out    = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1492 1492
             $parsed = 'func';
1493 1493
         } elseif ($first === ';') {
1494 1494
             // instruction end
1495 1495
             if ($this->debug) {
1496
-                echo 'END OF INSTRUCTION' . "\n";
1496
+                echo 'END OF INSTRUCTION'."\n";
1497 1497
             }
1498 1498
             if ($pointer !== null) {
1499
-                ++ $pointer;
1499
+                ++$pointer;
1500 1500
             }
1501 1501
 
1502
-            return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1502
+            return $this->parse($in, $from+1, $to, false, 'root', $pointer);
1503 1503
         } elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1504 1504
             // close block
1505 1505
             if (!empty($match[1]) && $match[1] == 'else') {
@@ -1516,13 +1516,13 @@  discard block
 block discarded – undo
1516 1516
                     $pointer -= strlen($match[0]);
1517 1517
                 }
1518 1518
                 if ($this->debug) {
1519
-                    echo 'TOP BLOCK CLOSED' . "\n";
1519
+                    echo 'TOP BLOCK CLOSED'."\n";
1520 1520
                 }
1521 1521
 
1522 1522
                 return $this->removeTopBlock();
1523 1523
             } else {
1524 1524
                 if ($this->debug) {
1525
-                    echo 'BLOCK OF TYPE ' . $match[1] . ' CLOSED' . "\n";
1525
+                    echo 'BLOCK OF TYPE '.$match[1].' CLOSED'."\n";
1526 1526
                 }
1527 1527
 
1528 1528
                 return $this->removeBlock($match[1]);
@@ -1530,19 +1530,19 @@  discard block
 block discarded – undo
1530 1530
         } elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1531 1531
             // end template tag
1532 1532
             if ($this->debug) {
1533
-                echo 'TAG PARSING ENDED' . "\n";
1533
+                echo 'TAG PARSING ENDED'."\n";
1534 1534
             }
1535 1535
             $pointer += strlen($this->rd);
1536 1536
 
1537 1537
             return false;
1538
-        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*=' . ($curBlock === 'array' ? '>?' : '') . ')(?:\s+|[^=]).*#i', $substr, $match)) {
1538
+        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*='.($curBlock === 'array' ? '>?' : '').')(?:\s+|[^=]).*#i', $substr, $match)) {
1539 1539
             // named parameter
1540 1540
             if ($this->debug) {
1541
-                echo 'NAMED PARAM FOUND' . "\n";
1541
+                echo 'NAMED PARAM FOUND'."\n";
1542 1542
             }
1543 1543
             $len = strlen($match[1]);
1544
-            while (substr($in, $from + $len, 1) === ' ') {
1545
-                ++ $len;
1544
+            while (substr($in, $from+$len, 1) === ' ') {
1545
+                ++$len;
1546 1546
             }
1547 1547
             if ($pointer !== null) {
1548 1548
                 $pointer += $len;
@@ -1550,7 +1550,7 @@  discard block
 block discarded – undo
1550 1550
 
1551 1551
             $output = array(
1552 1552
                 trim($match[1], " \t\r\n=>'\""),
1553
-                $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer)
1553
+                $this->parse($in, $from+$len, $to, false, 'namedparam', $pointer)
1554 1554
             );
1555 1555
 
1556 1556
             $parsingParams[] = $output;
@@ -1571,31 +1571,31 @@  discard block
 block discarded – undo
1571 1571
             $out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1572 1572
         } else {
1573 1573
             // parse error
1574
-            throw new CompilationException($this, 'Parse error in "' . substr($in, $from, $to - $from) . '"');
1574
+            throw new CompilationException($this, 'Parse error in "'.substr($in, $from, $to-$from).'"');
1575 1575
         }
1576 1576
 
1577 1577
         if (empty($out)) {
1578 1578
             return '';
1579 1579
         }
1580 1580
 
1581
-        $substr = substr($in, $pointer, $to - $pointer);
1581
+        $substr = substr($in, $pointer, $to-$pointer);
1582 1582
 
1583 1583
         // var parsed, check if any var-extension applies
1584 1584
         if ($parsed === 'var') {
1585 1585
             if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1586 1586
                 if ($this->debug) {
1587
-                    echo 'PARSING POST-VAR EXPRESSION ' . $substr . "\n";
1587
+                    echo 'PARSING POST-VAR EXPRESSION '.$substr."\n";
1588 1588
                 }
1589 1589
                 // parse expressions
1590
-                $pointer += strlen($match[0]) - 1;
1590
+                $pointer += strlen($match[0])-1;
1591 1591
                 if (is_array($parsingParams)) {
1592 1592
                     if ($match[2] == '$') {
1593 1593
                         $expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1594 1594
                     } else {
1595 1595
                         $expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1596 1596
                     }
1597
-                    $out[count($out) - 1][0] .= $match[1] . $expr[0][0];
1598
-                    $out[count($out) - 1][1] .= $match[1] . $expr[0][1];
1597
+                    $out[count($out)-1][0] .= $match[1].$expr[0][0];
1598
+                    $out[count($out)-1][1] .= $match[1].$expr[0][1];
1599 1599
                 } else {
1600 1600
                     if ($match[2] == '$') {
1601 1601
                         $expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
@@ -1603,26 +1603,26 @@  discard block
 block discarded – undo
1603 1603
                         $expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1604 1604
                     }
1605 1605
                     if (is_array($out) && is_array($expr)) {
1606
-                        $out[0] .= $match[1] . $expr[0];
1607
-                        $out[1] .= $match[1] . $expr[1];
1606
+                        $out[0] .= $match[1].$expr[0];
1607
+                        $out[1] .= $match[1].$expr[1];
1608 1608
                     } elseif (is_array($out)) {
1609
-                        $out[0] .= $match[1] . $expr;
1610
-                        $out[1] .= $match[1] . $expr;
1609
+                        $out[0] .= $match[1].$expr;
1610
+                        $out[1] .= $match[1].$expr;
1611 1611
                     } elseif (is_array($expr)) {
1612
-                        $out .= $match[1] . $expr[0];
1612
+                        $out .= $match[1].$expr[0];
1613 1613
                     } else {
1614
-                        $out .= $match[1] . $expr;
1614
+                        $out .= $match[1].$expr;
1615 1615
                     }
1616 1616
                 }
1617 1617
             } elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1618 1618
                 if ($this->debug) {
1619
-                    echo 'PARSING POST-VAR ASSIGNMENT ' . $substr . "\n";
1619
+                    echo 'PARSING POST-VAR ASSIGNMENT '.$substr."\n";
1620 1620
                 }
1621 1621
                 // parse assignment
1622 1622
                 $value    = $match[2];
1623 1623
                 $operator = trim($match[1]);
1624 1624
                 if (substr($value, 0, 1) == '=') {
1625
-                    throw new CompilationException($this, 'Unexpected "=" in <em>' . $substr . '</em>');
1625
+                    throw new CompilationException($this, 'Unexpected "=" in <em>'.$substr.'</em>');
1626 1626
                 }
1627 1627
 
1628 1628
                 if ($pointer !== null) {
@@ -1643,7 +1643,7 @@  discard block
 block discarded – undo
1643 1643
                         throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1644 1644
                     }
1645 1645
 
1646
-                    $parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS . 'PluginIf', 'init'), 1);
1646
+                    $parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS.'PluginIf', 'init'), 1);
1647 1647
                     $tokens = $this->getParamTokens($parts);
1648 1648
                     $parts  = $this->getCompiledParams($parts);
1649 1649
 
@@ -1657,14 +1657,14 @@  discard block
 block discarded – undo
1657 1657
                 if ($this->autoEscape) {
1658 1658
                     $out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1659 1659
                 }
1660
-                $out = self::PHP_OPEN . $echo . $out . $operator . implode(' ', $value) . self::PHP_CLOSE;
1660
+                $out = self::PHP_OPEN.$echo.$out.$operator.implode(' ', $value).self::PHP_CLOSE;
1661 1661
             } elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1662 1662
                 // parse namedparam with var as name (only for array)
1663 1663
                 if ($this->debug) {
1664
-                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND' . "\n";
1664
+                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND'."\n";
1665 1665
                 }
1666 1666
                 $len = strlen($match[1]);
1667
-                $var = $out[count($out) - 1];
1667
+                $var = $out[count($out)-1];
1668 1668
                 $pointer += $len;
1669 1669
 
1670 1670
                 $output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
@@ -1679,16 +1679,16 @@  discard block
 block discarded – undo
1679 1679
             // parse modifier on funcs or vars
1680 1680
             $srcPointer = $pointer;
1681 1681
             if (is_array($parsingParams)) {
1682
-                $tmp                     = $this->replaceModifiers(
1682
+                $tmp = $this->replaceModifiers(
1683 1683
                     array(
1684 1684
                     null,
1685 1685
                     null,
1686
-                    $out[count($out) - 1][0],
1686
+                    $out[count($out)-1][0],
1687 1687
                     $match[0]
1688 1688
                     ), $curBlock, $pointer
1689 1689
                 );
1690
-                $out[count($out) - 1][0] = $tmp;
1691
-                $out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1690
+                $out[count($out)-1][0] = $tmp;
1691
+                $out[count($out)-1][1] .= substr($substr, $srcPointer, $srcPointer-$pointer);
1692 1692
             } else {
1693 1693
                 $out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1694 1694
             }
@@ -1700,10 +1700,10 @@  discard block
 block discarded – undo
1700 1700
             $ptr = 0;
1701 1701
 
1702 1702
             if (is_array($parsingParams)) {
1703
-                $output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1703
+                $output = $this->parseMethodCall($out[count($out)-1][1], $match[0], $curBlock, $ptr);
1704 1704
 
1705
-                $out[count($out) - 1][0] = $output;
1706
-                $out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1705
+                $out[count($out)-1][0] = $output;
1706
+                $out[count($out)-1][1] .= substr($match[0], 0, $ptr);
1707 1707
             } else {
1708 1708
                 $out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1709 1709
             }
@@ -1712,7 +1712,7 @@  discard block
 block discarded – undo
1712 1712
         }
1713 1713
 
1714 1714
         if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1715
-            return self::PHP_OPEN . 'echo ' . $out . ';' . self::PHP_CLOSE;
1715
+            return self::PHP_OPEN.'echo '.$out.';'.self::PHP_CLOSE;
1716 1716
         }
1717 1717
 
1718 1718
         return $out;
@@ -1738,11 +1738,11 @@  discard block
 block discarded – undo
1738 1738
     protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1739 1739
     {
1740 1740
         $output = '';
1741
-        $cmdstr = substr($in, $from, $to - $from);
1742
-        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*' . $this->rdr . '|\s*;)?/i', $cmdstr, $match);
1741
+        $cmdstr = substr($in, $from, $to-$from);
1742
+        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*'.$this->rdr.'|\s*;)?/i', $cmdstr, $match);
1743 1743
 
1744 1744
         if (empty($match[1])) {
1745
-            throw new CompilationException($this, 'Parse error, invalid function name : ' . substr($cmdstr, 0, 15));
1745
+            throw new CompilationException($this, 'Parse error, invalid function name : '.substr($cmdstr, 0, 15));
1746 1746
         }
1747 1747
 
1748 1748
         $func = $match[1];
@@ -1752,7 +1752,7 @@  discard block
 block discarded – undo
1752 1752
         }
1753 1753
 
1754 1754
         if ($this->debug) {
1755
-            echo 'FUNC FOUND (' . $func . ')' . "\n";
1755
+            echo 'FUNC FOUND ('.$func.')'."\n";
1756 1756
         }
1757 1757
 
1758 1758
         $paramsep = '';
@@ -1764,11 +1764,11 @@  discard block
 block discarded – undo
1764 1764
             $paramspos = $match[1][0][1];
1765 1765
             $paramsep  = substr($match[1][0][0], - 1) === '(' ? ')' : '';
1766 1766
             if ($paramsep === ')') {
1767
-                $paramspos += strlen($match[1][0][0]) - 1;
1767
+                $paramspos += strlen($match[1][0][0])-1;
1768 1768
                 if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1769 1769
                     $paramsep = '';
1770 1770
                     if (strlen($match[1][0][0]) > 1) {
1771
-                        -- $paramspos;
1771
+                        --$paramspos;
1772 1772
                     }
1773 1773
                 }
1774 1774
             }
@@ -1793,8 +1793,8 @@  discard block
 block discarded – undo
1793 1793
                     return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1794 1794
                 }
1795 1795
             }
1796
-            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1797
-            $paramstr   = substr($cmdstr, $paramspos + 1);
1796
+            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos-strlen($func)));
1797
+            $paramstr   = substr($cmdstr, $paramspos+1);
1798 1798
             if (substr($paramstr, - 1, 1) === $paramsep) {
1799 1799
                 $paramstr = substr($paramstr, 0, - 1);
1800 1800
             }
@@ -1816,36 +1816,36 @@  discard block
 block discarded – undo
1816 1816
 
1817 1817
                             if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1818 1818
                                 if ($this->debug) {
1819
-                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT ' . $ptr . "\n";
1819
+                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT '.$ptr."\n";
1820 1820
                                 }
1821 1821
                                 break 2;
1822 1822
                             } elseif ($paramstr[$ptr] === ';') {
1823
-                                ++ $ptr;
1823
+                                ++$ptr;
1824 1824
                                 if ($this->debug) {
1825
-                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT ' . $ptr . "\n";
1825
+                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT '.$ptr."\n";
1826 1826
                                 }
1827 1827
                                 break 2;
1828 1828
                             } elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1829 1829
                                 if ($this->debug) {
1830
-                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT ' . $ptr . "\n";
1830
+                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT '.$ptr."\n";
1831 1831
                                 }
1832 1832
                                 break 2;
1833 1833
                             } elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1834 1834
                                 if ($this->debug) {
1835
-                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT ' . $ptr . "\n";
1835
+                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT '.$ptr."\n";
1836 1836
                                 }
1837 1837
                                 break 2;
1838 1838
                             }
1839 1839
 
1840 1840
                             if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1841
-                                ++ $ptr;
1841
+                                ++$ptr;
1842 1842
                             } else {
1843 1843
                                 break;
1844 1844
                             }
1845 1845
                         }
1846 1846
 
1847 1847
                         if ($this->debug) {
1848
-                            echo 'FUNC START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
1848
+                            echo 'FUNC START PARAM PARSING WITH POINTER AT '.$ptr."\n";
1849 1849
                         }
1850 1850
 
1851 1851
                         if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
@@ -1857,7 +1857,7 @@  discard block
 block discarded – undo
1857 1857
                         }
1858 1858
 
1859 1859
                         if ($this->debug) {
1860
-                            echo 'PARAM PARSED, POINTER AT ' . $ptr . ' (' . substr($paramstr, $ptr - 1, 3) . ')' . "\n";
1860
+                            echo 'PARAM PARSED, POINTER AT '.$ptr.' ('.substr($paramstr, $ptr-1, 3).')'."\n";
1861 1861
                         }
1862 1862
                     }
1863 1863
                 }
@@ -1881,16 +1881,16 @@  discard block
 block discarded – undo
1881 1881
         }
1882 1882
 
1883 1883
         if ($pointer !== null) {
1884
-            $pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1884
+            $pointer += (isset($paramstr) ? strlen($paramstr) : 0)+(')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1))+strlen($func)+(isset($whitespace) ? $whitespace : 0);
1885 1885
             if ($this->debug) {
1886
-                echo 'FUNC ADDS ' . ((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)) . ' TO POINTER' . "\n";
1886
+                echo 'FUNC ADDS '.((isset($paramstr) ? strlen($paramstr) : 0)+(')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1))+strlen($func)).' TO POINTER'."\n";
1887 1887
             }
1888 1888
         }
1889 1889
 
1890 1890
         if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1891 1891
             // handle static method calls with security policy
1892 1892
             if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1893
-                throw new SecurityException('Call to a disallowed php function : ' . $func);
1893
+                throw new SecurityException('Call to a disallowed php function : '.$func);
1894 1894
             }
1895 1895
             $pluginType = Core::NATIVE_PLUGIN;
1896 1896
         } else {
@@ -1935,19 +1935,19 @@  discard block
 block discarded – undo
1935 1935
                     $this->customPlugins[$func]['function']
1936 1936
                 ), $state);
1937 1937
             } else {
1938
-                if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
1938
+                if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
1939 1939
                     $params = $this->mapParams($params, array(
1940
-                        'Plugin' . Core::toCamelCase($func),
1940
+                        'Plugin'.Core::toCamelCase($func),
1941 1941
                         ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1942 1942
                     ), $state);
1943
-                } elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !== false) {
1943
+                } elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func)) !== false) {
1944 1944
                     $params = $this->mapParams($params, array(
1945
-                        Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func),
1945
+                        Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func),
1946 1946
                         ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1947 1947
                     ), $state);
1948 1948
                 } else {
1949 1949
                     $params = $this->mapParams($params, array(
1950
-                        Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
1950
+                        Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func),
1951 1951
                         ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1952 1952
                     ), $state);
1953 1953
                 }
@@ -1958,24 +1958,22 @@  discard block
 block discarded – undo
1958 1958
                 $params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1959 1959
             } else {
1960 1960
                 // Custom plugin
1961
-                if (function_exists('Plugin' . Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ?
1961
+                if (function_exists('Plugin'.Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ?
1962 1962
                         'Compile' : '')) !== false) {
1963
-                    $params = $this->mapParams($params, 'Plugin' . Core::toCamelCase($func) . (($pluginType &
1963
+                    $params = $this->mapParams($params, 'Plugin'.Core::toCamelCase($func).(($pluginType &
1964 1964
                             Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1965 1965
                 } // Builtin helper plugin
1966
-                elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . (
1966
+                elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).(
1967 1967
                     ($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '')) !== false) {
1968
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase
1969
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1968
+                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1970 1969
                 } // Builtin function plugin
1971 1970
                 else {
1972
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
1973
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1971
+                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1974 1972
                 }
1975 1973
             }
1976 1974
         } // Smarty modifier
1977 1975
         elseif ($pluginType & Core::SMARTY_MODIFIER) {
1978
-            $output = 'smarty_modifier_' . $func . '(' . implode(', ', $params) . ')';
1976
+            $output = 'smarty_modifier_'.$func.'('.implode(', ', $params).')';
1979 1977
         } // Proxy plugin
1980 1978
         elseif ($pluginType & Core::PROXY_PLUGIN) {
1981 1979
             $params = $this->mapParams($params, $this->getCore()->getPluginProxy()->getCallback($func), $state);
@@ -2015,19 +2013,19 @@  discard block
 block discarded – undo
2015 2013
             if ($func === 'do') {
2016 2014
                 $output = '';
2017 2015
                 if (isset($params['*'])) {
2018
-                    $output = implode(';', $params['*']) . ';';
2016
+                    $output = implode(';', $params['*']).';';
2019 2017
                 }
2020 2018
 
2021 2019
                 if (is_array($parsingParams) || $curBlock !== 'root') {
2022 2020
                     throw new CompilationException($this, 'Do can not be used inside another function or block');
2023 2021
                 }
2024 2022
 
2025
-                return self::PHP_OPEN . $output . self::PHP_CLOSE;
2023
+                return self::PHP_OPEN.$output.self::PHP_CLOSE;
2026 2024
             } else {
2027 2025
                 if (isset($params['*'])) {
2028
-                    $output = $func . '(' . implode(', ', $params['*']) . ')';
2026
+                    $output = $func.'('.implode(', ', $params['*']).')';
2029 2027
                 } else {
2030
-                    $output = $func . '()';
2028
+                    $output = $func.'()';
2031 2029
                 }
2032 2030
             }
2033 2031
         } // Block class OR Function class
@@ -2037,7 +2035,7 @@  discard block
 block discarded – undo
2037 2035
                     $callback = $this->customPlugins[$func]['callback'];
2038 2036
                     if (!is_array($callback)) {
2039 2037
                         if (!method_exists($callback, 'compile')) {
2040
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2038
+                            throw new Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2041 2039
                         }
2042 2040
                         if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
2043 2041
                             $funcCompiler = array($callback, 'compile');
@@ -2048,13 +2046,13 @@  discard block
 block discarded – undo
2048 2046
                         $funcCompiler = $callback;
2049 2047
                     }
2050 2048
                 } else {
2051
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2052
-                        $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
2053
-                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !== false) {
2054
-                        $funcCompiler = array(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func), 'compile');
2049
+                    if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
2050
+                        $funcCompiler = array('Plugin'.Core::toCamelCase($func), 'compile');
2051
+                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func)) !== false) {
2052
+                        $funcCompiler = array(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func), 'compile');
2055 2053
                     } else {
2056 2054
                         $funcCompiler = array(
2057
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
2055
+                            Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func),
2058 2056
                             'compile'
2059 2057
                         );
2060 2058
                     }
@@ -2071,34 +2069,34 @@  discard block
 block discarded – undo
2071 2069
                     $callback = $this->customPlugins[$func]['callback'];
2072 2070
                     if (!is_array($callback)) {
2073 2071
                         if (!method_exists($callback, 'process')) {
2074
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2072
+                            throw new Exception('Custom plugin '.$func.' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2075 2073
                         }
2076 2074
                         if (is_object($callback)) {
2077 2075
                             $callback = get_class($callback);
2078 2076
                         }
2079 2077
                         if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
2080
-                            $output = 'call_user_func(array(\'' . $callback . '\', \'process\'), ' . $params . ')';
2078
+                            $output = 'call_user_func(array(\''.$callback.'\', \'process\'), '.$params.')';
2081 2079
                         } else {
2082
-                            $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback . '\'), \'process\'), ' . $params . ')';
2080
+                            $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback.'\'), \'process\'), '.$params.')';
2083 2081
                         }
2084 2082
                     } elseif (is_object($callback[0])) {
2085
-                        $output = 'call_user_func(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), ' . $params . ')';
2083
+                        $output = 'call_user_func(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), '.$params.')';
2086 2084
                     } elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
2087
-                        $output = 'call_user_func(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), ' . $params . ')';
2085
+                        $output = 'call_user_func(array(\''.$callback[0].'\', \''.$callback[1].'\'), '.$params.')';
2088 2086
                     } else {
2089
-                        $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback[0] . '\'), \'' . $callback[1] . '\'), ' . $params . ')';
2087
+                        $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback[0].'\'), \''.$callback[1].'\'), '.$params.')';
2090 2088
                     }
2091 2089
                     if (empty($params)) {
2092
-                        $output = substr($output, 0, - 3) . ')';
2090
+                        $output = substr($output, 0, - 3).')';
2093 2091
                     }
2094 2092
                 } else {
2095
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2096
-                        $output = '$this->classCall(\'Plugin' . $func . '\', array(' . $params . '))';
2097
-                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !== false) {
2098
-                        $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\',
2099
-                        array(' . $params . '))';
2093
+                    if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
2094
+                        $output = '$this->classCall(\'Plugin'.$func.'\', array('.$params.'))';
2095
+                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func)) !== false) {
2096
+                        $output = '$this->classCall(\''.Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.$func.'\',
2097
+                        array(' . $params.'))';
2100 2098
                     } else {
2101
-                        $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
2099
+                        $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
2102 2100
                     }
2103 2101
                 }
2104 2102
             }
@@ -2109,15 +2107,15 @@  discard block
 block discarded – undo
2109 2107
                     $funcCompiler = $this->customPlugins[$func]['callback'];
2110 2108
                 } else {
2111 2109
                     // Custom plugin
2112
-                    if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2113
-                        $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
2110
+                    if (function_exists('Plugin'.Core::toCamelCase($func).'Compile') !== false) {
2111
+                        $funcCompiler = 'Plugin'.Core::toCamelCase($func).'Compile';
2114 2112
                     } // Builtin helper plugin
2115
-                    elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2116
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2113
+                    elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).'Compile') !== false) {
2114
+                        $funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).
2117 2115
                             'Compile';
2118 2116
                     } // Builtin function plugin
2119 2117
                     else {
2120
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
2118
+                        $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).
2121 2119
                             'Compile';
2122 2120
                     }
2123 2121
                 }
@@ -2133,24 +2131,24 @@  discard block
 block discarded – undo
2133 2131
                 if ($pluginType & Core::CUSTOM_PLUGIN) {
2134 2132
                     $callback = $this->customPlugins[$func]['callback'];
2135 2133
                     if ($callback instanceof Closure) {
2136
-                        $output = 'call_user_func($this->getCustomPlugin(\'' . $func . '\'), ' . $params . ')';
2134
+                        $output = 'call_user_func($this->getCustomPlugin(\''.$func.'\'), '.$params.')';
2137 2135
                     } else {
2138
-                        $output = 'call_user_func(\'' . $callback . '\', ' . $params . ')';
2136
+                        $output = 'call_user_func(\''.$callback.'\', '.$params.')';
2139 2137
                     }
2140 2138
                 } else {
2141 2139
                     // Custom plugin
2142
-                    if (function_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2143
-                        $output = 'Plugin' . Core::toCamelCase($func) . '(' . $params .
2140
+                    if (function_exists('Plugin'.Core::toCamelCase($func)) !== false) {
2141
+                        $output = 'Plugin'.Core::toCamelCase($func).'('.$params.
2144 2142
                             ')';
2145 2143
                     } // Builtin helper plugin
2146
-                    elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !==
2144
+                    elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func)) !==
2147 2145
                         false) {
2148
-                        $output = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . '(' .
2149
-                            $params . ')';
2146
+                        $output = Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).'('.
2147
+                            $params.')';
2150 2148
                     } // Builtin function plugin
2151 2149
                     else {
2152
-                        $output = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '(' .
2153
-                            $params . ')';
2150
+                        $output = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).'('.
2151
+                            $params.')';
2154 2152
                     }
2155 2153
                 }
2156 2154
             }
@@ -2168,22 +2166,22 @@  discard block
 block discarded – undo
2168 2166
                 $callback = $this->customPlugins[$func]['callback'];
2169 2167
                 if (is_array($callback)) {
2170 2168
                     if (is_object($callback[0])) {
2171
-                        $output = 'call_user_func_array(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2169
+                        $output = 'call_user_func_array(array($this->getCustomPlugin(\''.$func.'\'), \''.$callback[1].'\'), array(array('.$params.'), $this))';
2172 2170
                     } else {
2173
-                        $output = 'call_user_func_array(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2171
+                        $output = 'call_user_func_array(array(\''.$callback[0].'\', \''.$callback[1].'\'), array(array('.$params.'), $this))';
2174 2172
                     }
2175 2173
                 } else {
2176
-                    $output = $callback . '(array(' . $params . '), $this)';
2174
+                    $output = $callback.'(array('.$params.'), $this)';
2177 2175
                 }
2178 2176
             } else {
2179
-                $output = 'smarty_function_' . $func . '(array(' . $params . '), $this)';
2177
+                $output = 'smarty_function_'.$func.'(array('.$params.'), $this)';
2180 2178
             }
2181 2179
         } // Template plugin
2182 2180
         elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
2183 2181
             array_unshift($params, '$this');
2184 2182
             $params                                 = self::implode_r($params);
2185
-            $output                                 = 'Plugin' . Core::toCamelCase($func) .
2186
-                $this->templatePlugins[$func]['uuid'] . '(' . $params . ')';
2183
+            $output                                 = 'Plugin'.Core::toCamelCase($func).
2184
+                $this->templatePlugins[$func]['uuid'].'('.$params.')';
2187 2185
             $this->templatePlugins[$func]['called'] = true;
2188 2186
         }
2189 2187
 
@@ -2215,29 +2213,29 @@  discard block
 block discarded – undo
2215 2213
      */
2216 2214
     protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2217 2215
     {
2218
-        $substr = substr($in, $from, $to - $from);
2216
+        $substr = substr($in, $from, $to-$from);
2219 2217
         $first  = $substr[0];
2220 2218
 
2221 2219
         if ($this->debug) {
2222
-            echo 'STRING FOUND (in ' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . ')' . "\n";
2220
+            echo 'STRING FOUND (in '.htmlentities(substr($in, $from, min($to-$from, 50))).(($to-$from) > 50 ? '...' : '').')'."\n";
2223 2221
         }
2224 2222
         $strend = false;
2225
-        $o      = $from + 1;
2223
+        $o      = $from+1;
2226 2224
         while ($strend === false) {
2227 2225
             $strend = strpos($in, $first, $o);
2228 2226
             if ($strend === false) {
2229
-                throw new CompilationException($this, 'Unfinished string, started with ' . substr($in, $from, $to - $from));
2227
+                throw new CompilationException($this, 'Unfinished string, started with '.substr($in, $from, $to-$from));
2230 2228
             }
2231
-            if (substr($in, $strend - 1, 1) === '\\') {
2232
-                $o      = $strend + 1;
2229
+            if (substr($in, $strend-1, 1) === '\\') {
2230
+                $o      = $strend+1;
2233 2231
                 $strend = false;
2234 2232
             }
2235 2233
         }
2236 2234
         if ($this->debug) {
2237
-            echo 'STRING DELIMITED: ' . substr($in, $from, $strend + 1 - $from) . "\n";
2235
+            echo 'STRING DELIMITED: '.substr($in, $from, $strend+1-$from)."\n";
2238 2236
         }
2239 2237
 
2240
-        $srcOutput = substr($in, $from, $strend + 1 - $from);
2238
+        $srcOutput = substr($in, $from, $strend+1-$from);
2241 2239
 
2242 2240
         if ($pointer !== null) {
2243 2241
             $pointer += strlen($srcOutput);
@@ -2246,13 +2244,13 @@  discard block
 block discarded – undo
2246 2244
         $output = $this->replaceStringVars($srcOutput, $first);
2247 2245
 
2248 2246
         // handle modifiers
2249
-        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2247
+        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend+1-$from), $match)) {
2250 2248
             $modstr = $match[1];
2251 2249
 
2252 2250
             if ($curBlock === 'root' && substr($modstr, - 1) === '}') {
2253 2251
                 $modstr = substr($modstr, 0, - 1);
2254 2252
             }
2255
-            $modstr = str_replace('\\' . $first, $first, $modstr);
2253
+            $modstr = str_replace('\\'.$first, $first, $modstr);
2256 2254
             $ptr    = 0;
2257 2255
             $output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2258 2256
 
@@ -2260,7 +2258,7 @@  discard block
 block discarded – undo
2260 2258
             if ($pointer !== null) {
2261 2259
                 $pointer += $ptr;
2262 2260
             }
2263
-            $srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2261
+            $srcOutput .= substr($substr, $strend+1-$from, $ptr);
2264 2262
         }
2265 2263
 
2266 2264
         if (is_array($parsingParams)) {
@@ -2291,10 +2289,10 @@  discard block
 block discarded – undo
2291 2289
      */
2292 2290
     protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2293 2291
     {
2294
-        $substr = substr($in, $from, $to - $from);
2292
+        $substr = substr($in, $from, $to-$from);
2295 2293
 
2296 2294
         if ($this->debug) {
2297
-            echo 'CONST FOUND : ' . $substr . "\n";
2295
+            echo 'CONST FOUND : '.$substr."\n";
2298 2296
         }
2299 2297
 
2300 2298
         if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
@@ -2335,7 +2333,7 @@  discard block
 block discarded – undo
2335 2333
         }
2336 2334
 
2337 2335
         if ($curBlock !== 'root') {
2338
-            return '(defined("' . $key . '") ? ' . $key . ' : null)';
2336
+            return '(defined("'.$key.'") ? '.$key.' : null)';
2339 2337
         }
2340 2338
 
2341 2339
         return $key;
@@ -2358,7 +2356,7 @@  discard block
 block discarded – undo
2358 2356
      */
2359 2357
     protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2360 2358
     {
2361
-        $substr = substr($in, $from, $to - $from);
2359
+        $substr = substr($in, $from, $to-$from);
2362 2360
 
2363 2361
         // var key
2364 2362
         $varRegex = '(\\$?\\.?[a-z0-9\\\\_:]*(?:(?:(?:\\.|->)(?:[a-z0-9\\\\_:]+|(?R))|\\[(?:[a-z0-9\\\\_:]+|(?R)|(["\'])[^\\2]*?\\2)\\]))*)';
@@ -2386,13 +2384,13 @@  discard block
 block discarded – undo
2386 2384
 
2387 2385
             if (substr($key, - 1) == '.') {
2388 2386
                 $key = substr($key, 0, - 1);
2389
-                -- $matchedLength;
2387
+                --$matchedLength;
2390 2388
             }
2391 2389
 
2392 2390
             if ($hasMethodCall) {
2393
-                $matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2394
-                $key        = substr($match[1], 1, strrpos($match[1], '->') - 1);
2395
-                $methodCall = substr($match[1], strrpos($match[1], '->')) . $match[3];
2391
+                $matchedLength -= strlen($match[3])+strlen(substr($match[1], strrpos($match[1], '->')));
2392
+                $key        = substr($match[1], 1, strrpos($match[1], '->')-1);
2393
+                $methodCall = substr($match[1], strrpos($match[1], '->')).$match[3];
2396 2394
             }
2397 2395
 
2398 2396
             if ($hasModifiers) {
@@ -2408,9 +2406,9 @@  discard block
 block discarded – undo
2408 2406
 
2409 2407
             if ($this->debug) {
2410 2408
                 if ($hasMethodCall) {
2411
-                    echo 'METHOD CALL FOUND : $' . $key . substr($methodCall, 0, 30) . "\n";
2409
+                    echo 'METHOD CALL FOUND : $'.$key.substr($methodCall, 0, 30)."\n";
2412 2410
                 } else {
2413
-                    echo 'VAR FOUND : $' . $key . "\n";
2411
+                    echo 'VAR FOUND : $'.$key."\n";
2414 2412
                 }
2415 2413
             }
2416 2414
 
@@ -2421,7 +2419,7 @@  discard block
 block discarded – undo
2421 2419
                 $uid           = 0;
2422 2420
                 $parsed        = array($uid => '');
2423 2421
                 $current       = &$parsed;
2424
-                $curTxt        = &$parsed[$uid ++];
2422
+                $curTxt        = &$parsed[$uid++];
2425 2423
                 $tree          = array();
2426 2424
                 $chars         = str_split($key, 1);
2427 2425
                 $inSplittedVar = false;
@@ -2430,33 +2428,33 @@  discard block
 block discarded – undo
2430 2428
                 while (($char = array_shift($chars)) !== null) {
2431 2429
                     if ($char === '[') {
2432 2430
                         if (count($tree) > 0) {
2433
-                            ++ $bracketCount;
2431
+                            ++$bracketCount;
2434 2432
                         } else {
2435 2433
                             $tree[]        = &$current;
2436
-                            $current[$uid] = array($uid + 1 => '');
2437
-                            $current       = &$current[$uid ++];
2438
-                            $curTxt        = &$current[$uid ++];
2434
+                            $current[$uid] = array($uid+1 => '');
2435
+                            $current       = &$current[$uid++];
2436
+                            $curTxt        = &$current[$uid++];
2439 2437
                             continue;
2440 2438
                         }
2441 2439
                     } elseif ($char === ']') {
2442 2440
                         if ($bracketCount > 0) {
2443
-                            -- $bracketCount;
2441
+                            --$bracketCount;
2444 2442
                         } else {
2445
-                            $current = &$tree[count($tree) - 1];
2443
+                            $current = &$tree[count($tree)-1];
2446 2444
                             array_pop($tree);
2447 2445
                             if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2448 2446
                                 $current[$uid] = '';
2449
-                                $curTxt        = &$current[$uid ++];
2447
+                                $curTxt        = &$current[$uid++];
2450 2448
                             }
2451 2449
                             continue;
2452 2450
                         }
2453 2451
                     } elseif ($char === '$') {
2454 2452
                         if (count($tree) == 0) {
2455
-                            $curTxt        = &$current[$uid ++];
2453
+                            $curTxt        = &$current[$uid++];
2456 2454
                             $inSplittedVar = true;
2457 2455
                         }
2458 2456
                     } elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2459
-                        $curTxt        = &$current[$uid ++];
2457
+                        $curTxt        = &$current[$uid++];
2460 2458
                         $inSplittedVar = false;
2461 2459
                     }
2462 2460
 
@@ -2465,16 +2463,16 @@  discard block
 block discarded – undo
2465 2463
                 unset($uid, $current, $curTxt, $tree, $chars);
2466 2464
 
2467 2465
                 if ($this->debug) {
2468
-                    echo 'RECURSIVE VAR REPLACEMENT : ' . $key . "\n";
2466
+                    echo 'RECURSIVE VAR REPLACEMENT : '.$key."\n";
2469 2467
                 }
2470 2468
 
2471 2469
                 $key = $this->flattenVarTree($parsed);
2472 2470
 
2473 2471
                 if ($this->debug) {
2474
-                    echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2472
+                    echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2475 2473
                 }
2476 2474
 
2477
-                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("' . $key . '")');
2475
+                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("'.$key.'")');
2478 2476
             } else {
2479 2477
                 $output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2480 2478
             }
@@ -2499,10 +2497,10 @@  discard block
 block discarded – undo
2499 2497
                     if (substr($expMatch[2][$k], 0, 1) === '=') {
2500 2498
                         $assign = true;
2501 2499
                         if ($operator === '=') {
2502
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, can not use "==" in expressions');
2500
+                            throw new CompilationException($this, 'Invalid expression <em>'.$substr.'</em>, can not use "==" in expressions');
2503 2501
                         }
2504 2502
                         if ($curBlock !== 'root') {
2505
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2503
+                            throw new CompilationException($this, 'Invalid expression <em>'.$substr.'</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2506 2504
                         }
2507 2505
                         $operator .= '=';
2508 2506
                         $expMatch[2][$k] = substr($expMatch[2][$k], 1);
@@ -2513,22 +2511,22 @@  discard block
 block discarded – undo
2513 2511
                         $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2514 2512
                     }
2515 2513
                     if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2516
-                        $output = '(' . $output . $operator . $operator . ')';
2514
+                        $output = '('.$output.$operator.$operator.')';
2517 2515
                         break;
2518 2516
                     } elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2519
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2517
+                        $output = '('.$output.' '.$operator.' '.$this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2520 2518
                     } elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2521
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2519
+                        $output = '('.$output.' '.$operator.' '.$this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2522 2520
                     } elseif (!empty($expMatch[2][$k])) {
2523
-                        $output = '(' . $output . ' ' . $operator . ' ' . str_replace(',', '.', $expMatch[2][$k]) . ')';
2521
+                        $output = '('.$output.' '.$operator.' '.str_replace(',', '.', $expMatch[2][$k]).')';
2524 2522
                     } else {
2525
-                        throw new CompilationException($this, 'Unfinished expression <em>' . $substr . '</em>, missing var or number after math operator');
2523
+                        throw new CompilationException($this, 'Unfinished expression <em>'.$substr.'</em>, missing var or number after math operator');
2526 2524
                     }
2527 2525
                 }
2528 2526
             }
2529 2527
 
2530 2528
             if ($this->autoEscape === true && $curBlock !== 'condition') {
2531
-                $output = '(is_string($tmp=' . $output . ') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2529
+                $output = '(is_string($tmp='.$output.') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2532 2530
             }
2533 2531
 
2534 2532
             // handle modifiers
@@ -2552,7 +2550,7 @@  discard block
 block discarded – undo
2552 2550
             } elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2553 2551
                 return $output;
2554 2552
             } elseif (isset($assign)) {
2555
-                return self::PHP_OPEN . $output . ';' . self::PHP_CLOSE;
2553
+                return self::PHP_OPEN.$output.';'.self::PHP_CLOSE;
2556 2554
             }
2557 2555
 
2558 2556
             return $output;
@@ -2560,7 +2558,7 @@  discard block
 block discarded – undo
2560 2558
             if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2561 2559
                 return array(0, '');
2562 2560
             }
2563
-            throw new CompilationException($this, 'Invalid variable name <em>' . $substr . '</em>');
2561
+            throw new CompilationException($this, 'Invalid variable name <em>'.$substr.'</em>');
2564 2562
         }
2565 2563
     }
2566 2564
 
@@ -2614,16 +2612,16 @@  discard block
 block discarded – undo
2614 2612
             if (empty($methMatch[2])) {
2615 2613
                 // property
2616 2614
                 if ($curBlock === 'root') {
2617
-                    $output .= '->' . $methMatch[1];
2615
+                    $output .= '->'.$methMatch[1];
2618 2616
                 } else {
2619
-                    $output = '(($tmp = ' . $output . ') ? $tmp->' . $methMatch[1] . ' : null)';
2617
+                    $output = '(($tmp = '.$output.') ? $tmp->'.$methMatch[1].' : null)';
2620 2618
                 }
2621 2619
                 $ptr += strlen($methMatch[1]);
2622 2620
             } else {
2623 2621
                 // method
2624 2622
                 if (substr($methMatch[2], 0, 2) === '()') {
2625
-                    $parsedCall = $methMatch[1] . '()';
2626
-                    $ptr += strlen($methMatch[1]) + 2;
2623
+                    $parsedCall = $methMatch[1].'()';
2624
+                    $ptr += strlen($methMatch[1])+2;
2627 2625
                 } else {
2628 2626
                     $parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2629 2627
                 }
@@ -2632,15 +2630,15 @@  discard block
 block discarded – undo
2632 2630
                     $method = strtolower(substr($parsedCall, 0, $argPos));
2633 2631
                     $args   = substr($parsedCall, $argPos);
2634 2632
                     if ($curBlock === 'root') {
2635
-                        $output = '$this->getSecurityPolicy()->callMethod($this, ' . $output . ', ' . var_export($method, true) . ', array' . $args . ')';
2633
+                        $output = '$this->getSecurityPolicy()->callMethod($this, '.$output.', '.var_export($method, true).', array'.$args.')';
2636 2634
                     } else {
2637
-                        $output = '(($tmp = ' . $output . ') ? $this->getSecurityPolicy()->callMethod($this, $tmp, ' . var_export($method, true) . ', array' . $args . ') : null)';
2635
+                        $output = '(($tmp = '.$output.') ? $this->getSecurityPolicy()->callMethod($this, $tmp, '.var_export($method, true).', array'.$args.') : null)';
2638 2636
                     }
2639 2637
                 } else {
2640 2638
                     if ($curBlock === 'root') {
2641
-                        $output .= '->' . $parsedCall;
2639
+                        $output .= '->'.$parsedCall;
2642 2640
                     } else {
2643
-                        $output = '(($tmp = ' . $output . ') ? $tmp->' . $parsedCall . ' : null)';
2641
+                        $output = '(($tmp = '.$output.') ? $tmp->'.$parsedCall.' : null)';
2644 2642
                     }
2645 2643
                 }
2646 2644
             }
@@ -2666,21 +2664,21 @@  discard block
 block discarded – undo
2666 2664
             return '$this->scope';
2667 2665
         }
2668 2666
         if (substr($key, 0, 1) === '.') {
2669
-            $key = 'dwoo' . $key;
2667
+            $key = 'dwoo'.$key;
2670 2668
         }
2671 2669
         if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2672 2670
             $global = strtoupper($m[1]);
2673 2671
             if ($global === 'COOKIES') {
2674 2672
                 $global = 'COOKIE';
2675 2673
             }
2676
-            $key = '$_' . $global;
2674
+            $key = '$_'.$global;
2677 2675
             foreach (explode('.', ltrim($m[2], '.')) as $part) {
2678
-                $key .= '[' . var_export($part, true) . ']';
2676
+                $key .= '['.var_export($part, true).']';
2679 2677
             }
2680 2678
             if ($curBlock === 'root') {
2681 2679
                 $output = $key;
2682 2680
             } else {
2683
-                $output = '(isset(' . $key . ')?' . $key . ':null)';
2681
+                $output = '(isset('.$key.')?'.$key.':null)';
2684 2682
             }
2685 2683
         } elseif (preg_match('#dwoo\\.const\\.([a-z0-9\\\\_:]+)#i', $key, $m)) {
2686 2684
             return $this->parseConstKey($m[1], $curBlock);
@@ -2696,9 +2694,9 @@  discard block
 block discarded – undo
2696 2694
                     $output = '$tmp_key';
2697 2695
                 } else {
2698 2696
                     if ($curBlock === 'root') {
2699
-                        $output = '$this->scope["' . $key . '"]';
2697
+                        $output = '$this->scope["'.$key.'"]';
2700 2698
                     } else {
2701
-                        $output = '(isset($this->scope["' . $key . '"]) ? $this->scope["' . $key . '"] : null)';
2699
+                        $output = '(isset($this->scope["'.$key.'"]) ? $this->scope["'.$key.'"] : null)';
2702 2700
                     }
2703 2701
                 }
2704 2702
             } else {
@@ -2709,7 +2707,7 @@  discard block
 block discarded – undo
2709 2707
                     $parentCnt = 0;
2710 2708
 
2711 2709
                     while (true) {
2712
-                        ++ $parentCnt;
2710
+                        ++$parentCnt;
2713 2711
                         array_shift($m[2]);
2714 2712
                         array_shift($m[1]);
2715 2713
                         if (current($m[2]) === '_parent') {
@@ -2718,7 +2716,7 @@  discard block
 block discarded – undo
2718 2716
                         break;
2719 2717
                     }
2720 2718
 
2721
-                    $output = '$this->readParentVar(' . $parentCnt . ')';
2719
+                    $output = '$this->readParentVar('.$parentCnt.')';
2722 2720
                 } else {
2723 2721
                     if ($i === 'dwoo') {
2724 2722
                         $output = '$this->globals';
@@ -2737,28 +2735,28 @@  discard block
 block discarded – undo
2737 2735
                     while (count($m[1]) && $m[1][0] !== '->') {
2738 2736
                         $m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2739 2737
                         if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2740
-                            $output .= '[' . $m[2][0] . ']';
2738
+                            $output .= '['.$m[2][0].']';
2741 2739
                         } else {
2742
-                            $output .= '["' . $m[2][0] . '"]';
2740
+                            $output .= '["'.$m[2][0].'"]';
2743 2741
                         }
2744 2742
                         array_shift($m[2]);
2745 2743
                         array_shift($m[1]);
2746 2744
                     }
2747 2745
 
2748 2746
                     if ($curBlock !== 'root') {
2749
-                        $output = '(isset(' . $output . ') ? ' . $output . ':null)';
2747
+                        $output = '(isset('.$output.') ? '.$output.':null)';
2750 2748
                     }
2751 2749
                 }
2752 2750
 
2753 2751
                 if (count($m[2])) {
2754 2752
                     unset($m[0]);
2755
-                    $output = '$this->readVarInto(' . str_replace("\n", '', var_export($m, true)) . ', ' . $output . ', ' . ($curBlock == 'root' ? 'false' : 'true') . ')';
2753
+                    $output = '$this->readVarInto('.str_replace("\n", '', var_export($m, true)).', '.$output.', '.($curBlock == 'root' ? 'false' : 'true').')';
2756 2754
                 }
2757 2755
             }
2758 2756
         } else {
2759 2757
             preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2760 2758
             unset($m[0]);
2761
-            $output = '$this->readVar(' . str_replace("\n", '', var_export($m, true)) . ')';
2759
+            $output = '$this->readVar('.str_replace("\n", '', var_export($m, true)).')';
2762 2760
         }
2763 2761
 
2764 2762
         return $output;
@@ -2778,38 +2776,38 @@  discard block
 block discarded – undo
2778 2776
         $out = $recursed ? '".$this->readVarInto(' : '';
2779 2777
         foreach ($tree as $bit) {
2780 2778
             if (is_array($bit)) {
2781
-                $out .= '.' . $this->flattenVarTree($bit, false);
2779
+                $out .= '.'.$this->flattenVarTree($bit, false);
2782 2780
             } else {
2783 2781
                 $key = str_replace('"', '\\"', $bit);
2784 2782
 
2785 2783
                 if (substr($key, 0, 1) === '$') {
2786
-                    $out .= '".' . $this->parseVar($key, 0, strlen($key), false, 'variable') . '."';
2784
+                    $out .= '".'.$this->parseVar($key, 0, strlen($key), false, 'variable').'."';
2787 2785
                 } else {
2788 2786
                     $cnt = substr_count($key, '$');
2789 2787
 
2790 2788
                     if ($this->debug) {
2791
-                        echo 'PARSING SUBVARS IN : ' . $key . "\n";
2789
+                        echo 'PARSING SUBVARS IN : '.$key."\n";
2792 2790
                     }
2793 2791
                     if ($cnt > 0) {
2794
-                        while (-- $cnt >= 0) {
2792
+                        while (--$cnt >= 0) {
2795 2793
                             if (isset($last)) {
2796
-                                $last = strrpos($key, '$', - (strlen($key) - $last + 1));
2794
+                                $last = strrpos($key, '$', - (strlen($key)-$last+1));
2797 2795
                             } else {
2798 2796
                                 $last = strrpos($key, '$');
2799 2797
                             }
2800
-                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2798
+                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*'.'((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2801 2799
 
2802 2800
                             $len = strlen($submatch[0]);
2803 2801
                             $key = substr_replace(
2804 2802
                                 $key, preg_replace_callback(
2805
-                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2803
+                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)'.'((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2806 2804
                                         $this,
2807 2805
                                         'replaceVarKeyHelper'
2808 2806
                                     ), substr($key, $last, $len)
2809 2807
                                 ), $last, $len
2810 2808
                             );
2811 2809
                             if ($this->debug) {
2812
-                                echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2810
+                                echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2813 2811
                             }
2814 2812
                         }
2815 2813
                         unset($last);
@@ -2835,7 +2833,7 @@  discard block
 block discarded – undo
2835 2833
      */
2836 2834
     protected function replaceVarKeyHelper($match)
2837 2835
     {
2838
-        return '".' . $this->parseVar($match[0], 0, strlen($match[0]), false, 'variable') . '."';
2836
+        return '".'.$this->parseVar($match[0], 0, strlen($match[0]), false, 'variable').'."';
2839 2837
     }
2840 2838
 
2841 2839
     /**
@@ -2855,7 +2853,7 @@  discard block
 block discarded – undo
2855 2853
      */
2856 2854
     protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2857 2855
     {
2858
-        $substr = substr($in, $from, $to - $from);
2856
+        $substr = substr($in, $from, $to-$from);
2859 2857
 
2860 2858
         $end = strlen($substr);
2861 2859
 
@@ -2929,48 +2927,48 @@  discard block
 block discarded – undo
2929 2927
 
2930 2928
         if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2931 2929
             if ($this->debug) {
2932
-                echo 'BOOLEAN(FALSE) PARSED' . "\n";
2930
+                echo 'BOOLEAN(FALSE) PARSED'."\n";
2933 2931
             }
2934 2932
             $substr = 'false';
2935 2933
             $type   = self::T_BOOL;
2936 2934
         } elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2937 2935
             if ($this->debug) {
2938
-                echo 'BOOLEAN(TRUE) PARSED' . "\n";
2936
+                echo 'BOOLEAN(TRUE) PARSED'."\n";
2939 2937
             }
2940 2938
             $substr = 'true';
2941 2939
             $type   = self::T_BOOL;
2942 2940
         } elseif ($substr === 'null' || $substr === 'NULL') {
2943 2941
             if ($this->debug) {
2944
-                echo 'NULL PARSED' . "\n";
2942
+                echo 'NULL PARSED'."\n";
2945 2943
             }
2946 2944
             $substr = 'null';
2947 2945
             $type   = self::T_NULL;
2948 2946
         } elseif (is_numeric($substr)) {
2949
-            $substr = (float)$substr;
2950
-            if ((int)$substr == $substr) {
2951
-                $substr = (int)$substr;
2947
+            $substr = (float) $substr;
2948
+            if ((int) $substr == $substr) {
2949
+                $substr = (int) $substr;
2952 2950
             }
2953 2951
             $type = self::T_NUMERIC;
2954 2952
             if ($this->debug) {
2955
-                echo 'NUMBER (' . $substr . ') PARSED' . "\n";
2953
+                echo 'NUMBER ('.$substr.') PARSED'."\n";
2956 2954
             }
2957 2955
         } elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2958 2956
             if ($this->debug) {
2959 2957
                 echo 'SIMPLE MATH PARSED . "\n"';
2960 2958
             }
2961 2959
             $type   = self::T_MATH;
2962
-            $substr = '(' . $substr . ')';
2960
+            $substr = '('.$substr.')';
2963 2961
         } elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2964 2962
             if ($this->debug) {
2965
-                echo 'BREAKCHAR (' . $substr . ') PARSED' . "\n";
2963
+                echo 'BREAKCHAR ('.$substr.') PARSED'."\n";
2966 2964
             }
2967 2965
             $type = self::T_BREAKCHAR;
2968 2966
             //$substr = '"'.$substr.'"';
2969 2967
         } else {
2970
-            $substr = $this->replaceStringVars('\'' . str_replace('\'', '\\\'', $substr) . '\'', '\'', $curBlock);
2968
+            $substr = $this->replaceStringVars('\''.str_replace('\'', '\\\'', $substr).'\'', '\'', $curBlock);
2971 2969
             $type   = self::T_UNQUOTED_STRING;
2972 2970
             if ($this->debug) {
2973
-                echo 'BLABBER (' . $substr . ') CASTED AS STRING' . "\n";
2971
+                echo 'BLABBER ('.$substr.') CASTED AS STRING'."\n";
2974 2972
             }
2975 2973
         }
2976 2974
 
@@ -3000,28 +2998,28 @@  discard block
 block discarded – undo
3000 2998
     {
3001 2999
         $pos = 0;
3002 3000
         if ($this->debug) {
3003
-            echo 'STRING VAR REPLACEMENT : ' . $string . "\n";
3001
+            echo 'STRING VAR REPLACEMENT : '.$string."\n";
3004 3002
         }
3005 3003
         // replace vars
3006 3004
         while (($pos = strpos($string, '$', $pos)) !== false) {
3007
-            $prev = substr($string, $pos - 1, 1);
3005
+            $prev = substr($string, $pos-1, 1);
3008 3006
             if ($prev === '\\') {
3009
-                ++ $pos;
3007
+                ++$pos;
3010 3008
                 continue;
3011 3009
             }
3012 3010
 
3013 3011
             $var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3014 3012
             $len = $var[0];
3015
-            $var = $this->parse(str_replace('\\' . $first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3013
+            $var = $this->parse(str_replace('\\'.$first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3016 3014
 
3017
-            if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
3018
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos - 1, $len + 2);
3015
+            if ($prev === '`' && substr($string, $pos+$len, 1) === '`') {
3016
+                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos-1, $len+2);
3019 3017
             } else {
3020
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos, $len);
3018
+                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos, $len);
3021 3019
             }
3022
-            $pos += strlen($var[1]) + 2;
3020
+            $pos += strlen($var[1])+2;
3023 3021
             if ($this->debug) {
3024
-                echo 'STRING VAR REPLACEMENT DONE : ' . $string . "\n";
3022
+                echo 'STRING VAR REPLACEMENT DONE : '.$string."\n";
3025 3023
             }
3026 3024
         }
3027 3025
 
@@ -3057,7 +3055,7 @@  discard block
 block discarded – undo
3057 3055
     protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
3058 3056
     {
3059 3057
         if ($this->debug) {
3060
-            echo 'PARSING MODIFIERS : ' . $m[3] . "\n";
3058
+            echo 'PARSING MODIFIERS : '.$m[3]."\n";
3061 3059
         }
3062 3060
 
3063 3061
         if ($pointer !== null) {
@@ -3081,7 +3079,7 @@  discard block
 block discarded – undo
3081 3079
             }
3082 3080
             if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
3083 3081
                 if ($this->debug) {
3084
-                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND' . "\n";
3082
+                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND'."\n";
3085 3083
                 }
3086 3084
                 $continue = false;
3087 3085
                 if ($pointer !== null) {
@@ -3092,7 +3090,7 @@  discard block
 block discarded – undo
3092 3090
             $cmdstr   = $cmdstrsrc;
3093 3091
             $paramsep = ':';
3094 3092
             if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
3095
-                throw new CompilationException($this, 'Invalid modifier name, started with : ' . substr($cmdstr, 0, 10));
3093
+                throw new CompilationException($this, 'Invalid modifier name, started with : '.substr($cmdstr, 0, 10));
3096 3094
             }
3097 3095
             $paramspos = !empty($match[2]) ? strlen($match[1]) : false;
3098 3096
             $func      = $match[1];
@@ -3102,10 +3100,10 @@  discard block
 block discarded – undo
3102 3100
                 $cmdstrsrc = substr($cmdstrsrc, strlen($func));
3103 3101
                 $params    = array();
3104 3102
                 if ($this->debug) {
3105
-                    echo 'MODIFIER (' . $func . ') CALLED WITH NO PARAMS' . "\n";
3103
+                    echo 'MODIFIER ('.$func.') CALLED WITH NO PARAMS'."\n";
3106 3104
                 }
3107 3105
             } else {
3108
-                $paramstr = substr($cmdstr, $paramspos + 1);
3106
+                $paramstr = substr($cmdstr, $paramspos+1);
3109 3107
                 if (substr($paramstr, - 1, 1) === $paramsep) {
3110 3108
                     $paramstr = substr($paramstr, 0, - 1);
3111 3109
                 }
@@ -3114,41 +3112,41 @@  discard block
 block discarded – undo
3114 3112
                 $params = array();
3115 3113
                 while ($ptr < strlen($paramstr)) {
3116 3114
                     if ($this->debug) {
3117
-                        echo 'MODIFIER (' . $func . ') START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
3115
+                        echo 'MODIFIER ('.$func.') START PARAM PARSING WITH POINTER AT '.$ptr."\n";
3118 3116
                     }
3119 3117
                     if ($this->debug) {
3120
-                        echo $paramstr . '--' . $ptr . '--' . strlen($paramstr) . '--modifier' . "\n";
3118
+                        echo $paramstr.'--'.$ptr.'--'.strlen($paramstr).'--modifier'."\n";
3121 3119
                     }
3122 3120
                     $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
3123 3121
                     if ($this->debug) {
3124
-                        echo 'PARAM PARSED, POINTER AT ' . $ptr . "\n";
3122
+                        echo 'PARAM PARSED, POINTER AT '.$ptr."\n";
3125 3123
                     }
3126 3124
 
3127 3125
                     if ($ptr >= strlen($paramstr)) {
3128 3126
                         if ($this->debug) {
3129
-                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED' . "\n";
3127
+                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED'."\n";
3130 3128
                         }
3131 3129
                         break;
3132 3130
                     }
3133 3131
 
3134 3132
                     if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
3135 3133
                         if ($this->debug) {
3136
-                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT ' . $ptr . "\n";
3134
+                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT '.$ptr."\n";
3137 3135
                         }
3138 3136
                         if ($paramstr[$ptr] !== '|') {
3139 3137
                             $continue = false;
3140 3138
                             if ($pointer !== null) {
3141
-                                $pointer -= strlen($paramstr) - $ptr;
3139
+                                $pointer -= strlen($paramstr)-$ptr;
3142 3140
                             }
3143 3141
                         }
3144
-                        ++ $ptr;
3142
+                        ++$ptr;
3145 3143
                         break;
3146 3144
                     }
3147 3145
                     if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
3148
-                        ++ $ptr;
3146
+                        ++$ptr;
3149 3147
                     }
3150 3148
                 }
3151
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
3149
+                $cmdstrsrc = substr($cmdstrsrc, strlen($func)+1+$ptr);
3152 3150
                 foreach ($params as $k => $p) {
3153 3151
                     if (is_array($p) && is_array($p[1])) {
3154 3152
                         $state |= 2;
@@ -3188,9 +3186,9 @@  discard block
 block discarded – undo
3188 3186
                 $params = self::implode_r($params);
3189 3187
 
3190 3188
                 if ($mapped) {
3191
-                    $output = '$this->arrayMap(\'' . $func . '\', array(' . $params . '))';
3189
+                    $output = '$this->arrayMap(\''.$func.'\', array('.$params.'))';
3192 3190
                 } else {
3193
-                    $output = $func . '(' . $params . ')';
3191
+                    $output = $func.'('.$params.')';
3194 3192
                 }
3195 3193
             } elseif ($pluginType & Core::PROXY_PLUGIN) {
3196 3194
                 $params = $this->mapParams($params, $this->getCore()->getPluginProxy()->getCallback($func), $state);
@@ -3208,19 +3206,19 @@  discard block
 block discarded – undo
3208 3206
                     $callback = $this->customPlugins[$func]['callback'];
3209 3207
                     if (is_array($callback)) {
3210 3208
                         if (is_object($callback[0])) {
3211
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(' . $params . '))';
3209
+                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->getCustomPlugin(\''.$func.'\'), \''.$callback[1].'\'), array('.$params.'))';
3212 3210
                         } else {
3213
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3211
+                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
3214 3212
                         }
3215 3213
                     } elseif ($mapped) {
3216
-                        $output = '$this->arrayMap(\'' . $callback . '\', array(' . $params . '))';
3214
+                        $output = '$this->arrayMap(\''.$callback.'\', array('.$params.'))';
3217 3215
                     } else {
3218
-                        $output = $callback . '(' . $params . ')';
3216
+                        $output = $callback.'('.$params.')';
3219 3217
                     }
3220 3218
                 } elseif ($mapped) {
3221
-                    $output = '$this->arrayMap(\'smarty_modifier_' . $func . '\', array(' . $params . '))';
3219
+                    $output = '$this->arrayMap(\'smarty_modifier_'.$func.'\', array('.$params.'))';
3222 3220
                 } else {
3223
-                    $output = 'smarty_modifier_' . $func . '(' . $params . ')';
3221
+                    $output = 'smarty_modifier_'.$func.'('.$params.')';
3224 3222
                 }
3225 3223
             } else {
3226 3224
                 if ($pluginType & Core::CUSTOM_PLUGIN) {
@@ -3230,17 +3228,17 @@  discard block
 block discarded – undo
3230 3228
                         $callback   = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3231 3229
                     }
3232 3230
                 } else {
3233
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false || function_exists('Plugin' .
3234
-                            Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3231
+                    if (class_exists('Plugin'.Core::toCamelCase($func)) !== false || function_exists('Plugin'.
3232
+                            Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3235 3233
                         !== false) {
3236
-                        $pluginName = 'Plugin' . Core::toCamelCase($func);
3234
+                        $pluginName = 'Plugin'.Core::toCamelCase($func);
3237 3235
                     } else {
3238
-                        $pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func);
3236
+                        $pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func);
3239 3237
                     }
3240 3238
                     if ($pluginType & Core::CLASS_PLUGIN) {
3241 3239
                         $callback = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3242 3240
                     } else {
3243
-                        $callback = $pluginName . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3241
+                        $callback = $pluginName.(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3244 3242
                     }
3245 3243
                 }
3246 3244
                 $params = $this->mapParams($params, $callback, $state);
@@ -3258,10 +3256,10 @@  discard block
 block discarded – undo
3258 3256
                         if ($pluginType & Core::CUSTOM_PLUGIN) {
3259 3257
                             $funcCompiler = $this->customPlugins[$func]['callback'];
3260 3258
                         } else {
3261
-                            if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
3262
-                                $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
3259
+                            if (function_exists('Plugin'.Core::toCamelCase($func).'Compile') !== false) {
3260
+                                $funcCompiler = 'Plugin'.Core::toCamelCase($func).'Compile';
3263 3261
                             } else {
3264
-                                $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
3262
+                                $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).
3265 3263
                                     'Compile';
3266 3264
                             }
3267 3265
                         }
@@ -3272,9 +3270,9 @@  discard block
 block discarded – undo
3272 3270
 
3273 3271
                         $params = self::implode_r($params);
3274 3272
                         if ($mapped) {
3275
-                            $output = '$this->arrayMap(\'' . $pluginName . '\', array(' . $params . '))';
3273
+                            $output = '$this->arrayMap(\''.$pluginName.'\', array('.$params.'))';
3276 3274
                         } else {
3277
-                            $output = $pluginName . '(' . $params . ')';
3275
+                            $output = $pluginName.'('.$params.')';
3278 3276
                         }
3279 3277
                     }
3280 3278
                 } else {
@@ -3286,7 +3284,7 @@  discard block
 block discarded – undo
3286 3284
                             $callback = $this->customPlugins[$func]['callback'];
3287 3285
                             if (!is_array($callback)) {
3288 3286
                                 if (!method_exists($callback, 'compile')) {
3289
-                                    throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3287
+                                    throw new Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3290 3288
                                 }
3291 3289
                                 if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3292 3290
                                     $funcCompiler = array($callback, 'compile');
@@ -3297,10 +3295,10 @@  discard block
 block discarded – undo
3297 3295
                                 $funcCompiler = $callback;
3298 3296
                             }
3299 3297
                         } else {
3300
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3301
-                                $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
3298
+                            if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
3299
+                                $funcCompiler = array('Plugin'.Core::toCamelCase($func), 'compile');
3302 3300
                             } else {
3303
-                                $funcCompiler = array(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func), 'compile');
3301
+                                $funcCompiler = array(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func), 'compile');
3304 3302
                             }
3305 3303
                             array_unshift($params, $this);
3306 3304
                         }
@@ -3311,26 +3309,26 @@  discard block
 block discarded – undo
3311 3309
                         if ($pluginType & Core::CUSTOM_PLUGIN) {
3312 3310
                             if (is_object($callback[0])) {
3313 3311
                                 if (is_array($this->getCore()->getCustomPlugin($func))) {
3314
-                                    $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3312
+                                    $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
3315 3313
                                 } else {
3316
-                                    $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(' . $params . '))';
3314
+                                    $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->getCustomPlugin(\''.$func.'\'), \''.$callback[1].'\'), array('.$params.'))';
3317 3315
                                 }
3318 3316
                             } else {
3319
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3317
+                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
3320 3318
                             }
3321 3319
                         } elseif ($mapped) {
3322 3320
                             $output = '$this->arrayMap(array($this->getObjectPlugin(\''.
3323
-                                Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '\'),
3324
-                            \'process\'), array(' . $params . '))';
3321
+                                Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).'\'),
3322
+                            \'process\'), array(' . $params.'))';
3325 3323
                         } else {
3326
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3327
-                                $output = '$this->classCall(\'Plugin' . Core::toCamelCase($func) . '\', array(' . $params . '))';
3328
-                            } elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($func)) !== false) {
3329
-                                $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . $func . '\', array(' . $params . '))';
3330
-                            } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !== false) {
3331
-                                $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\', array(' . $params . '))';
3324
+                            if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
3325
+                                $output = '$this->classCall(\'Plugin'.Core::toCamelCase($func).'\', array('.$params.'))';
3326
+                            } elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($func)) !== false) {
3327
+                                $output = '$this->classCall(\''.Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.$func.'\', array('.$params.'))';
3328
+                            } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func)) !== false) {
3329
+                                $output = '$this->classCall(\''.Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.$func.'\', array('.$params.'))';
3332 3330
                             } else {
3333
-                                $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
3331
+                                $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
3334 3332
                             }
3335 3333
                         }
3336 3334
                     }
@@ -3343,7 +3341,7 @@  discard block
 block discarded – undo
3343 3341
         } elseif ($curBlock === 'var' || $m[1] === null) {
3344 3342
             return $output;
3345 3343
         } elseif ($curBlock === 'string' || $curBlock === 'root') {
3346
-            return $m[1] . '.' . $output . '.' . $m[1] . (isset($add) ? $add : null);
3344
+            return $m[1].'.'.$output.'.'.$m[1].(isset($add) ? $add : null);
3347 3345
         }
3348 3346
 
3349 3347
         return '';
@@ -3366,14 +3364,14 @@  discard block
 block discarded – undo
3366 3364
             if (is_array($p)) {
3367 3365
                 $out2 = 'array(';
3368 3366
                 foreach ($p as $k2 => $v) {
3369
-                    $out2 .= var_export($k2, true) . ' => ' . (is_array($v) ? 'array(' . self::implode_r($v, true) . ')' : $v) . ', ';
3367
+                    $out2 .= var_export($k2, true).' => '.(is_array($v) ? 'array('.self::implode_r($v, true).')' : $v).', ';
3370 3368
                 }
3371
-                $p = rtrim($out2, ', ') . ')';
3369
+                $p = rtrim($out2, ', ').')';
3372 3370
             }
3373 3371
             if ($recursiveCall) {
3374
-                $out .= var_export($k, true) . ' => ' . $p . ', ';
3372
+                $out .= var_export($k, true).' => '.$p.', ';
3375 3373
             } else {
3376
-                $out .= $p . ', ';
3374
+                $out .= $p.', ';
3377 3375
             }
3378 3376
         }
3379 3377
 
@@ -3397,7 +3395,7 @@  discard block
 block discarded – undo
3397 3395
         if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) || ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3398 3396
             $phpFunc = true;
3399 3397
         } elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3400
-            throw new SecurityException('Call to a disallowed php function : ' . $name);
3398
+            throw new SecurityException('Call to a disallowed php function : '.$name);
3401 3399
         }
3402 3400
 
3403 3401
         while ($pluginType <= 0) {
@@ -3408,61 +3406,61 @@  discard block
 block discarded – undo
3408 3406
             elseif (isset($this->customPlugins[$name])) {
3409 3407
                 $pluginType = $this->customPlugins[$name]['type'] | Core::CUSTOM_PLUGIN;
3410 3408
             } // Class blocks plugin
3411
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3409
+            elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($name)) !== false) {
3412 3410
                 $pluginType = Core::CLASS_PLUGIN;
3413
-                if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3411
+                if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3414 3412
                     $pluginType += Core::BLOCK_PLUGIN;
3415 3413
                 }
3416
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name));
3414
+                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($name));
3417 3415
                 if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3418 3416
                     $pluginType |= Core::COMPILABLE_PLUGIN;
3419 3417
                 }
3420 3418
             } // Class functions plugin
3421
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3422
-                $pluginType = Core::FUNC_PLUGIN + Core::CLASS_PLUGIN;
3423
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name));
3419
+            elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name)) !== false) {
3420
+                $pluginType = Core::FUNC_PLUGIN+Core::CLASS_PLUGIN;
3421
+                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name));
3424 3422
                 if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3425 3423
                     $pluginType |= Core::COMPILABLE_PLUGIN;
3426 3424
                 }
3427 3425
             } // Class without namespace
3428
-            elseif (class_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3426
+            elseif (class_exists('Plugin'.Core::toCamelCase($name)) !== false) {
3429 3427
                 $pluginType = Core::CLASS_PLUGIN;
3430
-                if (is_subclass_of('Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3428
+                if (is_subclass_of('Plugin'.Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3431 3429
                     $pluginType += Core::BLOCK_PLUGIN;
3432 3430
                 }
3433
-                $interfaces = class_implements('Plugin' . Core::toCamelCase($name));
3431
+                $interfaces = class_implements('Plugin'.Core::toCamelCase($name));
3434 3432
                 if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3435 3433
                     $pluginType |= Core::COMPILABLE_PLUGIN;
3436 3434
                 }
3437 3435
             } // Function plugin (with/without namespaces)
3438
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase ($name)) !==
3439
-                false || function_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3436
+            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name)) !==
3437
+                false || function_exists('Plugin'.Core::toCamelCase($name)) !== false) {
3440 3438
                 $pluginType = Core::FUNC_PLUGIN;
3441 3439
             } // Function plugin compile (with/without namespaces)
3442
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name) .
3443
-                    'Compile') !== false || function_exists('Plugin' . Core::toCamelCase($name) . 'Compile') !==
3440
+            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name).
3441
+                    'Compile') !== false || function_exists('Plugin'.Core::toCamelCase($name).'Compile') !==
3444 3442
                 false) {
3445 3443
                 $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3446 3444
             } // Helper plugin class compile
3447
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3445
+            elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($name)) !== false) {
3448 3446
                 $pluginType = Core::CLASS_PLUGIN | Core::COMPILABLE_PLUGIN;
3449 3447
             } // Helper plugin function compile
3450
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name) . 'Compile') !== false) {
3448
+            elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($name).'Compile') !== false) {
3451 3449
                 $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3452 3450
             } // Smarty modifier
3453
-            elseif (function_exists('smarty_modifier_' . $name) !== false) {
3451
+            elseif (function_exists('smarty_modifier_'.$name) !== false) {
3454 3452
                 $pluginType = Core::SMARTY_MODIFIER;
3455 3453
             } // Smarty function
3456
-            elseif (function_exists('smarty_function_' . $name) !== false) {
3454
+            elseif (function_exists('smarty_function_'.$name) !== false) {
3457 3455
                 $pluginType = Core::SMARTY_FUNCTION;
3458 3456
             } // Smarty block
3459
-            elseif (function_exists('smarty_block_' . $name) !== false) {
3457
+            elseif (function_exists('smarty_block_'.$name) !== false) {
3460 3458
                 $pluginType = Core::SMARTY_BLOCK;
3461 3459
             } // Everything else
3462 3460
             else {
3463 3461
                 if ($pluginType === - 1) {
3464 3462
                     try {
3465
-                        $this->getCore()->getLoader()->loadPlugin('Plugin' . Core::toCamelCase($name));
3463
+                        $this->getCore()->getLoader()->loadPlugin('Plugin'.Core::toCamelCase($name));
3466 3464
                     }
3467 3465
                     catch (Exception $e) {
3468 3466
                         if (isset($phpFunc)) {
@@ -3475,9 +3473,9 @@  discard block
 block discarded – undo
3475 3473
                         }
3476 3474
                     }
3477 3475
                 } else {
3478
-                    throw new Exception('Plugin "' . $name . '" could not be found, type:' . $pluginType);
3476
+                    throw new Exception('Plugin "'.$name.'" could not be found, type:'.$pluginType);
3479 3477
                 }
3480
-                ++ $pluginType;
3478
+                ++$pluginType;
3481 3479
             }
3482 3480
         }
3483 3481
 
@@ -3546,15 +3544,15 @@  discard block
 block discarded – undo
3546 3544
         }
3547 3545
 
3548 3546
         // loops over the param map and assigns values from the template or default value for unset optional params
3549
-        foreach ($map as $k => $v){
3547
+        foreach ($map as $k => $v) {
3550 3548
             if ($v[0] === '*') {
3551 3549
                 // "rest" array parameter, fill every remaining params in it and then break
3552 3550
                 if (count($ps) === 0) {
3553 3551
                     if ($v[1] === false) {
3554 3552
                         throw new CompilationException(
3555
-                            $this, 'Rest argument missing for ' . str_replace(
3553
+                            $this, 'Rest argument missing for '.str_replace(
3556 3554
                                 array(
3557
-                                    Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3555
+                                    Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin',
3558 3556
                                 'Compile'
3559 3557
                                 ), '', (is_array($callback) ? $callback[0] : $callback)
3560 3558
                             )
@@ -3587,7 +3585,7 @@  discard block
 block discarded – undo
3587 3585
                 // parameter is not defined and not optional, throw error
3588 3586
                 if (is_array($callback)) {
3589 3587
                     if (is_object($callback[0])) {
3590
-                        $name = get_class($callback[0]) . '::' . $callback[1];
3588
+                        $name = get_class($callback[0]).'::'.$callback[1];
3591 3589
                     } else {
3592 3590
                         $name = $callback[0];
3593 3591
                     }
@@ -3596,9 +3594,9 @@  discard block
 block discarded – undo
3596 3594
                 }
3597 3595
 
3598 3596
                 throw new CompilationException(
3599
-                    $this, 'Argument ' . $k . '/' . $v[0] . ' missing for ' . str_replace(
3597
+                    $this, 'Argument '.$k.'/'.$v[0].' missing for '.str_replace(
3600 3598
                         array(
3601
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3599
+                            Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin',
3602 3600
                         'Compile'
3603 3601
                         ), '', $name
3604 3602
                     )
Please login to merge, or discard this patch.
Indentation   +3645 added lines, -3645 removed lines patch added patch discarded remove patch
@@ -31,3651 +31,3651 @@
 block discarded – undo
31 31
  */
32 32
 class Compiler implements ICompiler
33 33
 {
34
-    /**
35
-     * Constant that represents a php opening tag.
36
-     * use it in case it needs to be adjusted
37
-     *
38
-     * @var string
39
-     */
40
-    const PHP_OPEN = '<?php ';
41
-
42
-    /**
43
-     * Constant that represents a php closing tag.
44
-     * use it in case it needs to be adjusted
45
-     *
46
-     * @var string
47
-     */
48
-    const PHP_CLOSE = '?>';
49
-
50
-    /**
51
-     * Boolean flag to enable or disable debugging output.
52
-     *
53
-     * @var bool
54
-     */
55
-    public $debug = false;
56
-
57
-    /**
58
-     * Left script delimiter.
59
-     *
60
-     * @var string
61
-     */
62
-    protected $ld = '{';
63
-
64
-    /**
65
-     * Left script delimiter with escaped regex meta characters.
66
-     *
67
-     * @var string
68
-     */
69
-    protected $ldr = '\\{';
70
-
71
-    /**
72
-     * Right script delimiter.
73
-     *
74
-     * @var string
75
-     */
76
-    protected $rd = '}';
77
-
78
-    /**
79
-     * Right script delimiter with escaped regex meta characters.
80
-     *
81
-     * @var string
82
-     */
83
-    protected $rdr = '\\}';
84
-
85
-    /**
86
-     * Defines whether the nested comments should be parsed as nested or not.
87
-     * defaults to false (classic block comment parsing as in all languages)
88
-     *
89
-     * @var bool
90
-     */
91
-    protected $allowNestedComments = false;
92
-
93
-    /**
94
-     * Defines whether opening and closing tags can contain spaces before valid data or not.
95
-     * turn to true if you want to be sloppy with the syntax, but when set to false it allows
96
-     * to skip javascript and css tags as long as they are in the form "{ something", which is
97
-     * nice. default is false.
98
-     *
99
-     * @var bool
100
-     */
101
-    protected $allowLooseOpenings = false;
102
-
103
-    /**
104
-     * Defines whether the compiler will automatically html-escape variables or not.
105
-     * default is false
106
-     *
107
-     * @var bool
108
-     */
109
-    protected $autoEscape = false;
110
-
111
-    /**
112
-     * Security policy object.
113
-     *
114
-     * @var SecurityPolicy
115
-     */
116
-    protected $securityPolicy;
117
-
118
-    /**
119
-     * Stores the custom plugins registered with this compiler.
120
-     *
121
-     * @var array
122
-     */
123
-    protected $customPlugins = array();
124
-
125
-    /**
126
-     * Stores the template plugins registered with this compiler.
127
-     *
128
-     * @var array
129
-     */
130
-    protected $templatePlugins = array();
131
-
132
-    /**
133
-     * Stores the pre- and post-processors callbacks.
134
-     *
135
-     * @var array
136
-     */
137
-    protected $processors = array('pre' => array(), 'post' => array());
138
-
139
-    /**
140
-     * Stores a list of plugins that are used in the currently compiled
141
-     * template, and that are not compilable. these plugins will be loaded
142
-     * during the template's runtime if required.
143
-     * it is a 1D array formatted as key:pluginName value:pluginType
144
-     *
145
-     * @var array
146
-     */
147
-    protected $usedPlugins;
148
-
149
-    /**
150
-     * Stores the template undergoing compilation.
151
-     *
152
-     * @var string
153
-     */
154
-    protected $template;
155
-
156
-    /**
157
-     * Stores the current pointer position inside the template.
158
-     *
159
-     * @var int
160
-     */
161
-    protected $pointer;
162
-
163
-    /**
164
-     * Stores the current line count inside the template for debugging purposes.
165
-     *
166
-     * @var int
167
-     */
168
-    protected $line;
169
-
170
-    /**
171
-     * Stores the current template source while compiling it.
172
-     *
173
-     * @var string
174
-     */
175
-    protected $templateSource;
176
-
177
-    /**
178
-     * Stores the data within which the scope moves.
179
-     *
180
-     * @var array
181
-     */
182
-    protected $data;
183
-
184
-    /**
185
-     * Variable scope of the compiler, set to null if
186
-     * it can not be resolved to a static string (i.e. if some
187
-     * plugin defines a new scope based on a variable array key).
188
-     *
189
-     * @var mixed
190
-     */
191
-    protected $scope;
192
-
193
-    /**
194
-     * Variable scope tree, that allows to rebuild the current
195
-     * scope if required, i.e. when going to a parent level.
196
-     *
197
-     * @var array
198
-     */
199
-    protected $scopeTree;
200
-
201
-    /**
202
-     * Block plugins stack, accessible through some methods.
203
-     *
204
-     * @see findBlock
205
-     * @see getCurrentBlock
206
-     * @see addBlock
207
-     * @see addCustomBlock
208
-     * @see injectBlock
209
-     * @see removeBlock
210
-     * @see removeTopBlock
211
-     * @var array
212
-     */
213
-    protected $stack = array();
214
-
215
-    /**
216
-     * Current block at the top of the block plugins stack,
217
-     * accessible through getCurrentBlock.
218
-     *
219
-     * @see getCurrentBlock
220
-     * @var array
221
-     */
222
-    protected $curBlock;
223
-
224
-    /**
225
-     * Current dwoo object that uses this compiler, or null.
226
-     *
227
-     * @var Core
228
-     */
229
-    public $core;
230
-
231
-    /**
232
-     * Holds an instance of this class, used by getInstance when you don't
233
-     * provide a custom compiler in order to save resources.
234
-     *
235
-     * @var Compiler
236
-     */
237
-    protected static $instance;
238
-
239
-    /**
240
-     * Token types.
241
-     *
242
-     * @var int
243
-     */
244
-    const T_UNQUOTED_STRING = 1;
245
-    const T_NUMERIC         = 2;
246
-    const T_NULL            = 4;
247
-    const T_BOOL            = 8;
248
-    const T_MATH            = 16;
249
-    const T_BREAKCHAR       = 32;
250
-
251
-    /**
252
-     * Compiler constructor.
253
-     * saves the created instance so that child templates get the same one
254
-     */
255
-    public function __construct()
256
-    {
257
-        self::$instance = $this;
258
-    }
259
-
260
-    /**
261
-     * Sets the delimiters to use in the templates.
262
-     * delimiters can be multi-character strings but should not be one of those as they will
263
-     * make it very hard to work with templates or might even break the compiler entirely : "\", "$", "|", ":" and
264
-     * finally "#" only if you intend to use config-vars with the #var# syntax.
265
-     *
266
-     * @param string $left  left delimiter
267
-     * @param string $right right delimiter
268
-     */
269
-    public function setDelimiters($left, $right)
270
-    {
271
-        $this->ld  = $left;
272
-        $this->rd  = $right;
273
-        $this->ldr = preg_quote($left, '/');
274
-        $this->rdr = preg_quote($right, '/');
275
-    }
276
-
277
-    /**
278
-     * Returns the left and right template delimiters.
279
-     *
280
-     * @return array containing the left and the right delimiters
281
-     */
282
-    public function getDelimiters()
283
-    {
284
-        return array($this->ld, $this->rd);
285
-    }
286
-
287
-    /**
288
-     * Sets the way to handle nested comments, if set to true
289
-     * {* foo {* some other *} comment *} will be stripped correctly.
290
-     * if false it will remove {* foo {* some other *} and leave "comment *}" alone,
291
-     * this is the default behavior
292
-     *
293
-     * @param bool $allow allow nested comments or not, defaults to true (but the default internal value is false)
294
-     */
295
-    public function setNestedCommentsHandling($allow = true)
296
-    {
297
-        $this->allowNestedComments = (bool)$allow;
298
-    }
299
-
300
-    /**
301
-     * Returns the nested comments handling setting.
302
-     *
303
-     * @see    setNestedCommentsHandling
304
-     * @return bool true if nested comments are allowed
305
-     */
306
-    public function getNestedCommentsHandling()
307
-    {
308
-        return $this->allowNestedComments;
309
-    }
310
-
311
-    /**
312
-     * Sets the tag openings handling strictness, if set to true, template tags can
313
-     * contain spaces before the first function/string/variable such as { $foo} is valid.
314
-     * if set to false (default setting), { $foo} is invalid but that is however a good thing
315
-     * as it allows css (i.e. #foo { color:red; }) to be parsed silently without triggering
316
-     * an error, same goes for javascript.
317
-     *
318
-     * @param bool $allow true to allow loose handling, false to restore default setting
319
-     */
320
-    public function setLooseOpeningHandling($allow = false)
321
-    {
322
-        $this->allowLooseOpenings = (bool)$allow;
323
-    }
324
-
325
-    /**
326
-     * Returns the tag openings handling strictness setting.
327
-     *
328
-     * @see    setLooseOpeningHandling
329
-     * @return bool true if loose tags are allowed
330
-     */
331
-    public function getLooseOpeningHandling()
332
-    {
333
-        return $this->allowLooseOpenings;
334
-    }
335
-
336
-    /**
337
-     * Changes the auto escape setting.
338
-     * if enabled, the compiler will automatically html-escape variables,
339
-     * unless they are passed through the safe function such as {$var|safe}
340
-     * or {safe $var}
341
-     * default setting is disabled/false
342
-     *
343
-     * @param bool $enabled set to true to enable, false to disable
344
-     */
345
-    public function setAutoEscape($enabled)
346
-    {
347
-        $this->autoEscape = (bool)$enabled;
348
-    }
349
-
350
-    /**
351
-     * Returns the auto escape setting.
352
-     * default setting is disabled/false
353
-     *
354
-     * @return bool
355
-     */
356
-    public function getAutoEscape()
357
-    {
358
-        return $this->autoEscape;
359
-    }
360
-
361
-    /**
362
-     * Adds a preprocessor to the compiler, it will be called
363
-     * before the template is compiled.
364
-     *
365
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
366
-     *                        true
367
-     * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else
368
-     *                        you must provide a valid callback
369
-     */
370
-    public function addPreProcessor($callback, $autoload = false)
371
-    {
372
-        if ($autoload) {
373
-            $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', Core::toCamelCase($callback));
374
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . $name;
375
-
376
-            if (class_exists($class)) {
377
-                $callback = array(new $class($this), 'process');
378
-            } elseif (function_exists($class)) {
379
-                $callback = $class;
380
-            } else {
381
-                $callback = array('autoload' => true, 'class' => $class, 'name' => $name);
382
-            }
383
-
384
-            $this->processors['pre'][] = $callback;
385
-        } else {
386
-            $this->processors['pre'][] = $callback;
387
-        }
388
-    }
389
-
390
-    /**
391
-     * Removes a preprocessor from the compiler.
392
-     *
393
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if it was autoloaded
394
-     */
395
-    public function removePreProcessor($callback)
396
-    {
397
-        if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
398
-            unset($this->processors['pre'][$index]);
399
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
400
-                    $callback),
401
-                $this->processors['pre'], true)) !== false) {
402
-            unset($this->processors['pre'][$index]);
403
-        } else {
404
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
405
-            foreach ($this->processors['pre'] as $index => $proc) {
406
-                if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
407
-                    unset($this->processors['pre'][$index]);
408
-                    break;
409
-                }
410
-            }
411
-        }
412
-    }
413
-
414
-    /**
415
-     * Adds a postprocessor to the compiler, it will be called
416
-     * before the template is compiled.
417
-     *
418
-     * @param mixed $callback either a valid callback to the postprocessor or a simple name if the autoload is set to
419
-     *                        true
420
-     * @param bool  $autoload if set to true, the postprocessor is auto-loaded from one of the plugin directories, else
421
-     *                        you must provide a valid callback
422
-     */
423
-    public function addPostProcessor($callback, $autoload = false)
424
-    {
425
-        if ($autoload) {
426
-            $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
427
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . Core::toCamelCase($name);
428
-
429
-            if (class_exists($class)) {
430
-                $callback = array(new $class($this), 'process');
431
-            } elseif (function_exists($class)) {
432
-                $callback = $class;
433
-            } else {
434
-                $callback = array('autoload' => true, 'class' => $class, 'name' => $name);
435
-            }
436
-
437
-            $this->processors['post'][] = $callback;
438
-        } else {
439
-            $this->processors['post'][] = $callback;
440
-        }
441
-    }
442
-
443
-    /**
444
-     * Removes a postprocessor from the compiler.
445
-     *
446
-     * @param mixed $callback either a valid callback to the postprocessor or a simple name if it was autoloaded
447
-     */
448
-    public function removePostProcessor($callback)
449
-    {
450
-        if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
451
-            unset($this->processors['post'][$index]);
452
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
453
-                    $callback),
454
-                $this->processors['post'], true)) !== false) {
455
-            unset($this->processors['post'][$index]);
456
-        } else {
457
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
458
-            foreach ($this->processors['post'] as $index => $proc) {
459
-                if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
460
-                    unset($this->processors['post'][$index]);
461
-                    break;
462
-                }
463
-            }
464
-        }
465
-    }
466
-
467
-    /**
468
-     * Internal function to autoload processors at runtime if required.
469
-     *
470
-     * @param string $class the class/function name
471
-     * @param string $name  the plugin name (without Dwoo_Plugin_ prefix)
472
-     *
473
-     * @return array|string
474
-     * @throws Exception
475
-     */
476
-    protected function loadProcessor($class, $name)
477
-    {
478
-        if (!class_exists($class) && !function_exists($class)) {
479
-            try {
480
-                $this->getCore()->getLoader()->loadPlugin($name);
481
-            }
482
-            catch (Exception $e) {
483
-                throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
484
-            }
485
-        }
486
-
487
-        if (class_exists($class)) {
488
-            return array(new $class($this), 'process');
489
-        }
490
-
491
-        if (function_exists($class)) {
492
-            return $class;
493
-        }
494
-
495
-        throw new Exception('Wrong processor name, when using autoload the processor must be in one of your plugin dir as "name.php" containg a class or function named "Dwoo_Processor_name"');
496
-    }
497
-
498
-    /**
499
-     * Adds an used plugin, this is reserved for use by the {template} plugin.
500
-     * this is required so that plugin loading bubbles up from loaded
501
-     * template files to the current one
502
-     *
503
-     * @private
504
-     *
505
-     * @param string $name function name
506
-     * @param int    $type plugin type (Core::*_PLUGIN)
507
-     */
508
-    public function addUsedPlugin($name, $type)
509
-    {
510
-        $this->usedPlugins[$name] = $type;
511
-    }
512
-
513
-    /**
514
-     * Returns all the plugins this template uses.
515
-     *
516
-     * @private
517
-     * @return  array the list of used plugins in the parsed template
518
-     */
519
-    public function getUsedPlugins()
520
-    {
521
-        return $this->usedPlugins;
522
-    }
523
-
524
-    /**
525
-     * Adds a template plugin, this is reserved for use by the {template} plugin.
526
-     * this is required because the template functions are not declared yet
527
-     * during compilation, so we must have a way of validating their argument
528
-     * signature without using the reflection api
529
-     *
530
-     * @private
531
-     *
532
-     * @param string $name   function name
533
-     * @param array  $params parameter array to help validate the function call
534
-     * @param string $uuid   unique id of the function
535
-     * @param string $body   function php code
536
-     */
537
-    public function addTemplatePlugin($name, array $params, $uuid, $body = null)
538
-    {
539
-        $this->templatePlugins[$name] = array('params' => $params, 'body' => $body, 'uuid' => $uuid);
540
-    }
541
-
542
-    /**
543
-     * Returns all the parsed sub-templates.
544
-     *
545
-     * @private
546
-     * @return  array the parsed sub-templates
547
-     */
548
-    public function getTemplatePlugins()
549
-    {
550
-        return $this->templatePlugins;
551
-    }
552
-
553
-    /**
554
-     * Marks a template plugin as being called, which means its source must be included in the compiled template.
555
-     *
556
-     * @param string $name function name
557
-     */
558
-    public function useTemplatePlugin($name)
559
-    {
560
-        $this->templatePlugins[$name]['called'] = true;
561
-    }
562
-
563
-    /**
564
-     * Adds the custom plugins loaded into Dwoo to the compiler so it can load them.
565
-     *
566
-     * @see Core::addPlugin
567
-     *
568
-     * @param array $customPlugins an array of custom plugins
569
-     */
570
-    public function setCustomPlugins(array $customPlugins)
571
-    {
572
-        $this->customPlugins = $customPlugins;
573
-    }
574
-
575
-    /**
576
-     * Sets the security policy object to enforce some php security settings.
577
-     * use this if untrusted persons can modify templates,
578
-     * set it on the Dwoo object as it will be passed onto the compiler automatically
579
-     *
580
-     * @param SecurityPolicy $policy the security policy object
581
-     */
582
-    public function setSecurityPolicy(SecurityPolicy $policy = null)
583
-    {
584
-        $this->securityPolicy = $policy;
585
-    }
586
-
587
-    /**
588
-     * Returns the current security policy object or null by default.
589
-     *
590
-     * @return SecurityPolicy|null the security policy object if any
591
-     */
592
-    public function getSecurityPolicy()
593
-    {
594
-        return $this->securityPolicy;
595
-    }
596
-
597
-    /**
598
-     * Sets the pointer position.
599
-     *
600
-     * @param int  $position the new pointer position
601
-     * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
602
-     */
603
-    public function setPointer($position, $isOffset = false)
604
-    {
605
-        if ($isOffset) {
606
-            $this->pointer += $position;
607
-        } else {
608
-            $this->pointer = $position;
609
-        }
610
-    }
611
-
612
-    /**
613
-     * Returns the current pointer position, only available during compilation of a template.
614
-     *
615
-     * @return int
616
-     */
617
-    public function getPointer()
618
-    {
619
-        return $this->pointer;
620
-    }
621
-
622
-    /**
623
-     * Sets the line number.
624
-     *
625
-     * @param int  $number   the new line number
626
-     * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
627
-     */
628
-    public function setLine($number, $isOffset = false)
629
-    {
630
-        if ($isOffset) {
631
-            $this->line += $number;
632
-        } else {
633
-            $this->line = $number;
634
-        }
635
-    }
636
-
637
-    /**
638
-     * Returns the current line number, only available during compilation of a template.
639
-     *
640
-     * @return int
641
-     */
642
-    public function getLine()
643
-    {
644
-        return $this->line;
645
-    }
646
-
647
-    /**
648
-     * Returns the dwoo object that initiated this template compilation, only available during compilation of a
649
-     * template.
650
-     *
651
-     * @return Core
652
-     */
653
-    public function getCore()
654
-    {
655
-        return $this->core;
656
-    }
657
-
658
-    /**
659
-     * Overwrites the template that is being compiled.
660
-     *
661
-     * @param string $newSource   the template source that must replace the current one
662
-     * @param bool   $fromPointer if set to true, only the source from the current pointer position is replaced
663
-     *
664
-     * @return void
665
-     */
666
-    public function setTemplateSource($newSource, $fromPointer = false)
667
-    {
668
-        if ($fromPointer === true) {
669
-            $this->templateSource = substr($this->templateSource, 0, $this->pointer) . $newSource;
670
-        } else {
671
-            $this->templateSource = $newSource;
672
-        }
673
-    }
674
-
675
-    /**
676
-     * Returns the template that is being compiled.
677
-     *
678
-     * @param mixed $fromPointer if set to true, only the source from the current pointer
679
-     *                           position is returned, if a number is given it overrides the current pointer
680
-     *
681
-     * @return string the template or partial template
682
-     */
683
-    public function getTemplateSource($fromPointer = false)
684
-    {
685
-        if ($fromPointer === true) {
686
-            return substr($this->templateSource, $this->pointer);
687
-        } elseif (is_numeric($fromPointer)) {
688
-            return substr($this->templateSource, $fromPointer);
689
-        } else {
690
-            return $this->templateSource;
691
-        }
692
-    }
693
-
694
-    /**
695
-     * Resets the compilation pointer, effectively restarting the compilation process.
696
-     * this is useful if a plugin modifies the template source since it might need to be recompiled
697
-     */
698
-    public function recompile()
699
-    {
700
-        $this->setPointer(0);
701
-    }
702
-
703
-    /**
704
-     * Compiles the provided string down to php code.
705
-     *
706
-     * @param Core      $core
707
-     * @param ITemplate $template the template to compile
708
-     *
709
-     * @return string a compiled php string
710
-     * @throws CompilationException
711
-     */
712
-    public function compile(Core $core, ITemplate $template)
713
-    {
714
-        // init vars
715
-        //		$compiled = '';
716
-        $tpl                  = $template->getSource();
717
-        $ptr                  = 0;
718
-        $this->core           = $core;
719
-        $this->template       = $template;
720
-        $this->templateSource = &$tpl;
721
-        $this->pointer        = &$ptr;
722
-
723
-        while (true) {
724
-            // if pointer is at the beginning, reset everything, that allows a plugin to externally reset the compiler if everything must be reparsed
725
-            if ($ptr === 0) {
726
-                // resets variables
727
-                $this->usedPlugins     = array();
728
-                $this->data            = array();
729
-                $this->scope           = &$this->data;
730
-                $this->scopeTree       = array();
731
-                $this->stack           = array();
732
-                $this->line            = 1;
733
-                $this->templatePlugins = array();
734
-                // add top level block
735
-                $compiled                 = $this->addBlock('TopLevelBlock', array(), 0);
736
-                $this->stack[0]['buffer'] = '';
737
-
738
-                if ($this->debug) {
739
-                    echo "\n";
740
-                    echo 'COMPILER INIT' . "\n";
741
-                }
742
-
743
-                if ($this->debug) {
744
-                    echo 'PROCESSING PREPROCESSORS (' . count($this->processors['pre']) . ')' . "\n";
745
-                }
746
-
747
-                // runs preprocessors
748
-                foreach ($this->processors['pre'] as $preProc) {
749
-                    if (is_array($preProc) && isset($preProc['autoload'])) {
750
-                        $preProc = $this->loadProcessor($preProc['class'], $preProc['name']);
751
-                    }
752
-                    if (is_array($preProc) && $preProc[0] instanceof Processor) {
753
-                        $tpl = call_user_func($preProc, $tpl);
754
-                    } else {
755
-                        $tpl = call_user_func($preProc, $this, $tpl);
756
-                    }
757
-                }
758
-                unset($preProc);
759
-
760
-                // show template source if debug
761
-                if ($this->debug) {
762
-                    echo '<pre>'.print_r(htmlentities($tpl), true).'</pre>'."\n";
763
-                }
764
-
765
-                // strips php tags if required by the security policy
766
-                if ($this->securityPolicy !== null) {
767
-                    $search = array('{<\?php.*?\?>}');
768
-                    if (ini_get('short_open_tags')) {
769
-                        $search = array('{<\?.*?\?>}', '{<%.*?%>}');
770
-                    }
771
-                    switch ($this->securityPolicy->getPhpHandling()) {
772
-                        case SecurityPolicy::PHP_ALLOW:
773
-                            break;
774
-                        case SecurityPolicy::PHP_ENCODE:
775
-                            $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
-                            break;
777
-                        case SecurityPolicy::PHP_REMOVE:
778
-                            $tpl = preg_replace($search, '', $tpl);
779
-                    }
780
-                }
781
-            }
782
-
783
-            $pos = strpos($tpl, $this->ld, $ptr);
784
-
785
-            if ($pos === false) {
786
-                $this->push(substr($tpl, $ptr), 0);
787
-                break;
788
-            } elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
789
-                $this->push(substr($tpl, $ptr, $pos - $ptr - 1) . $this->ld);
790
-                $ptr = $pos + strlen($this->ld);
791
-            } elseif (preg_match('/^' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . 'literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', substr($tpl, $pos), $litOpen)) {
792
-                if (!preg_match('/' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . '\/literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
793
-                    throw new CompilationException($this, 'The {literal} blocks must be closed explicitly with {/literal}');
794
-                }
795
-                $endpos = $litClose[0][1];
796
-                $this->push(substr($tpl, $ptr, $pos - $ptr) . substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
797
-                $ptr = $endpos + strlen($litClose[0][0]);
798
-            } else {
799
-                if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
800
-                    $this->push(substr($tpl, $ptr, $pos - $ptr - 1));
801
-                    $ptr = $pos;
802
-                }
803
-
804
-                $this->push(substr($tpl, $ptr, $pos - $ptr));
805
-                $ptr = $pos;
806
-
807
-                $pos += strlen($this->ld);
808
-                if ($this->allowLooseOpenings) {
809
-                    while (substr($tpl, $pos, 1) === ' ') {
810
-                        $pos += 1;
811
-                    }
812
-                } else {
813
-                    if (substr($tpl, $pos, 1) === ' ' || substr($tpl, $pos, 1) === "\r" || substr($tpl, $pos, 1) === "\n" || substr($tpl, $pos, 1) === "\t") {
814
-                        $ptr = $pos;
815
-                        $this->push($this->ld);
816
-                        continue;
817
-                    }
818
-                }
819
-
820
-                // check that there is an end tag present
821
-                if (strpos($tpl, $this->rd, $pos) === false) {
822
-                    throw new CompilationException($this, 'A template tag was not closed, started with "' . substr($tpl, $ptr, 30) . '"');
823
-                }
824
-
825
-                $ptr += strlen($this->ld);
826
-                $subptr = $ptr;
827
-
828
-                while (true) {
829
-                    $parsed = $this->parse($tpl, $subptr, null, false, 'root', $subptr);
830
-
831
-                    // reload loop if the compiler was reset
832
-                    if ($ptr === 0) {
833
-                        continue 2;
834
-                    }
835
-
836
-                    $len = $subptr - $ptr;
837
-                    $this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
838
-                    $ptr += $len;
839
-
840
-                    if ($parsed === false) {
841
-                        break;
842
-                    }
843
-                }
844
-            }
845
-        }
846
-
847
-        $compiled .= $this->removeBlock('TopLevelBlock');
848
-
849
-        if ($this->debug) {
850
-            echo 'PROCESSING POSTPROCESSORS' . "\n";
851
-        }
852
-
853
-        foreach ($this->processors['post'] as $postProc) {
854
-            if (is_array($postProc) && isset($postProc['autoload'])) {
855
-                $postProc = $this->loadProcessor($postProc['class'], $postProc['name']);
856
-            }
857
-            if (is_array($postProc) && $postProc[0] instanceof Processor) {
858
-                $compiled = call_user_func($postProc, $compiled);
859
-            } else {
860
-                $compiled = call_user_func($postProc, $this, $compiled);
861
-            }
862
-        }
863
-        unset($postProc);
864
-
865
-        if ($this->debug) {
866
-            echo 'COMPILATION COMPLETE : MEM USAGE : ' . memory_get_usage() . "\n";
867
-        }
868
-
869
-        $output = "<?php\n/* template head */\n";
870
-
871
-        // build plugin preloader
872
-        foreach ($this->getUsedPlugins() as $plugin => $type) {
873
-            if ($type & Core::CUSTOM_PLUGIN) {
874
-                continue;
875
-            }
876
-
877
-            switch ($type) {
878
-                case Core::CLASS_PLUGIN:
879
-                case Core::CLASS_PLUGIN + Core::BLOCK_PLUGIN:
880
-                    if (class_exists('Plugin' . $plugin) !== false) {
881
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
-                    } else {
884
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
-                    }
887
-                    break;
888
-                case Core::CLASS_PLUGIN + Core::FUNC_PLUGIN:
889
-                    if (class_exists('Plugin' . $plugin) !== false) {
890
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
891
-                            "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
-                    } else {
893
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
-                            "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
-                    }
896
-                    break;
897
-                case Core::FUNC_PLUGIN:
898
-                    if (function_exists('Plugin' . $plugin) !== false) {
899
-                        $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
900
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
901
-                    } else {
902
-                        $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
903
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
904
-                    }
905
-                    break;
906
-                case Core::SMARTY_MODIFIER:
907
-                    $output .= "if (function_exists('smarty_modifier_$plugin')===false)".
908
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
909
-                    break;
910
-                case Core::SMARTY_FUNCTION:
911
-                    $output .= "if (function_exists('smarty_function_$plugin')===false)".
912
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
913
-                    break;
914
-                case Core::SMARTY_BLOCK:
915
-                    $output .= "if (function_exists('smarty_block_$plugin')===false)".
916
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
917
-                    break;
918
-                case Core::PROXY_PLUGIN:
919
-                    $output .= $this->getCore()->getPluginProxy()->getLoader($plugin);
920
-                    break;
921
-                default:
922
-                    throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
923
-            }
924
-        }
925
-
926
-        foreach ($this->templatePlugins as $function => $attr) {
927
-            if (isset($attr['called']) && $attr['called'] === true && !isset($attr['checked'])) {
928
-                $this->resolveSubTemplateDependencies($function);
929
-            }
930
-        }
931
-        foreach ($this->templatePlugins as $function) {
932
-            if (isset($function['called']) && $function['called'] === true) {
933
-                $output .= $function['body'] . PHP_EOL;
934
-            }
935
-        }
936
-
937
-        $output .= $compiled . "\n?>";
938
-
939
-        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*' . preg_quote(self::PHP_CLOSE, '/') . preg_quote(self::PHP_OPEN, '/') . ')/', ";\n", $output);
940
-        $output = str_replace(self::PHP_CLOSE . self::PHP_OPEN, "\n", $output);
941
-
942
-        // handle <?xml tag at the beginning
943
-        $output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
944
-
945
-        // add another line break after PHP closing tags that have a line break following,
946
-        // as we do not know whether it's intended, and PHP will strip it otherwise
947
-        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0' . "\n", $output);
948
-
949
-        if ($this->debug) {
950
-            echo '=============================================================================================' . "\n";
951
-            $lines = preg_split('{\r\n|\n|<br />}', $output);
952
-            array_shift($lines);
953
-            foreach ($lines as $i => $line) {
954
-                echo ($i + 1) . '. ' . $line . "\r\n";
955
-            }
956
-            echo '=============================================================================================' . "\n";
957
-        }
958
-
959
-        $this->template = $this->dwoo = null;
960
-        $tpl            = null;
961
-
962
-        return $output;
963
-    }
964
-
965
-    /**
966
-     * Checks what sub-templates are used in every sub-template so that we're sure they are all compiled.
967
-     *
968
-     * @param string $function the sub-template name
969
-     */
970
-    protected function resolveSubTemplateDependencies($function)
971
-    {
972
-        if ($this->debug) {
973
-            echo 'Compiler::' . __FUNCTION__ . "\n";
974
-        }
975
-
976
-        $body = $this->templatePlugins[$function]['body'];
977
-        foreach ($this->templatePlugins as $func => $attr) {
978
-            if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS .
979
-            'Plugin' . Core::toCamelCase($func)) !== false) {
980
-                $this->templatePlugins[$func]['called'] = true;
981
-                $this->resolveSubTemplateDependencies($func);
982
-            }
983
-        }
984
-        $this->templatePlugins[$function]['checked'] = true;
985
-    }
986
-
987
-    /**
988
-     * Adds compiled content to the current block.
989
-     *
990
-     * @param string $content   the content to push
991
-     * @param int    $lineCount newlines count in content, optional
992
-     *
993
-     * @throws CompilationException
994
-     */
995
-    public function push($content, $lineCount = null)
996
-    {
997
-        if ($lineCount === null) {
998
-            $lineCount = substr_count($content, "\n");
999
-        }
1000
-
1001
-        if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
1002
-            // buffer is not initialized yet (the block has just been created)
1003
-            $this->stack[count($this->stack) - 2]['buffer'] .= (string)$content;
1004
-            $this->curBlock['buffer'] = '';
1005
-        } else {
1006
-            if (!isset($this->curBlock['buffer'])) {
1007
-                throw new CompilationException($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
1008
-            }
1009
-            // append current content to current block's buffer
1010
-            $this->curBlock['buffer'] .= (string)$content;
1011
-        }
1012
-        $this->line += $lineCount;
1013
-    }
1014
-
1015
-    /**
1016
-     * Sets the scope.
1017
-     * set to null if the scope becomes "unstable" (i.e. too variable or unknown) so that
1018
-     * variables are compiled in a more evaluative way than just $this->scope['key']
1019
-     *
1020
-     * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1021
-     * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1022
-     *
1023
-     * @return array the current scope tree
1024
-     */
1025
-    public function setScope($scope, $absolute = false)
1026
-    {
1027
-        $old = $this->scopeTree;
1028
-
1029
-        if ($scope === null) {
1030
-            unset($this->scope);
1031
-            $this->scope = null;
1032
-        }
1033
-
1034
-        if (is_array($scope) === false) {
1035
-            $scope = explode('.', $scope);
1036
-        }
1037
-
1038
-        if ($absolute === true) {
1039
-            $this->scope     = &$this->data;
1040
-            $this->scopeTree = array();
1041
-        }
1042
-
1043
-        while (($bit = array_shift($scope)) !== null) {
1044
-            if ($bit === '_parent' || $bit === '_') {
1045
-                array_pop($this->scopeTree);
1046
-                reset($this->scopeTree);
1047
-                $this->scope = &$this->data;
1048
-                $cnt         = count($this->scopeTree);
1049
-                for ($i = 0; $i < $cnt; ++ $i) {
1050
-                    $this->scope = &$this->scope[$this->scopeTree[$i]];
1051
-                }
1052
-            } elseif ($bit === '_root' || $bit === '__') {
1053
-                $this->scope     = &$this->data;
1054
-                $this->scopeTree = array();
1055
-            } elseif (isset($this->scope[$bit])) {
1056
-                $this->scope       = &$this->scope[$bit];
1057
-                $this->scopeTree[] = $bit;
1058
-            } else {
1059
-                $this->scope[$bit] = array();
1060
-                $this->scope       = &$this->scope[$bit];
1061
-                $this->scopeTree[] = $bit;
1062
-            }
1063
-        }
1064
-
1065
-        return $old;
1066
-    }
1067
-
1068
-    /**
1069
-     * Adds a block to the top of the block stack.
1070
-     *
1071
-     * @param string $type      block type (name)
1072
-     * @param array  $params    the parameters array
1073
-     * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1074
-     *
1075
-     * @return string the preProcessing() method's output
1076
-     */
1077
-    public function addBlock($type, array $params, $paramtype)
1078
-    {
1079
-        if ($this->debug) {
1080
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1081
-        }
1082
-
1083
-        $class = current(array_filter([
1084
-            'Plugin' . Core::toCamelCase($type),
1085
-            Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type)
1086
-        ], 'class_exists'));
1087
-        if (false === $class) {
1088
-            $this->getCore()->getLoader()->loadPlugin($type);
1089
-        }
1090
-        $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1091
-
1092
-        $this->stack[]  = array(
1093
-            'type'   => $type,
1094
-            'params' => $params,
1095
-            'custom' => false,
1096
-            'class'  => $class,
1097
-            'buffer' => null
1098
-        );
1099
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1100
-
1101
-        return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1102
-    }
1103
-
1104
-    /**
1105
-     * Adds a custom block to the top of the block stack.
1106
-     *
1107
-     * @param string $type      block type (name)
1108
-     * @param array  $params    the parameters array
1109
-     * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1110
-     *
1111
-     * @return string the preProcessing() method's output
1112
-     */
1113
-    public function addCustomBlock($type, array $params, $paramtype)
1114
-    {
1115
-        $callback = $this->customPlugins[$type]['callback'];
1116
-        if (is_array($callback)) {
1117
-            $class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
1118
-        } else {
1119
-            $class = $callback;
1120
-        }
1121
-
1122
-        $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1123
-
1124
-        $this->stack[]  = array(
1125
-            'type'   => $type,
1126
-            'params' => $params,
1127
-            'custom' => true,
1128
-            'class'  => $class,
1129
-            'buffer' => null
1130
-        );
1131
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1132
-
1133
-        return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1134
-    }
1135
-
1136
-    /**
1137
-     * Injects a block at the top of the plugin stack without calling its preProcessing method.
1138
-     * used by {else} blocks to re-add themselves after having closed everything up to their parent
1139
-     *
1140
-     * @param string $type   block type (name)
1141
-     * @param array  $params parameters array
1142
-     */
1143
-    public function injectBlock($type, array $params)
1144
-    {
1145
-        if ($this->debug) {
1146
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1147
-        }
1148
-
1149
-        $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1150
-        if (class_exists($class) === false) {
1151
-            $this->getCore()->getLoader()->loadPlugin($type);
1152
-        }
1153
-        $this->stack[]  = array(
1154
-            'type'   => $type,
1155
-            'params' => $params,
1156
-            'custom' => false,
1157
-            'class'  => $class,
1158
-            'buffer' => null
1159
-        );
1160
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1161
-    }
1162
-
1163
-    /**
1164
-     * Removes the closest-to-top block of the given type and all other
1165
-     * blocks encountered while going down the block stack.
1166
-     *
1167
-     * @param string $type block type (name)
1168
-     *
1169
-     * @return string the output of all postProcessing() method's return values of the closed blocks
1170
-     * @throws CompilationException
1171
-     */
1172
-    public function removeBlock($type)
1173
-    {
1174
-        if ($this->debug) {
1175
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1176
-        }
1177
-
1178
-        $output = '';
1179
-
1180
-        $pluginType = $this->getPluginType($type);
1181
-        if ($pluginType & Core::SMARTY_BLOCK) {
1182
-            $type = 'Smartyinterface';
1183
-        }
1184
-        while (true) {
1185
-            while ($top = array_pop($this->stack)) {
1186
-                if ($top['custom']) {
1187
-                    $class = $top['class'];
1188
-                } else {
1189
-                    $class = current(array_filter([
1190
-                        'Plugin' . Core::toCamelCase($top['type']),
1191
-                        Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($top['type'])
1192
-                    ], 'class_exists'));
1193
-                }
1194
-                if (count($this->stack)) {
1195
-                    $this->curBlock = &$this->stack[count($this->stack) - 1];
1196
-                    $this->push(call_user_func(array(
1197
-                        $class,
1198
-                        'postProcessing'
1199
-                    ), $this, $top['params'], '', '', $top['buffer']), 0);
1200
-                } else {
1201
-                    $null           = null;
1202
-                    $this->curBlock = &$null;
1203
-                    $output         = call_user_func(
1204
-                        array(
1205
-                        $class,
1206
-                        'postProcessing'
1207
-                        ), $this, $top['params'], '', '', $top['buffer']
1208
-                    );
1209
-                }
1210
-
1211
-                if ($top['type'] === $type) {
1212
-                    break 2;
1213
-                }
1214
-            }
1215
-
1216
-            throw new CompilationException($this, 'Syntax malformation, a block of type "' . $type . '" was closed but was not opened');
1217
-        }
1218
-
1219
-        return $output;
1220
-    }
1221
-
1222
-    /**
1223
-     * Returns a reference to the first block of the given type encountered and
1224
-     * optionally closes all blocks until it finds it
1225
-     * this is mainly used by {else} plugins to close everything that was opened
1226
-     * between their parent and themselves.
1227
-     *
1228
-     * @param string $type       the block type (name)
1229
-     * @param bool   $closeAlong whether to close all blocks encountered while going down the block stack or not
1230
-     *
1231
-     * @return mixed &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1232
-     *               'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1233
-     * @throws CompilationException
1234
-     */
1235
-    public function &findBlock($type, $closeAlong = false)
1236
-    {
1237
-        if ($closeAlong === true) {
1238
-            while ($b = end($this->stack)) {
1239
-                if ($b['type'] === $type) {
1240
-                    return $this->stack[key($this->stack)];
1241
-                }
1242
-                $this->push($this->removeTopBlock(), 0);
1243
-            }
1244
-        } else {
1245
-            end($this->stack);
1246
-            while ($b = current($this->stack)) {
1247
-                if ($b['type'] === $type) {
1248
-                    return $this->stack[key($this->stack)];
1249
-                }
1250
-                prev($this->stack);
1251
-            }
1252
-        }
1253
-
1254
-        throw new CompilationException($this, 'A parent block of type "' . $type . '" is required and can not be found');
1255
-    }
1256
-
1257
-    /**
1258
-     * Returns a reference to the current block array.
1259
-     *
1260
-     * @return array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1261
-     *                'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1262
-     */
1263
-    public function &getCurrentBlock()
1264
-    {
1265
-        return $this->curBlock;
1266
-    }
1267
-
1268
-    /**
1269
-     * Removes the block at the top of the stack and calls its postProcessing() method.
1270
-     *
1271
-     * @return string the postProcessing() method's output
1272
-     * @throws CompilationException
1273
-     */
1274
-    public function removeTopBlock()
1275
-    {
1276
-        if ($this->debug) {
1277
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1278
-        }
1279
-
1280
-        $o = array_pop($this->stack);
1281
-        if ($o === null) {
1282
-            throw new CompilationException($this, 'Syntax malformation, a block of unknown type was closed but was not opened.');
1283
-        }
1284
-        if ($o['custom']) {
1285
-            $class = $o['class'];
1286
-        } else {
1287
-            $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($o['type']);
1288
-        }
1289
-
1290
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1291
-
1292
-        return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1293
-    }
1294
-
1295
-    /**
1296
-     * Returns the compiled parameters (for example a variable's compiled parameter will be "$this->scope['key']") out
1297
-     * of the given parameter array.
1298
-     *
1299
-     * @param array $params parameter array
1300
-     *
1301
-     * @return array filtered parameters
1302
-     */
1303
-    public function getCompiledParams(array $params)
1304
-    {
1305
-        foreach ($params as $k => $p) {
1306
-            if (is_array($p)) {
1307
-                $params[$k] = $p[0];
1308
-            }
1309
-        }
1310
-
1311
-        return $params;
1312
-    }
1313
-
1314
-    /**
1315
-     * Returns the real parameters (for example a variable's real parameter will be its key, etc) out of the given
1316
-     * parameter array.
1317
-     *
1318
-     * @param array $params parameter array
1319
-     *
1320
-     * @return array filtered parameters
1321
-     */
1322
-    public function getRealParams(array $params)
1323
-    {
1324
-        foreach ($params as $k => $p) {
1325
-            if (is_array($p)) {
1326
-                $params[$k] = $p[1];
1327
-            }
1328
-        }
1329
-
1330
-        return $params;
1331
-    }
1332
-
1333
-    /**
1334
-     * Returns the token of each parameter out of the given parameter array.
1335
-     *
1336
-     * @param array $params parameter array
1337
-     *
1338
-     * @return array tokens
1339
-     */
1340
-    public function getParamTokens(array $params)
1341
-    {
1342
-        foreach ($params as $k => $p) {
1343
-            if (is_array($p)) {
1344
-                $params[$k] = isset($p[2]) ? $p[2] : 0;
1345
-            }
1346
-        }
1347
-
1348
-        return $params;
1349
-    }
1350
-
1351
-    /**
1352
-     * Entry point of the parser, it redirects calls to other parse* functions.
1353
-     *
1354
-     * @param string $in            the string within which we must parse something
1355
-     * @param int    $from          the starting offset of the parsed area
1356
-     * @param int    $to            the ending offset of the parsed area
1357
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1358
-     *                              default
1359
-     * @param string $curBlock      the current parser-block being processed
1360
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1361
-     *                              or null by default
1362
-     *
1363
-     * @return string parsed values
1364
-     * @throws CompilationException
1365
-     */
1366
-    protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1367
-    {
1368
-        if ($this->debug) {
1369
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1370
-        }
1371
-
1372
-        if ($to === null) {
1373
-            $to = strlen($in);
1374
-        }
1375
-        $first = substr($in, $from, 1);
1376
-
1377
-        if ($first === false) {
1378
-            throw new CompilationException($this, 'Unexpected EOF, a template tag was not closed');
1379
-        }
1380
-
1381
-        while ($first === ' ' || $first === "\n" || $first === "\t" || $first === "\r") {
1382
-            if ($curBlock === 'root' && substr($in, $from, strlen($this->rd)) === $this->rd) {
1383
-                // end template tag
1384
-                $pointer += strlen($this->rd);
1385
-                if ($this->debug) {
1386
-                    echo 'TEMPLATE PARSING ENDED' . "\n";
1387
-                }
1388
-
1389
-                return false;
1390
-            }
1391
-            ++ $from;
1392
-            if ($pointer !== null) {
1393
-                ++ $pointer;
1394
-            }
1395
-            if ($from >= $to) {
1396
-                if (is_array($parsingParams)) {
1397
-                    return $parsingParams;
1398
-                } else {
1399
-                    return '';
1400
-                }
1401
-            }
1402
-            $first = $in[$from];
1403
-        }
1404
-
1405
-        $substr = substr($in, $from, $to - $from);
1406
-
1407
-        if ($this->debug) {
1408
-            echo 'PARSE CALL : PARSING "' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . '" @ ' . $from . ':' . $to . ' in ' . $curBlock . ' : pointer=' . $pointer . "\n";
1409
-        }
1410
-        $parsed = '';
1411
-
1412
-        if ($curBlock === 'root' && $first === '*') {
1413
-            $src      = $this->getTemplateSource();
1414
-            $startpos = $this->getPointer() - strlen($this->ld);
1415
-            if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1416
-                if ($startpos > 0) {
1417
-                    do {
1418
-                        $char = substr($src, -- $startpos, 1);
1419
-                        if ($char == "\n") {
1420
-                            ++ $startpos;
1421
-                            $whitespaceStart = true;
1422
-                            break;
1423
-                        }
1424
-                    }
1425
-                    while ($startpos > 0 && ($char == ' ' || $char == "\t"));
1426
-                }
1427
-
1428
-                if (!isset($whitespaceStart)) {
1429
-                    $startpos = $this->getPointer();
1430
-                } else {
1431
-                    $pointer -= $this->getPointer() - $startpos;
1432
-                }
1433
-
1434
-                if ($this->allowNestedComments && strpos($src, $this->ld . '*', $this->getPointer()) !== false) {
1435
-                    $comOpen  = $this->ld . '*';
1436
-                    $comClose = '*' . $this->rd;
1437
-                    $level    = 1;
1438
-                    $ptr      = $this->getPointer();
1439
-
1440
-                    while ($level > 0 && $ptr < strlen($src)) {
1441
-                        $open  = strpos($src, $comOpen, $ptr);
1442
-                        $close = strpos($src, $comClose, $ptr);
1443
-
1444
-                        if ($open !== false && $close !== false) {
1445
-                            if ($open < $close) {
1446
-                                $ptr = $open + strlen($comOpen);
1447
-                                ++ $level;
1448
-                            } else {
1449
-                                $ptr = $close + strlen($comClose);
1450
-                                -- $level;
1451
-                            }
1452
-                        } elseif ($open !== false) {
1453
-                            $ptr = $open + strlen($comOpen);
1454
-                            ++ $level;
1455
-                        } elseif ($close !== false) {
1456
-                            $ptr = $close + strlen($comClose);
1457
-                            -- $level;
1458
-                        } else {
1459
-                            $ptr = strlen($src);
1460
-                        }
1461
-                    }
1462
-                    $endpos = $ptr - strlen('*' . $this->rd);
1463
-                } else {
1464
-                    $endpos = strpos($src, '*' . $this->rd, $startpos);
1465
-                    if ($endpos == false) {
1466
-                        throw new CompilationException($this, 'Un-ended comment');
1467
-                    }
1468
-                }
1469
-                $pointer += $endpos - $startpos + strlen('*' . $this->rd);
1470
-                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*' . $this->rd)), $m)) {
1471
-                    $pointer += strlen($m[0]);
1472
-                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1473
-                }
1474
-
1475
-                return false;
1476
-            }
1477
-        }
1478
-
1479
-        if ($first === '$') {
1480
-            // var
1481
-            $out    = $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
1482
-            $parsed = 'var';
1483
-        } elseif ($first === '%' && preg_match('#^%[a-z_\\\\]#i', $substr)) {
1484
-            // Short constant
1485
-            $out = $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
1486
-        } elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1487
-            // string
1488
-            $out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1489
-        } elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?(' . (is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|') . '\s*\(|\s*' . $this->rdr . '|\s*;)/i', $substr)) {
1490
-            // func
1491
-            $out    = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1492
-            $parsed = 'func';
1493
-        } elseif ($first === ';') {
1494
-            // instruction end
1495
-            if ($this->debug) {
1496
-                echo 'END OF INSTRUCTION' . "\n";
1497
-            }
1498
-            if ($pointer !== null) {
1499
-                ++ $pointer;
1500
-            }
1501
-
1502
-            return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1503
-        } elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1504
-            // close block
1505
-            if (!empty($match[1]) && $match[1] == 'else') {
1506
-                throw new CompilationException($this, 'Else blocks must not be closed explicitly, they are automatically closed when their parent block is closed');
1507
-            }
1508
-            if (!empty($match[1]) && $match[1] == 'elseif') {
1509
-                throw new CompilationException($this, 'Elseif blocks must not be closed explicitly, they are automatically closed when their parent block is closed or a new else/elseif block is declared after them');
1510
-            }
1511
-            if ($pointer !== null) {
1512
-                $pointer += strlen($match[0]);
1513
-            }
1514
-            if (empty($match[1])) {
1515
-                if ($this->curBlock['type'] == 'else' || $this->curBlock['type'] == 'elseif') {
1516
-                    $pointer -= strlen($match[0]);
1517
-                }
1518
-                if ($this->debug) {
1519
-                    echo 'TOP BLOCK CLOSED' . "\n";
1520
-                }
1521
-
1522
-                return $this->removeTopBlock();
1523
-            } else {
1524
-                if ($this->debug) {
1525
-                    echo 'BLOCK OF TYPE ' . $match[1] . ' CLOSED' . "\n";
1526
-                }
1527
-
1528
-                return $this->removeBlock($match[1]);
1529
-            }
1530
-        } elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1531
-            // end template tag
1532
-            if ($this->debug) {
1533
-                echo 'TAG PARSING ENDED' . "\n";
1534
-            }
1535
-            $pointer += strlen($this->rd);
1536
-
1537
-            return false;
1538
-        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*=' . ($curBlock === 'array' ? '>?' : '') . ')(?:\s+|[^=]).*#i', $substr, $match)) {
1539
-            // named parameter
1540
-            if ($this->debug) {
1541
-                echo 'NAMED PARAM FOUND' . "\n";
1542
-            }
1543
-            $len = strlen($match[1]);
1544
-            while (substr($in, $from + $len, 1) === ' ') {
1545
-                ++ $len;
1546
-            }
1547
-            if ($pointer !== null) {
1548
-                $pointer += $len;
1549
-            }
1550
-
1551
-            $output = array(
1552
-                trim($match[1], " \t\r\n=>'\""),
1553
-                $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer)
1554
-            );
1555
-
1556
-            $parsingParams[] = $output;
1557
-
1558
-            return $parsingParams;
1559
-        } elseif (preg_match('#^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*::\$[a-z0-9_]+)#i', $substr, $match)) {
1560
-            // static member access
1561
-            $parsed = 'var';
1562
-            if (is_array($parsingParams)) {
1563
-                $parsingParams[] = array($match[1], $match[1]);
1564
-                $out             = $parsingParams;
1565
-            } else {
1566
-                $out = $match[1];
1567
-            }
1568
-            $pointer += strlen($match[1]);
1569
-        } elseif ($substr !== '' && (is_array($parsingParams) || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'expression')) {
1570
-            // unquoted string, bool or number
1571
-            $out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1572
-        } else {
1573
-            // parse error
1574
-            throw new CompilationException($this, 'Parse error in "' . substr($in, $from, $to - $from) . '"');
1575
-        }
1576
-
1577
-        if (empty($out)) {
1578
-            return '';
1579
-        }
1580
-
1581
-        $substr = substr($in, $pointer, $to - $pointer);
1582
-
1583
-        // var parsed, check if any var-extension applies
1584
-        if ($parsed === 'var') {
1585
-            if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1586
-                if ($this->debug) {
1587
-                    echo 'PARSING POST-VAR EXPRESSION ' . $substr . "\n";
1588
-                }
1589
-                // parse expressions
1590
-                $pointer += strlen($match[0]) - 1;
1591
-                if (is_array($parsingParams)) {
1592
-                    if ($match[2] == '$') {
1593
-                        $expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1594
-                    } else {
1595
-                        $expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1596
-                    }
1597
-                    $out[count($out) - 1][0] .= $match[1] . $expr[0][0];
1598
-                    $out[count($out) - 1][1] .= $match[1] . $expr[0][1];
1599
-                } else {
1600
-                    if ($match[2] == '$') {
1601
-                        $expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
1602
-                    } else {
1603
-                        $expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1604
-                    }
1605
-                    if (is_array($out) && is_array($expr)) {
1606
-                        $out[0] .= $match[1] . $expr[0];
1607
-                        $out[1] .= $match[1] . $expr[1];
1608
-                    } elseif (is_array($out)) {
1609
-                        $out[0] .= $match[1] . $expr;
1610
-                        $out[1] .= $match[1] . $expr;
1611
-                    } elseif (is_array($expr)) {
1612
-                        $out .= $match[1] . $expr[0];
1613
-                    } else {
1614
-                        $out .= $match[1] . $expr;
1615
-                    }
1616
-                }
1617
-            } elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1618
-                if ($this->debug) {
1619
-                    echo 'PARSING POST-VAR ASSIGNMENT ' . $substr . "\n";
1620
-                }
1621
-                // parse assignment
1622
-                $value    = $match[2];
1623
-                $operator = trim($match[1]);
1624
-                if (substr($value, 0, 1) == '=') {
1625
-                    throw new CompilationException($this, 'Unexpected "=" in <em>' . $substr . '</em>');
1626
-                }
1627
-
1628
-                if ($pointer !== null) {
1629
-                    $pointer += strlen($match[1]);
1630
-                }
1631
-
1632
-                if ($operator !== '++' && $operator !== '--') {
1633
-                    $parts = array();
1634
-                    $ptr   = 0;
1635
-                    $parts = $this->parse($value, 0, strlen($value), $parts, 'condition', $ptr);
1636
-                    $pointer += $ptr;
1637
-
1638
-                    // load if plugin
1639
-                    try {
1640
-                        $this->getPluginType('if');
1641
-                    }
1642
-                    catch (Exception $e) {
1643
-                        throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1644
-                    }
1645
-
1646
-                    $parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS . 'PluginIf', 'init'), 1);
1647
-                    $tokens = $this->getParamTokens($parts);
1648
-                    $parts  = $this->getCompiledParams($parts);
1649
-
1650
-                    $value = PluginIf::replaceKeywords($parts['*'], $tokens['*'], $this);
1651
-                    $echo  = '';
1652
-                } else {
1653
-                    $value = array();
1654
-                    $echo  = 'echo ';
1655
-                }
1656
-
1657
-                if ($this->autoEscape) {
1658
-                    $out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1659
-                }
1660
-                $out = self::PHP_OPEN . $echo . $out . $operator . implode(' ', $value) . self::PHP_CLOSE;
1661
-            } elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1662
-                // parse namedparam with var as name (only for array)
1663
-                if ($this->debug) {
1664
-                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND' . "\n";
1665
-                }
1666
-                $len = strlen($match[1]);
1667
-                $var = $out[count($out) - 1];
1668
-                $pointer += $len;
1669
-
1670
-                $output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
1671
-
1672
-                $parsingParams[] = $output;
1673
-
1674
-                return $parsingParams;
1675
-            }
1676
-        }
1677
-
1678
-        if ($curBlock !== 'modifier' && ($parsed === 'func' || $parsed === 'var') && preg_match('#^(\|@?[a-z0-9_]+(:.*)?)+#i', $substr, $match)) {
1679
-            // parse modifier on funcs or vars
1680
-            $srcPointer = $pointer;
1681
-            if (is_array($parsingParams)) {
1682
-                $tmp                     = $this->replaceModifiers(
1683
-                    array(
1684
-                    null,
1685
-                    null,
1686
-                    $out[count($out) - 1][0],
1687
-                    $match[0]
1688
-                    ), $curBlock, $pointer
1689
-                );
1690
-                $out[count($out) - 1][0] = $tmp;
1691
-                $out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1692
-            } else {
1693
-                $out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1694
-            }
1695
-        }
1696
-
1697
-        // func parsed, check if any func-extension applies
1698
-        if ($parsed === 'func' && preg_match('#^->[a-z0-9_]+(\s*\(.+|->[a-z_].*)?#is', $substr, $match)) {
1699
-            // parse method call or property read
1700
-            $ptr = 0;
1701
-
1702
-            if (is_array($parsingParams)) {
1703
-                $output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1704
-
1705
-                $out[count($out) - 1][0] = $output;
1706
-                $out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1707
-            } else {
1708
-                $out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1709
-            }
1710
-
1711
-            $pointer += $ptr;
1712
-        }
1713
-
1714
-        if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1715
-            return self::PHP_OPEN . 'echo ' . $out . ';' . self::PHP_CLOSE;
1716
-        }
1717
-
1718
-        return $out;
1719
-    }
1720
-
1721
-    /**
1722
-     * Parses a function call.
1723
-     *
1724
-     * @param string $in            the string within which we must parse something
1725
-     * @param int    $from          the starting offset of the parsed area
1726
-     * @param int    $to            the ending offset of the parsed area
1727
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1728
-     *                              default
1729
-     * @param string $curBlock      the current parser-block being processed
1730
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1731
-     *                              or null by default
1732
-     *
1733
-     * @return string parsed values
1734
-     * @throws CompilationException
1735
-     * @throws Exception
1736
-     * @throws SecurityException
1737
-     */
1738
-    protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1739
-    {
1740
-        $output = '';
1741
-        $cmdstr = substr($in, $from, $to - $from);
1742
-        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*' . $this->rdr . '|\s*;)?/i', $cmdstr, $match);
1743
-
1744
-        if (empty($match[1])) {
1745
-            throw new CompilationException($this, 'Parse error, invalid function name : ' . substr($cmdstr, 0, 15));
1746
-        }
1747
-
1748
-        $func = $match[1];
1749
-
1750
-        if (!empty($match[2])) {
1751
-            $cmdstr = $match[1];
1752
-        }
1753
-
1754
-        if ($this->debug) {
1755
-            echo 'FUNC FOUND (' . $func . ')' . "\n";
1756
-        }
1757
-
1758
-        $paramsep = '';
1759
-
1760
-        if (is_array($parsingParams) || $curBlock != 'root') {
1761
-            $paramspos = strpos($cmdstr, '(');
1762
-            $paramsep  = ')';
1763
-        } elseif (preg_match_all('#^\s*[\\\\:a-z0-9_]+(\s*\(|\s+[^(])#i', $cmdstr, $match, PREG_OFFSET_CAPTURE)) {
1764
-            $paramspos = $match[1][0][1];
1765
-            $paramsep  = substr($match[1][0][0], - 1) === '(' ? ')' : '';
1766
-            if ($paramsep === ')') {
1767
-                $paramspos += strlen($match[1][0][0]) - 1;
1768
-                if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1769
-                    $paramsep = '';
1770
-                    if (strlen($match[1][0][0]) > 1) {
1771
-                        -- $paramspos;
1772
-                    }
1773
-                }
1774
-            }
1775
-        } else {
1776
-            $paramspos = false;
1777
-        }
1778
-
1779
-        $state = 0;
1780
-
1781
-        if ($paramspos === false) {
1782
-            $params = array();
1783
-
1784
-            if ($curBlock !== 'root') {
1785
-                return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1786
-            }
1787
-        } else {
1788
-            if ($curBlock === 'condition') {
1789
-                // load if plugin
1790
-                $this->getPluginType('if');
1791
-
1792
-                if (PluginIf::replaceKeywords(array($func), array(self::T_UNQUOTED_STRING), $this) !== array($func)) {
1793
-                    return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1794
-                }
1795
-            }
1796
-            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1797
-            $paramstr   = substr($cmdstr, $paramspos + 1);
1798
-            if (substr($paramstr, - 1, 1) === $paramsep) {
1799
-                $paramstr = substr($paramstr, 0, - 1);
1800
-            }
1801
-
1802
-            if (strlen($paramstr) === 0) {
1803
-                $params   = array();
1804
-                $paramstr = '';
1805
-            } else {
1806
-                $ptr    = 0;
1807
-                $params = array();
1808
-                if ($func === 'empty') {
1809
-                    $params = $this->parseVar($paramstr, $ptr, strlen($paramstr), $params, 'root', $ptr);
1810
-                } else {
1811
-                    while ($ptr < strlen($paramstr)) {
1812
-                        while (true) {
1813
-                            if ($ptr >= strlen($paramstr)) {
1814
-                                break 2;
1815
-                            }
1816
-
1817
-                            if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1818
-                                if ($this->debug) {
1819
-                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT ' . $ptr . "\n";
1820
-                                }
1821
-                                break 2;
1822
-                            } elseif ($paramstr[$ptr] === ';') {
1823
-                                ++ $ptr;
1824
-                                if ($this->debug) {
1825
-                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT ' . $ptr . "\n";
1826
-                                }
1827
-                                break 2;
1828
-                            } elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1829
-                                if ($this->debug) {
1830
-                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT ' . $ptr . "\n";
1831
-                                }
1832
-                                break 2;
1833
-                            } elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1834
-                                if ($this->debug) {
1835
-                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT ' . $ptr . "\n";
1836
-                                }
1837
-                                break 2;
1838
-                            }
1839
-
1840
-                            if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1841
-                                ++ $ptr;
1842
-                            } else {
1843
-                                break;
1844
-                            }
1845
-                        }
1846
-
1847
-                        if ($this->debug) {
1848
-                            echo 'FUNC START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
1849
-                        }
1850
-
1851
-                        if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
1852
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'condition', $ptr);
1853
-                        } elseif ($func === 'array') {
1854
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'array', $ptr);
1855
-                        } else {
1856
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'function', $ptr);
1857
-                        }
1858
-
1859
-                        if ($this->debug) {
1860
-                            echo 'PARAM PARSED, POINTER AT ' . $ptr . ' (' . substr($paramstr, $ptr - 1, 3) . ')' . "\n";
1861
-                        }
1862
-                    }
1863
-                }
1864
-                $paramstr = substr($paramstr, 0, $ptr);
1865
-                $state    = 0;
1866
-                foreach ($params as $k => $p) {
1867
-                    if (is_array($p) && is_array($p[1])) {
1868
-                        $state |= 2;
1869
-                    } else {
1870
-                        if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m) && $func !== 'array') {
1871
-                            $params[$k] = array($m[2], array('true', 'true'));
1872
-                        } else {
1873
-                            if ($state & 2 && $func !== 'array') {
1874
-                                throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
1875
-                            }
1876
-                            $state |= 1;
1877
-                        }
1878
-                    }
1879
-                }
1880
-            }
1881
-        }
1882
-
1883
-        if ($pointer !== null) {
1884
-            $pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1885
-            if ($this->debug) {
1886
-                echo 'FUNC ADDS ' . ((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)) . ' TO POINTER' . "\n";
1887
-            }
1888
-        }
1889
-
1890
-        if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1891
-            // handle static method calls with security policy
1892
-            if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1893
-                throw new SecurityException('Call to a disallowed php function : ' . $func);
1894
-            }
1895
-            $pluginType = Core::NATIVE_PLUGIN;
1896
-        } else {
1897
-            $pluginType = $this->getPluginType($func);
1898
-        }
1899
-
1900
-        // Blocks plugin
1901
-        if ($pluginType & Core::BLOCK_PLUGIN) {
1902
-            if ($curBlock !== 'root' || is_array($parsingParams)) {
1903
-                throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1904
-            }
1905
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
1906
-                return $this->addCustomBlock($func, $params, $state);
1907
-            } else {
1908
-                return $this->addBlock($func, $params, $state);
1909
-            }
1910
-        } elseif ($pluginType & Core::SMARTY_BLOCK) {
1911
-            if ($curBlock !== 'root' || is_array($parsingParams)) {
1912
-                throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1913
-            }
1914
-
1915
-            if ($state & 2) {
1916
-                array_unshift($params, array('__functype', array($pluginType, $pluginType)));
1917
-                array_unshift($params, array('__funcname', array($func, $func)));
1918
-            } else {
1919
-                array_unshift($params, array($pluginType, $pluginType));
1920
-                array_unshift($params, array($func, $func));
1921
-            }
1922
-
1923
-            return $this->addBlock('smartyinterface', $params, $state);
1924
-        }
1925
-
1926
-        // Native & Smarty plugins
1927
-        if ($pluginType & Core::NATIVE_PLUGIN || $pluginType & Core::SMARTY_FUNCTION || $pluginType & Core::SMARTY_BLOCK) {
1928
-            $params = $this->mapParams($params, null, $state);
1929
-        } // PHP class plugin
1930
-        elseif ($pluginType & Core::CLASS_PLUGIN) {
1931
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
1932
-                $params = $this->mapParams(
1933
-                    $params, array(
1934
-                    $this->customPlugins[$func]['class'],
1935
-                    $this->customPlugins[$func]['function']
1936
-                ), $state);
1937
-            } else {
1938
-                if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
1939
-                    $params = $this->mapParams($params, array(
1940
-                        'Plugin' . Core::toCamelCase($func),
1941
-                        ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1942
-                    ), $state);
1943
-                } elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !== false) {
1944
-                    $params = $this->mapParams($params, array(
1945
-                        Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func),
1946
-                        ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1947
-                    ), $state);
1948
-                } else {
1949
-                    $params = $this->mapParams($params, array(
1950
-                        Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
1951
-                        ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1952
-                    ), $state);
1953
-                }
1954
-            }
1955
-        } // PHP function plugin
1956
-        elseif ($pluginType & Core::FUNC_PLUGIN) {
1957
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
1958
-                $params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1959
-            } else {
1960
-                // Custom plugin
1961
-                if (function_exists('Plugin' . Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ?
1962
-                        'Compile' : '')) !== false) {
1963
-                    $params = $this->mapParams($params, 'Plugin' . Core::toCamelCase($func) . (($pluginType &
1964
-                            Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1965
-                } // Builtin helper plugin
1966
-                elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . (
1967
-                    ($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '')) !== false) {
1968
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase
1969
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1970
-                } // Builtin function plugin
1971
-                else {
1972
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
1973
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1974
-                }
1975
-            }
1976
-        } // Smarty modifier
1977
-        elseif ($pluginType & Core::SMARTY_MODIFIER) {
1978
-            $output = 'smarty_modifier_' . $func . '(' . implode(', ', $params) . ')';
1979
-        } // Proxy plugin
1980
-        elseif ($pluginType & Core::PROXY_PLUGIN) {
1981
-            $params = $this->mapParams($params, $this->getCore()->getPluginProxy()->getCallback($func), $state);
1982
-        } // Template plugin
1983
-        elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
1984
-            // transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
1985
-            $map = array();
1986
-            foreach ($this->templatePlugins[$func]['params'] as $param => $defValue) {
1987
-                if ($param == 'rest') {
1988
-                    $param = '*';
1989
-                }
1990
-                $hasDefault = $defValue !== null;
1991
-                if ($defValue === 'null') {
1992
-                    $defValue = null;
1993
-                } elseif ($defValue === 'false') {
1994
-                    $defValue = false;
1995
-                } elseif ($defValue === 'true') {
1996
-                    $defValue = true;
1997
-                } elseif (preg_match('#^([\'"]).*?\1$#', $defValue)) {
1998
-                    $defValue = substr($defValue, 1, - 1);
1999
-                }
2000
-                $map[] = array($param, $hasDefault, $defValue);
2001
-            }
2002
-
2003
-            $params = $this->mapParams($params, null, $state, $map);
2004
-        }
2005
-
2006
-        // only keep php-syntax-safe values for non-block plugins
2007
-        $tokens = array();
2008
-        foreach ($params as $k => $p) {
2009
-            $tokens[$k] = isset($p[2]) ? $p[2] : 0;
2010
-            $params[$k] = $p[0];
2011
-        }
2012
-
2013
-        // Native plugin
2014
-        if ($pluginType & Core::NATIVE_PLUGIN) {
2015
-            if ($func === 'do') {
2016
-                $output = '';
2017
-                if (isset($params['*'])) {
2018
-                    $output = implode(';', $params['*']) . ';';
2019
-                }
2020
-
2021
-                if (is_array($parsingParams) || $curBlock !== 'root') {
2022
-                    throw new CompilationException($this, 'Do can not be used inside another function or block');
2023
-                }
2024
-
2025
-                return self::PHP_OPEN . $output . self::PHP_CLOSE;
2026
-            } else {
2027
-                if (isset($params['*'])) {
2028
-                    $output = $func . '(' . implode(', ', $params['*']) . ')';
2029
-                } else {
2030
-                    $output = $func . '()';
2031
-                }
2032
-            }
2033
-        } // Block class OR Function class
2034
-        elseif ($pluginType & Core::CLASS_PLUGIN || ($pluginType & Core::FUNC_PLUGIN && $pluginType & Core::CLASS_PLUGIN)) {
2035
-            if ($pluginType & Core::COMPILABLE_PLUGIN) {
2036
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2037
-                    $callback = $this->customPlugins[$func]['callback'];
2038
-                    if (!is_array($callback)) {
2039
-                        if (!method_exists($callback, 'compile')) {
2040
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2041
-                        }
2042
-                        if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
2043
-                            $funcCompiler = array($callback, 'compile');
2044
-                        } else {
2045
-                            $funcCompiler = array(new $callback(), 'compile');
2046
-                        }
2047
-                    } else {
2048
-                        $funcCompiler = $callback;
2049
-                    }
2050
-                } else {
2051
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2052
-                        $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
2053
-                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !== false) {
2054
-                        $funcCompiler = array(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func), 'compile');
2055
-                    } else {
2056
-                        $funcCompiler = array(
2057
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
2058
-                            'compile'
2059
-                        );
2060
-                    }
2061
-                    array_unshift($params, $this);
2062
-                }
2063
-                // @TODO: Is it a real fix ?
2064
-                if ($func === 'tif') {
2065
-                    $params[] = $tokens;
2066
-                }
2067
-                $output = call_user_func_array($funcCompiler, $params);
2068
-            } else {
2069
-                $params = self::implode_r($params);
2070
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2071
-                    $callback = $this->customPlugins[$func]['callback'];
2072
-                    if (!is_array($callback)) {
2073
-                        if (!method_exists($callback, 'process')) {
2074
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2075
-                        }
2076
-                        if (is_object($callback)) {
2077
-                            $callback = get_class($callback);
2078
-                        }
2079
-                        if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
2080
-                            $output = 'call_user_func(array(\'' . $callback . '\', \'process\'), ' . $params . ')';
2081
-                        } else {
2082
-                            $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback . '\'), \'process\'), ' . $params . ')';
2083
-                        }
2084
-                    } elseif (is_object($callback[0])) {
2085
-                        $output = 'call_user_func(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), ' . $params . ')';
2086
-                    } elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
2087
-                        $output = 'call_user_func(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), ' . $params . ')';
2088
-                    } else {
2089
-                        $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback[0] . '\'), \'' . $callback[1] . '\'), ' . $params . ')';
2090
-                    }
2091
-                    if (empty($params)) {
2092
-                        $output = substr($output, 0, - 3) . ')';
2093
-                    }
2094
-                } else {
2095
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2096
-                        $output = '$this->classCall(\'Plugin' . $func . '\', array(' . $params . '))';
2097
-                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !== false) {
2098
-                        $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\',
34
+	/**
35
+	 * Constant that represents a php opening tag.
36
+	 * use it in case it needs to be adjusted
37
+	 *
38
+	 * @var string
39
+	 */
40
+	const PHP_OPEN = '<?php ';
41
+
42
+	/**
43
+	 * Constant that represents a php closing tag.
44
+	 * use it in case it needs to be adjusted
45
+	 *
46
+	 * @var string
47
+	 */
48
+	const PHP_CLOSE = '?>';
49
+
50
+	/**
51
+	 * Boolean flag to enable or disable debugging output.
52
+	 *
53
+	 * @var bool
54
+	 */
55
+	public $debug = false;
56
+
57
+	/**
58
+	 * Left script delimiter.
59
+	 *
60
+	 * @var string
61
+	 */
62
+	protected $ld = '{';
63
+
64
+	/**
65
+	 * Left script delimiter with escaped regex meta characters.
66
+	 *
67
+	 * @var string
68
+	 */
69
+	protected $ldr = '\\{';
70
+
71
+	/**
72
+	 * Right script delimiter.
73
+	 *
74
+	 * @var string
75
+	 */
76
+	protected $rd = '}';
77
+
78
+	/**
79
+	 * Right script delimiter with escaped regex meta characters.
80
+	 *
81
+	 * @var string
82
+	 */
83
+	protected $rdr = '\\}';
84
+
85
+	/**
86
+	 * Defines whether the nested comments should be parsed as nested or not.
87
+	 * defaults to false (classic block comment parsing as in all languages)
88
+	 *
89
+	 * @var bool
90
+	 */
91
+	protected $allowNestedComments = false;
92
+
93
+	/**
94
+	 * Defines whether opening and closing tags can contain spaces before valid data or not.
95
+	 * turn to true if you want to be sloppy with the syntax, but when set to false it allows
96
+	 * to skip javascript and css tags as long as they are in the form "{ something", which is
97
+	 * nice. default is false.
98
+	 *
99
+	 * @var bool
100
+	 */
101
+	protected $allowLooseOpenings = false;
102
+
103
+	/**
104
+	 * Defines whether the compiler will automatically html-escape variables or not.
105
+	 * default is false
106
+	 *
107
+	 * @var bool
108
+	 */
109
+	protected $autoEscape = false;
110
+
111
+	/**
112
+	 * Security policy object.
113
+	 *
114
+	 * @var SecurityPolicy
115
+	 */
116
+	protected $securityPolicy;
117
+
118
+	/**
119
+	 * Stores the custom plugins registered with this compiler.
120
+	 *
121
+	 * @var array
122
+	 */
123
+	protected $customPlugins = array();
124
+
125
+	/**
126
+	 * Stores the template plugins registered with this compiler.
127
+	 *
128
+	 * @var array
129
+	 */
130
+	protected $templatePlugins = array();
131
+
132
+	/**
133
+	 * Stores the pre- and post-processors callbacks.
134
+	 *
135
+	 * @var array
136
+	 */
137
+	protected $processors = array('pre' => array(), 'post' => array());
138
+
139
+	/**
140
+	 * Stores a list of plugins that are used in the currently compiled
141
+	 * template, and that are not compilable. these plugins will be loaded
142
+	 * during the template's runtime if required.
143
+	 * it is a 1D array formatted as key:pluginName value:pluginType
144
+	 *
145
+	 * @var array
146
+	 */
147
+	protected $usedPlugins;
148
+
149
+	/**
150
+	 * Stores the template undergoing compilation.
151
+	 *
152
+	 * @var string
153
+	 */
154
+	protected $template;
155
+
156
+	/**
157
+	 * Stores the current pointer position inside the template.
158
+	 *
159
+	 * @var int
160
+	 */
161
+	protected $pointer;
162
+
163
+	/**
164
+	 * Stores the current line count inside the template for debugging purposes.
165
+	 *
166
+	 * @var int
167
+	 */
168
+	protected $line;
169
+
170
+	/**
171
+	 * Stores the current template source while compiling it.
172
+	 *
173
+	 * @var string
174
+	 */
175
+	protected $templateSource;
176
+
177
+	/**
178
+	 * Stores the data within which the scope moves.
179
+	 *
180
+	 * @var array
181
+	 */
182
+	protected $data;
183
+
184
+	/**
185
+	 * Variable scope of the compiler, set to null if
186
+	 * it can not be resolved to a static string (i.e. if some
187
+	 * plugin defines a new scope based on a variable array key).
188
+	 *
189
+	 * @var mixed
190
+	 */
191
+	protected $scope;
192
+
193
+	/**
194
+	 * Variable scope tree, that allows to rebuild the current
195
+	 * scope if required, i.e. when going to a parent level.
196
+	 *
197
+	 * @var array
198
+	 */
199
+	protected $scopeTree;
200
+
201
+	/**
202
+	 * Block plugins stack, accessible through some methods.
203
+	 *
204
+	 * @see findBlock
205
+	 * @see getCurrentBlock
206
+	 * @see addBlock
207
+	 * @see addCustomBlock
208
+	 * @see injectBlock
209
+	 * @see removeBlock
210
+	 * @see removeTopBlock
211
+	 * @var array
212
+	 */
213
+	protected $stack = array();
214
+
215
+	/**
216
+	 * Current block at the top of the block plugins stack,
217
+	 * accessible through getCurrentBlock.
218
+	 *
219
+	 * @see getCurrentBlock
220
+	 * @var array
221
+	 */
222
+	protected $curBlock;
223
+
224
+	/**
225
+	 * Current dwoo object that uses this compiler, or null.
226
+	 *
227
+	 * @var Core
228
+	 */
229
+	public $core;
230
+
231
+	/**
232
+	 * Holds an instance of this class, used by getInstance when you don't
233
+	 * provide a custom compiler in order to save resources.
234
+	 *
235
+	 * @var Compiler
236
+	 */
237
+	protected static $instance;
238
+
239
+	/**
240
+	 * Token types.
241
+	 *
242
+	 * @var int
243
+	 */
244
+	const T_UNQUOTED_STRING = 1;
245
+	const T_NUMERIC         = 2;
246
+	const T_NULL            = 4;
247
+	const T_BOOL            = 8;
248
+	const T_MATH            = 16;
249
+	const T_BREAKCHAR       = 32;
250
+
251
+	/**
252
+	 * Compiler constructor.
253
+	 * saves the created instance so that child templates get the same one
254
+	 */
255
+	public function __construct()
256
+	{
257
+		self::$instance = $this;
258
+	}
259
+
260
+	/**
261
+	 * Sets the delimiters to use in the templates.
262
+	 * delimiters can be multi-character strings but should not be one of those as they will
263
+	 * make it very hard to work with templates or might even break the compiler entirely : "\", "$", "|", ":" and
264
+	 * finally "#" only if you intend to use config-vars with the #var# syntax.
265
+	 *
266
+	 * @param string $left  left delimiter
267
+	 * @param string $right right delimiter
268
+	 */
269
+	public function setDelimiters($left, $right)
270
+	{
271
+		$this->ld  = $left;
272
+		$this->rd  = $right;
273
+		$this->ldr = preg_quote($left, '/');
274
+		$this->rdr = preg_quote($right, '/');
275
+	}
276
+
277
+	/**
278
+	 * Returns the left and right template delimiters.
279
+	 *
280
+	 * @return array containing the left and the right delimiters
281
+	 */
282
+	public function getDelimiters()
283
+	{
284
+		return array($this->ld, $this->rd);
285
+	}
286
+
287
+	/**
288
+	 * Sets the way to handle nested comments, if set to true
289
+	 * {* foo {* some other *} comment *} will be stripped correctly.
290
+	 * if false it will remove {* foo {* some other *} and leave "comment *}" alone,
291
+	 * this is the default behavior
292
+	 *
293
+	 * @param bool $allow allow nested comments or not, defaults to true (but the default internal value is false)
294
+	 */
295
+	public function setNestedCommentsHandling($allow = true)
296
+	{
297
+		$this->allowNestedComments = (bool)$allow;
298
+	}
299
+
300
+	/**
301
+	 * Returns the nested comments handling setting.
302
+	 *
303
+	 * @see    setNestedCommentsHandling
304
+	 * @return bool true if nested comments are allowed
305
+	 */
306
+	public function getNestedCommentsHandling()
307
+	{
308
+		return $this->allowNestedComments;
309
+	}
310
+
311
+	/**
312
+	 * Sets the tag openings handling strictness, if set to true, template tags can
313
+	 * contain spaces before the first function/string/variable such as { $foo} is valid.
314
+	 * if set to false (default setting), { $foo} is invalid but that is however a good thing
315
+	 * as it allows css (i.e. #foo { color:red; }) to be parsed silently without triggering
316
+	 * an error, same goes for javascript.
317
+	 *
318
+	 * @param bool $allow true to allow loose handling, false to restore default setting
319
+	 */
320
+	public function setLooseOpeningHandling($allow = false)
321
+	{
322
+		$this->allowLooseOpenings = (bool)$allow;
323
+	}
324
+
325
+	/**
326
+	 * Returns the tag openings handling strictness setting.
327
+	 *
328
+	 * @see    setLooseOpeningHandling
329
+	 * @return bool true if loose tags are allowed
330
+	 */
331
+	public function getLooseOpeningHandling()
332
+	{
333
+		return $this->allowLooseOpenings;
334
+	}
335
+
336
+	/**
337
+	 * Changes the auto escape setting.
338
+	 * if enabled, the compiler will automatically html-escape variables,
339
+	 * unless they are passed through the safe function such as {$var|safe}
340
+	 * or {safe $var}
341
+	 * default setting is disabled/false
342
+	 *
343
+	 * @param bool $enabled set to true to enable, false to disable
344
+	 */
345
+	public function setAutoEscape($enabled)
346
+	{
347
+		$this->autoEscape = (bool)$enabled;
348
+	}
349
+
350
+	/**
351
+	 * Returns the auto escape setting.
352
+	 * default setting is disabled/false
353
+	 *
354
+	 * @return bool
355
+	 */
356
+	public function getAutoEscape()
357
+	{
358
+		return $this->autoEscape;
359
+	}
360
+
361
+	/**
362
+	 * Adds a preprocessor to the compiler, it will be called
363
+	 * before the template is compiled.
364
+	 *
365
+	 * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
366
+	 *                        true
367
+	 * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else
368
+	 *                        you must provide a valid callback
369
+	 */
370
+	public function addPreProcessor($callback, $autoload = false)
371
+	{
372
+		if ($autoload) {
373
+			$name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', Core::toCamelCase($callback));
374
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . $name;
375
+
376
+			if (class_exists($class)) {
377
+				$callback = array(new $class($this), 'process');
378
+			} elseif (function_exists($class)) {
379
+				$callback = $class;
380
+			} else {
381
+				$callback = array('autoload' => true, 'class' => $class, 'name' => $name);
382
+			}
383
+
384
+			$this->processors['pre'][] = $callback;
385
+		} else {
386
+			$this->processors['pre'][] = $callback;
387
+		}
388
+	}
389
+
390
+	/**
391
+	 * Removes a preprocessor from the compiler.
392
+	 *
393
+	 * @param mixed $callback either a valid callback to the preprocessor or a simple name if it was autoloaded
394
+	 */
395
+	public function removePreProcessor($callback)
396
+	{
397
+		if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
398
+			unset($this->processors['pre'][$index]);
399
+		} elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
400
+					$callback),
401
+				$this->processors['pre'], true)) !== false) {
402
+			unset($this->processors['pre'][$index]);
403
+		} else {
404
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
405
+			foreach ($this->processors['pre'] as $index => $proc) {
406
+				if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
407
+					unset($this->processors['pre'][$index]);
408
+					break;
409
+				}
410
+			}
411
+		}
412
+	}
413
+
414
+	/**
415
+	 * Adds a postprocessor to the compiler, it will be called
416
+	 * before the template is compiled.
417
+	 *
418
+	 * @param mixed $callback either a valid callback to the postprocessor or a simple name if the autoload is set to
419
+	 *                        true
420
+	 * @param bool  $autoload if set to true, the postprocessor is auto-loaded from one of the plugin directories, else
421
+	 *                        you must provide a valid callback
422
+	 */
423
+	public function addPostProcessor($callback, $autoload = false)
424
+	{
425
+		if ($autoload) {
426
+			$name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
427
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . Core::toCamelCase($name);
428
+
429
+			if (class_exists($class)) {
430
+				$callback = array(new $class($this), 'process');
431
+			} elseif (function_exists($class)) {
432
+				$callback = $class;
433
+			} else {
434
+				$callback = array('autoload' => true, 'class' => $class, 'name' => $name);
435
+			}
436
+
437
+			$this->processors['post'][] = $callback;
438
+		} else {
439
+			$this->processors['post'][] = $callback;
440
+		}
441
+	}
442
+
443
+	/**
444
+	 * Removes a postprocessor from the compiler.
445
+	 *
446
+	 * @param mixed $callback either a valid callback to the postprocessor or a simple name if it was autoloaded
447
+	 */
448
+	public function removePostProcessor($callback)
449
+	{
450
+		if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
451
+			unset($this->processors['post'][$index]);
452
+		} elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
453
+					$callback),
454
+				$this->processors['post'], true)) !== false) {
455
+			unset($this->processors['post'][$index]);
456
+		} else {
457
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
458
+			foreach ($this->processors['post'] as $index => $proc) {
459
+				if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
460
+					unset($this->processors['post'][$index]);
461
+					break;
462
+				}
463
+			}
464
+		}
465
+	}
466
+
467
+	/**
468
+	 * Internal function to autoload processors at runtime if required.
469
+	 *
470
+	 * @param string $class the class/function name
471
+	 * @param string $name  the plugin name (without Dwoo_Plugin_ prefix)
472
+	 *
473
+	 * @return array|string
474
+	 * @throws Exception
475
+	 */
476
+	protected function loadProcessor($class, $name)
477
+	{
478
+		if (!class_exists($class) && !function_exists($class)) {
479
+			try {
480
+				$this->getCore()->getLoader()->loadPlugin($name);
481
+			}
482
+			catch (Exception $e) {
483
+				throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
484
+			}
485
+		}
486
+
487
+		if (class_exists($class)) {
488
+			return array(new $class($this), 'process');
489
+		}
490
+
491
+		if (function_exists($class)) {
492
+			return $class;
493
+		}
494
+
495
+		throw new Exception('Wrong processor name, when using autoload the processor must be in one of your plugin dir as "name.php" containg a class or function named "Dwoo_Processor_name"');
496
+	}
497
+
498
+	/**
499
+	 * Adds an used plugin, this is reserved for use by the {template} plugin.
500
+	 * this is required so that plugin loading bubbles up from loaded
501
+	 * template files to the current one
502
+	 *
503
+	 * @private
504
+	 *
505
+	 * @param string $name function name
506
+	 * @param int    $type plugin type (Core::*_PLUGIN)
507
+	 */
508
+	public function addUsedPlugin($name, $type)
509
+	{
510
+		$this->usedPlugins[$name] = $type;
511
+	}
512
+
513
+	/**
514
+	 * Returns all the plugins this template uses.
515
+	 *
516
+	 * @private
517
+	 * @return  array the list of used plugins in the parsed template
518
+	 */
519
+	public function getUsedPlugins()
520
+	{
521
+		return $this->usedPlugins;
522
+	}
523
+
524
+	/**
525
+	 * Adds a template plugin, this is reserved for use by the {template} plugin.
526
+	 * this is required because the template functions are not declared yet
527
+	 * during compilation, so we must have a way of validating their argument
528
+	 * signature without using the reflection api
529
+	 *
530
+	 * @private
531
+	 *
532
+	 * @param string $name   function name
533
+	 * @param array  $params parameter array to help validate the function call
534
+	 * @param string $uuid   unique id of the function
535
+	 * @param string $body   function php code
536
+	 */
537
+	public function addTemplatePlugin($name, array $params, $uuid, $body = null)
538
+	{
539
+		$this->templatePlugins[$name] = array('params' => $params, 'body' => $body, 'uuid' => $uuid);
540
+	}
541
+
542
+	/**
543
+	 * Returns all the parsed sub-templates.
544
+	 *
545
+	 * @private
546
+	 * @return  array the parsed sub-templates
547
+	 */
548
+	public function getTemplatePlugins()
549
+	{
550
+		return $this->templatePlugins;
551
+	}
552
+
553
+	/**
554
+	 * Marks a template plugin as being called, which means its source must be included in the compiled template.
555
+	 *
556
+	 * @param string $name function name
557
+	 */
558
+	public function useTemplatePlugin($name)
559
+	{
560
+		$this->templatePlugins[$name]['called'] = true;
561
+	}
562
+
563
+	/**
564
+	 * Adds the custom plugins loaded into Dwoo to the compiler so it can load them.
565
+	 *
566
+	 * @see Core::addPlugin
567
+	 *
568
+	 * @param array $customPlugins an array of custom plugins
569
+	 */
570
+	public function setCustomPlugins(array $customPlugins)
571
+	{
572
+		$this->customPlugins = $customPlugins;
573
+	}
574
+
575
+	/**
576
+	 * Sets the security policy object to enforce some php security settings.
577
+	 * use this if untrusted persons can modify templates,
578
+	 * set it on the Dwoo object as it will be passed onto the compiler automatically
579
+	 *
580
+	 * @param SecurityPolicy $policy the security policy object
581
+	 */
582
+	public function setSecurityPolicy(SecurityPolicy $policy = null)
583
+	{
584
+		$this->securityPolicy = $policy;
585
+	}
586
+
587
+	/**
588
+	 * Returns the current security policy object or null by default.
589
+	 *
590
+	 * @return SecurityPolicy|null the security policy object if any
591
+	 */
592
+	public function getSecurityPolicy()
593
+	{
594
+		return $this->securityPolicy;
595
+	}
596
+
597
+	/**
598
+	 * Sets the pointer position.
599
+	 *
600
+	 * @param int  $position the new pointer position
601
+	 * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
602
+	 */
603
+	public function setPointer($position, $isOffset = false)
604
+	{
605
+		if ($isOffset) {
606
+			$this->pointer += $position;
607
+		} else {
608
+			$this->pointer = $position;
609
+		}
610
+	}
611
+
612
+	/**
613
+	 * Returns the current pointer position, only available during compilation of a template.
614
+	 *
615
+	 * @return int
616
+	 */
617
+	public function getPointer()
618
+	{
619
+		return $this->pointer;
620
+	}
621
+
622
+	/**
623
+	 * Sets the line number.
624
+	 *
625
+	 * @param int  $number   the new line number
626
+	 * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
627
+	 */
628
+	public function setLine($number, $isOffset = false)
629
+	{
630
+		if ($isOffset) {
631
+			$this->line += $number;
632
+		} else {
633
+			$this->line = $number;
634
+		}
635
+	}
636
+
637
+	/**
638
+	 * Returns the current line number, only available during compilation of a template.
639
+	 *
640
+	 * @return int
641
+	 */
642
+	public function getLine()
643
+	{
644
+		return $this->line;
645
+	}
646
+
647
+	/**
648
+	 * Returns the dwoo object that initiated this template compilation, only available during compilation of a
649
+	 * template.
650
+	 *
651
+	 * @return Core
652
+	 */
653
+	public function getCore()
654
+	{
655
+		return $this->core;
656
+	}
657
+
658
+	/**
659
+	 * Overwrites the template that is being compiled.
660
+	 *
661
+	 * @param string $newSource   the template source that must replace the current one
662
+	 * @param bool   $fromPointer if set to true, only the source from the current pointer position is replaced
663
+	 *
664
+	 * @return void
665
+	 */
666
+	public function setTemplateSource($newSource, $fromPointer = false)
667
+	{
668
+		if ($fromPointer === true) {
669
+			$this->templateSource = substr($this->templateSource, 0, $this->pointer) . $newSource;
670
+		} else {
671
+			$this->templateSource = $newSource;
672
+		}
673
+	}
674
+
675
+	/**
676
+	 * Returns the template that is being compiled.
677
+	 *
678
+	 * @param mixed $fromPointer if set to true, only the source from the current pointer
679
+	 *                           position is returned, if a number is given it overrides the current pointer
680
+	 *
681
+	 * @return string the template or partial template
682
+	 */
683
+	public function getTemplateSource($fromPointer = false)
684
+	{
685
+		if ($fromPointer === true) {
686
+			return substr($this->templateSource, $this->pointer);
687
+		} elseif (is_numeric($fromPointer)) {
688
+			return substr($this->templateSource, $fromPointer);
689
+		} else {
690
+			return $this->templateSource;
691
+		}
692
+	}
693
+
694
+	/**
695
+	 * Resets the compilation pointer, effectively restarting the compilation process.
696
+	 * this is useful if a plugin modifies the template source since it might need to be recompiled
697
+	 */
698
+	public function recompile()
699
+	{
700
+		$this->setPointer(0);
701
+	}
702
+
703
+	/**
704
+	 * Compiles the provided string down to php code.
705
+	 *
706
+	 * @param Core      $core
707
+	 * @param ITemplate $template the template to compile
708
+	 *
709
+	 * @return string a compiled php string
710
+	 * @throws CompilationException
711
+	 */
712
+	public function compile(Core $core, ITemplate $template)
713
+	{
714
+		// init vars
715
+		//		$compiled = '';
716
+		$tpl                  = $template->getSource();
717
+		$ptr                  = 0;
718
+		$this->core           = $core;
719
+		$this->template       = $template;
720
+		$this->templateSource = &$tpl;
721
+		$this->pointer        = &$ptr;
722
+
723
+		while (true) {
724
+			// if pointer is at the beginning, reset everything, that allows a plugin to externally reset the compiler if everything must be reparsed
725
+			if ($ptr === 0) {
726
+				// resets variables
727
+				$this->usedPlugins     = array();
728
+				$this->data            = array();
729
+				$this->scope           = &$this->data;
730
+				$this->scopeTree       = array();
731
+				$this->stack           = array();
732
+				$this->line            = 1;
733
+				$this->templatePlugins = array();
734
+				// add top level block
735
+				$compiled                 = $this->addBlock('TopLevelBlock', array(), 0);
736
+				$this->stack[0]['buffer'] = '';
737
+
738
+				if ($this->debug) {
739
+					echo "\n";
740
+					echo 'COMPILER INIT' . "\n";
741
+				}
742
+
743
+				if ($this->debug) {
744
+					echo 'PROCESSING PREPROCESSORS (' . count($this->processors['pre']) . ')' . "\n";
745
+				}
746
+
747
+				// runs preprocessors
748
+				foreach ($this->processors['pre'] as $preProc) {
749
+					if (is_array($preProc) && isset($preProc['autoload'])) {
750
+						$preProc = $this->loadProcessor($preProc['class'], $preProc['name']);
751
+					}
752
+					if (is_array($preProc) && $preProc[0] instanceof Processor) {
753
+						$tpl = call_user_func($preProc, $tpl);
754
+					} else {
755
+						$tpl = call_user_func($preProc, $this, $tpl);
756
+					}
757
+				}
758
+				unset($preProc);
759
+
760
+				// show template source if debug
761
+				if ($this->debug) {
762
+					echo '<pre>'.print_r(htmlentities($tpl), true).'</pre>'."\n";
763
+				}
764
+
765
+				// strips php tags if required by the security policy
766
+				if ($this->securityPolicy !== null) {
767
+					$search = array('{<\?php.*?\?>}');
768
+					if (ini_get('short_open_tags')) {
769
+						$search = array('{<\?.*?\?>}', '{<%.*?%>}');
770
+					}
771
+					switch ($this->securityPolicy->getPhpHandling()) {
772
+						case SecurityPolicy::PHP_ALLOW:
773
+							break;
774
+						case SecurityPolicy::PHP_ENCODE:
775
+							$tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
+							break;
777
+						case SecurityPolicy::PHP_REMOVE:
778
+							$tpl = preg_replace($search, '', $tpl);
779
+					}
780
+				}
781
+			}
782
+
783
+			$pos = strpos($tpl, $this->ld, $ptr);
784
+
785
+			if ($pos === false) {
786
+				$this->push(substr($tpl, $ptr), 0);
787
+				break;
788
+			} elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
789
+				$this->push(substr($tpl, $ptr, $pos - $ptr - 1) . $this->ld);
790
+				$ptr = $pos + strlen($this->ld);
791
+			} elseif (preg_match('/^' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . 'literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', substr($tpl, $pos), $litOpen)) {
792
+				if (!preg_match('/' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . '\/literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
793
+					throw new CompilationException($this, 'The {literal} blocks must be closed explicitly with {/literal}');
794
+				}
795
+				$endpos = $litClose[0][1];
796
+				$this->push(substr($tpl, $ptr, $pos - $ptr) . substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
797
+				$ptr = $endpos + strlen($litClose[0][0]);
798
+			} else {
799
+				if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
800
+					$this->push(substr($tpl, $ptr, $pos - $ptr - 1));
801
+					$ptr = $pos;
802
+				}
803
+
804
+				$this->push(substr($tpl, $ptr, $pos - $ptr));
805
+				$ptr = $pos;
806
+
807
+				$pos += strlen($this->ld);
808
+				if ($this->allowLooseOpenings) {
809
+					while (substr($tpl, $pos, 1) === ' ') {
810
+						$pos += 1;
811
+					}
812
+				} else {
813
+					if (substr($tpl, $pos, 1) === ' ' || substr($tpl, $pos, 1) === "\r" || substr($tpl, $pos, 1) === "\n" || substr($tpl, $pos, 1) === "\t") {
814
+						$ptr = $pos;
815
+						$this->push($this->ld);
816
+						continue;
817
+					}
818
+				}
819
+
820
+				// check that there is an end tag present
821
+				if (strpos($tpl, $this->rd, $pos) === false) {
822
+					throw new CompilationException($this, 'A template tag was not closed, started with "' . substr($tpl, $ptr, 30) . '"');
823
+				}
824
+
825
+				$ptr += strlen($this->ld);
826
+				$subptr = $ptr;
827
+
828
+				while (true) {
829
+					$parsed = $this->parse($tpl, $subptr, null, false, 'root', $subptr);
830
+
831
+					// reload loop if the compiler was reset
832
+					if ($ptr === 0) {
833
+						continue 2;
834
+					}
835
+
836
+					$len = $subptr - $ptr;
837
+					$this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
838
+					$ptr += $len;
839
+
840
+					if ($parsed === false) {
841
+						break;
842
+					}
843
+				}
844
+			}
845
+		}
846
+
847
+		$compiled .= $this->removeBlock('TopLevelBlock');
848
+
849
+		if ($this->debug) {
850
+			echo 'PROCESSING POSTPROCESSORS' . "\n";
851
+		}
852
+
853
+		foreach ($this->processors['post'] as $postProc) {
854
+			if (is_array($postProc) && isset($postProc['autoload'])) {
855
+				$postProc = $this->loadProcessor($postProc['class'], $postProc['name']);
856
+			}
857
+			if (is_array($postProc) && $postProc[0] instanceof Processor) {
858
+				$compiled = call_user_func($postProc, $compiled);
859
+			} else {
860
+				$compiled = call_user_func($postProc, $this, $compiled);
861
+			}
862
+		}
863
+		unset($postProc);
864
+
865
+		if ($this->debug) {
866
+			echo 'COMPILATION COMPLETE : MEM USAGE : ' . memory_get_usage() . "\n";
867
+		}
868
+
869
+		$output = "<?php\n/* template head */\n";
870
+
871
+		// build plugin preloader
872
+		foreach ($this->getUsedPlugins() as $plugin => $type) {
873
+			if ($type & Core::CUSTOM_PLUGIN) {
874
+				continue;
875
+			}
876
+
877
+			switch ($type) {
878
+				case Core::CLASS_PLUGIN:
879
+				case Core::CLASS_PLUGIN + Core::BLOCK_PLUGIN:
880
+					if (class_exists('Plugin' . $plugin) !== false) {
881
+						$output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
+					} else {
884
+						$output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
+					}
887
+					break;
888
+				case Core::CLASS_PLUGIN + Core::FUNC_PLUGIN:
889
+					if (class_exists('Plugin' . $plugin) !== false) {
890
+						$output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
891
+							"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
+					} else {
893
+						$output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
+							"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
+					}
896
+					break;
897
+				case Core::FUNC_PLUGIN:
898
+					if (function_exists('Plugin' . $plugin) !== false) {
899
+						$output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
900
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
901
+					} else {
902
+						$output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
903
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
904
+					}
905
+					break;
906
+				case Core::SMARTY_MODIFIER:
907
+					$output .= "if (function_exists('smarty_modifier_$plugin')===false)".
908
+					"\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
909
+					break;
910
+				case Core::SMARTY_FUNCTION:
911
+					$output .= "if (function_exists('smarty_function_$plugin')===false)".
912
+					"\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
913
+					break;
914
+				case Core::SMARTY_BLOCK:
915
+					$output .= "if (function_exists('smarty_block_$plugin')===false)".
916
+					"\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
917
+					break;
918
+				case Core::PROXY_PLUGIN:
919
+					$output .= $this->getCore()->getPluginProxy()->getLoader($plugin);
920
+					break;
921
+				default:
922
+					throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
923
+			}
924
+		}
925
+
926
+		foreach ($this->templatePlugins as $function => $attr) {
927
+			if (isset($attr['called']) && $attr['called'] === true && !isset($attr['checked'])) {
928
+				$this->resolveSubTemplateDependencies($function);
929
+			}
930
+		}
931
+		foreach ($this->templatePlugins as $function) {
932
+			if (isset($function['called']) && $function['called'] === true) {
933
+				$output .= $function['body'] . PHP_EOL;
934
+			}
935
+		}
936
+
937
+		$output .= $compiled . "\n?>";
938
+
939
+		$output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*' . preg_quote(self::PHP_CLOSE, '/') . preg_quote(self::PHP_OPEN, '/') . ')/', ";\n", $output);
940
+		$output = str_replace(self::PHP_CLOSE . self::PHP_OPEN, "\n", $output);
941
+
942
+		// handle <?xml tag at the beginning
943
+		$output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
944
+
945
+		// add another line break after PHP closing tags that have a line break following,
946
+		// as we do not know whether it's intended, and PHP will strip it otherwise
947
+		$output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0' . "\n", $output);
948
+
949
+		if ($this->debug) {
950
+			echo '=============================================================================================' . "\n";
951
+			$lines = preg_split('{\r\n|\n|<br />}', $output);
952
+			array_shift($lines);
953
+			foreach ($lines as $i => $line) {
954
+				echo ($i + 1) . '. ' . $line . "\r\n";
955
+			}
956
+			echo '=============================================================================================' . "\n";
957
+		}
958
+
959
+		$this->template = $this->dwoo = null;
960
+		$tpl            = null;
961
+
962
+		return $output;
963
+	}
964
+
965
+	/**
966
+	 * Checks what sub-templates are used in every sub-template so that we're sure they are all compiled.
967
+	 *
968
+	 * @param string $function the sub-template name
969
+	 */
970
+	protected function resolveSubTemplateDependencies($function)
971
+	{
972
+		if ($this->debug) {
973
+			echo 'Compiler::' . __FUNCTION__ . "\n";
974
+		}
975
+
976
+		$body = $this->templatePlugins[$function]['body'];
977
+		foreach ($this->templatePlugins as $func => $attr) {
978
+			if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS .
979
+			'Plugin' . Core::toCamelCase($func)) !== false) {
980
+				$this->templatePlugins[$func]['called'] = true;
981
+				$this->resolveSubTemplateDependencies($func);
982
+			}
983
+		}
984
+		$this->templatePlugins[$function]['checked'] = true;
985
+	}
986
+
987
+	/**
988
+	 * Adds compiled content to the current block.
989
+	 *
990
+	 * @param string $content   the content to push
991
+	 * @param int    $lineCount newlines count in content, optional
992
+	 *
993
+	 * @throws CompilationException
994
+	 */
995
+	public function push($content, $lineCount = null)
996
+	{
997
+		if ($lineCount === null) {
998
+			$lineCount = substr_count($content, "\n");
999
+		}
1000
+
1001
+		if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
1002
+			// buffer is not initialized yet (the block has just been created)
1003
+			$this->stack[count($this->stack) - 2]['buffer'] .= (string)$content;
1004
+			$this->curBlock['buffer'] = '';
1005
+		} else {
1006
+			if (!isset($this->curBlock['buffer'])) {
1007
+				throw new CompilationException($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
1008
+			}
1009
+			// append current content to current block's buffer
1010
+			$this->curBlock['buffer'] .= (string)$content;
1011
+		}
1012
+		$this->line += $lineCount;
1013
+	}
1014
+
1015
+	/**
1016
+	 * Sets the scope.
1017
+	 * set to null if the scope becomes "unstable" (i.e. too variable or unknown) so that
1018
+	 * variables are compiled in a more evaluative way than just $this->scope['key']
1019
+	 *
1020
+	 * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1021
+	 * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1022
+	 *
1023
+	 * @return array the current scope tree
1024
+	 */
1025
+	public function setScope($scope, $absolute = false)
1026
+	{
1027
+		$old = $this->scopeTree;
1028
+
1029
+		if ($scope === null) {
1030
+			unset($this->scope);
1031
+			$this->scope = null;
1032
+		}
1033
+
1034
+		if (is_array($scope) === false) {
1035
+			$scope = explode('.', $scope);
1036
+		}
1037
+
1038
+		if ($absolute === true) {
1039
+			$this->scope     = &$this->data;
1040
+			$this->scopeTree = array();
1041
+		}
1042
+
1043
+		while (($bit = array_shift($scope)) !== null) {
1044
+			if ($bit === '_parent' || $bit === '_') {
1045
+				array_pop($this->scopeTree);
1046
+				reset($this->scopeTree);
1047
+				$this->scope = &$this->data;
1048
+				$cnt         = count($this->scopeTree);
1049
+				for ($i = 0; $i < $cnt; ++ $i) {
1050
+					$this->scope = &$this->scope[$this->scopeTree[$i]];
1051
+				}
1052
+			} elseif ($bit === '_root' || $bit === '__') {
1053
+				$this->scope     = &$this->data;
1054
+				$this->scopeTree = array();
1055
+			} elseif (isset($this->scope[$bit])) {
1056
+				$this->scope       = &$this->scope[$bit];
1057
+				$this->scopeTree[] = $bit;
1058
+			} else {
1059
+				$this->scope[$bit] = array();
1060
+				$this->scope       = &$this->scope[$bit];
1061
+				$this->scopeTree[] = $bit;
1062
+			}
1063
+		}
1064
+
1065
+		return $old;
1066
+	}
1067
+
1068
+	/**
1069
+	 * Adds a block to the top of the block stack.
1070
+	 *
1071
+	 * @param string $type      block type (name)
1072
+	 * @param array  $params    the parameters array
1073
+	 * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1074
+	 *
1075
+	 * @return string the preProcessing() method's output
1076
+	 */
1077
+	public function addBlock($type, array $params, $paramtype)
1078
+	{
1079
+		if ($this->debug) {
1080
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1081
+		}
1082
+
1083
+		$class = current(array_filter([
1084
+			'Plugin' . Core::toCamelCase($type),
1085
+			Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type)
1086
+		], 'class_exists'));
1087
+		if (false === $class) {
1088
+			$this->getCore()->getLoader()->loadPlugin($type);
1089
+		}
1090
+		$params = $this->mapParams($params, array($class, 'init'), $paramtype);
1091
+
1092
+		$this->stack[]  = array(
1093
+			'type'   => $type,
1094
+			'params' => $params,
1095
+			'custom' => false,
1096
+			'class'  => $class,
1097
+			'buffer' => null
1098
+		);
1099
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1100
+
1101
+		return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1102
+	}
1103
+
1104
+	/**
1105
+	 * Adds a custom block to the top of the block stack.
1106
+	 *
1107
+	 * @param string $type      block type (name)
1108
+	 * @param array  $params    the parameters array
1109
+	 * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1110
+	 *
1111
+	 * @return string the preProcessing() method's output
1112
+	 */
1113
+	public function addCustomBlock($type, array $params, $paramtype)
1114
+	{
1115
+		$callback = $this->customPlugins[$type]['callback'];
1116
+		if (is_array($callback)) {
1117
+			$class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
1118
+		} else {
1119
+			$class = $callback;
1120
+		}
1121
+
1122
+		$params = $this->mapParams($params, array($class, 'init'), $paramtype);
1123
+
1124
+		$this->stack[]  = array(
1125
+			'type'   => $type,
1126
+			'params' => $params,
1127
+			'custom' => true,
1128
+			'class'  => $class,
1129
+			'buffer' => null
1130
+		);
1131
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1132
+
1133
+		return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1134
+	}
1135
+
1136
+	/**
1137
+	 * Injects a block at the top of the plugin stack without calling its preProcessing method.
1138
+	 * used by {else} blocks to re-add themselves after having closed everything up to their parent
1139
+	 *
1140
+	 * @param string $type   block type (name)
1141
+	 * @param array  $params parameters array
1142
+	 */
1143
+	public function injectBlock($type, array $params)
1144
+	{
1145
+		if ($this->debug) {
1146
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1147
+		}
1148
+
1149
+		$class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1150
+		if (class_exists($class) === false) {
1151
+			$this->getCore()->getLoader()->loadPlugin($type);
1152
+		}
1153
+		$this->stack[]  = array(
1154
+			'type'   => $type,
1155
+			'params' => $params,
1156
+			'custom' => false,
1157
+			'class'  => $class,
1158
+			'buffer' => null
1159
+		);
1160
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1161
+	}
1162
+
1163
+	/**
1164
+	 * Removes the closest-to-top block of the given type and all other
1165
+	 * blocks encountered while going down the block stack.
1166
+	 *
1167
+	 * @param string $type block type (name)
1168
+	 *
1169
+	 * @return string the output of all postProcessing() method's return values of the closed blocks
1170
+	 * @throws CompilationException
1171
+	 */
1172
+	public function removeBlock($type)
1173
+	{
1174
+		if ($this->debug) {
1175
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1176
+		}
1177
+
1178
+		$output = '';
1179
+
1180
+		$pluginType = $this->getPluginType($type);
1181
+		if ($pluginType & Core::SMARTY_BLOCK) {
1182
+			$type = 'Smartyinterface';
1183
+		}
1184
+		while (true) {
1185
+			while ($top = array_pop($this->stack)) {
1186
+				if ($top['custom']) {
1187
+					$class = $top['class'];
1188
+				} else {
1189
+					$class = current(array_filter([
1190
+						'Plugin' . Core::toCamelCase($top['type']),
1191
+						Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($top['type'])
1192
+					], 'class_exists'));
1193
+				}
1194
+				if (count($this->stack)) {
1195
+					$this->curBlock = &$this->stack[count($this->stack) - 1];
1196
+					$this->push(call_user_func(array(
1197
+						$class,
1198
+						'postProcessing'
1199
+					), $this, $top['params'], '', '', $top['buffer']), 0);
1200
+				} else {
1201
+					$null           = null;
1202
+					$this->curBlock = &$null;
1203
+					$output         = call_user_func(
1204
+						array(
1205
+						$class,
1206
+						'postProcessing'
1207
+						), $this, $top['params'], '', '', $top['buffer']
1208
+					);
1209
+				}
1210
+
1211
+				if ($top['type'] === $type) {
1212
+					break 2;
1213
+				}
1214
+			}
1215
+
1216
+			throw new CompilationException($this, 'Syntax malformation, a block of type "' . $type . '" was closed but was not opened');
1217
+		}
1218
+
1219
+		return $output;
1220
+	}
1221
+
1222
+	/**
1223
+	 * Returns a reference to the first block of the given type encountered and
1224
+	 * optionally closes all blocks until it finds it
1225
+	 * this is mainly used by {else} plugins to close everything that was opened
1226
+	 * between their parent and themselves.
1227
+	 *
1228
+	 * @param string $type       the block type (name)
1229
+	 * @param bool   $closeAlong whether to close all blocks encountered while going down the block stack or not
1230
+	 *
1231
+	 * @return mixed &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1232
+	 *               'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1233
+	 * @throws CompilationException
1234
+	 */
1235
+	public function &findBlock($type, $closeAlong = false)
1236
+	{
1237
+		if ($closeAlong === true) {
1238
+			while ($b = end($this->stack)) {
1239
+				if ($b['type'] === $type) {
1240
+					return $this->stack[key($this->stack)];
1241
+				}
1242
+				$this->push($this->removeTopBlock(), 0);
1243
+			}
1244
+		} else {
1245
+			end($this->stack);
1246
+			while ($b = current($this->stack)) {
1247
+				if ($b['type'] === $type) {
1248
+					return $this->stack[key($this->stack)];
1249
+				}
1250
+				prev($this->stack);
1251
+			}
1252
+		}
1253
+
1254
+		throw new CompilationException($this, 'A parent block of type "' . $type . '" is required and can not be found');
1255
+	}
1256
+
1257
+	/**
1258
+	 * Returns a reference to the current block array.
1259
+	 *
1260
+	 * @return array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1261
+	 *                'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1262
+	 */
1263
+	public function &getCurrentBlock()
1264
+	{
1265
+		return $this->curBlock;
1266
+	}
1267
+
1268
+	/**
1269
+	 * Removes the block at the top of the stack and calls its postProcessing() method.
1270
+	 *
1271
+	 * @return string the postProcessing() method's output
1272
+	 * @throws CompilationException
1273
+	 */
1274
+	public function removeTopBlock()
1275
+	{
1276
+		if ($this->debug) {
1277
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1278
+		}
1279
+
1280
+		$o = array_pop($this->stack);
1281
+		if ($o === null) {
1282
+			throw new CompilationException($this, 'Syntax malformation, a block of unknown type was closed but was not opened.');
1283
+		}
1284
+		if ($o['custom']) {
1285
+			$class = $o['class'];
1286
+		} else {
1287
+			$class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($o['type']);
1288
+		}
1289
+
1290
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1291
+
1292
+		return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1293
+	}
1294
+
1295
+	/**
1296
+	 * Returns the compiled parameters (for example a variable's compiled parameter will be "$this->scope['key']") out
1297
+	 * of the given parameter array.
1298
+	 *
1299
+	 * @param array $params parameter array
1300
+	 *
1301
+	 * @return array filtered parameters
1302
+	 */
1303
+	public function getCompiledParams(array $params)
1304
+	{
1305
+		foreach ($params as $k => $p) {
1306
+			if (is_array($p)) {
1307
+				$params[$k] = $p[0];
1308
+			}
1309
+		}
1310
+
1311
+		return $params;
1312
+	}
1313
+
1314
+	/**
1315
+	 * Returns the real parameters (for example a variable's real parameter will be its key, etc) out of the given
1316
+	 * parameter array.
1317
+	 *
1318
+	 * @param array $params parameter array
1319
+	 *
1320
+	 * @return array filtered parameters
1321
+	 */
1322
+	public function getRealParams(array $params)
1323
+	{
1324
+		foreach ($params as $k => $p) {
1325
+			if (is_array($p)) {
1326
+				$params[$k] = $p[1];
1327
+			}
1328
+		}
1329
+
1330
+		return $params;
1331
+	}
1332
+
1333
+	/**
1334
+	 * Returns the token of each parameter out of the given parameter array.
1335
+	 *
1336
+	 * @param array $params parameter array
1337
+	 *
1338
+	 * @return array tokens
1339
+	 */
1340
+	public function getParamTokens(array $params)
1341
+	{
1342
+		foreach ($params as $k => $p) {
1343
+			if (is_array($p)) {
1344
+				$params[$k] = isset($p[2]) ? $p[2] : 0;
1345
+			}
1346
+		}
1347
+
1348
+		return $params;
1349
+	}
1350
+
1351
+	/**
1352
+	 * Entry point of the parser, it redirects calls to other parse* functions.
1353
+	 *
1354
+	 * @param string $in            the string within which we must parse something
1355
+	 * @param int    $from          the starting offset of the parsed area
1356
+	 * @param int    $to            the ending offset of the parsed area
1357
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1358
+	 *                              default
1359
+	 * @param string $curBlock      the current parser-block being processed
1360
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1361
+	 *                              or null by default
1362
+	 *
1363
+	 * @return string parsed values
1364
+	 * @throws CompilationException
1365
+	 */
1366
+	protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1367
+	{
1368
+		if ($this->debug) {
1369
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1370
+		}
1371
+
1372
+		if ($to === null) {
1373
+			$to = strlen($in);
1374
+		}
1375
+		$first = substr($in, $from, 1);
1376
+
1377
+		if ($first === false) {
1378
+			throw new CompilationException($this, 'Unexpected EOF, a template tag was not closed');
1379
+		}
1380
+
1381
+		while ($first === ' ' || $first === "\n" || $first === "\t" || $first === "\r") {
1382
+			if ($curBlock === 'root' && substr($in, $from, strlen($this->rd)) === $this->rd) {
1383
+				// end template tag
1384
+				$pointer += strlen($this->rd);
1385
+				if ($this->debug) {
1386
+					echo 'TEMPLATE PARSING ENDED' . "\n";
1387
+				}
1388
+
1389
+				return false;
1390
+			}
1391
+			++ $from;
1392
+			if ($pointer !== null) {
1393
+				++ $pointer;
1394
+			}
1395
+			if ($from >= $to) {
1396
+				if (is_array($parsingParams)) {
1397
+					return $parsingParams;
1398
+				} else {
1399
+					return '';
1400
+				}
1401
+			}
1402
+			$first = $in[$from];
1403
+		}
1404
+
1405
+		$substr = substr($in, $from, $to - $from);
1406
+
1407
+		if ($this->debug) {
1408
+			echo 'PARSE CALL : PARSING "' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . '" @ ' . $from . ':' . $to . ' in ' . $curBlock . ' : pointer=' . $pointer . "\n";
1409
+		}
1410
+		$parsed = '';
1411
+
1412
+		if ($curBlock === 'root' && $first === '*') {
1413
+			$src      = $this->getTemplateSource();
1414
+			$startpos = $this->getPointer() - strlen($this->ld);
1415
+			if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1416
+				if ($startpos > 0) {
1417
+					do {
1418
+						$char = substr($src, -- $startpos, 1);
1419
+						if ($char == "\n") {
1420
+							++ $startpos;
1421
+							$whitespaceStart = true;
1422
+							break;
1423
+						}
1424
+					}
1425
+					while ($startpos > 0 && ($char == ' ' || $char == "\t"));
1426
+				}
1427
+
1428
+				if (!isset($whitespaceStart)) {
1429
+					$startpos = $this->getPointer();
1430
+				} else {
1431
+					$pointer -= $this->getPointer() - $startpos;
1432
+				}
1433
+
1434
+				if ($this->allowNestedComments && strpos($src, $this->ld . '*', $this->getPointer()) !== false) {
1435
+					$comOpen  = $this->ld . '*';
1436
+					$comClose = '*' . $this->rd;
1437
+					$level    = 1;
1438
+					$ptr      = $this->getPointer();
1439
+
1440
+					while ($level > 0 && $ptr < strlen($src)) {
1441
+						$open  = strpos($src, $comOpen, $ptr);
1442
+						$close = strpos($src, $comClose, $ptr);
1443
+
1444
+						if ($open !== false && $close !== false) {
1445
+							if ($open < $close) {
1446
+								$ptr = $open + strlen($comOpen);
1447
+								++ $level;
1448
+							} else {
1449
+								$ptr = $close + strlen($comClose);
1450
+								-- $level;
1451
+							}
1452
+						} elseif ($open !== false) {
1453
+							$ptr = $open + strlen($comOpen);
1454
+							++ $level;
1455
+						} elseif ($close !== false) {
1456
+							$ptr = $close + strlen($comClose);
1457
+							-- $level;
1458
+						} else {
1459
+							$ptr = strlen($src);
1460
+						}
1461
+					}
1462
+					$endpos = $ptr - strlen('*' . $this->rd);
1463
+				} else {
1464
+					$endpos = strpos($src, '*' . $this->rd, $startpos);
1465
+					if ($endpos == false) {
1466
+						throw new CompilationException($this, 'Un-ended comment');
1467
+					}
1468
+				}
1469
+				$pointer += $endpos - $startpos + strlen('*' . $this->rd);
1470
+				if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*' . $this->rd)), $m)) {
1471
+					$pointer += strlen($m[0]);
1472
+					$this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1473
+				}
1474
+
1475
+				return false;
1476
+			}
1477
+		}
1478
+
1479
+		if ($first === '$') {
1480
+			// var
1481
+			$out    = $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
1482
+			$parsed = 'var';
1483
+		} elseif ($first === '%' && preg_match('#^%[a-z_\\\\]#i', $substr)) {
1484
+			// Short constant
1485
+			$out = $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
1486
+		} elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1487
+			// string
1488
+			$out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1489
+		} elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?(' . (is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|') . '\s*\(|\s*' . $this->rdr . '|\s*;)/i', $substr)) {
1490
+			// func
1491
+			$out    = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1492
+			$parsed = 'func';
1493
+		} elseif ($first === ';') {
1494
+			// instruction end
1495
+			if ($this->debug) {
1496
+				echo 'END OF INSTRUCTION' . "\n";
1497
+			}
1498
+			if ($pointer !== null) {
1499
+				++ $pointer;
1500
+			}
1501
+
1502
+			return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1503
+		} elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1504
+			// close block
1505
+			if (!empty($match[1]) && $match[1] == 'else') {
1506
+				throw new CompilationException($this, 'Else blocks must not be closed explicitly, they are automatically closed when their parent block is closed');
1507
+			}
1508
+			if (!empty($match[1]) && $match[1] == 'elseif') {
1509
+				throw new CompilationException($this, 'Elseif blocks must not be closed explicitly, they are automatically closed when their parent block is closed or a new else/elseif block is declared after them');
1510
+			}
1511
+			if ($pointer !== null) {
1512
+				$pointer += strlen($match[0]);
1513
+			}
1514
+			if (empty($match[1])) {
1515
+				if ($this->curBlock['type'] == 'else' || $this->curBlock['type'] == 'elseif') {
1516
+					$pointer -= strlen($match[0]);
1517
+				}
1518
+				if ($this->debug) {
1519
+					echo 'TOP BLOCK CLOSED' . "\n";
1520
+				}
1521
+
1522
+				return $this->removeTopBlock();
1523
+			} else {
1524
+				if ($this->debug) {
1525
+					echo 'BLOCK OF TYPE ' . $match[1] . ' CLOSED' . "\n";
1526
+				}
1527
+
1528
+				return $this->removeBlock($match[1]);
1529
+			}
1530
+		} elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1531
+			// end template tag
1532
+			if ($this->debug) {
1533
+				echo 'TAG PARSING ENDED' . "\n";
1534
+			}
1535
+			$pointer += strlen($this->rd);
1536
+
1537
+			return false;
1538
+		} elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*=' . ($curBlock === 'array' ? '>?' : '') . ')(?:\s+|[^=]).*#i', $substr, $match)) {
1539
+			// named parameter
1540
+			if ($this->debug) {
1541
+				echo 'NAMED PARAM FOUND' . "\n";
1542
+			}
1543
+			$len = strlen($match[1]);
1544
+			while (substr($in, $from + $len, 1) === ' ') {
1545
+				++ $len;
1546
+			}
1547
+			if ($pointer !== null) {
1548
+				$pointer += $len;
1549
+			}
1550
+
1551
+			$output = array(
1552
+				trim($match[1], " \t\r\n=>'\""),
1553
+				$this->parse($in, $from + $len, $to, false, 'namedparam', $pointer)
1554
+			);
1555
+
1556
+			$parsingParams[] = $output;
1557
+
1558
+			return $parsingParams;
1559
+		} elseif (preg_match('#^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*::\$[a-z0-9_]+)#i', $substr, $match)) {
1560
+			// static member access
1561
+			$parsed = 'var';
1562
+			if (is_array($parsingParams)) {
1563
+				$parsingParams[] = array($match[1], $match[1]);
1564
+				$out             = $parsingParams;
1565
+			} else {
1566
+				$out = $match[1];
1567
+			}
1568
+			$pointer += strlen($match[1]);
1569
+		} elseif ($substr !== '' && (is_array($parsingParams) || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'expression')) {
1570
+			// unquoted string, bool or number
1571
+			$out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1572
+		} else {
1573
+			// parse error
1574
+			throw new CompilationException($this, 'Parse error in "' . substr($in, $from, $to - $from) . '"');
1575
+		}
1576
+
1577
+		if (empty($out)) {
1578
+			return '';
1579
+		}
1580
+
1581
+		$substr = substr($in, $pointer, $to - $pointer);
1582
+
1583
+		// var parsed, check if any var-extension applies
1584
+		if ($parsed === 'var') {
1585
+			if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1586
+				if ($this->debug) {
1587
+					echo 'PARSING POST-VAR EXPRESSION ' . $substr . "\n";
1588
+				}
1589
+				// parse expressions
1590
+				$pointer += strlen($match[0]) - 1;
1591
+				if (is_array($parsingParams)) {
1592
+					if ($match[2] == '$') {
1593
+						$expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1594
+					} else {
1595
+						$expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1596
+					}
1597
+					$out[count($out) - 1][0] .= $match[1] . $expr[0][0];
1598
+					$out[count($out) - 1][1] .= $match[1] . $expr[0][1];
1599
+				} else {
1600
+					if ($match[2] == '$') {
1601
+						$expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
1602
+					} else {
1603
+						$expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1604
+					}
1605
+					if (is_array($out) && is_array($expr)) {
1606
+						$out[0] .= $match[1] . $expr[0];
1607
+						$out[1] .= $match[1] . $expr[1];
1608
+					} elseif (is_array($out)) {
1609
+						$out[0] .= $match[1] . $expr;
1610
+						$out[1] .= $match[1] . $expr;
1611
+					} elseif (is_array($expr)) {
1612
+						$out .= $match[1] . $expr[0];
1613
+					} else {
1614
+						$out .= $match[1] . $expr;
1615
+					}
1616
+				}
1617
+			} elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1618
+				if ($this->debug) {
1619
+					echo 'PARSING POST-VAR ASSIGNMENT ' . $substr . "\n";
1620
+				}
1621
+				// parse assignment
1622
+				$value    = $match[2];
1623
+				$operator = trim($match[1]);
1624
+				if (substr($value, 0, 1) == '=') {
1625
+					throw new CompilationException($this, 'Unexpected "=" in <em>' . $substr . '</em>');
1626
+				}
1627
+
1628
+				if ($pointer !== null) {
1629
+					$pointer += strlen($match[1]);
1630
+				}
1631
+
1632
+				if ($operator !== '++' && $operator !== '--') {
1633
+					$parts = array();
1634
+					$ptr   = 0;
1635
+					$parts = $this->parse($value, 0, strlen($value), $parts, 'condition', $ptr);
1636
+					$pointer += $ptr;
1637
+
1638
+					// load if plugin
1639
+					try {
1640
+						$this->getPluginType('if');
1641
+					}
1642
+					catch (Exception $e) {
1643
+						throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1644
+					}
1645
+
1646
+					$parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS . 'PluginIf', 'init'), 1);
1647
+					$tokens = $this->getParamTokens($parts);
1648
+					$parts  = $this->getCompiledParams($parts);
1649
+
1650
+					$value = PluginIf::replaceKeywords($parts['*'], $tokens['*'], $this);
1651
+					$echo  = '';
1652
+				} else {
1653
+					$value = array();
1654
+					$echo  = 'echo ';
1655
+				}
1656
+
1657
+				if ($this->autoEscape) {
1658
+					$out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1659
+				}
1660
+				$out = self::PHP_OPEN . $echo . $out . $operator . implode(' ', $value) . self::PHP_CLOSE;
1661
+			} elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1662
+				// parse namedparam with var as name (only for array)
1663
+				if ($this->debug) {
1664
+					echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND' . "\n";
1665
+				}
1666
+				$len = strlen($match[1]);
1667
+				$var = $out[count($out) - 1];
1668
+				$pointer += $len;
1669
+
1670
+				$output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
1671
+
1672
+				$parsingParams[] = $output;
1673
+
1674
+				return $parsingParams;
1675
+			}
1676
+		}
1677
+
1678
+		if ($curBlock !== 'modifier' && ($parsed === 'func' || $parsed === 'var') && preg_match('#^(\|@?[a-z0-9_]+(:.*)?)+#i', $substr, $match)) {
1679
+			// parse modifier on funcs or vars
1680
+			$srcPointer = $pointer;
1681
+			if (is_array($parsingParams)) {
1682
+				$tmp                     = $this->replaceModifiers(
1683
+					array(
1684
+					null,
1685
+					null,
1686
+					$out[count($out) - 1][0],
1687
+					$match[0]
1688
+					), $curBlock, $pointer
1689
+				);
1690
+				$out[count($out) - 1][0] = $tmp;
1691
+				$out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1692
+			} else {
1693
+				$out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1694
+			}
1695
+		}
1696
+
1697
+		// func parsed, check if any func-extension applies
1698
+		if ($parsed === 'func' && preg_match('#^->[a-z0-9_]+(\s*\(.+|->[a-z_].*)?#is', $substr, $match)) {
1699
+			// parse method call or property read
1700
+			$ptr = 0;
1701
+
1702
+			if (is_array($parsingParams)) {
1703
+				$output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1704
+
1705
+				$out[count($out) - 1][0] = $output;
1706
+				$out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1707
+			} else {
1708
+				$out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1709
+			}
1710
+
1711
+			$pointer += $ptr;
1712
+		}
1713
+
1714
+		if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1715
+			return self::PHP_OPEN . 'echo ' . $out . ';' . self::PHP_CLOSE;
1716
+		}
1717
+
1718
+		return $out;
1719
+	}
1720
+
1721
+	/**
1722
+	 * Parses a function call.
1723
+	 *
1724
+	 * @param string $in            the string within which we must parse something
1725
+	 * @param int    $from          the starting offset of the parsed area
1726
+	 * @param int    $to            the ending offset of the parsed area
1727
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1728
+	 *                              default
1729
+	 * @param string $curBlock      the current parser-block being processed
1730
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1731
+	 *                              or null by default
1732
+	 *
1733
+	 * @return string parsed values
1734
+	 * @throws CompilationException
1735
+	 * @throws Exception
1736
+	 * @throws SecurityException
1737
+	 */
1738
+	protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1739
+	{
1740
+		$output = '';
1741
+		$cmdstr = substr($in, $from, $to - $from);
1742
+		preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*' . $this->rdr . '|\s*;)?/i', $cmdstr, $match);
1743
+
1744
+		if (empty($match[1])) {
1745
+			throw new CompilationException($this, 'Parse error, invalid function name : ' . substr($cmdstr, 0, 15));
1746
+		}
1747
+
1748
+		$func = $match[1];
1749
+
1750
+		if (!empty($match[2])) {
1751
+			$cmdstr = $match[1];
1752
+		}
1753
+
1754
+		if ($this->debug) {
1755
+			echo 'FUNC FOUND (' . $func . ')' . "\n";
1756
+		}
1757
+
1758
+		$paramsep = '';
1759
+
1760
+		if (is_array($parsingParams) || $curBlock != 'root') {
1761
+			$paramspos = strpos($cmdstr, '(');
1762
+			$paramsep  = ')';
1763
+		} elseif (preg_match_all('#^\s*[\\\\:a-z0-9_]+(\s*\(|\s+[^(])#i', $cmdstr, $match, PREG_OFFSET_CAPTURE)) {
1764
+			$paramspos = $match[1][0][1];
1765
+			$paramsep  = substr($match[1][0][0], - 1) === '(' ? ')' : '';
1766
+			if ($paramsep === ')') {
1767
+				$paramspos += strlen($match[1][0][0]) - 1;
1768
+				if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1769
+					$paramsep = '';
1770
+					if (strlen($match[1][0][0]) > 1) {
1771
+						-- $paramspos;
1772
+					}
1773
+				}
1774
+			}
1775
+		} else {
1776
+			$paramspos = false;
1777
+		}
1778
+
1779
+		$state = 0;
1780
+
1781
+		if ($paramspos === false) {
1782
+			$params = array();
1783
+
1784
+			if ($curBlock !== 'root') {
1785
+				return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1786
+			}
1787
+		} else {
1788
+			if ($curBlock === 'condition') {
1789
+				// load if plugin
1790
+				$this->getPluginType('if');
1791
+
1792
+				if (PluginIf::replaceKeywords(array($func), array(self::T_UNQUOTED_STRING), $this) !== array($func)) {
1793
+					return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1794
+				}
1795
+			}
1796
+			$whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1797
+			$paramstr   = substr($cmdstr, $paramspos + 1);
1798
+			if (substr($paramstr, - 1, 1) === $paramsep) {
1799
+				$paramstr = substr($paramstr, 0, - 1);
1800
+			}
1801
+
1802
+			if (strlen($paramstr) === 0) {
1803
+				$params   = array();
1804
+				$paramstr = '';
1805
+			} else {
1806
+				$ptr    = 0;
1807
+				$params = array();
1808
+				if ($func === 'empty') {
1809
+					$params = $this->parseVar($paramstr, $ptr, strlen($paramstr), $params, 'root', $ptr);
1810
+				} else {
1811
+					while ($ptr < strlen($paramstr)) {
1812
+						while (true) {
1813
+							if ($ptr >= strlen($paramstr)) {
1814
+								break 2;
1815
+							}
1816
+
1817
+							if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1818
+								if ($this->debug) {
1819
+									echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT ' . $ptr . "\n";
1820
+								}
1821
+								break 2;
1822
+							} elseif ($paramstr[$ptr] === ';') {
1823
+								++ $ptr;
1824
+								if ($this->debug) {
1825
+									echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT ' . $ptr . "\n";
1826
+								}
1827
+								break 2;
1828
+							} elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1829
+								if ($this->debug) {
1830
+									echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT ' . $ptr . "\n";
1831
+								}
1832
+								break 2;
1833
+							} elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1834
+								if ($this->debug) {
1835
+									echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT ' . $ptr . "\n";
1836
+								}
1837
+								break 2;
1838
+							}
1839
+
1840
+							if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1841
+								++ $ptr;
1842
+							} else {
1843
+								break;
1844
+							}
1845
+						}
1846
+
1847
+						if ($this->debug) {
1848
+							echo 'FUNC START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
1849
+						}
1850
+
1851
+						if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
1852
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'condition', $ptr);
1853
+						} elseif ($func === 'array') {
1854
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'array', $ptr);
1855
+						} else {
1856
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'function', $ptr);
1857
+						}
1858
+
1859
+						if ($this->debug) {
1860
+							echo 'PARAM PARSED, POINTER AT ' . $ptr . ' (' . substr($paramstr, $ptr - 1, 3) . ')' . "\n";
1861
+						}
1862
+					}
1863
+				}
1864
+				$paramstr = substr($paramstr, 0, $ptr);
1865
+				$state    = 0;
1866
+				foreach ($params as $k => $p) {
1867
+					if (is_array($p) && is_array($p[1])) {
1868
+						$state |= 2;
1869
+					} else {
1870
+						if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m) && $func !== 'array') {
1871
+							$params[$k] = array($m[2], array('true', 'true'));
1872
+						} else {
1873
+							if ($state & 2 && $func !== 'array') {
1874
+								throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
1875
+							}
1876
+							$state |= 1;
1877
+						}
1878
+					}
1879
+				}
1880
+			}
1881
+		}
1882
+
1883
+		if ($pointer !== null) {
1884
+			$pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1885
+			if ($this->debug) {
1886
+				echo 'FUNC ADDS ' . ((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)) . ' TO POINTER' . "\n";
1887
+			}
1888
+		}
1889
+
1890
+		if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1891
+			// handle static method calls with security policy
1892
+			if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1893
+				throw new SecurityException('Call to a disallowed php function : ' . $func);
1894
+			}
1895
+			$pluginType = Core::NATIVE_PLUGIN;
1896
+		} else {
1897
+			$pluginType = $this->getPluginType($func);
1898
+		}
1899
+
1900
+		// Blocks plugin
1901
+		if ($pluginType & Core::BLOCK_PLUGIN) {
1902
+			if ($curBlock !== 'root' || is_array($parsingParams)) {
1903
+				throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1904
+			}
1905
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
1906
+				return $this->addCustomBlock($func, $params, $state);
1907
+			} else {
1908
+				return $this->addBlock($func, $params, $state);
1909
+			}
1910
+		} elseif ($pluginType & Core::SMARTY_BLOCK) {
1911
+			if ($curBlock !== 'root' || is_array($parsingParams)) {
1912
+				throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1913
+			}
1914
+
1915
+			if ($state & 2) {
1916
+				array_unshift($params, array('__functype', array($pluginType, $pluginType)));
1917
+				array_unshift($params, array('__funcname', array($func, $func)));
1918
+			} else {
1919
+				array_unshift($params, array($pluginType, $pluginType));
1920
+				array_unshift($params, array($func, $func));
1921
+			}
1922
+
1923
+			return $this->addBlock('smartyinterface', $params, $state);
1924
+		}
1925
+
1926
+		// Native & Smarty plugins
1927
+		if ($pluginType & Core::NATIVE_PLUGIN || $pluginType & Core::SMARTY_FUNCTION || $pluginType & Core::SMARTY_BLOCK) {
1928
+			$params = $this->mapParams($params, null, $state);
1929
+		} // PHP class plugin
1930
+		elseif ($pluginType & Core::CLASS_PLUGIN) {
1931
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
1932
+				$params = $this->mapParams(
1933
+					$params, array(
1934
+					$this->customPlugins[$func]['class'],
1935
+					$this->customPlugins[$func]['function']
1936
+				), $state);
1937
+			} else {
1938
+				if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
1939
+					$params = $this->mapParams($params, array(
1940
+						'Plugin' . Core::toCamelCase($func),
1941
+						($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1942
+					), $state);
1943
+				} elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !== false) {
1944
+					$params = $this->mapParams($params, array(
1945
+						Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func),
1946
+						($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1947
+					), $state);
1948
+				} else {
1949
+					$params = $this->mapParams($params, array(
1950
+						Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
1951
+						($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1952
+					), $state);
1953
+				}
1954
+			}
1955
+		} // PHP function plugin
1956
+		elseif ($pluginType & Core::FUNC_PLUGIN) {
1957
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
1958
+				$params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1959
+			} else {
1960
+				// Custom plugin
1961
+				if (function_exists('Plugin' . Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ?
1962
+						'Compile' : '')) !== false) {
1963
+					$params = $this->mapParams($params, 'Plugin' . Core::toCamelCase($func) . (($pluginType &
1964
+							Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1965
+				} // Builtin helper plugin
1966
+				elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . (
1967
+					($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '')) !== false) {
1968
+					$params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase
1969
+						($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1970
+				} // Builtin function plugin
1971
+				else {
1972
+					$params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
1973
+						($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1974
+				}
1975
+			}
1976
+		} // Smarty modifier
1977
+		elseif ($pluginType & Core::SMARTY_MODIFIER) {
1978
+			$output = 'smarty_modifier_' . $func . '(' . implode(', ', $params) . ')';
1979
+		} // Proxy plugin
1980
+		elseif ($pluginType & Core::PROXY_PLUGIN) {
1981
+			$params = $this->mapParams($params, $this->getCore()->getPluginProxy()->getCallback($func), $state);
1982
+		} // Template plugin
1983
+		elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
1984
+			// transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
1985
+			$map = array();
1986
+			foreach ($this->templatePlugins[$func]['params'] as $param => $defValue) {
1987
+				if ($param == 'rest') {
1988
+					$param = '*';
1989
+				}
1990
+				$hasDefault = $defValue !== null;
1991
+				if ($defValue === 'null') {
1992
+					$defValue = null;
1993
+				} elseif ($defValue === 'false') {
1994
+					$defValue = false;
1995
+				} elseif ($defValue === 'true') {
1996
+					$defValue = true;
1997
+				} elseif (preg_match('#^([\'"]).*?\1$#', $defValue)) {
1998
+					$defValue = substr($defValue, 1, - 1);
1999
+				}
2000
+				$map[] = array($param, $hasDefault, $defValue);
2001
+			}
2002
+
2003
+			$params = $this->mapParams($params, null, $state, $map);
2004
+		}
2005
+
2006
+		// only keep php-syntax-safe values for non-block plugins
2007
+		$tokens = array();
2008
+		foreach ($params as $k => $p) {
2009
+			$tokens[$k] = isset($p[2]) ? $p[2] : 0;
2010
+			$params[$k] = $p[0];
2011
+		}
2012
+
2013
+		// Native plugin
2014
+		if ($pluginType & Core::NATIVE_PLUGIN) {
2015
+			if ($func === 'do') {
2016
+				$output = '';
2017
+				if (isset($params['*'])) {
2018
+					$output = implode(';', $params['*']) . ';';
2019
+				}
2020
+
2021
+				if (is_array($parsingParams) || $curBlock !== 'root') {
2022
+					throw new CompilationException($this, 'Do can not be used inside another function or block');
2023
+				}
2024
+
2025
+				return self::PHP_OPEN . $output . self::PHP_CLOSE;
2026
+			} else {
2027
+				if (isset($params['*'])) {
2028
+					$output = $func . '(' . implode(', ', $params['*']) . ')';
2029
+				} else {
2030
+					$output = $func . '()';
2031
+				}
2032
+			}
2033
+		} // Block class OR Function class
2034
+		elseif ($pluginType & Core::CLASS_PLUGIN || ($pluginType & Core::FUNC_PLUGIN && $pluginType & Core::CLASS_PLUGIN)) {
2035
+			if ($pluginType & Core::COMPILABLE_PLUGIN) {
2036
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2037
+					$callback = $this->customPlugins[$func]['callback'];
2038
+					if (!is_array($callback)) {
2039
+						if (!method_exists($callback, 'compile')) {
2040
+							throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2041
+						}
2042
+						if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
2043
+							$funcCompiler = array($callback, 'compile');
2044
+						} else {
2045
+							$funcCompiler = array(new $callback(), 'compile');
2046
+						}
2047
+					} else {
2048
+						$funcCompiler = $callback;
2049
+					}
2050
+				} else {
2051
+					if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2052
+						$funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
2053
+					} elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !== false) {
2054
+						$funcCompiler = array(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func), 'compile');
2055
+					} else {
2056
+						$funcCompiler = array(
2057
+							Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
2058
+							'compile'
2059
+						);
2060
+					}
2061
+					array_unshift($params, $this);
2062
+				}
2063
+				// @TODO: Is it a real fix ?
2064
+				if ($func === 'tif') {
2065
+					$params[] = $tokens;
2066
+				}
2067
+				$output = call_user_func_array($funcCompiler, $params);
2068
+			} else {
2069
+				$params = self::implode_r($params);
2070
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2071
+					$callback = $this->customPlugins[$func]['callback'];
2072
+					if (!is_array($callback)) {
2073
+						if (!method_exists($callback, 'process')) {
2074
+							throw new Exception('Custom plugin ' . $func . ' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2075
+						}
2076
+						if (is_object($callback)) {
2077
+							$callback = get_class($callback);
2078
+						}
2079
+						if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
2080
+							$output = 'call_user_func(array(\'' . $callback . '\', \'process\'), ' . $params . ')';
2081
+						} else {
2082
+							$output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback . '\'), \'process\'), ' . $params . ')';
2083
+						}
2084
+					} elseif (is_object($callback[0])) {
2085
+						$output = 'call_user_func(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), ' . $params . ')';
2086
+					} elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
2087
+						$output = 'call_user_func(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), ' . $params . ')';
2088
+					} else {
2089
+						$output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback[0] . '\'), \'' . $callback[1] . '\'), ' . $params . ')';
2090
+					}
2091
+					if (empty($params)) {
2092
+						$output = substr($output, 0, - 3) . ')';
2093
+					}
2094
+				} else {
2095
+					if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2096
+						$output = '$this->classCall(\'Plugin' . $func . '\', array(' . $params . '))';
2097
+					} elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !== false) {
2098
+						$output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\',
2099 2099
                         array(' . $params . '))';
2100
-                    } else {
2101
-                        $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
2102
-                    }
2103
-                }
2104
-            }
2105
-        } // Function plugin only (cannot be a class)
2106
-        elseif ($pluginType & Core::FUNC_PLUGIN) {
2107
-            if ($pluginType & Core::COMPILABLE_PLUGIN) {
2108
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2109
-                    $funcCompiler = $this->customPlugins[$func]['callback'];
2110
-                } else {
2111
-                    // Custom plugin
2112
-                    if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2113
-                        $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
2114
-                    } // Builtin helper plugin
2115
-                    elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2116
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2117
-                            'Compile';
2118
-                    } // Builtin function plugin
2119
-                    else {
2120
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
2121
-                            'Compile';
2122
-                    }
2123
-                }
2124
-                array_unshift($params, $this);
2125
-                // @TODO: Is it a real fix ?
2126
-                if ($func === 'tif') {
2127
-                    $params[] = $tokens;
2128
-                }
2129
-                $output = call_user_func_array($funcCompiler, $params);
2130
-            } else {
2131
-                array_unshift($params, '$this');
2132
-                $params = self::implode_r($params);
2133
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2134
-                    $callback = $this->customPlugins[$func]['callback'];
2135
-                    if ($callback instanceof Closure) {
2136
-                        $output = 'call_user_func($this->getCustomPlugin(\'' . $func . '\'), ' . $params . ')';
2137
-                    } else {
2138
-                        $output = 'call_user_func(\'' . $callback . '\', ' . $params . ')';
2139
-                    }
2140
-                } else {
2141
-                    // Custom plugin
2142
-                    if (function_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2143
-                        $output = 'Plugin' . Core::toCamelCase($func) . '(' . $params .
2144
-                            ')';
2145
-                    } // Builtin helper plugin
2146
-                    elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !==
2147
-                        false) {
2148
-                        $output = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . '(' .
2149
-                            $params . ')';
2150
-                    } // Builtin function plugin
2151
-                    else {
2152
-                        $output = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '(' .
2153
-                            $params . ')';
2154
-                    }
2155
-                }
2156
-            }
2157
-        } // Proxy plugin
2158
-        elseif ($pluginType & Core::PROXY_PLUGIN) {
2159
-            $output = call_user_func(array($this->getCore()->getPluginProxy(), 'getCode'), $func, $params);
2160
-        } // Smarty function (@deprecated)
2161
-        elseif ($pluginType & Core::SMARTY_FUNCTION) {
2162
-            $params = '';
2163
-            if (isset($params['*'])) {
2164
-                $params = self::implode_r($params['*'], true);
2165
-            }
2166
-
2167
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
2168
-                $callback = $this->customPlugins[$func]['callback'];
2169
-                if (is_array($callback)) {
2170
-                    if (is_object($callback[0])) {
2171
-                        $output = 'call_user_func_array(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2172
-                    } else {
2173
-                        $output = 'call_user_func_array(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2174
-                    }
2175
-                } else {
2176
-                    $output = $callback . '(array(' . $params . '), $this)';
2177
-                }
2178
-            } else {
2179
-                $output = 'smarty_function_' . $func . '(array(' . $params . '), $this)';
2180
-            }
2181
-        } // Template plugin
2182
-        elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
2183
-            array_unshift($params, '$this');
2184
-            $params                                 = self::implode_r($params);
2185
-            $output                                 = 'Plugin' . Core::toCamelCase($func) .
2186
-                $this->templatePlugins[$func]['uuid'] . '(' . $params . ')';
2187
-            $this->templatePlugins[$func]['called'] = true;
2188
-        }
2189
-
2190
-        if (is_array($parsingParams)) {
2191
-            $parsingParams[] = array($output, $output);
2192
-
2193
-            return $parsingParams;
2194
-        } elseif ($curBlock === 'namedparam') {
2195
-            return array($output, $output);
2196
-        }
2197
-
2198
-        return $output;
2199
-    }
2200
-
2201
-    /**
2202
-     * Parses a string.
2203
-     *
2204
-     * @param string $in            the string within which we must parse something
2205
-     * @param int    $from          the starting offset of the parsed area
2206
-     * @param int    $to            the ending offset of the parsed area
2207
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2208
-     *                              default
2209
-     * @param string $curBlock      the current parser-block being processed
2210
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2211
-     *                              or null by default
2212
-     *
2213
-     * @return string parsed values
2214
-     * @throws CompilationException
2215
-     */
2216
-    protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2217
-    {
2218
-        $substr = substr($in, $from, $to - $from);
2219
-        $first  = $substr[0];
2220
-
2221
-        if ($this->debug) {
2222
-            echo 'STRING FOUND (in ' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . ')' . "\n";
2223
-        }
2224
-        $strend = false;
2225
-        $o      = $from + 1;
2226
-        while ($strend === false) {
2227
-            $strend = strpos($in, $first, $o);
2228
-            if ($strend === false) {
2229
-                throw new CompilationException($this, 'Unfinished string, started with ' . substr($in, $from, $to - $from));
2230
-            }
2231
-            if (substr($in, $strend - 1, 1) === '\\') {
2232
-                $o      = $strend + 1;
2233
-                $strend = false;
2234
-            }
2235
-        }
2236
-        if ($this->debug) {
2237
-            echo 'STRING DELIMITED: ' . substr($in, $from, $strend + 1 - $from) . "\n";
2238
-        }
2239
-
2240
-        $srcOutput = substr($in, $from, $strend + 1 - $from);
2241
-
2242
-        if ($pointer !== null) {
2243
-            $pointer += strlen($srcOutput);
2244
-        }
2245
-
2246
-        $output = $this->replaceStringVars($srcOutput, $first);
2247
-
2248
-        // handle modifiers
2249
-        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2250
-            $modstr = $match[1];
2251
-
2252
-            if ($curBlock === 'root' && substr($modstr, - 1) === '}') {
2253
-                $modstr = substr($modstr, 0, - 1);
2254
-            }
2255
-            $modstr = str_replace('\\' . $first, $first, $modstr);
2256
-            $ptr    = 0;
2257
-            $output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2258
-
2259
-            $strend += $ptr;
2260
-            if ($pointer !== null) {
2261
-                $pointer += $ptr;
2262
-            }
2263
-            $srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2264
-        }
2265
-
2266
-        if (is_array($parsingParams)) {
2267
-            $parsingParams[] = array($output, substr($srcOutput, 1, - 1));
2268
-
2269
-            return $parsingParams;
2270
-        } elseif ($curBlock === 'namedparam') {
2271
-            return array($output, substr($srcOutput, 1, - 1));
2272
-        }
2273
-
2274
-        return $output;
2275
-    }
2276
-
2277
-    /**
2278
-     * Parses a constant.
2279
-     *
2280
-     * @param string $in            the string within which we must parse something
2281
-     * @param int    $from          the starting offset of the parsed area
2282
-     * @param int    $to            the ending offset of the parsed area
2283
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2284
-     *                              default
2285
-     * @param string $curBlock      the current parser-block being processed
2286
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2287
-     *                              or null by default
2288
-     *
2289
-     * @return string parsed values
2290
-     * @throws CompilationException
2291
-     */
2292
-    protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2293
-    {
2294
-        $substr = substr($in, $from, $to - $from);
2295
-
2296
-        if ($this->debug) {
2297
-            echo 'CONST FOUND : ' . $substr . "\n";
2298
-        }
2299
-
2300
-        if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
2301
-            throw new CompilationException($this, 'Invalid constant');
2302
-        }
2303
-
2304
-        if ($pointer !== null) {
2305
-            $pointer += strlen($m[0]);
2306
-        }
2307
-
2308
-        $output = $this->parseConstKey($m[1], $curBlock);
2309
-
2310
-        if (is_array($parsingParams)) {
2311
-            $parsingParams[] = array($output, $m[1]);
2312
-
2313
-            return $parsingParams;
2314
-        } elseif ($curBlock === 'namedparam') {
2315
-            return array($output, $m[1]);
2316
-        }
2317
-
2318
-        return $output;
2319
-    }
2320
-
2321
-    /**
2322
-     * Parses a constant.
2323
-     *
2324
-     * @param string $key      the constant to parse
2325
-     * @param string $curBlock the current parser-block being processed
2326
-     *
2327
-     * @return string parsed constant
2328
-     */
2329
-    protected function parseConstKey($key, $curBlock)
2330
-    {
2331
-        $key = str_replace('\\\\', '\\', $key);
2332
-
2333
-        if ($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === SecurityPolicy::CONST_DISALLOW) {
2334
-            return 'null';
2335
-        }
2336
-
2337
-        if ($curBlock !== 'root') {
2338
-            return '(defined("' . $key . '") ? ' . $key . ' : null)';
2339
-        }
2340
-
2341
-        return $key;
2342
-    }
2343
-
2344
-    /**
2345
-     * Parses a variable.
2346
-     *
2347
-     * @param string $in            the string within which we must parse something
2348
-     * @param int    $from          the starting offset of the parsed area
2349
-     * @param int    $to            the ending offset of the parsed area
2350
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2351
-     *                              default
2352
-     * @param string $curBlock      the current parser-block being processed
2353
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2354
-     *                              or null by default
2355
-     *
2356
-     * @return string parsed values
2357
-     * @throws CompilationException
2358
-     */
2359
-    protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2360
-    {
2361
-        $substr = substr($in, $from, $to - $from);
2362
-
2363
-        // var key
2364
-        $varRegex = '(\\$?\\.?[a-z0-9\\\\_:]*(?:(?:(?:\\.|->)(?:[a-z0-9\\\\_:]+|(?R))|\\[(?:[a-z0-9\\\\_:]+|(?R)|(["\'])[^\\2]*?\\2)\\]))*)';
2365
-        // method call
2366
-        $methodCall = ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()');
2367
-        // simple math expressions
2368
-        $simpleMathExpressions = ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+\/*%=-])(?:(?<!=)=?-?[$%][a-z0-9\\\\.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9\.,]*|[+-]))*)' : '()');
2369
-        // modifiers
2370
-        $modifiers = $curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9\\\\_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())';
2371
-
2372
-        $regex = '#';
2373
-        $regex .= $varRegex;
2374
-        $regex .= $methodCall;
2375
-        $regex .= $simpleMathExpressions;
2376
-        $regex .= $modifiers;
2377
-        $regex .= '#i';
2378
-
2379
-        if (preg_match($regex, $substr, $match)) {
2380
-            $key = substr($match[1], 1);
2381
-
2382
-            $matchedLength = strlen($match[0]);
2383
-            $hasModifiers  = !empty($match[5]);
2384
-            $hasExpression = !empty($match[4]);
2385
-            $hasMethodCall = !empty($match[3]);
2386
-
2387
-            if (substr($key, - 1) == '.') {
2388
-                $key = substr($key, 0, - 1);
2389
-                -- $matchedLength;
2390
-            }
2391
-
2392
-            if ($hasMethodCall) {
2393
-                $matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2394
-                $key        = substr($match[1], 1, strrpos($match[1], '->') - 1);
2395
-                $methodCall = substr($match[1], strrpos($match[1], '->')) . $match[3];
2396
-            }
2397
-
2398
-            if ($hasModifiers) {
2399
-                $matchedLength -= strlen($match[5]);
2400
-            }
2401
-
2402
-            if ($pointer !== null) {
2403
-                $pointer += $matchedLength;
2404
-            }
2405
-
2406
-            // replace useless brackets by dot accessed vars and strip enclosing quotes if present
2407
-            $key = preg_replace('#\[(["\']?)([^$%\[.>-]+)\1\]#', '.$2', $key);
2408
-
2409
-            if ($this->debug) {
2410
-                if ($hasMethodCall) {
2411
-                    echo 'METHOD CALL FOUND : $' . $key . substr($methodCall, 0, 30) . "\n";
2412
-                } else {
2413
-                    echo 'VAR FOUND : $' . $key . "\n";
2414
-                }
2415
-            }
2416
-
2417
-            $key = str_replace('"', '\\"', $key);
2418
-
2419
-            $cnt = substr_count($key, '$');
2420
-            if ($cnt > 0) {
2421
-                $uid           = 0;
2422
-                $parsed        = array($uid => '');
2423
-                $current       = &$parsed;
2424
-                $curTxt        = &$parsed[$uid ++];
2425
-                $tree          = array();
2426
-                $chars         = str_split($key, 1);
2427
-                $inSplittedVar = false;
2428
-                $bracketCount  = 0;
2429
-
2430
-                while (($char = array_shift($chars)) !== null) {
2431
-                    if ($char === '[') {
2432
-                        if (count($tree) > 0) {
2433
-                            ++ $bracketCount;
2434
-                        } else {
2435
-                            $tree[]        = &$current;
2436
-                            $current[$uid] = array($uid + 1 => '');
2437
-                            $current       = &$current[$uid ++];
2438
-                            $curTxt        = &$current[$uid ++];
2439
-                            continue;
2440
-                        }
2441
-                    } elseif ($char === ']') {
2442
-                        if ($bracketCount > 0) {
2443
-                            -- $bracketCount;
2444
-                        } else {
2445
-                            $current = &$tree[count($tree) - 1];
2446
-                            array_pop($tree);
2447
-                            if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2448
-                                $current[$uid] = '';
2449
-                                $curTxt        = &$current[$uid ++];
2450
-                            }
2451
-                            continue;
2452
-                        }
2453
-                    } elseif ($char === '$') {
2454
-                        if (count($tree) == 0) {
2455
-                            $curTxt        = &$current[$uid ++];
2456
-                            $inSplittedVar = true;
2457
-                        }
2458
-                    } elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2459
-                        $curTxt        = &$current[$uid ++];
2460
-                        $inSplittedVar = false;
2461
-                    }
2462
-
2463
-                    $curTxt .= $char;
2464
-                }
2465
-                unset($uid, $current, $curTxt, $tree, $chars);
2466
-
2467
-                if ($this->debug) {
2468
-                    echo 'RECURSIVE VAR REPLACEMENT : ' . $key . "\n";
2469
-                }
2470
-
2471
-                $key = $this->flattenVarTree($parsed);
2472
-
2473
-                if ($this->debug) {
2474
-                    echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2475
-                }
2476
-
2477
-                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("' . $key . '")');
2478
-            } else {
2479
-                $output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2480
-            }
2481
-
2482
-
2483
-            // methods
2484
-            if ($hasMethodCall) {
2485
-                $ptr = 0;
2486
-
2487
-                $output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
2488
-
2489
-                if ($pointer !== null) {
2490
-                    $pointer += $ptr;
2491
-                }
2492
-                $matchedLength += $ptr;
2493
-            }
2494
-
2495
-            if ($hasExpression) {
2496
-                // expressions
2497
-                preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9\\\\.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[4], $expMatch);
2498
-                foreach ($expMatch[1] as $k => $operator) {
2499
-                    if (substr($expMatch[2][$k], 0, 1) === '=') {
2500
-                        $assign = true;
2501
-                        if ($operator === '=') {
2502
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, can not use "==" in expressions');
2503
-                        }
2504
-                        if ($curBlock !== 'root') {
2505
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2506
-                        }
2507
-                        $operator .= '=';
2508
-                        $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2509
-                    }
2510
-
2511
-                    if (substr($expMatch[2][$k], 0, 1) === '-' && strlen($expMatch[2][$k]) > 1) {
2512
-                        $operator .= '-';
2513
-                        $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2514
-                    }
2515
-                    if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2516
-                        $output = '(' . $output . $operator . $operator . ')';
2517
-                        break;
2518
-                    } elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2519
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2520
-                    } elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2521
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2522
-                    } elseif (!empty($expMatch[2][$k])) {
2523
-                        $output = '(' . $output . ' ' . $operator . ' ' . str_replace(',', '.', $expMatch[2][$k]) . ')';
2524
-                    } else {
2525
-                        throw new CompilationException($this, 'Unfinished expression <em>' . $substr . '</em>, missing var or number after math operator');
2526
-                    }
2527
-                }
2528
-            }
2529
-
2530
-            if ($this->autoEscape === true && $curBlock !== 'condition') {
2531
-                $output = '(is_string($tmp=' . $output . ') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2532
-            }
2533
-
2534
-            // handle modifiers
2535
-            if ($curBlock !== 'modifier' && $hasModifiers) {
2536
-                $ptr    = 0;
2537
-                $output = $this->replaceModifiers(array(null, null, $output, $match[5]), 'var', $ptr);
2538
-                if ($pointer !== null) {
2539
-                    $pointer += $ptr;
2540
-                }
2541
-                $matchedLength += $ptr;
2542
-            }
2543
-
2544
-            if (is_array($parsingParams)) {
2545
-                $parsingParams[] = array($output, $key);
2546
-
2547
-                return $parsingParams;
2548
-            } elseif ($curBlock === 'namedparam') {
2549
-                return array($output, $key);
2550
-            } elseif ($curBlock === 'string' || $curBlock === 'delimited_string') {
2551
-                return array($matchedLength, $output);
2552
-            } elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2553
-                return $output;
2554
-            } elseif (isset($assign)) {
2555
-                return self::PHP_OPEN . $output . ';' . self::PHP_CLOSE;
2556
-            }
2557
-
2558
-            return $output;
2559
-        } else {
2560
-            if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2561
-                return array(0, '');
2562
-            }
2563
-            throw new CompilationException($this, 'Invalid variable name <em>' . $substr . '</em>');
2564
-        }
2565
-    }
2566
-
2567
-    /**
2568
-     * Parses any number of chained method calls/property reads.
2569
-     *
2570
-     * @param string $output     the variable or whatever upon which the method are called
2571
-     * @param string $methodCall method call source, starting at "->"
2572
-     * @param string $curBlock   the current parser-block being processed
2573
-     * @param int    $pointer    a reference to a pointer that will be increased by the amount of characters parsed
2574
-     *
2575
-     * @return string parsed call(s)/read(s)
2576
-     */
2577
-    protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
2578
-    {
2579
-        $ptr = 0;
2580
-        $len = strlen($methodCall);
2581
-
2582
-        while ($ptr < $len) {
2583
-            if (strpos($methodCall, '->', $ptr) === $ptr) {
2584
-                $ptr += 2;
2585
-            }
2586
-
2587
-            if (in_array(
2588
-                $methodCall[$ptr], array(
2589
-                    ';',
2590
-                    ',',
2591
-                    '/',
2592
-                    ' ',
2593
-                    "\t",
2594
-                    "\r",
2595
-                    "\n",
2596
-                    ')',
2597
-                    '+',
2598
-                    '*',
2599
-                    '%',
2600
-                    '=',
2601
-                    '-',
2602
-                    '|'
2603
-                )
2604
-            ) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd
2605
-            ) {
2606
-                // break char found
2607
-                break;
2608
-            }
2609
-
2610
-            if (!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
2611
-                break;
2612
-            }
2613
-
2614
-            if (empty($methMatch[2])) {
2615
-                // property
2616
-                if ($curBlock === 'root') {
2617
-                    $output .= '->' . $methMatch[1];
2618
-                } else {
2619
-                    $output = '(($tmp = ' . $output . ') ? $tmp->' . $methMatch[1] . ' : null)';
2620
-                }
2621
-                $ptr += strlen($methMatch[1]);
2622
-            } else {
2623
-                // method
2624
-                if (substr($methMatch[2], 0, 2) === '()') {
2625
-                    $parsedCall = $methMatch[1] . '()';
2626
-                    $ptr += strlen($methMatch[1]) + 2;
2627
-                } else {
2628
-                    $parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2629
-                }
2630
-                if ($this->securityPolicy !== null) {
2631
-                    $argPos = strpos($parsedCall, '(');
2632
-                    $method = strtolower(substr($parsedCall, 0, $argPos));
2633
-                    $args   = substr($parsedCall, $argPos);
2634
-                    if ($curBlock === 'root') {
2635
-                        $output = '$this->getSecurityPolicy()->callMethod($this, ' . $output . ', ' . var_export($method, true) . ', array' . $args . ')';
2636
-                    } else {
2637
-                        $output = '(($tmp = ' . $output . ') ? $this->getSecurityPolicy()->callMethod($this, $tmp, ' . var_export($method, true) . ', array' . $args . ') : null)';
2638
-                    }
2639
-                } else {
2640
-                    if ($curBlock === 'root') {
2641
-                        $output .= '->' . $parsedCall;
2642
-                    } else {
2643
-                        $output = '(($tmp = ' . $output . ') ? $tmp->' . $parsedCall . ' : null)';
2644
-                    }
2645
-                }
2646
-            }
2647
-        }
2648
-
2649
-        $pointer += $ptr;
2650
-
2651
-        return $output;
2652
-    }
2653
-
2654
-    /**
2655
-     * Parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save
2656
-     * runtime processing time.
2657
-     *
2658
-     * @param string $key      the variable to parse
2659
-     * @param string $curBlock the current parser-block being processed
2660
-     *
2661
-     * @return string parsed variable
2662
-     */
2663
-    protected function parseVarKey($key, $curBlock)
2664
-    {
2665
-        if ($key === '') {
2666
-            return '$this->scope';
2667
-        }
2668
-        if (substr($key, 0, 1) === '.') {
2669
-            $key = 'dwoo' . $key;
2670
-        }
2671
-        if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2672
-            $global = strtoupper($m[1]);
2673
-            if ($global === 'COOKIES') {
2674
-                $global = 'COOKIE';
2675
-            }
2676
-            $key = '$_' . $global;
2677
-            foreach (explode('.', ltrim($m[2], '.')) as $part) {
2678
-                $key .= '[' . var_export($part, true) . ']';
2679
-            }
2680
-            if ($curBlock === 'root') {
2681
-                $output = $key;
2682
-            } else {
2683
-                $output = '(isset(' . $key . ')?' . $key . ':null)';
2684
-            }
2685
-        } elseif (preg_match('#dwoo\\.const\\.([a-z0-9\\\\_:]+)#i', $key, $m)) {
2686
-            return $this->parseConstKey($m[1], $curBlock);
2687
-        } elseif ($this->scope !== null) {
2688
-            if (strstr($key, '.') === false && strstr($key, '[') === false && strstr($key, '->') === false) {
2689
-                if ($key === 'dwoo') {
2690
-                    $output = '$this->globals';
2691
-                } elseif ($key === '_root' || $key === '__') {
2692
-                    $output = '$this->data';
2693
-                } elseif ($key === '_parent' || $key === '_') {
2694
-                    $output = '$this->readParentVar(1)';
2695
-                } elseif ($key === '_key') {
2696
-                    $output = '$tmp_key';
2697
-                } else {
2698
-                    if ($curBlock === 'root') {
2699
-                        $output = '$this->scope["' . $key . '"]';
2700
-                    } else {
2701
-                        $output = '(isset($this->scope["' . $key . '"]) ? $this->scope["' . $key . '"] : null)';
2702
-                    }
2703
-                }
2704
-            } else {
2705
-                preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+|(\\\?[\'"])[^\3]*?\3)\]?#i', $key, $m);
2706
-
2707
-                $i = $m[2][0];
2708
-                if ($i === '_parent' || $i === '_') {
2709
-                    $parentCnt = 0;
2710
-
2711
-                    while (true) {
2712
-                        ++ $parentCnt;
2713
-                        array_shift($m[2]);
2714
-                        array_shift($m[1]);
2715
-                        if (current($m[2]) === '_parent') {
2716
-                            continue;
2717
-                        }
2718
-                        break;
2719
-                    }
2720
-
2721
-                    $output = '$this->readParentVar(' . $parentCnt . ')';
2722
-                } else {
2723
-                    if ($i === 'dwoo') {
2724
-                        $output = '$this->globals';
2725
-                        array_shift($m[2]);
2726
-                        array_shift($m[1]);
2727
-                    } elseif ($i === '_root' || $i === '__') {
2728
-                        // $output = '$this->data';
2729
-                        $output = '$this->getData()';
2730
-                        array_shift($m[2]);
2731
-                        array_shift($m[1]);
2732
-                    } elseif ($i === '_key') {
2733
-                        $output = '$tmp_key';
2734
-                    } else {
2735
-                        $output = '$this->scope';
2736
-                    }
2737
-
2738
-                    while (count($m[1]) && $m[1][0] !== '->') {
2739
-                        $m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2740
-                        if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2741
-                            $output .= '[' . $m[2][0] . ']';
2742
-                        } else {
2743
-                            $output .= '["' . $m[2][0] . '"]';
2744
-                        }
2745
-                        array_shift($m[2]);
2746
-                        array_shift($m[1]);
2747
-                    }
2748
-
2749
-                    if ($curBlock !== 'root') {
2750
-                        $output = '(isset(' . $output . ') ? ' . $output . ':null)';
2751
-                    }
2752
-                }
2753
-
2754
-                if (count($m[2])) {
2755
-                    unset($m[0]);
2756
-                    $output = '$this->readVarInto(' . str_replace("\n", '', var_export($m, true)) . ', ' . $output . ', ' . ($curBlock == 'root' ? 'false' : 'true') . ')';
2757
-                }
2758
-            }
2759
-        } else {
2760
-            preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2761
-            unset($m[0]);
2762
-            $output = '$this->readVar(' . str_replace("\n", '', var_export($m, true)) . ')';
2763
-        }
2764
-
2765
-        return $output;
2766
-    }
2767
-
2768
-    /**
2769
-     * Flattens a variable tree, this helps in parsing very complex variables such as $var.foo[$foo.bar->baz].baz,
2770
-     * it computes the contents of the brackets first and works out from there.
2771
-     *
2772
-     * @param array $tree     the variable tree parsed by he parseVar() method that must be flattened
2773
-     * @param bool  $recursed leave that to false by default, it is only for internal use
2774
-     *
2775
-     * @return string flattened tree
2776
-     */
2777
-    protected function flattenVarTree(array $tree, $recursed = false)
2778
-    {
2779
-        $out = $recursed ? '".$this->readVarInto(' : '';
2780
-        foreach ($tree as $bit) {
2781
-            if (is_array($bit)) {
2782
-                $out .= '.' . $this->flattenVarTree($bit, false);
2783
-            } else {
2784
-                $key = str_replace('"', '\\"', $bit);
2785
-
2786
-                if (substr($key, 0, 1) === '$') {
2787
-                    $out .= '".' . $this->parseVar($key, 0, strlen($key), false, 'variable') . '."';
2788
-                } else {
2789
-                    $cnt = substr_count($key, '$');
2790
-
2791
-                    if ($this->debug) {
2792
-                        echo 'PARSING SUBVARS IN : ' . $key . "\n";
2793
-                    }
2794
-                    if ($cnt > 0) {
2795
-                        while (-- $cnt >= 0) {
2796
-                            if (isset($last)) {
2797
-                                $last = strrpos($key, '$', - (strlen($key) - $last + 1));
2798
-                            } else {
2799
-                                $last = strrpos($key, '$');
2800
-                            }
2801
-                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2802
-
2803
-                            $len = strlen($submatch[0]);
2804
-                            $key = substr_replace(
2805
-                                $key, preg_replace_callback(
2806
-                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2807
-                                        $this,
2808
-                                        'replaceVarKeyHelper'
2809
-                                    ), substr($key, $last, $len)
2810
-                                ), $last, $len
2811
-                            );
2812
-                            if ($this->debug) {
2813
-                                echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2814
-                            }
2815
-                        }
2816
-                        unset($last);
2817
-
2818
-                        $out .= $key;
2819
-                    } else {
2820
-                        $out .= $key;
2821
-                    }
2822
-                }
2823
-            }
2824
-        }
2825
-        $out .= $recursed ? ', true)."' : '';
2826
-
2827
-        return $out;
2828
-    }
2829
-
2830
-    /**
2831
-     * Helper function that parses a variable.
2832
-     *
2833
-     * @param array $match the matched variable, array(1=>"string match")
2834
-     *
2835
-     * @return string parsed variable
2836
-     */
2837
-    protected function replaceVarKeyHelper($match)
2838
-    {
2839
-        return '".' . $this->parseVar($match[0], 0, strlen($match[0]), false, 'variable') . '."';
2840
-    }
2841
-
2842
-    /**
2843
-     * Parses various constants, operators or non-quoted strings.
2844
-     *
2845
-     * @param string $in            the string within which we must parse something
2846
-     * @param int    $from          the starting offset of the parsed area
2847
-     * @param int    $to            the ending offset of the parsed area
2848
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2849
-     *                              default
2850
-     * @param string $curBlock      the current parser-block being processed
2851
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2852
-     *                              or null by default
2853
-     *
2854
-     * @return string parsed values
2855
-     * @throws Exception
2856
-     */
2857
-    protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2858
-    {
2859
-        $substr = substr($in, $from, $to - $from);
2860
-
2861
-        $end = strlen($substr);
2862
-
2863
-        if ($curBlock === 'condition') {
2864
-            $breakChars = array(
2865
-                '(',
2866
-                ')',
2867
-                ' ',
2868
-                '||',
2869
-                '&&',
2870
-                '|',
2871
-                '&',
2872
-                '>=',
2873
-                '<=',
2874
-                '===',
2875
-                '==',
2876
-                '=',
2877
-                '!==',
2878
-                '!=',
2879
-                '<<',
2880
-                '<',
2881
-                '>>',
2882
-                '>',
2883
-                '^',
2884
-                '~',
2885
-                ',',
2886
-                '+',
2887
-                '-',
2888
-                '*',
2889
-                '/',
2890
-                '%',
2891
-                '!',
2892
-                '?',
2893
-                ':',
2894
-                $this->rd,
2895
-                ';'
2896
-            );
2897
-        } elseif ($curBlock === 'modifier') {
2898
-            $breakChars = array(' ', ',', ')', ':', '|', "\r", "\n", "\t", ';', $this->rd);
2899
-        } elseif ($curBlock === 'expression') {
2900
-            $breakChars = array('/', '%', '+', '-', '*', ' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2901
-        } else {
2902
-            $breakChars = array(' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2903
-        }
2904
-
2905
-        $breaker = false;
2906
-        foreach ($breakChars as $k => $char) {
2907
-            $test = strpos($substr, $char);
2908
-            if ($test !== false && $test < $end) {
2909
-                $end     = $test;
2910
-                $breaker = $k;
2911
-            }
2912
-        }
2913
-
2914
-        if ($curBlock === 'condition') {
2915
-            if ($end === 0 && $breaker !== false) {
2916
-                $end = strlen($breakChars[$breaker]);
2917
-            }
2918
-        }
2919
-
2920
-        if ($end !== false) {
2921
-            $substr = substr($substr, 0, $end);
2922
-        }
2923
-
2924
-        if ($pointer !== null) {
2925
-            $pointer += strlen($substr);
2926
-        }
2927
-
2928
-        $src    = $substr;
2929
-        $substr = trim($substr);
2930
-
2931
-        if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2932
-            if ($this->debug) {
2933
-                echo 'BOOLEAN(FALSE) PARSED' . "\n";
2934
-            }
2935
-            $substr = 'false';
2936
-            $type   = self::T_BOOL;
2937
-        } elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2938
-            if ($this->debug) {
2939
-                echo 'BOOLEAN(TRUE) PARSED' . "\n";
2940
-            }
2941
-            $substr = 'true';
2942
-            $type   = self::T_BOOL;
2943
-        } elseif ($substr === 'null' || $substr === 'NULL') {
2944
-            if ($this->debug) {
2945
-                echo 'NULL PARSED' . "\n";
2946
-            }
2947
-            $substr = 'null';
2948
-            $type   = self::T_NULL;
2949
-        } elseif (is_numeric($substr)) {
2950
-            $substr = (float)$substr;
2951
-            if ((int)$substr == $substr) {
2952
-                $substr = (int)$substr;
2953
-            }
2954
-            $type = self::T_NUMERIC;
2955
-            if ($this->debug) {
2956
-                echo 'NUMBER (' . $substr . ') PARSED' . "\n";
2957
-            }
2958
-        } elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2959
-            if ($this->debug) {
2960
-                echo 'SIMPLE MATH PARSED . "\n"';
2961
-            }
2962
-            $type   = self::T_MATH;
2963
-            $substr = '(' . $substr . ')';
2964
-        } elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2965
-            if ($this->debug) {
2966
-                echo 'BREAKCHAR (' . $substr . ') PARSED' . "\n";
2967
-            }
2968
-            $type = self::T_BREAKCHAR;
2969
-            //$substr = '"'.$substr.'"';
2970
-        } else {
2971
-            $substr = $this->replaceStringVars('\'' . str_replace('\'', '\\\'', $substr) . '\'', '\'', $curBlock);
2972
-            $type   = self::T_UNQUOTED_STRING;
2973
-            if ($this->debug) {
2974
-                echo 'BLABBER (' . $substr . ') CASTED AS STRING' . "\n";
2975
-            }
2976
-        }
2977
-
2978
-        if (is_array($parsingParams)) {
2979
-            $parsingParams[] = array($substr, $src, $type);
2980
-
2981
-            return $parsingParams;
2982
-        } elseif ($curBlock === 'namedparam') {
2983
-            return array($substr, $src, $type);
2984
-        } elseif ($curBlock === 'expression') {
2985
-            return $substr;
2986
-        } else {
2987
-            throw new Exception('Something went wrong');
2988
-        }
2989
-    }
2990
-
2991
-    /**
2992
-     * Replaces variables within a parsed string.
2993
-     *
2994
-     * @param string $string   the parsed string
2995
-     * @param string $first    the first character parsed in the string, which is the string delimiter (' or ")
2996
-     * @param string $curBlock the current parser-block being processed
2997
-     *
2998
-     * @return string the original string with variables replaced
2999
-     */
3000
-    protected function replaceStringVars($string, $first, $curBlock = '')
3001
-    {
3002
-        $pos = 0;
3003
-        if ($this->debug) {
3004
-            echo 'STRING VAR REPLACEMENT : ' . $string . "\n";
3005
-        }
3006
-        // replace vars
3007
-        while (($pos = strpos($string, '$', $pos)) !== false) {
3008
-            $prev = substr($string, $pos - 1, 1);
3009
-            if ($prev === '\\') {
3010
-                ++ $pos;
3011
-                continue;
3012
-            }
3013
-
3014
-            $var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3015
-            $len = $var[0];
3016
-            $var = $this->parse(str_replace('\\' . $first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3017
-
3018
-            if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
3019
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos - 1, $len + 2);
3020
-            } else {
3021
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos, $len);
3022
-            }
3023
-            $pos += strlen($var[1]) + 2;
3024
-            if ($this->debug) {
3025
-                echo 'STRING VAR REPLACEMENT DONE : ' . $string . "\n";
3026
-            }
3027
-        }
3028
-
3029
-        // handle modifiers
3030
-        // TODO Obsolete?
3031
-        $string = preg_replace_callback(
3032
-            '#("|\')\.(.+?)\.\1((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\4|:[^`]*))*))+)#i', array(
3033
-            $this,
3034
-            'replaceModifiers'
3035
-            ), $string
3036
-        );
3037
-
3038
-        // replace escaped dollar operators by unescaped ones if required
3039
-        if ($first === "'") {
3040
-            $string = str_replace('\\$', '$', $string);
3041
-        }
3042
-
3043
-        return $string;
3044
-    }
3045
-
3046
-    /**
3047
-     * Replaces the modifiers applied to a string or a variable.
3048
-     *
3049
-     * @param array  $m        the regex matches that must be array(1=>"double or single quotes enclosing a string,
3050
-     *                         when applicable", 2=>"the string or var", 3=>"the modifiers matched")
3051
-     * @param string $curBlock the current parser-block being processed
3052
-     * @param null   $pointer
3053
-     *
3054
-     * @return string the input enclosed with various function calls according to the modifiers found
3055
-     * @throws CompilationException
3056
-     * @throws Exception
3057
-     */
3058
-    protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
3059
-    {
3060
-        if ($this->debug) {
3061
-            echo 'PARSING MODIFIERS : ' . $m[3] . "\n";
3062
-        }
3063
-
3064
-        if ($pointer !== null) {
3065
-            $pointer += strlen($m[3]);
3066
-        }
3067
-        // remove first pipe
3068
-        $cmdstrsrc = substr($m[3], 1);
3069
-        // remove last quote if present
3070
-        if (substr($cmdstrsrc, - 1, 1) === $m[1]) {
3071
-            $cmdstrsrc = substr($cmdstrsrc, 0, - 1);
3072
-            $add       = $m[1];
3073
-        }
3074
-
3075
-        $output = $m[2];
3076
-
3077
-        $continue = true;
3078
-        while (strlen($cmdstrsrc) > 0 && $continue) {
3079
-            if ($cmdstrsrc[0] === '|') {
3080
-                $cmdstrsrc = substr($cmdstrsrc, 1);
3081
-                continue;
3082
-            }
3083
-            if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
3084
-                if ($this->debug) {
3085
-                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND' . "\n";
3086
-                }
3087
-                $continue = false;
3088
-                if ($pointer !== null) {
3089
-                    $pointer -= strlen($cmdstrsrc);
3090
-                }
3091
-                break;
3092
-            }
3093
-            $cmdstr   = $cmdstrsrc;
3094
-            $paramsep = ':';
3095
-            if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
3096
-                throw new CompilationException($this, 'Invalid modifier name, started with : ' . substr($cmdstr, 0, 10));
3097
-            }
3098
-            $paramspos = !empty($match[2]) ? strlen($match[1]) : false;
3099
-            $func      = $match[1];
3100
-
3101
-            $state = 0;
3102
-            if ($paramspos === false) {
3103
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func));
3104
-                $params    = array();
3105
-                if ($this->debug) {
3106
-                    echo 'MODIFIER (' . $func . ') CALLED WITH NO PARAMS' . "\n";
3107
-                }
3108
-            } else {
3109
-                $paramstr = substr($cmdstr, $paramspos + 1);
3110
-                if (substr($paramstr, - 1, 1) === $paramsep) {
3111
-                    $paramstr = substr($paramstr, 0, - 1);
3112
-                }
3113
-
3114
-                $ptr    = 0;
3115
-                $params = array();
3116
-                while ($ptr < strlen($paramstr)) {
3117
-                    if ($this->debug) {
3118
-                        echo 'MODIFIER (' . $func . ') START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
3119
-                    }
3120
-                    if ($this->debug) {
3121
-                        echo $paramstr . '--' . $ptr . '--' . strlen($paramstr) . '--modifier' . "\n";
3122
-                    }
3123
-                    $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
3124
-                    if ($this->debug) {
3125
-                        echo 'PARAM PARSED, POINTER AT ' . $ptr . "\n";
3126
-                    }
3127
-
3128
-                    if ($ptr >= strlen($paramstr)) {
3129
-                        if ($this->debug) {
3130
-                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED' . "\n";
3131
-                        }
3132
-                        break;
3133
-                    }
3134
-
3135
-                    if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
3136
-                        if ($this->debug) {
3137
-                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT ' . $ptr . "\n";
3138
-                        }
3139
-                        if ($paramstr[$ptr] !== '|') {
3140
-                            $continue = false;
3141
-                            if ($pointer !== null) {
3142
-                                $pointer -= strlen($paramstr) - $ptr;
3143
-                            }
3144
-                        }
3145
-                        ++ $ptr;
3146
-                        break;
3147
-                    }
3148
-                    if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
3149
-                        ++ $ptr;
3150
-                    }
3151
-                }
3152
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
3153
-                foreach ($params as $k => $p) {
3154
-                    if (is_array($p) && is_array($p[1])) {
3155
-                        $state |= 2;
3156
-                    } else {
3157
-                        if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m)) {
3158
-                            $params[$k] = array($m[2], array('true', 'true'));
3159
-                        } else {
3160
-                            if ($state & 2) {
3161
-                                throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
3162
-                            }
3163
-                            $state |= 1;
3164
-                        }
3165
-                    }
3166
-                }
3167
-            }
3168
-
3169
-            // check if we must use array_map with this plugin or not
3170
-            $mapped = false;
3171
-            if (substr($func, 0, 1) === '@') {
3172
-                $func   = substr($func, 1);
3173
-                $mapped = true;
3174
-            }
3175
-
3176
-            $pluginType = $this->getPluginType($func);
3177
-
3178
-            if ($state & 2) {
3179
-                array_unshift($params, array('value', is_array($output) ? $output : array($output, $output)));
3180
-            } else {
3181
-                array_unshift($params, is_array($output) ? $output : array($output, $output));
3182
-            }
3183
-
3184
-            if ($pluginType & Core::NATIVE_PLUGIN) {
3185
-                $params = $this->mapParams($params, null, $state);
3186
-
3187
-                $params = $params['*'][0];
3188
-
3189
-                $params = self::implode_r($params);
3190
-
3191
-                if ($mapped) {
3192
-                    $output = '$this->arrayMap(\'' . $func . '\', array(' . $params . '))';
3193
-                } else {
3194
-                    $output = $func . '(' . $params . ')';
3195
-                }
3196
-            } elseif ($pluginType & Core::PROXY_PLUGIN) {
3197
-                $params = $this->mapParams($params, $this->getCore()->getPluginProxy()->getCallback($func), $state);
3198
-                foreach ($params as &$p) {
3199
-                    $p = $p[0];
3200
-                }
3201
-                $output = call_user_func(array($this->getCore()->getPluginProxy(), 'getCode'), $func, $params);
3202
-            } elseif ($pluginType & Core::SMARTY_MODIFIER) {
3203
-                $params = $this->mapParams($params, null, $state);
3204
-                $params = $params['*'][0];
3205
-
3206
-                $params = self::implode_r($params);
3207
-
3208
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
3209
-                    $callback = $this->customPlugins[$func]['callback'];
3210
-                    if (is_array($callback)) {
3211
-                        if (is_object($callback[0])) {
3212
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(' . $params . '))';
3213
-                        } else {
3214
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3215
-                        }
3216
-                    } elseif ($mapped) {
3217
-                        $output = '$this->arrayMap(\'' . $callback . '\', array(' . $params . '))';
3218
-                    } else {
3219
-                        $output = $callback . '(' . $params . ')';
3220
-                    }
3221
-                } elseif ($mapped) {
3222
-                    $output = '$this->arrayMap(\'smarty_modifier_' . $func . '\', array(' . $params . '))';
3223
-                } else {
3224
-                    $output = 'smarty_modifier_' . $func . '(' . $params . ')';
3225
-                }
3226
-            } else {
3227
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
3228
-                    $pluginName = $callback = $this->customPlugins[$func]['callback'];
3229
-                    if (($pluginType & Core::CLASS_PLUGIN) && !is_array($callback)) {
3230
-                        $pluginName = $this->customPlugins[$func]['callback'];
3231
-                        $callback   = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3232
-                    }
3233
-                } else {
3234
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false || function_exists('Plugin' .
3235
-                            Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3236
-                        !== false) {
3237
-                        $pluginName = 'Plugin' . Core::toCamelCase($func);
3238
-                    } else {
3239
-                        $pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func);
3240
-                    }
3241
-                    if ($pluginType & Core::CLASS_PLUGIN) {
3242
-                        $callback = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3243
-                    } else {
3244
-                        $callback = $pluginName . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3245
-                    }
3246
-                }
3247
-                $params = $this->mapParams($params, $callback, $state);
3248
-
3249
-                foreach ($params as &$p) {
3250
-                    $p = $p[0];
3251
-                }
3252
-
3253
-                // Only for PHP function, who is not a PHP class
3254
-                if ($pluginType & Core::FUNC_PLUGIN && !($pluginType & Core::CLASS_PLUGIN)) {
3255
-                    if ($pluginType & Core::COMPILABLE_PLUGIN) {
3256
-                        if ($mapped) {
3257
-                            throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3258
-                        }
3259
-                        if ($pluginType & Core::CUSTOM_PLUGIN) {
3260
-                            $funcCompiler = $this->customPlugins[$func]['callback'];
3261
-                        } else {
3262
-                            if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
3263
-                                $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
3264
-                            } else {
3265
-                                $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
3266
-                                    'Compile';
3267
-                            }
3268
-                        }
3269
-                        array_unshift($params, $this);
3270
-                        $output = call_user_func_array($funcCompiler, $params);
3271
-                    } else {
3272
-                        array_unshift($params, '$this');
3273
-
3274
-                        $params = self::implode_r($params);
3275
-                        if ($mapped) {
3276
-                            $output = '$this->arrayMap(\'' . $pluginName . '\', array(' . $params . '))';
3277
-                        } else {
3278
-                            $output = $pluginName . '(' . $params . ')';
3279
-                        }
3280
-                    }
3281
-                } else {
3282
-                    if ($pluginType & Core::COMPILABLE_PLUGIN) {
3283
-                        if ($mapped) {
3284
-                            throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3285
-                        }
3286
-                        if ($pluginType & Core::CUSTOM_PLUGIN) {
3287
-                            $callback = $this->customPlugins[$func]['callback'];
3288
-                            if (!is_array($callback)) {
3289
-                                if (!method_exists($callback, 'compile')) {
3290
-                                    throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3291
-                                }
3292
-                                if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3293
-                                    $funcCompiler = array($callback, 'compile');
3294
-                                } else {
3295
-                                    $funcCompiler = array(new $callback(), 'compile');
3296
-                                }
3297
-                            } else {
3298
-                                $funcCompiler = $callback;
3299
-                            }
3300
-                        } else {
3301
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3302
-                                $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
3303
-                            } else {
3304
-                                $funcCompiler = array(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func), 'compile');
3305
-                            }
3306
-                            array_unshift($params, $this);
3307
-                        }
3308
-                        $output = call_user_func_array($funcCompiler, $params);
3309
-                    } else {
3310
-                        $params = self::implode_r($params);
3311
-
3312
-                        if ($pluginType & Core::CUSTOM_PLUGIN) {
3313
-                            if (is_object($callback[0])) {
3314
-                                if (is_array($this->getCore()->getCustomPlugin($func))) {
3315
-                                    $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3316
-                                } else {
3317
-                                    $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(' . $params . '))';
3318
-                                }
3319
-                            } else {
3320
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3321
-                            }
3322
-                        } elseif ($mapped) {
3323
-                            $output = '$this->arrayMap(array($this->getObjectPlugin(\''.
3324
-                                Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '\'),
2100
+					} else {
2101
+						$output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
2102
+					}
2103
+				}
2104
+			}
2105
+		} // Function plugin only (cannot be a class)
2106
+		elseif ($pluginType & Core::FUNC_PLUGIN) {
2107
+			if ($pluginType & Core::COMPILABLE_PLUGIN) {
2108
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2109
+					$funcCompiler = $this->customPlugins[$func]['callback'];
2110
+				} else {
2111
+					// Custom plugin
2112
+					if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2113
+						$funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
2114
+					} // Builtin helper plugin
2115
+					elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2116
+						$funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2117
+							'Compile';
2118
+					} // Builtin function plugin
2119
+					else {
2120
+						$funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
2121
+							'Compile';
2122
+					}
2123
+				}
2124
+				array_unshift($params, $this);
2125
+				// @TODO: Is it a real fix ?
2126
+				if ($func === 'tif') {
2127
+					$params[] = $tokens;
2128
+				}
2129
+				$output = call_user_func_array($funcCompiler, $params);
2130
+			} else {
2131
+				array_unshift($params, '$this');
2132
+				$params = self::implode_r($params);
2133
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2134
+					$callback = $this->customPlugins[$func]['callback'];
2135
+					if ($callback instanceof Closure) {
2136
+						$output = 'call_user_func($this->getCustomPlugin(\'' . $func . '\'), ' . $params . ')';
2137
+					} else {
2138
+						$output = 'call_user_func(\'' . $callback . '\', ' . $params . ')';
2139
+					}
2140
+				} else {
2141
+					// Custom plugin
2142
+					if (function_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2143
+						$output = 'Plugin' . Core::toCamelCase($func) . '(' . $params .
2144
+							')';
2145
+					} // Builtin helper plugin
2146
+					elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !==
2147
+						false) {
2148
+						$output = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . '(' .
2149
+							$params . ')';
2150
+					} // Builtin function plugin
2151
+					else {
2152
+						$output = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '(' .
2153
+							$params . ')';
2154
+					}
2155
+				}
2156
+			}
2157
+		} // Proxy plugin
2158
+		elseif ($pluginType & Core::PROXY_PLUGIN) {
2159
+			$output = call_user_func(array($this->getCore()->getPluginProxy(), 'getCode'), $func, $params);
2160
+		} // Smarty function (@deprecated)
2161
+		elseif ($pluginType & Core::SMARTY_FUNCTION) {
2162
+			$params = '';
2163
+			if (isset($params['*'])) {
2164
+				$params = self::implode_r($params['*'], true);
2165
+			}
2166
+
2167
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
2168
+				$callback = $this->customPlugins[$func]['callback'];
2169
+				if (is_array($callback)) {
2170
+					if (is_object($callback[0])) {
2171
+						$output = 'call_user_func_array(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2172
+					} else {
2173
+						$output = 'call_user_func_array(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2174
+					}
2175
+				} else {
2176
+					$output = $callback . '(array(' . $params . '), $this)';
2177
+				}
2178
+			} else {
2179
+				$output = 'smarty_function_' . $func . '(array(' . $params . '), $this)';
2180
+			}
2181
+		} // Template plugin
2182
+		elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
2183
+			array_unshift($params, '$this');
2184
+			$params                                 = self::implode_r($params);
2185
+			$output                                 = 'Plugin' . Core::toCamelCase($func) .
2186
+				$this->templatePlugins[$func]['uuid'] . '(' . $params . ')';
2187
+			$this->templatePlugins[$func]['called'] = true;
2188
+		}
2189
+
2190
+		if (is_array($parsingParams)) {
2191
+			$parsingParams[] = array($output, $output);
2192
+
2193
+			return $parsingParams;
2194
+		} elseif ($curBlock === 'namedparam') {
2195
+			return array($output, $output);
2196
+		}
2197
+
2198
+		return $output;
2199
+	}
2200
+
2201
+	/**
2202
+	 * Parses a string.
2203
+	 *
2204
+	 * @param string $in            the string within which we must parse something
2205
+	 * @param int    $from          the starting offset of the parsed area
2206
+	 * @param int    $to            the ending offset of the parsed area
2207
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2208
+	 *                              default
2209
+	 * @param string $curBlock      the current parser-block being processed
2210
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2211
+	 *                              or null by default
2212
+	 *
2213
+	 * @return string parsed values
2214
+	 * @throws CompilationException
2215
+	 */
2216
+	protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2217
+	{
2218
+		$substr = substr($in, $from, $to - $from);
2219
+		$first  = $substr[0];
2220
+
2221
+		if ($this->debug) {
2222
+			echo 'STRING FOUND (in ' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . ')' . "\n";
2223
+		}
2224
+		$strend = false;
2225
+		$o      = $from + 1;
2226
+		while ($strend === false) {
2227
+			$strend = strpos($in, $first, $o);
2228
+			if ($strend === false) {
2229
+				throw new CompilationException($this, 'Unfinished string, started with ' . substr($in, $from, $to - $from));
2230
+			}
2231
+			if (substr($in, $strend - 1, 1) === '\\') {
2232
+				$o      = $strend + 1;
2233
+				$strend = false;
2234
+			}
2235
+		}
2236
+		if ($this->debug) {
2237
+			echo 'STRING DELIMITED: ' . substr($in, $from, $strend + 1 - $from) . "\n";
2238
+		}
2239
+
2240
+		$srcOutput = substr($in, $from, $strend + 1 - $from);
2241
+
2242
+		if ($pointer !== null) {
2243
+			$pointer += strlen($srcOutput);
2244
+		}
2245
+
2246
+		$output = $this->replaceStringVars($srcOutput, $first);
2247
+
2248
+		// handle modifiers
2249
+		if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2250
+			$modstr = $match[1];
2251
+
2252
+			if ($curBlock === 'root' && substr($modstr, - 1) === '}') {
2253
+				$modstr = substr($modstr, 0, - 1);
2254
+			}
2255
+			$modstr = str_replace('\\' . $first, $first, $modstr);
2256
+			$ptr    = 0;
2257
+			$output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2258
+
2259
+			$strend += $ptr;
2260
+			if ($pointer !== null) {
2261
+				$pointer += $ptr;
2262
+			}
2263
+			$srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2264
+		}
2265
+
2266
+		if (is_array($parsingParams)) {
2267
+			$parsingParams[] = array($output, substr($srcOutput, 1, - 1));
2268
+
2269
+			return $parsingParams;
2270
+		} elseif ($curBlock === 'namedparam') {
2271
+			return array($output, substr($srcOutput, 1, - 1));
2272
+		}
2273
+
2274
+		return $output;
2275
+	}
2276
+
2277
+	/**
2278
+	 * Parses a constant.
2279
+	 *
2280
+	 * @param string $in            the string within which we must parse something
2281
+	 * @param int    $from          the starting offset of the parsed area
2282
+	 * @param int    $to            the ending offset of the parsed area
2283
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2284
+	 *                              default
2285
+	 * @param string $curBlock      the current parser-block being processed
2286
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2287
+	 *                              or null by default
2288
+	 *
2289
+	 * @return string parsed values
2290
+	 * @throws CompilationException
2291
+	 */
2292
+	protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2293
+	{
2294
+		$substr = substr($in, $from, $to - $from);
2295
+
2296
+		if ($this->debug) {
2297
+			echo 'CONST FOUND : ' . $substr . "\n";
2298
+		}
2299
+
2300
+		if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
2301
+			throw new CompilationException($this, 'Invalid constant');
2302
+		}
2303
+
2304
+		if ($pointer !== null) {
2305
+			$pointer += strlen($m[0]);
2306
+		}
2307
+
2308
+		$output = $this->parseConstKey($m[1], $curBlock);
2309
+
2310
+		if (is_array($parsingParams)) {
2311
+			$parsingParams[] = array($output, $m[1]);
2312
+
2313
+			return $parsingParams;
2314
+		} elseif ($curBlock === 'namedparam') {
2315
+			return array($output, $m[1]);
2316
+		}
2317
+
2318
+		return $output;
2319
+	}
2320
+
2321
+	/**
2322
+	 * Parses a constant.
2323
+	 *
2324
+	 * @param string $key      the constant to parse
2325
+	 * @param string $curBlock the current parser-block being processed
2326
+	 *
2327
+	 * @return string parsed constant
2328
+	 */
2329
+	protected function parseConstKey($key, $curBlock)
2330
+	{
2331
+		$key = str_replace('\\\\', '\\', $key);
2332
+
2333
+		if ($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === SecurityPolicy::CONST_DISALLOW) {
2334
+			return 'null';
2335
+		}
2336
+
2337
+		if ($curBlock !== 'root') {
2338
+			return '(defined("' . $key . '") ? ' . $key . ' : null)';
2339
+		}
2340
+
2341
+		return $key;
2342
+	}
2343
+
2344
+	/**
2345
+	 * Parses a variable.
2346
+	 *
2347
+	 * @param string $in            the string within which we must parse something
2348
+	 * @param int    $from          the starting offset of the parsed area
2349
+	 * @param int    $to            the ending offset of the parsed area
2350
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2351
+	 *                              default
2352
+	 * @param string $curBlock      the current parser-block being processed
2353
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2354
+	 *                              or null by default
2355
+	 *
2356
+	 * @return string parsed values
2357
+	 * @throws CompilationException
2358
+	 */
2359
+	protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2360
+	{
2361
+		$substr = substr($in, $from, $to - $from);
2362
+
2363
+		// var key
2364
+		$varRegex = '(\\$?\\.?[a-z0-9\\\\_:]*(?:(?:(?:\\.|->)(?:[a-z0-9\\\\_:]+|(?R))|\\[(?:[a-z0-9\\\\_:]+|(?R)|(["\'])[^\\2]*?\\2)\\]))*)';
2365
+		// method call
2366
+		$methodCall = ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()');
2367
+		// simple math expressions
2368
+		$simpleMathExpressions = ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+\/*%=-])(?:(?<!=)=?-?[$%][a-z0-9\\\\.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9\.,]*|[+-]))*)' : '()');
2369
+		// modifiers
2370
+		$modifiers = $curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9\\\\_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())';
2371
+
2372
+		$regex = '#';
2373
+		$regex .= $varRegex;
2374
+		$regex .= $methodCall;
2375
+		$regex .= $simpleMathExpressions;
2376
+		$regex .= $modifiers;
2377
+		$regex .= '#i';
2378
+
2379
+		if (preg_match($regex, $substr, $match)) {
2380
+			$key = substr($match[1], 1);
2381
+
2382
+			$matchedLength = strlen($match[0]);
2383
+			$hasModifiers  = !empty($match[5]);
2384
+			$hasExpression = !empty($match[4]);
2385
+			$hasMethodCall = !empty($match[3]);
2386
+
2387
+			if (substr($key, - 1) == '.') {
2388
+				$key = substr($key, 0, - 1);
2389
+				-- $matchedLength;
2390
+			}
2391
+
2392
+			if ($hasMethodCall) {
2393
+				$matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2394
+				$key        = substr($match[1], 1, strrpos($match[1], '->') - 1);
2395
+				$methodCall = substr($match[1], strrpos($match[1], '->')) . $match[3];
2396
+			}
2397
+
2398
+			if ($hasModifiers) {
2399
+				$matchedLength -= strlen($match[5]);
2400
+			}
2401
+
2402
+			if ($pointer !== null) {
2403
+				$pointer += $matchedLength;
2404
+			}
2405
+
2406
+			// replace useless brackets by dot accessed vars and strip enclosing quotes if present
2407
+			$key = preg_replace('#\[(["\']?)([^$%\[.>-]+)\1\]#', '.$2', $key);
2408
+
2409
+			if ($this->debug) {
2410
+				if ($hasMethodCall) {
2411
+					echo 'METHOD CALL FOUND : $' . $key . substr($methodCall, 0, 30) . "\n";
2412
+				} else {
2413
+					echo 'VAR FOUND : $' . $key . "\n";
2414
+				}
2415
+			}
2416
+
2417
+			$key = str_replace('"', '\\"', $key);
2418
+
2419
+			$cnt = substr_count($key, '$');
2420
+			if ($cnt > 0) {
2421
+				$uid           = 0;
2422
+				$parsed        = array($uid => '');
2423
+				$current       = &$parsed;
2424
+				$curTxt        = &$parsed[$uid ++];
2425
+				$tree          = array();
2426
+				$chars         = str_split($key, 1);
2427
+				$inSplittedVar = false;
2428
+				$bracketCount  = 0;
2429
+
2430
+				while (($char = array_shift($chars)) !== null) {
2431
+					if ($char === '[') {
2432
+						if (count($tree) > 0) {
2433
+							++ $bracketCount;
2434
+						} else {
2435
+							$tree[]        = &$current;
2436
+							$current[$uid] = array($uid + 1 => '');
2437
+							$current       = &$current[$uid ++];
2438
+							$curTxt        = &$current[$uid ++];
2439
+							continue;
2440
+						}
2441
+					} elseif ($char === ']') {
2442
+						if ($bracketCount > 0) {
2443
+							-- $bracketCount;
2444
+						} else {
2445
+							$current = &$tree[count($tree) - 1];
2446
+							array_pop($tree);
2447
+							if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2448
+								$current[$uid] = '';
2449
+								$curTxt        = &$current[$uid ++];
2450
+							}
2451
+							continue;
2452
+						}
2453
+					} elseif ($char === '$') {
2454
+						if (count($tree) == 0) {
2455
+							$curTxt        = &$current[$uid ++];
2456
+							$inSplittedVar = true;
2457
+						}
2458
+					} elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2459
+						$curTxt        = &$current[$uid ++];
2460
+						$inSplittedVar = false;
2461
+					}
2462
+
2463
+					$curTxt .= $char;
2464
+				}
2465
+				unset($uid, $current, $curTxt, $tree, $chars);
2466
+
2467
+				if ($this->debug) {
2468
+					echo 'RECURSIVE VAR REPLACEMENT : ' . $key . "\n";
2469
+				}
2470
+
2471
+				$key = $this->flattenVarTree($parsed);
2472
+
2473
+				if ($this->debug) {
2474
+					echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2475
+				}
2476
+
2477
+				$output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("' . $key . '")');
2478
+			} else {
2479
+				$output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2480
+			}
2481
+
2482
+
2483
+			// methods
2484
+			if ($hasMethodCall) {
2485
+				$ptr = 0;
2486
+
2487
+				$output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
2488
+
2489
+				if ($pointer !== null) {
2490
+					$pointer += $ptr;
2491
+				}
2492
+				$matchedLength += $ptr;
2493
+			}
2494
+
2495
+			if ($hasExpression) {
2496
+				// expressions
2497
+				preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9\\\\.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[4], $expMatch);
2498
+				foreach ($expMatch[1] as $k => $operator) {
2499
+					if (substr($expMatch[2][$k], 0, 1) === '=') {
2500
+						$assign = true;
2501
+						if ($operator === '=') {
2502
+							throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, can not use "==" in expressions');
2503
+						}
2504
+						if ($curBlock !== 'root') {
2505
+							throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2506
+						}
2507
+						$operator .= '=';
2508
+						$expMatch[2][$k] = substr($expMatch[2][$k], 1);
2509
+					}
2510
+
2511
+					if (substr($expMatch[2][$k], 0, 1) === '-' && strlen($expMatch[2][$k]) > 1) {
2512
+						$operator .= '-';
2513
+						$expMatch[2][$k] = substr($expMatch[2][$k], 1);
2514
+					}
2515
+					if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2516
+						$output = '(' . $output . $operator . $operator . ')';
2517
+						break;
2518
+					} elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2519
+						$output = '(' . $output . ' ' . $operator . ' ' . $this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2520
+					} elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2521
+						$output = '(' . $output . ' ' . $operator . ' ' . $this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2522
+					} elseif (!empty($expMatch[2][$k])) {
2523
+						$output = '(' . $output . ' ' . $operator . ' ' . str_replace(',', '.', $expMatch[2][$k]) . ')';
2524
+					} else {
2525
+						throw new CompilationException($this, 'Unfinished expression <em>' . $substr . '</em>, missing var or number after math operator');
2526
+					}
2527
+				}
2528
+			}
2529
+
2530
+			if ($this->autoEscape === true && $curBlock !== 'condition') {
2531
+				$output = '(is_string($tmp=' . $output . ') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2532
+			}
2533
+
2534
+			// handle modifiers
2535
+			if ($curBlock !== 'modifier' && $hasModifiers) {
2536
+				$ptr    = 0;
2537
+				$output = $this->replaceModifiers(array(null, null, $output, $match[5]), 'var', $ptr);
2538
+				if ($pointer !== null) {
2539
+					$pointer += $ptr;
2540
+				}
2541
+				$matchedLength += $ptr;
2542
+			}
2543
+
2544
+			if (is_array($parsingParams)) {
2545
+				$parsingParams[] = array($output, $key);
2546
+
2547
+				return $parsingParams;
2548
+			} elseif ($curBlock === 'namedparam') {
2549
+				return array($output, $key);
2550
+			} elseif ($curBlock === 'string' || $curBlock === 'delimited_string') {
2551
+				return array($matchedLength, $output);
2552
+			} elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2553
+				return $output;
2554
+			} elseif (isset($assign)) {
2555
+				return self::PHP_OPEN . $output . ';' . self::PHP_CLOSE;
2556
+			}
2557
+
2558
+			return $output;
2559
+		} else {
2560
+			if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2561
+				return array(0, '');
2562
+			}
2563
+			throw new CompilationException($this, 'Invalid variable name <em>' . $substr . '</em>');
2564
+		}
2565
+	}
2566
+
2567
+	/**
2568
+	 * Parses any number of chained method calls/property reads.
2569
+	 *
2570
+	 * @param string $output     the variable or whatever upon which the method are called
2571
+	 * @param string $methodCall method call source, starting at "->"
2572
+	 * @param string $curBlock   the current parser-block being processed
2573
+	 * @param int    $pointer    a reference to a pointer that will be increased by the amount of characters parsed
2574
+	 *
2575
+	 * @return string parsed call(s)/read(s)
2576
+	 */
2577
+	protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
2578
+	{
2579
+		$ptr = 0;
2580
+		$len = strlen($methodCall);
2581
+
2582
+		while ($ptr < $len) {
2583
+			if (strpos($methodCall, '->', $ptr) === $ptr) {
2584
+				$ptr += 2;
2585
+			}
2586
+
2587
+			if (in_array(
2588
+				$methodCall[$ptr], array(
2589
+					';',
2590
+					',',
2591
+					'/',
2592
+					' ',
2593
+					"\t",
2594
+					"\r",
2595
+					"\n",
2596
+					')',
2597
+					'+',
2598
+					'*',
2599
+					'%',
2600
+					'=',
2601
+					'-',
2602
+					'|'
2603
+				)
2604
+			) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd
2605
+			) {
2606
+				// break char found
2607
+				break;
2608
+			}
2609
+
2610
+			if (!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
2611
+				break;
2612
+			}
2613
+
2614
+			if (empty($methMatch[2])) {
2615
+				// property
2616
+				if ($curBlock === 'root') {
2617
+					$output .= '->' . $methMatch[1];
2618
+				} else {
2619
+					$output = '(($tmp = ' . $output . ') ? $tmp->' . $methMatch[1] . ' : null)';
2620
+				}
2621
+				$ptr += strlen($methMatch[1]);
2622
+			} else {
2623
+				// method
2624
+				if (substr($methMatch[2], 0, 2) === '()') {
2625
+					$parsedCall = $methMatch[1] . '()';
2626
+					$ptr += strlen($methMatch[1]) + 2;
2627
+				} else {
2628
+					$parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2629
+				}
2630
+				if ($this->securityPolicy !== null) {
2631
+					$argPos = strpos($parsedCall, '(');
2632
+					$method = strtolower(substr($parsedCall, 0, $argPos));
2633
+					$args   = substr($parsedCall, $argPos);
2634
+					if ($curBlock === 'root') {
2635
+						$output = '$this->getSecurityPolicy()->callMethod($this, ' . $output . ', ' . var_export($method, true) . ', array' . $args . ')';
2636
+					} else {
2637
+						$output = '(($tmp = ' . $output . ') ? $this->getSecurityPolicy()->callMethod($this, $tmp, ' . var_export($method, true) . ', array' . $args . ') : null)';
2638
+					}
2639
+				} else {
2640
+					if ($curBlock === 'root') {
2641
+						$output .= '->' . $parsedCall;
2642
+					} else {
2643
+						$output = '(($tmp = ' . $output . ') ? $tmp->' . $parsedCall . ' : null)';
2644
+					}
2645
+				}
2646
+			}
2647
+		}
2648
+
2649
+		$pointer += $ptr;
2650
+
2651
+		return $output;
2652
+	}
2653
+
2654
+	/**
2655
+	 * Parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save
2656
+	 * runtime processing time.
2657
+	 *
2658
+	 * @param string $key      the variable to parse
2659
+	 * @param string $curBlock the current parser-block being processed
2660
+	 *
2661
+	 * @return string parsed variable
2662
+	 */
2663
+	protected function parseVarKey($key, $curBlock)
2664
+	{
2665
+		if ($key === '') {
2666
+			return '$this->scope';
2667
+		}
2668
+		if (substr($key, 0, 1) === '.') {
2669
+			$key = 'dwoo' . $key;
2670
+		}
2671
+		if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2672
+			$global = strtoupper($m[1]);
2673
+			if ($global === 'COOKIES') {
2674
+				$global = 'COOKIE';
2675
+			}
2676
+			$key = '$_' . $global;
2677
+			foreach (explode('.', ltrim($m[2], '.')) as $part) {
2678
+				$key .= '[' . var_export($part, true) . ']';
2679
+			}
2680
+			if ($curBlock === 'root') {
2681
+				$output = $key;
2682
+			} else {
2683
+				$output = '(isset(' . $key . ')?' . $key . ':null)';
2684
+			}
2685
+		} elseif (preg_match('#dwoo\\.const\\.([a-z0-9\\\\_:]+)#i', $key, $m)) {
2686
+			return $this->parseConstKey($m[1], $curBlock);
2687
+		} elseif ($this->scope !== null) {
2688
+			if (strstr($key, '.') === false && strstr($key, '[') === false && strstr($key, '->') === false) {
2689
+				if ($key === 'dwoo') {
2690
+					$output = '$this->globals';
2691
+				} elseif ($key === '_root' || $key === '__') {
2692
+					$output = '$this->data';
2693
+				} elseif ($key === '_parent' || $key === '_') {
2694
+					$output = '$this->readParentVar(1)';
2695
+				} elseif ($key === '_key') {
2696
+					$output = '$tmp_key';
2697
+				} else {
2698
+					if ($curBlock === 'root') {
2699
+						$output = '$this->scope["' . $key . '"]';
2700
+					} else {
2701
+						$output = '(isset($this->scope["' . $key . '"]) ? $this->scope["' . $key . '"] : null)';
2702
+					}
2703
+				}
2704
+			} else {
2705
+				preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+|(\\\?[\'"])[^\3]*?\3)\]?#i', $key, $m);
2706
+
2707
+				$i = $m[2][0];
2708
+				if ($i === '_parent' || $i === '_') {
2709
+					$parentCnt = 0;
2710
+
2711
+					while (true) {
2712
+						++ $parentCnt;
2713
+						array_shift($m[2]);
2714
+						array_shift($m[1]);
2715
+						if (current($m[2]) === '_parent') {
2716
+							continue;
2717
+						}
2718
+						break;
2719
+					}
2720
+
2721
+					$output = '$this->readParentVar(' . $parentCnt . ')';
2722
+				} else {
2723
+					if ($i === 'dwoo') {
2724
+						$output = '$this->globals';
2725
+						array_shift($m[2]);
2726
+						array_shift($m[1]);
2727
+					} elseif ($i === '_root' || $i === '__') {
2728
+						// $output = '$this->data';
2729
+						$output = '$this->getData()';
2730
+						array_shift($m[2]);
2731
+						array_shift($m[1]);
2732
+					} elseif ($i === '_key') {
2733
+						$output = '$tmp_key';
2734
+					} else {
2735
+						$output = '$this->scope';
2736
+					}
2737
+
2738
+					while (count($m[1]) && $m[1][0] !== '->') {
2739
+						$m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2740
+						if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2741
+							$output .= '[' . $m[2][0] . ']';
2742
+						} else {
2743
+							$output .= '["' . $m[2][0] . '"]';
2744
+						}
2745
+						array_shift($m[2]);
2746
+						array_shift($m[1]);
2747
+					}
2748
+
2749
+					if ($curBlock !== 'root') {
2750
+						$output = '(isset(' . $output . ') ? ' . $output . ':null)';
2751
+					}
2752
+				}
2753
+
2754
+				if (count($m[2])) {
2755
+					unset($m[0]);
2756
+					$output = '$this->readVarInto(' . str_replace("\n", '', var_export($m, true)) . ', ' . $output . ', ' . ($curBlock == 'root' ? 'false' : 'true') . ')';
2757
+				}
2758
+			}
2759
+		} else {
2760
+			preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2761
+			unset($m[0]);
2762
+			$output = '$this->readVar(' . str_replace("\n", '', var_export($m, true)) . ')';
2763
+		}
2764
+
2765
+		return $output;
2766
+	}
2767
+
2768
+	/**
2769
+	 * Flattens a variable tree, this helps in parsing very complex variables such as $var.foo[$foo.bar->baz].baz,
2770
+	 * it computes the contents of the brackets first and works out from there.
2771
+	 *
2772
+	 * @param array $tree     the variable tree parsed by he parseVar() method that must be flattened
2773
+	 * @param bool  $recursed leave that to false by default, it is only for internal use
2774
+	 *
2775
+	 * @return string flattened tree
2776
+	 */
2777
+	protected function flattenVarTree(array $tree, $recursed = false)
2778
+	{
2779
+		$out = $recursed ? '".$this->readVarInto(' : '';
2780
+		foreach ($tree as $bit) {
2781
+			if (is_array($bit)) {
2782
+				$out .= '.' . $this->flattenVarTree($bit, false);
2783
+			} else {
2784
+				$key = str_replace('"', '\\"', $bit);
2785
+
2786
+				if (substr($key, 0, 1) === '$') {
2787
+					$out .= '".' . $this->parseVar($key, 0, strlen($key), false, 'variable') . '."';
2788
+				} else {
2789
+					$cnt = substr_count($key, '$');
2790
+
2791
+					if ($this->debug) {
2792
+						echo 'PARSING SUBVARS IN : ' . $key . "\n";
2793
+					}
2794
+					if ($cnt > 0) {
2795
+						while (-- $cnt >= 0) {
2796
+							if (isset($last)) {
2797
+								$last = strrpos($key, '$', - (strlen($key) - $last + 1));
2798
+							} else {
2799
+								$last = strrpos($key, '$');
2800
+							}
2801
+							preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2802
+
2803
+							$len = strlen($submatch[0]);
2804
+							$key = substr_replace(
2805
+								$key, preg_replace_callback(
2806
+									'#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2807
+										$this,
2808
+										'replaceVarKeyHelper'
2809
+									), substr($key, $last, $len)
2810
+								), $last, $len
2811
+							);
2812
+							if ($this->debug) {
2813
+								echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2814
+							}
2815
+						}
2816
+						unset($last);
2817
+
2818
+						$out .= $key;
2819
+					} else {
2820
+						$out .= $key;
2821
+					}
2822
+				}
2823
+			}
2824
+		}
2825
+		$out .= $recursed ? ', true)."' : '';
2826
+
2827
+		return $out;
2828
+	}
2829
+
2830
+	/**
2831
+	 * Helper function that parses a variable.
2832
+	 *
2833
+	 * @param array $match the matched variable, array(1=>"string match")
2834
+	 *
2835
+	 * @return string parsed variable
2836
+	 */
2837
+	protected function replaceVarKeyHelper($match)
2838
+	{
2839
+		return '".' . $this->parseVar($match[0], 0, strlen($match[0]), false, 'variable') . '."';
2840
+	}
2841
+
2842
+	/**
2843
+	 * Parses various constants, operators or non-quoted strings.
2844
+	 *
2845
+	 * @param string $in            the string within which we must parse something
2846
+	 * @param int    $from          the starting offset of the parsed area
2847
+	 * @param int    $to            the ending offset of the parsed area
2848
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2849
+	 *                              default
2850
+	 * @param string $curBlock      the current parser-block being processed
2851
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2852
+	 *                              or null by default
2853
+	 *
2854
+	 * @return string parsed values
2855
+	 * @throws Exception
2856
+	 */
2857
+	protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2858
+	{
2859
+		$substr = substr($in, $from, $to - $from);
2860
+
2861
+		$end = strlen($substr);
2862
+
2863
+		if ($curBlock === 'condition') {
2864
+			$breakChars = array(
2865
+				'(',
2866
+				')',
2867
+				' ',
2868
+				'||',
2869
+				'&&',
2870
+				'|',
2871
+				'&',
2872
+				'>=',
2873
+				'<=',
2874
+				'===',
2875
+				'==',
2876
+				'=',
2877
+				'!==',
2878
+				'!=',
2879
+				'<<',
2880
+				'<',
2881
+				'>>',
2882
+				'>',
2883
+				'^',
2884
+				'~',
2885
+				',',
2886
+				'+',
2887
+				'-',
2888
+				'*',
2889
+				'/',
2890
+				'%',
2891
+				'!',
2892
+				'?',
2893
+				':',
2894
+				$this->rd,
2895
+				';'
2896
+			);
2897
+		} elseif ($curBlock === 'modifier') {
2898
+			$breakChars = array(' ', ',', ')', ':', '|', "\r", "\n", "\t", ';', $this->rd);
2899
+		} elseif ($curBlock === 'expression') {
2900
+			$breakChars = array('/', '%', '+', '-', '*', ' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2901
+		} else {
2902
+			$breakChars = array(' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2903
+		}
2904
+
2905
+		$breaker = false;
2906
+		foreach ($breakChars as $k => $char) {
2907
+			$test = strpos($substr, $char);
2908
+			if ($test !== false && $test < $end) {
2909
+				$end     = $test;
2910
+				$breaker = $k;
2911
+			}
2912
+		}
2913
+
2914
+		if ($curBlock === 'condition') {
2915
+			if ($end === 0 && $breaker !== false) {
2916
+				$end = strlen($breakChars[$breaker]);
2917
+			}
2918
+		}
2919
+
2920
+		if ($end !== false) {
2921
+			$substr = substr($substr, 0, $end);
2922
+		}
2923
+
2924
+		if ($pointer !== null) {
2925
+			$pointer += strlen($substr);
2926
+		}
2927
+
2928
+		$src    = $substr;
2929
+		$substr = trim($substr);
2930
+
2931
+		if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2932
+			if ($this->debug) {
2933
+				echo 'BOOLEAN(FALSE) PARSED' . "\n";
2934
+			}
2935
+			$substr = 'false';
2936
+			$type   = self::T_BOOL;
2937
+		} elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2938
+			if ($this->debug) {
2939
+				echo 'BOOLEAN(TRUE) PARSED' . "\n";
2940
+			}
2941
+			$substr = 'true';
2942
+			$type   = self::T_BOOL;
2943
+		} elseif ($substr === 'null' || $substr === 'NULL') {
2944
+			if ($this->debug) {
2945
+				echo 'NULL PARSED' . "\n";
2946
+			}
2947
+			$substr = 'null';
2948
+			$type   = self::T_NULL;
2949
+		} elseif (is_numeric($substr)) {
2950
+			$substr = (float)$substr;
2951
+			if ((int)$substr == $substr) {
2952
+				$substr = (int)$substr;
2953
+			}
2954
+			$type = self::T_NUMERIC;
2955
+			if ($this->debug) {
2956
+				echo 'NUMBER (' . $substr . ') PARSED' . "\n";
2957
+			}
2958
+		} elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2959
+			if ($this->debug) {
2960
+				echo 'SIMPLE MATH PARSED . "\n"';
2961
+			}
2962
+			$type   = self::T_MATH;
2963
+			$substr = '(' . $substr . ')';
2964
+		} elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2965
+			if ($this->debug) {
2966
+				echo 'BREAKCHAR (' . $substr . ') PARSED' . "\n";
2967
+			}
2968
+			$type = self::T_BREAKCHAR;
2969
+			//$substr = '"'.$substr.'"';
2970
+		} else {
2971
+			$substr = $this->replaceStringVars('\'' . str_replace('\'', '\\\'', $substr) . '\'', '\'', $curBlock);
2972
+			$type   = self::T_UNQUOTED_STRING;
2973
+			if ($this->debug) {
2974
+				echo 'BLABBER (' . $substr . ') CASTED AS STRING' . "\n";
2975
+			}
2976
+		}
2977
+
2978
+		if (is_array($parsingParams)) {
2979
+			$parsingParams[] = array($substr, $src, $type);
2980
+
2981
+			return $parsingParams;
2982
+		} elseif ($curBlock === 'namedparam') {
2983
+			return array($substr, $src, $type);
2984
+		} elseif ($curBlock === 'expression') {
2985
+			return $substr;
2986
+		} else {
2987
+			throw new Exception('Something went wrong');
2988
+		}
2989
+	}
2990
+
2991
+	/**
2992
+	 * Replaces variables within a parsed string.
2993
+	 *
2994
+	 * @param string $string   the parsed string
2995
+	 * @param string $first    the first character parsed in the string, which is the string delimiter (' or ")
2996
+	 * @param string $curBlock the current parser-block being processed
2997
+	 *
2998
+	 * @return string the original string with variables replaced
2999
+	 */
3000
+	protected function replaceStringVars($string, $first, $curBlock = '')
3001
+	{
3002
+		$pos = 0;
3003
+		if ($this->debug) {
3004
+			echo 'STRING VAR REPLACEMENT : ' . $string . "\n";
3005
+		}
3006
+		// replace vars
3007
+		while (($pos = strpos($string, '$', $pos)) !== false) {
3008
+			$prev = substr($string, $pos - 1, 1);
3009
+			if ($prev === '\\') {
3010
+				++ $pos;
3011
+				continue;
3012
+			}
3013
+
3014
+			$var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3015
+			$len = $var[0];
3016
+			$var = $this->parse(str_replace('\\' . $first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
3017
+
3018
+			if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
3019
+				$string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos - 1, $len + 2);
3020
+			} else {
3021
+				$string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos, $len);
3022
+			}
3023
+			$pos += strlen($var[1]) + 2;
3024
+			if ($this->debug) {
3025
+				echo 'STRING VAR REPLACEMENT DONE : ' . $string . "\n";
3026
+			}
3027
+		}
3028
+
3029
+		// handle modifiers
3030
+		// TODO Obsolete?
3031
+		$string = preg_replace_callback(
3032
+			'#("|\')\.(.+?)\.\1((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\4|:[^`]*))*))+)#i', array(
3033
+			$this,
3034
+			'replaceModifiers'
3035
+			), $string
3036
+		);
3037
+
3038
+		// replace escaped dollar operators by unescaped ones if required
3039
+		if ($first === "'") {
3040
+			$string = str_replace('\\$', '$', $string);
3041
+		}
3042
+
3043
+		return $string;
3044
+	}
3045
+
3046
+	/**
3047
+	 * Replaces the modifiers applied to a string or a variable.
3048
+	 *
3049
+	 * @param array  $m        the regex matches that must be array(1=>"double or single quotes enclosing a string,
3050
+	 *                         when applicable", 2=>"the string or var", 3=>"the modifiers matched")
3051
+	 * @param string $curBlock the current parser-block being processed
3052
+	 * @param null   $pointer
3053
+	 *
3054
+	 * @return string the input enclosed with various function calls according to the modifiers found
3055
+	 * @throws CompilationException
3056
+	 * @throws Exception
3057
+	 */
3058
+	protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
3059
+	{
3060
+		if ($this->debug) {
3061
+			echo 'PARSING MODIFIERS : ' . $m[3] . "\n";
3062
+		}
3063
+
3064
+		if ($pointer !== null) {
3065
+			$pointer += strlen($m[3]);
3066
+		}
3067
+		// remove first pipe
3068
+		$cmdstrsrc = substr($m[3], 1);
3069
+		// remove last quote if present
3070
+		if (substr($cmdstrsrc, - 1, 1) === $m[1]) {
3071
+			$cmdstrsrc = substr($cmdstrsrc, 0, - 1);
3072
+			$add       = $m[1];
3073
+		}
3074
+
3075
+		$output = $m[2];
3076
+
3077
+		$continue = true;
3078
+		while (strlen($cmdstrsrc) > 0 && $continue) {
3079
+			if ($cmdstrsrc[0] === '|') {
3080
+				$cmdstrsrc = substr($cmdstrsrc, 1);
3081
+				continue;
3082
+			}
3083
+			if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
3084
+				if ($this->debug) {
3085
+					echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND' . "\n";
3086
+				}
3087
+				$continue = false;
3088
+				if ($pointer !== null) {
3089
+					$pointer -= strlen($cmdstrsrc);
3090
+				}
3091
+				break;
3092
+			}
3093
+			$cmdstr   = $cmdstrsrc;
3094
+			$paramsep = ':';
3095
+			if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
3096
+				throw new CompilationException($this, 'Invalid modifier name, started with : ' . substr($cmdstr, 0, 10));
3097
+			}
3098
+			$paramspos = !empty($match[2]) ? strlen($match[1]) : false;
3099
+			$func      = $match[1];
3100
+
3101
+			$state = 0;
3102
+			if ($paramspos === false) {
3103
+				$cmdstrsrc = substr($cmdstrsrc, strlen($func));
3104
+				$params    = array();
3105
+				if ($this->debug) {
3106
+					echo 'MODIFIER (' . $func . ') CALLED WITH NO PARAMS' . "\n";
3107
+				}
3108
+			} else {
3109
+				$paramstr = substr($cmdstr, $paramspos + 1);
3110
+				if (substr($paramstr, - 1, 1) === $paramsep) {
3111
+					$paramstr = substr($paramstr, 0, - 1);
3112
+				}
3113
+
3114
+				$ptr    = 0;
3115
+				$params = array();
3116
+				while ($ptr < strlen($paramstr)) {
3117
+					if ($this->debug) {
3118
+						echo 'MODIFIER (' . $func . ') START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
3119
+					}
3120
+					if ($this->debug) {
3121
+						echo $paramstr . '--' . $ptr . '--' . strlen($paramstr) . '--modifier' . "\n";
3122
+					}
3123
+					$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
3124
+					if ($this->debug) {
3125
+						echo 'PARAM PARSED, POINTER AT ' . $ptr . "\n";
3126
+					}
3127
+
3128
+					if ($ptr >= strlen($paramstr)) {
3129
+						if ($this->debug) {
3130
+							echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED' . "\n";
3131
+						}
3132
+						break;
3133
+					}
3134
+
3135
+					if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
3136
+						if ($this->debug) {
3137
+							echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT ' . $ptr . "\n";
3138
+						}
3139
+						if ($paramstr[$ptr] !== '|') {
3140
+							$continue = false;
3141
+							if ($pointer !== null) {
3142
+								$pointer -= strlen($paramstr) - $ptr;
3143
+							}
3144
+						}
3145
+						++ $ptr;
3146
+						break;
3147
+					}
3148
+					if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
3149
+						++ $ptr;
3150
+					}
3151
+				}
3152
+				$cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
3153
+				foreach ($params as $k => $p) {
3154
+					if (is_array($p) && is_array($p[1])) {
3155
+						$state |= 2;
3156
+					} else {
3157
+						if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m)) {
3158
+							$params[$k] = array($m[2], array('true', 'true'));
3159
+						} else {
3160
+							if ($state & 2) {
3161
+								throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
3162
+							}
3163
+							$state |= 1;
3164
+						}
3165
+					}
3166
+				}
3167
+			}
3168
+
3169
+			// check if we must use array_map with this plugin or not
3170
+			$mapped = false;
3171
+			if (substr($func, 0, 1) === '@') {
3172
+				$func   = substr($func, 1);
3173
+				$mapped = true;
3174
+			}
3175
+
3176
+			$pluginType = $this->getPluginType($func);
3177
+
3178
+			if ($state & 2) {
3179
+				array_unshift($params, array('value', is_array($output) ? $output : array($output, $output)));
3180
+			} else {
3181
+				array_unshift($params, is_array($output) ? $output : array($output, $output));
3182
+			}
3183
+
3184
+			if ($pluginType & Core::NATIVE_PLUGIN) {
3185
+				$params = $this->mapParams($params, null, $state);
3186
+
3187
+				$params = $params['*'][0];
3188
+
3189
+				$params = self::implode_r($params);
3190
+
3191
+				if ($mapped) {
3192
+					$output = '$this->arrayMap(\'' . $func . '\', array(' . $params . '))';
3193
+				} else {
3194
+					$output = $func . '(' . $params . ')';
3195
+				}
3196
+			} elseif ($pluginType & Core::PROXY_PLUGIN) {
3197
+				$params = $this->mapParams($params, $this->getCore()->getPluginProxy()->getCallback($func), $state);
3198
+				foreach ($params as &$p) {
3199
+					$p = $p[0];
3200
+				}
3201
+				$output = call_user_func(array($this->getCore()->getPluginProxy(), 'getCode'), $func, $params);
3202
+			} elseif ($pluginType & Core::SMARTY_MODIFIER) {
3203
+				$params = $this->mapParams($params, null, $state);
3204
+				$params = $params['*'][0];
3205
+
3206
+				$params = self::implode_r($params);
3207
+
3208
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
3209
+					$callback = $this->customPlugins[$func]['callback'];
3210
+					if (is_array($callback)) {
3211
+						if (is_object($callback[0])) {
3212
+							$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(' . $params . '))';
3213
+						} else {
3214
+							$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3215
+						}
3216
+					} elseif ($mapped) {
3217
+						$output = '$this->arrayMap(\'' . $callback . '\', array(' . $params . '))';
3218
+					} else {
3219
+						$output = $callback . '(' . $params . ')';
3220
+					}
3221
+				} elseif ($mapped) {
3222
+					$output = '$this->arrayMap(\'smarty_modifier_' . $func . '\', array(' . $params . '))';
3223
+				} else {
3224
+					$output = 'smarty_modifier_' . $func . '(' . $params . ')';
3225
+				}
3226
+			} else {
3227
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
3228
+					$pluginName = $callback = $this->customPlugins[$func]['callback'];
3229
+					if (($pluginType & Core::CLASS_PLUGIN) && !is_array($callback)) {
3230
+						$pluginName = $this->customPlugins[$func]['callback'];
3231
+						$callback   = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3232
+					}
3233
+				} else {
3234
+					if (class_exists('Plugin' . Core::toCamelCase($func)) !== false || function_exists('Plugin' .
3235
+							Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3236
+						!== false) {
3237
+						$pluginName = 'Plugin' . Core::toCamelCase($func);
3238
+					} else {
3239
+						$pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func);
3240
+					}
3241
+					if ($pluginType & Core::CLASS_PLUGIN) {
3242
+						$callback = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3243
+					} else {
3244
+						$callback = $pluginName . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3245
+					}
3246
+				}
3247
+				$params = $this->mapParams($params, $callback, $state);
3248
+
3249
+				foreach ($params as &$p) {
3250
+					$p = $p[0];
3251
+				}
3252
+
3253
+				// Only for PHP function, who is not a PHP class
3254
+				if ($pluginType & Core::FUNC_PLUGIN && !($pluginType & Core::CLASS_PLUGIN)) {
3255
+					if ($pluginType & Core::COMPILABLE_PLUGIN) {
3256
+						if ($mapped) {
3257
+							throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3258
+						}
3259
+						if ($pluginType & Core::CUSTOM_PLUGIN) {
3260
+							$funcCompiler = $this->customPlugins[$func]['callback'];
3261
+						} else {
3262
+							if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
3263
+								$funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
3264
+							} else {
3265
+								$funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
3266
+									'Compile';
3267
+							}
3268
+						}
3269
+						array_unshift($params, $this);
3270
+						$output = call_user_func_array($funcCompiler, $params);
3271
+					} else {
3272
+						array_unshift($params, '$this');
3273
+
3274
+						$params = self::implode_r($params);
3275
+						if ($mapped) {
3276
+							$output = '$this->arrayMap(\'' . $pluginName . '\', array(' . $params . '))';
3277
+						} else {
3278
+							$output = $pluginName . '(' . $params . ')';
3279
+						}
3280
+					}
3281
+				} else {
3282
+					if ($pluginType & Core::COMPILABLE_PLUGIN) {
3283
+						if ($mapped) {
3284
+							throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3285
+						}
3286
+						if ($pluginType & Core::CUSTOM_PLUGIN) {
3287
+							$callback = $this->customPlugins[$func]['callback'];
3288
+							if (!is_array($callback)) {
3289
+								if (!method_exists($callback, 'compile')) {
3290
+									throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3291
+								}
3292
+								if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3293
+									$funcCompiler = array($callback, 'compile');
3294
+								} else {
3295
+									$funcCompiler = array(new $callback(), 'compile');
3296
+								}
3297
+							} else {
3298
+								$funcCompiler = $callback;
3299
+							}
3300
+						} else {
3301
+							if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3302
+								$funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
3303
+							} else {
3304
+								$funcCompiler = array(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func), 'compile');
3305
+							}
3306
+							array_unshift($params, $this);
3307
+						}
3308
+						$output = call_user_func_array($funcCompiler, $params);
3309
+					} else {
3310
+						$params = self::implode_r($params);
3311
+
3312
+						if ($pluginType & Core::CUSTOM_PLUGIN) {
3313
+							if (is_object($callback[0])) {
3314
+								if (is_array($this->getCore()->getCustomPlugin($func))) {
3315
+									$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3316
+								} else {
3317
+									$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->getCustomPlugin(\'' . $func . '\'), \'' . $callback[1] . '\'), array(' . $params . '))';
3318
+								}
3319
+							} else {
3320
+								$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3321
+							}
3322
+						} elseif ($mapped) {
3323
+							$output = '$this->arrayMap(array($this->getObjectPlugin(\''.
3324
+								Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '\'),
3325 3325
                             \'process\'), array(' . $params . '))';
3326
-                        } else {
3327
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3328
-                                $output = '$this->classCall(\'Plugin' . Core::toCamelCase($func) . '\', array(' . $params . '))';
3329
-                            } elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($func)) !== false) {
3330
-                                $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . $func . '\', array(' . $params . '))';
3331
-                            } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !== false) {
3332
-                                $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\', array(' . $params . '))';
3333
-                            } else {
3334
-                                $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
3335
-                            }
3336
-                        }
3337
-                    }
3338
-                }
3339
-            }
3340
-        }
3341
-
3342
-        if ($curBlock === 'namedparam') {
3343
-            return array($output, $output);
3344
-        } elseif ($curBlock === 'var' || $m[1] === null) {
3345
-            return $output;
3346
-        } elseif ($curBlock === 'string' || $curBlock === 'root') {
3347
-            return $m[1] . '.' . $output . '.' . $m[1] . (isset($add) ? $add : null);
3348
-        }
3349
-
3350
-        return '';
3351
-    }
3352
-
3353
-    /**
3354
-     * Recursively implodes an array in a similar manner as var_export() does but with some tweaks
3355
-     * to handle pre-compiled values and the fact that we do not need to enclose everything with
3356
-     * "array" and do not require top-level keys to be displayed.
3357
-     *
3358
-     * @param array $params        the array to implode
3359
-     * @param bool  $recursiveCall if set to true, the function outputs key names for the top level
3360
-     *
3361
-     * @return string the imploded array
3362
-     */
3363
-    public static function implode_r(array $params, $recursiveCall = false)
3364
-    {
3365
-        $out = '';
3366
-        foreach ($params as $k => $p) {
3367
-            if (is_array($p)) {
3368
-                $out2 = 'array(';
3369
-                foreach ($p as $k2 => $v) {
3370
-                    $out2 .= var_export($k2, true) . ' => ' . (is_array($v) ? 'array(' . self::implode_r($v, true) . ')' : $v) . ', ';
3371
-                }
3372
-                $p = rtrim($out2, ', ') . ')';
3373
-            }
3374
-            if ($recursiveCall) {
3375
-                $out .= var_export($k, true) . ' => ' . $p . ', ';
3376
-            } else {
3377
-                $out .= $p . ', ';
3378
-            }
3379
-        }
3380
-
3381
-        return rtrim($out, ', ');
3382
-    }
3383
-
3384
-    /**
3385
-     * Returns the plugin type of a plugin and adds it to the used plugins array if required.
3386
-     *
3387
-     * @param string $name plugin name, as found in the template
3388
-     *
3389
-     * @return int type as a multi bit flag composed of the Dwoo plugin types constants
3390
-     * @throws Exception
3391
-     * @throws SecurityException
3392
-     * @throws Exception
3393
-     */
3394
-    protected function getPluginType($name)
3395
-    {
3396
-        $pluginType = - 1;
3397
-
3398
-        if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) || ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3399
-            $phpFunc = true;
3400
-        } elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3401
-            throw new SecurityException('Call to a disallowed php function : ' . $name);
3402
-        }
3403
-
3404
-        while ($pluginType <= 0) {
3405
-            // Template plugin compilable
3406
-            if (isset($this->templatePlugins[$name])) {
3407
-                $pluginType = Core::TEMPLATE_PLUGIN | Core::COMPILABLE_PLUGIN;
3408
-            } // Custom plugin
3409
-            elseif (isset($this->customPlugins[$name])) {
3410
-                $pluginType = $this->customPlugins[$name]['type'] | Core::CUSTOM_PLUGIN;
3411
-            } // Class blocks plugin
3412
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3413
-                $pluginType = Core::CLASS_PLUGIN;
3414
-                if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3415
-                    $pluginType += Core::BLOCK_PLUGIN;
3416
-                }
3417
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name));
3418
-                if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3419
-                    $pluginType |= Core::COMPILABLE_PLUGIN;
3420
-                }
3421
-            } // Class functions plugin
3422
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3423
-                $pluginType = Core::FUNC_PLUGIN + Core::CLASS_PLUGIN;
3424
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name));
3425
-                if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3426
-                    $pluginType |= Core::COMPILABLE_PLUGIN;
3427
-                }
3428
-            } // Class without namespace
3429
-            elseif (class_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3430
-                $pluginType = Core::CLASS_PLUGIN;
3431
-                if (is_subclass_of('Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3432
-                    $pluginType += Core::BLOCK_PLUGIN;
3433
-                }
3434
-                $interfaces = class_implements('Plugin' . Core::toCamelCase($name));
3435
-                if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3436
-                    $pluginType |= Core::COMPILABLE_PLUGIN;
3437
-                }
3438
-            } // Function plugin (with/without namespaces)
3439
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase ($name)) !==
3440
-                false || function_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3441
-                $pluginType = Core::FUNC_PLUGIN;
3442
-            } // Function plugin compile (with/without namespaces)
3443
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name) .
3444
-                    'Compile') !== false || function_exists('Plugin' . Core::toCamelCase($name) . 'Compile') !==
3445
-                false) {
3446
-                $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3447
-            } // Helper plugin class compile
3448
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3449
-                $pluginType = Core::CLASS_PLUGIN | Core::COMPILABLE_PLUGIN;
3450
-            } // Helper plugin function compile
3451
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name) . 'Compile') !== false) {
3452
-                $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3453
-            } // Smarty modifier
3454
-            elseif (function_exists('smarty_modifier_' . $name) !== false) {
3455
-                $pluginType = Core::SMARTY_MODIFIER;
3456
-            } // Smarty function
3457
-            elseif (function_exists('smarty_function_' . $name) !== false) {
3458
-                $pluginType = Core::SMARTY_FUNCTION;
3459
-            } // Smarty block
3460
-            elseif (function_exists('smarty_block_' . $name) !== false) {
3461
-                $pluginType = Core::SMARTY_BLOCK;
3462
-            } // Everything else
3463
-            else {
3464
-                if ($pluginType === - 1) {
3465
-                    try {
3466
-                        $this->getCore()->getLoader()->loadPlugin('Plugin' . Core::toCamelCase($name));
3467
-                    }
3468
-                    catch (Exception $e) {
3469
-                        if (isset($phpFunc)) {
3470
-                            $pluginType = Core::NATIVE_PLUGIN;
3471
-                        } elseif (is_object($this->getCore()->getPluginProxy()) && $this->getCore()->getPluginProxy()->handles($name)) {
3472
-                            $pluginType = Core::PROXY_PLUGIN;
3473
-                            break;
3474
-                        } else {
3475
-                            throw $e;
3476
-                        }
3477
-                    }
3478
-                } else {
3479
-                    throw new Exception('Plugin "' . $name . '" could not be found, type:' . $pluginType);
3480
-                }
3481
-                ++ $pluginType;
3482
-            }
3483
-        }
3484
-
3485
-        if (($pluginType & Core::COMPILABLE_PLUGIN) === 0 && ($pluginType & Core::NATIVE_PLUGIN) === 0 && ($pluginType & Core::PROXY_PLUGIN) === 0) {
3486
-            $this->addUsedPlugin(Core::toCamelCase($name), $pluginType);
3487
-        }
3488
-
3489
-        return $pluginType;
3490
-    }
3491
-
3492
-    /**
3493
-     * Allows a plugin to load another one at compile time, this will also mark
3494
-     * it as used by this template so it will be loaded at runtime (which can be
3495
-     * useful for compiled plugins that rely on another plugin when their compiled
3496
-     * code runs).
3497
-     *
3498
-     * @param string $name the plugin name
3499
-     *
3500
-     * @return void
3501
-     */
3502
-    public function loadPlugin($name)
3503
-    {
3504
-        $this->getPluginType($name);
3505
-    }
3506
-
3507
-    /**
3508
-     * Runs htmlentities over the matched <?php ?> blocks when the security policy enforces that.
3509
-     *
3510
-     * @param array $match matched php block
3511
-     *
3512
-     * @return string the htmlentities-converted string
3513
-     */
3514
-    protected function phpTagEncodingHelper($match)
3515
-    {
3516
-        return htmlspecialchars($match[0]);
3517
-    }
3518
-
3519
-    /**
3520
-     * Maps the parameters received from the template onto the parameters required by the given callback.
3521
-     *
3522
-     * @param array    $params   the array of parameters
3523
-     * @param callback $callback the function or method to reflect on to find out the required parameters
3524
-     * @param int      $callType the type of call in the template, 0 = no params, 1 = php-style call, 2 = named
3525
-     *                           parameters call
3526
-     * @param array    $map      the parameter map to use, if not provided it will be built from the callback
3527
-     *
3528
-     * @return array parameters sorted in the correct order with missing optional parameters filled
3529
-     * @throws CompilationException
3530
-     */
3531
-    protected function mapParams(array $params, $callback, $callType = 2, $map = null)
3532
-    {
3533
-        if (!$map) {
3534
-            $map = $this->getParamMap($callback);
3535
-        }
3536
-
3537
-        $paramlist = array();
3538
-
3539
-        // transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
3540
-        $ps = array();
3541
-        foreach ($params as $p) {
3542
-            if (is_array($p[1])) {
3543
-                $ps[$p[0]] = $p[1];
3544
-            } else {
3545
-                $ps[] = $p;
3546
-            }
3547
-        }
3548
-
3549
-        // loops over the param map and assigns values from the template or default value for unset optional params
3550
-        foreach ($map as $k => $v){
3551
-            if ($v[0] === '*') {
3552
-                // "rest" array parameter, fill every remaining params in it and then break
3553
-                if (count($ps) === 0) {
3554
-                    if ($v[1] === false) {
3555
-                        throw new CompilationException(
3556
-                            $this, 'Rest argument missing for ' . str_replace(
3557
-                                array(
3558
-                                    Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3559
-                                'Compile'
3560
-                                ), '', (is_array($callback) ? $callback[0] : $callback)
3561
-                            )
3562
-                        );
3563
-                    } else {
3564
-                        break;
3565
-                    }
3566
-                }
3567
-                $tmp  = array();
3568
-                $tmp2 = array();
3569
-                $tmp3 = array();
3570
-                foreach ($ps as $i => $p) {
3571
-                    $tmp[$i]  = $p[0];
3572
-                    $tmp2[$i] = $p[1];
3573
-                    $tmp3[$i] = isset($p[2]) ? $p[2] : 0;
3574
-                    unset($ps[$i]);
3575
-                }
3576
-                $paramlist[$v[0]] = array($tmp, $tmp2, $tmp3);
3577
-                unset($tmp, $tmp2, $i, $p);
3578
-                break;
3579
-            } elseif (isset($ps[$v[0]])) {
3580
-                // parameter is defined as named param
3581
-                $paramlist[$v[0]] = $ps[$v[0]];
3582
-                unset($ps[$v[0]]);
3583
-            } elseif (isset($ps[$k])) {
3584
-                // parameter is defined as ordered param
3585
-                $paramlist[$v[0]] = $ps[$k];
3586
-                unset($ps[$k]);
3587
-            } elseif ($v[1] === false) {
3588
-                // parameter is not defined and not optional, throw error
3589
-                if (is_array($callback)) {
3590
-                    if (is_object($callback[0])) {
3591
-                        $name = get_class($callback[0]) . '::' . $callback[1];
3592
-                    } else {
3593
-                        $name = $callback[0];
3594
-                    }
3595
-                } else {
3596
-                    $name = $callback;
3597
-                }
3598
-
3599
-                throw new CompilationException(
3600
-                    $this, 'Argument ' . $k . '/' . $v[0] . ' missing for ' . str_replace(
3601
-                        array(
3602
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3603
-                        'Compile'
3604
-                        ), '', $name
3605
-                    )
3606
-                );
3607
-            } elseif ($v[2] === null) {
3608
-                // enforce lowercased null if default value is null (php outputs NULL with var export)
3609
-                $paramlist[$v[0]] = array('null', null, self::T_NULL);
3610
-            } else {
3611
-                // outputs default value with var_export
3612
-                $paramlist[$v[0]] = array(var_export($v[2], true), $v[2]);
3613
-            }
3614
-        }
3615
-
3616
-        if (count($ps)) {
3617
-            foreach ($ps as $i => $p) {
3618
-                array_push($paramlist, $p);
3619
-            }
3620
-        }
3621
-
3622
-        return $paramlist;
3623
-    }
3624
-
3625
-    /**
3626
-     * Returns the parameter map of the given callback, it filters out entries typed as Dwoo and Compiler and turns the
3627
-     * rest parameter into a "*".
3628
-     *
3629
-     * @param callback $callback the function/method to reflect on
3630
-     *
3631
-     * @return array processed parameter map
3632
-     */
3633
-    protected function getParamMap($callback)
3634
-    {
3635
-        if (is_null($callback)) {
3636
-            return array(array('*', true));
3637
-        }
3638
-        if (is_array($callback)) {
3639
-            $ref = new ReflectionMethod($callback[0], $callback[1]);
3640
-        } else {
3641
-            $ref = new ReflectionFunction($callback);
3642
-        }
3643
-
3644
-        $out = array();
3645
-        foreach ($ref->getParameters() as $param) {
3646
-            if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Core') {
3647
-                continue;
3648
-            }
3649
-            if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Compiler') {
3650
-                continue;
3651
-            }
3652
-            if ($param->getName() === 'rest' && $param->isArray() === true) {
3653
-                $out[] = array('*', $param->isOptional(), null);
3654
-                continue;
3655
-            }
3656
-            $out[] = array(
3657
-                $param->getName(),
3658
-                $param->isOptional(),
3659
-                $param->isOptional() ? $param->getDefaultValue() : null
3660
-            );
3661
-        }
3662
-
3663
-        return $out;
3664
-    }
3665
-
3666
-    /**
3667
-     * Returns a default instance of this compiler, used by default by all Dwoo templates that do not have a
3668
-     * specific compiler assigned and when you do not override the default compiler factory function.
3669
-     *
3670
-     * @see    Core::setDefaultCompilerFactory()
3671
-     * @return Compiler
3672
-     */
3673
-    public static function compilerFactory()
3674
-    {
3675
-        if (self::$instance === null) {
3676
-            self::$instance = new self();
3677
-        }
3678
-
3679
-        return self::$instance;
3680
-    }
3326
+						} else {
3327
+							if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3328
+								$output = '$this->classCall(\'Plugin' . Core::toCamelCase($func) . '\', array(' . $params . '))';
3329
+							} elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($func)) !== false) {
3330
+								$output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . $func . '\', array(' . $params . '))';
3331
+							} elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !== false) {
3332
+								$output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\', array(' . $params . '))';
3333
+							} else {
3334
+								$output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
3335
+							}
3336
+						}
3337
+					}
3338
+				}
3339
+			}
3340
+		}
3341
+
3342
+		if ($curBlock === 'namedparam') {
3343
+			return array($output, $output);
3344
+		} elseif ($curBlock === 'var' || $m[1] === null) {
3345
+			return $output;
3346
+		} elseif ($curBlock === 'string' || $curBlock === 'root') {
3347
+			return $m[1] . '.' . $output . '.' . $m[1] . (isset($add) ? $add : null);
3348
+		}
3349
+
3350
+		return '';
3351
+	}
3352
+
3353
+	/**
3354
+	 * Recursively implodes an array in a similar manner as var_export() does but with some tweaks
3355
+	 * to handle pre-compiled values and the fact that we do not need to enclose everything with
3356
+	 * "array" and do not require top-level keys to be displayed.
3357
+	 *
3358
+	 * @param array $params        the array to implode
3359
+	 * @param bool  $recursiveCall if set to true, the function outputs key names for the top level
3360
+	 *
3361
+	 * @return string the imploded array
3362
+	 */
3363
+	public static function implode_r(array $params, $recursiveCall = false)
3364
+	{
3365
+		$out = '';
3366
+		foreach ($params as $k => $p) {
3367
+			if (is_array($p)) {
3368
+				$out2 = 'array(';
3369
+				foreach ($p as $k2 => $v) {
3370
+					$out2 .= var_export($k2, true) . ' => ' . (is_array($v) ? 'array(' . self::implode_r($v, true) . ')' : $v) . ', ';
3371
+				}
3372
+				$p = rtrim($out2, ', ') . ')';
3373
+			}
3374
+			if ($recursiveCall) {
3375
+				$out .= var_export($k, true) . ' => ' . $p . ', ';
3376
+			} else {
3377
+				$out .= $p . ', ';
3378
+			}
3379
+		}
3380
+
3381
+		return rtrim($out, ', ');
3382
+	}
3383
+
3384
+	/**
3385
+	 * Returns the plugin type of a plugin and adds it to the used plugins array if required.
3386
+	 *
3387
+	 * @param string $name plugin name, as found in the template
3388
+	 *
3389
+	 * @return int type as a multi bit flag composed of the Dwoo plugin types constants
3390
+	 * @throws Exception
3391
+	 * @throws SecurityException
3392
+	 * @throws Exception
3393
+	 */
3394
+	protected function getPluginType($name)
3395
+	{
3396
+		$pluginType = - 1;
3397
+
3398
+		if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) || ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3399
+			$phpFunc = true;
3400
+		} elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3401
+			throw new SecurityException('Call to a disallowed php function : ' . $name);
3402
+		}
3403
+
3404
+		while ($pluginType <= 0) {
3405
+			// Template plugin compilable
3406
+			if (isset($this->templatePlugins[$name])) {
3407
+				$pluginType = Core::TEMPLATE_PLUGIN | Core::COMPILABLE_PLUGIN;
3408
+			} // Custom plugin
3409
+			elseif (isset($this->customPlugins[$name])) {
3410
+				$pluginType = $this->customPlugins[$name]['type'] | Core::CUSTOM_PLUGIN;
3411
+			} // Class blocks plugin
3412
+			elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3413
+				$pluginType = Core::CLASS_PLUGIN;
3414
+				if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3415
+					$pluginType += Core::BLOCK_PLUGIN;
3416
+				}
3417
+				$interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name));
3418
+				if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3419
+					$pluginType |= Core::COMPILABLE_PLUGIN;
3420
+				}
3421
+			} // Class functions plugin
3422
+			elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3423
+				$pluginType = Core::FUNC_PLUGIN + Core::CLASS_PLUGIN;
3424
+				$interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name));
3425
+				if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3426
+					$pluginType |= Core::COMPILABLE_PLUGIN;
3427
+				}
3428
+			} // Class without namespace
3429
+			elseif (class_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3430
+				$pluginType = Core::CLASS_PLUGIN;
3431
+				if (is_subclass_of('Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3432
+					$pluginType += Core::BLOCK_PLUGIN;
3433
+				}
3434
+				$interfaces = class_implements('Plugin' . Core::toCamelCase($name));
3435
+				if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3436
+					$pluginType |= Core::COMPILABLE_PLUGIN;
3437
+				}
3438
+			} // Function plugin (with/without namespaces)
3439
+			elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase ($name)) !==
3440
+				false || function_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3441
+				$pluginType = Core::FUNC_PLUGIN;
3442
+			} // Function plugin compile (with/without namespaces)
3443
+			elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name) .
3444
+					'Compile') !== false || function_exists('Plugin' . Core::toCamelCase($name) . 'Compile') !==
3445
+				false) {
3446
+				$pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3447
+			} // Helper plugin class compile
3448
+			elseif (class_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name)) !== false) {
3449
+				$pluginType = Core::CLASS_PLUGIN | Core::COMPILABLE_PLUGIN;
3450
+			} // Helper plugin function compile
3451
+			elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name) . 'Compile') !== false) {
3452
+				$pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3453
+			} // Smarty modifier
3454
+			elseif (function_exists('smarty_modifier_' . $name) !== false) {
3455
+				$pluginType = Core::SMARTY_MODIFIER;
3456
+			} // Smarty function
3457
+			elseif (function_exists('smarty_function_' . $name) !== false) {
3458
+				$pluginType = Core::SMARTY_FUNCTION;
3459
+			} // Smarty block
3460
+			elseif (function_exists('smarty_block_' . $name) !== false) {
3461
+				$pluginType = Core::SMARTY_BLOCK;
3462
+			} // Everything else
3463
+			else {
3464
+				if ($pluginType === - 1) {
3465
+					try {
3466
+						$this->getCore()->getLoader()->loadPlugin('Plugin' . Core::toCamelCase($name));
3467
+					}
3468
+					catch (Exception $e) {
3469
+						if (isset($phpFunc)) {
3470
+							$pluginType = Core::NATIVE_PLUGIN;
3471
+						} elseif (is_object($this->getCore()->getPluginProxy()) && $this->getCore()->getPluginProxy()->handles($name)) {
3472
+							$pluginType = Core::PROXY_PLUGIN;
3473
+							break;
3474
+						} else {
3475
+							throw $e;
3476
+						}
3477
+					}
3478
+				} else {
3479
+					throw new Exception('Plugin "' . $name . '" could not be found, type:' . $pluginType);
3480
+				}
3481
+				++ $pluginType;
3482
+			}
3483
+		}
3484
+
3485
+		if (($pluginType & Core::COMPILABLE_PLUGIN) === 0 && ($pluginType & Core::NATIVE_PLUGIN) === 0 && ($pluginType & Core::PROXY_PLUGIN) === 0) {
3486
+			$this->addUsedPlugin(Core::toCamelCase($name), $pluginType);
3487
+		}
3488
+
3489
+		return $pluginType;
3490
+	}
3491
+
3492
+	/**
3493
+	 * Allows a plugin to load another one at compile time, this will also mark
3494
+	 * it as used by this template so it will be loaded at runtime (which can be
3495
+	 * useful for compiled plugins that rely on another plugin when their compiled
3496
+	 * code runs).
3497
+	 *
3498
+	 * @param string $name the plugin name
3499
+	 *
3500
+	 * @return void
3501
+	 */
3502
+	public function loadPlugin($name)
3503
+	{
3504
+		$this->getPluginType($name);
3505
+	}
3506
+
3507
+	/**
3508
+	 * Runs htmlentities over the matched <?php ?> blocks when the security policy enforces that.
3509
+	 *
3510
+	 * @param array $match matched php block
3511
+	 *
3512
+	 * @return string the htmlentities-converted string
3513
+	 */
3514
+	protected function phpTagEncodingHelper($match)
3515
+	{
3516
+		return htmlspecialchars($match[0]);
3517
+	}
3518
+
3519
+	/**
3520
+	 * Maps the parameters received from the template onto the parameters required by the given callback.
3521
+	 *
3522
+	 * @param array    $params   the array of parameters
3523
+	 * @param callback $callback the function or method to reflect on to find out the required parameters
3524
+	 * @param int      $callType the type of call in the template, 0 = no params, 1 = php-style call, 2 = named
3525
+	 *                           parameters call
3526
+	 * @param array    $map      the parameter map to use, if not provided it will be built from the callback
3527
+	 *
3528
+	 * @return array parameters sorted in the correct order with missing optional parameters filled
3529
+	 * @throws CompilationException
3530
+	 */
3531
+	protected function mapParams(array $params, $callback, $callType = 2, $map = null)
3532
+	{
3533
+		if (!$map) {
3534
+			$map = $this->getParamMap($callback);
3535
+		}
3536
+
3537
+		$paramlist = array();
3538
+
3539
+		// transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
3540
+		$ps = array();
3541
+		foreach ($params as $p) {
3542
+			if (is_array($p[1])) {
3543
+				$ps[$p[0]] = $p[1];
3544
+			} else {
3545
+				$ps[] = $p;
3546
+			}
3547
+		}
3548
+
3549
+		// loops over the param map and assigns values from the template or default value for unset optional params
3550
+		foreach ($map as $k => $v){
3551
+			if ($v[0] === '*') {
3552
+				// "rest" array parameter, fill every remaining params in it and then break
3553
+				if (count($ps) === 0) {
3554
+					if ($v[1] === false) {
3555
+						throw new CompilationException(
3556
+							$this, 'Rest argument missing for ' . str_replace(
3557
+								array(
3558
+									Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3559
+								'Compile'
3560
+								), '', (is_array($callback) ? $callback[0] : $callback)
3561
+							)
3562
+						);
3563
+					} else {
3564
+						break;
3565
+					}
3566
+				}
3567
+				$tmp  = array();
3568
+				$tmp2 = array();
3569
+				$tmp3 = array();
3570
+				foreach ($ps as $i => $p) {
3571
+					$tmp[$i]  = $p[0];
3572
+					$tmp2[$i] = $p[1];
3573
+					$tmp3[$i] = isset($p[2]) ? $p[2] : 0;
3574
+					unset($ps[$i]);
3575
+				}
3576
+				$paramlist[$v[0]] = array($tmp, $tmp2, $tmp3);
3577
+				unset($tmp, $tmp2, $i, $p);
3578
+				break;
3579
+			} elseif (isset($ps[$v[0]])) {
3580
+				// parameter is defined as named param
3581
+				$paramlist[$v[0]] = $ps[$v[0]];
3582
+				unset($ps[$v[0]]);
3583
+			} elseif (isset($ps[$k])) {
3584
+				// parameter is defined as ordered param
3585
+				$paramlist[$v[0]] = $ps[$k];
3586
+				unset($ps[$k]);
3587
+			} elseif ($v[1] === false) {
3588
+				// parameter is not defined and not optional, throw error
3589
+				if (is_array($callback)) {
3590
+					if (is_object($callback[0])) {
3591
+						$name = get_class($callback[0]) . '::' . $callback[1];
3592
+					} else {
3593
+						$name = $callback[0];
3594
+					}
3595
+				} else {
3596
+					$name = $callback;
3597
+				}
3598
+
3599
+				throw new CompilationException(
3600
+					$this, 'Argument ' . $k . '/' . $v[0] . ' missing for ' . str_replace(
3601
+						array(
3602
+							Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3603
+						'Compile'
3604
+						), '', $name
3605
+					)
3606
+				);
3607
+			} elseif ($v[2] === null) {
3608
+				// enforce lowercased null if default value is null (php outputs NULL with var export)
3609
+				$paramlist[$v[0]] = array('null', null, self::T_NULL);
3610
+			} else {
3611
+				// outputs default value with var_export
3612
+				$paramlist[$v[0]] = array(var_export($v[2], true), $v[2]);
3613
+			}
3614
+		}
3615
+
3616
+		if (count($ps)) {
3617
+			foreach ($ps as $i => $p) {
3618
+				array_push($paramlist, $p);
3619
+			}
3620
+		}
3621
+
3622
+		return $paramlist;
3623
+	}
3624
+
3625
+	/**
3626
+	 * Returns the parameter map of the given callback, it filters out entries typed as Dwoo and Compiler and turns the
3627
+	 * rest parameter into a "*".
3628
+	 *
3629
+	 * @param callback $callback the function/method to reflect on
3630
+	 *
3631
+	 * @return array processed parameter map
3632
+	 */
3633
+	protected function getParamMap($callback)
3634
+	{
3635
+		if (is_null($callback)) {
3636
+			return array(array('*', true));
3637
+		}
3638
+		if (is_array($callback)) {
3639
+			$ref = new ReflectionMethod($callback[0], $callback[1]);
3640
+		} else {
3641
+			$ref = new ReflectionFunction($callback);
3642
+		}
3643
+
3644
+		$out = array();
3645
+		foreach ($ref->getParameters() as $param) {
3646
+			if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Core') {
3647
+				continue;
3648
+			}
3649
+			if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Compiler') {
3650
+				continue;
3651
+			}
3652
+			if ($param->getName() === 'rest' && $param->isArray() === true) {
3653
+				$out[] = array('*', $param->isOptional(), null);
3654
+				continue;
3655
+			}
3656
+			$out[] = array(
3657
+				$param->getName(),
3658
+				$param->isOptional(),
3659
+				$param->isOptional() ? $param->getDefaultValue() : null
3660
+			);
3661
+		}
3662
+
3663
+		return $out;
3664
+	}
3665
+
3666
+	/**
3667
+	 * Returns a default instance of this compiler, used by default by all Dwoo templates that do not have a
3668
+	 * specific compiler assigned and when you do not override the default compiler factory function.
3669
+	 *
3670
+	 * @see    Core::setDefaultCompilerFactory()
3671
+	 * @return Compiler
3672
+	 */
3673
+	public static function compilerFactory()
3674
+	{
3675
+		if (self::$instance === null) {
3676
+			self::$instance = new self();
3677
+		}
3678
+
3679
+		return self::$instance;
3680
+	}
3681 3681
 }
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Blocks/PluginDynamic.php 4 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -85,8 +85,8 @@
 block discarded – undo
85 85
 
86 86
     /**
87 87
      * @param $output
88
-     * @param $dynamicId
89
-     * @param $compiledFile
88
+     * @param string $dynamicId
89
+     * @param string $compiledFile
90 90
      *
91 91
      * @return mixed|string
92 92
      */
Please login to merge, or discard this patch.
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -28,89 +28,89 @@
 block discarded – undo
28 28
  */
29 29
 class PluginDynamic extends BlockPlugin implements ICompilableBlock
30 30
 {
31
-    /**
32
-     *
33
-     */
34
-    public function init()
35
-    {
36
-    }
31
+	/**
32
+	 *
33
+	 */
34
+	public function init()
35
+	{
36
+	}
37 37
 
38
-    /**
39
-     * @param Compiler $compiler
40
-     * @param array    $params
41
-     * @param string   $prepend
42
-     * @param string   $append
43
-     * @param string   $type
44
-     *
45
-     * @return string
46
-     */
47
-    public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
48
-    {
49
-        return '';
50
-    }
38
+	/**
39
+	 * @param Compiler $compiler
40
+	 * @param array    $params
41
+	 * @param string   $prepend
42
+	 * @param string   $append
43
+	 * @param string   $type
44
+	 *
45
+	 * @return string
46
+	 */
47
+	public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
48
+	{
49
+		return '';
50
+	}
51 51
 
52
-    /**
53
-     * @param Compiler $compiler
54
-     * @param array    $params
55
-     * @param string   $prepend
56
-     * @param string   $append
57
-     * @param string   $content
58
-     *
59
-     * @return string
60
-     */
61
-    public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
62
-    {
63
-        try {
64
-            $compiler->findBlock('dynamic');
52
+	/**
53
+	 * @param Compiler $compiler
54
+	 * @param array    $params
55
+	 * @param string   $prepend
56
+	 * @param string   $append
57
+	 * @param string   $content
58
+	 *
59
+	 * @return string
60
+	 */
61
+	public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
62
+	{
63
+		try {
64
+			$compiler->findBlock('dynamic');
65 65
 
66
-            return $content;
67
-        }
68
-        catch (CompilationException $e) {
69
-        }
70
-        $output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
71
-        if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
72
-            $output .= substr($content, strlen(Compiler::PHP_OPEN));
73
-        } else {
74
-            $output .= Compiler::PHP_CLOSE . $content;
75
-        }
76
-        if (substr($output, - strlen(Compiler::PHP_CLOSE)) == Compiler::PHP_CLOSE) {
77
-            $output = substr($output, 0, - strlen(Compiler::PHP_CLOSE));
78
-        } else {
79
-            $output .= Compiler::PHP_OPEN;
80
-        }
81
-        $output .= "\n}" . Compiler::PHP_CLOSE;
66
+			return $content;
67
+		}
68
+		catch (CompilationException $e) {
69
+		}
70
+		$output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
71
+		if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
72
+			$output .= substr($content, strlen(Compiler::PHP_OPEN));
73
+		} else {
74
+			$output .= Compiler::PHP_CLOSE . $content;
75
+		}
76
+		if (substr($output, - strlen(Compiler::PHP_CLOSE)) == Compiler::PHP_CLOSE) {
77
+			$output = substr($output, 0, - strlen(Compiler::PHP_CLOSE));
78
+		} else {
79
+			$output .= Compiler::PHP_OPEN;
80
+		}
81
+		$output .= "\n}" . Compiler::PHP_CLOSE;
82 82
 
83
-        return $output;
84
-    }
83
+		return $output;
84
+	}
85 85
 
86
-    /**
87
-     * @param $output
88
-     * @param $dynamicId
89
-     * @param $compiledFile
90
-     *
91
-     * @return mixed|string
92
-     */
93
-    public static function unescape($output, $dynamicId, $compiledFile)
94
-    {
95
-        $output = preg_replace_callback('/<dwoo:dynamic_(' . $dynamicId . ')>(.+?)<\/dwoo:dynamic_' . $dynamicId . '>/s', array(
96
-            'self',
97
-            'unescapePhp'
98
-        ), $output, - 1, $count);
99
-        // re-add the includes on top of the file
100
-        if ($count && preg_match('#/\* template head \*/(.+?)/\* end template head \*/#s', file_get_contents($compiledFile), $m)) {
101
-            $output = '<?php ' . $m[1] . ' ?>' . $output;
102
-        }
86
+	/**
87
+	 * @param $output
88
+	 * @param $dynamicId
89
+	 * @param $compiledFile
90
+	 *
91
+	 * @return mixed|string
92
+	 */
93
+	public static function unescape($output, $dynamicId, $compiledFile)
94
+	{
95
+		$output = preg_replace_callback('/<dwoo:dynamic_(' . $dynamicId . ')>(.+?)<\/dwoo:dynamic_' . $dynamicId . '>/s', array(
96
+			'self',
97
+			'unescapePhp'
98
+		), $output, - 1, $count);
99
+		// re-add the includes on top of the file
100
+		if ($count && preg_match('#/\* template head \*/(.+?)/\* end template head \*/#s', file_get_contents($compiledFile), $m)) {
101
+			$output = '<?php ' . $m[1] . ' ?>' . $output;
102
+		}
103 103
 
104
-        return $output;
105
-    }
104
+		return $output;
105
+	}
106 106
 
107
-    /**
108
-     * @param $match
109
-     *
110
-     * @return mixed
111
-     */
112
-    public static function unescapePhp($match)
113
-    {
114
-        return preg_replace('{<\?php /\*' . $match[1] . '\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
115
-    }
107
+	/**
108
+	 * @param $match
109
+	 *
110
+	 * @return mixed
111
+	 */
112
+	public static function unescapePhp($match)
113
+	{
114
+		return preg_replace('{<\?php /\*' . $match[1] . '\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
115
+	}
116 116
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -67,18 +67,18 @@  discard block
 block discarded – undo
67 67
         }
68 68
         catch (CompilationException $e) {
69 69
         }
70
-        $output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
70
+        $output = Compiler::PHP_OPEN.'if($doCache) {'."\n\t".'echo \'<dwoo:dynamic_\'.$dynamicId.\'>'.str_replace('\'', '\\\'', $content).'</dwoo:dynamic_\'.$dynamicId.\'>\';'."\n} else {\n\t";
71 71
         if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
72 72
             $output .= substr($content, strlen(Compiler::PHP_OPEN));
73 73
         } else {
74
-            $output .= Compiler::PHP_CLOSE . $content;
74
+            $output .= Compiler::PHP_CLOSE.$content;
75 75
         }
76 76
         if (substr($output, - strlen(Compiler::PHP_CLOSE)) == Compiler::PHP_CLOSE) {
77 77
             $output = substr($output, 0, - strlen(Compiler::PHP_CLOSE));
78 78
         } else {
79 79
             $output .= Compiler::PHP_OPEN;
80 80
         }
81
-        $output .= "\n}" . Compiler::PHP_CLOSE;
81
+        $output .= "\n}".Compiler::PHP_CLOSE;
82 82
 
83 83
         return $output;
84 84
     }
@@ -92,13 +92,13 @@  discard block
 block discarded – undo
92 92
      */
93 93
     public static function unescape($output, $dynamicId, $compiledFile)
94 94
     {
95
-        $output = preg_replace_callback('/<dwoo:dynamic_(' . $dynamicId . ')>(.+?)<\/dwoo:dynamic_' . $dynamicId . '>/s', array(
95
+        $output = preg_replace_callback('/<dwoo:dynamic_('.$dynamicId.')>(.+?)<\/dwoo:dynamic_'.$dynamicId.'>/s', array(
96 96
             'self',
97 97
             'unescapePhp'
98 98
         ), $output, - 1, $count);
99 99
         // re-add the includes on top of the file
100 100
         if ($count && preg_match('#/\* template head \*/(.+?)/\* end template head \*/#s', file_get_contents($compiledFile), $m)) {
101
-            $output = '<?php ' . $m[1] . ' ?>' . $output;
101
+            $output = '<?php '.$m[1].' ?>'.$output;
102 102
         }
103 103
 
104 104
         return $output;
@@ -111,6 +111,6 @@  discard block
 block discarded – undo
111 111
      */
112 112
     public static function unescapePhp($match)
113 113
     {
114
-        return preg_replace('{<\?php /\*' . $match[1] . '\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
114
+        return preg_replace('{<\?php /\*'.$match[1].'\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
115 115
     }
116 116
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -64,8 +64,7 @@
 block discarded – undo
64 64
             $compiler->findBlock('dynamic');
65 65
 
66 66
             return $content;
67
-        }
68
-        catch (CompilationException $e) {
67
+        } catch (CompilationException $e) {
69 68
         }
70 69
         $output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
71 70
         if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Blocks/PluginStrip.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -59,7 +59,7 @@
 block discarded – undo
59 59
      * @param string   $append
60 60
      * @param string   $content
61 61
      *
62
-     * @return mixed|string
62
+     * @return string
63 63
      */
64 64
     public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
65 65
     {
Please login to merge, or discard this patch.
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -31,59 +31,59 @@
 block discarded – undo
31 31
  */
32 32
 class PluginStrip extends BlockPlugin implements ICompilableBlock
33 33
 {
34
-    /**
35
-     * @param string $mode
36
-     */
37
-    public function init($mode = 'default')
38
-    {
39
-    }
34
+	/**
35
+	 * @param string $mode
36
+	 */
37
+	public function init($mode = 'default')
38
+	{
39
+	}
40 40
 
41
-    /**
42
-     * @param Compiler $compiler
43
-     * @param array    $params
44
-     * @param string   $prepend
45
-     * @param string   $append
46
-     * @param string   $type
47
-     *
48
-     * @return string
49
-     */
50
-    public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
51
-    {
52
-        return '';
53
-    }
41
+	/**
42
+	 * @param Compiler $compiler
43
+	 * @param array    $params
44
+	 * @param string   $prepend
45
+	 * @param string   $append
46
+	 * @param string   $type
47
+	 *
48
+	 * @return string
49
+	 */
50
+	public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
51
+	{
52
+		return '';
53
+	}
54 54
 
55
-    /**
56
-     * @param Compiler $compiler
57
-     * @param array    $params
58
-     * @param string   $prepend
59
-     * @param string   $append
60
-     * @param string   $content
61
-     *
62
-     * @return mixed|string
63
-     */
64
-    public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
65
-    {
66
-        $params = $compiler->getCompiledParams($params);
55
+	/**
56
+	 * @param Compiler $compiler
57
+	 * @param array    $params
58
+	 * @param string   $prepend
59
+	 * @param string   $append
60
+	 * @param string   $content
61
+	 *
62
+	 * @return mixed|string
63
+	 */
64
+	public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
65
+	{
66
+		$params = $compiler->getCompiledParams($params);
67 67
 
68
-        $mode = trim($params['mode'], '"\'');
69
-        switch ($mode) {
70
-            case 'js':
71
-            case 'javascript':
72
-                $content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
68
+		$mode = trim($params['mode'], '"\'');
69
+		switch ($mode) {
70
+			case 'js':
71
+			case 'javascript':
72
+				$content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
73 73
 
74
-            case 'default':
75
-            default:
76
-        }
77
-        $content = preg_replace(array(
78
-            "/\n/",
79
-            "/\r/",
80
-            '/(<\?(?:php)?|<%)\s*/'
81
-        ), array(
82
-            '',
83
-            '',
84
-            '$1 '
85
-        ), preg_replace('#^\s*(.+?)\s*$#m', '$1', $content));
74
+			case 'default':
75
+			default:
76
+		}
77
+		$content = preg_replace(array(
78
+			"/\n/",
79
+			"/\r/",
80
+			'/(<\?(?:php)?|<%)\s*/'
81
+		), array(
82
+			'',
83
+			'',
84
+			'$1 '
85
+		), preg_replace('#^\s*(.+?)\s*$#m', '$1', $content));
86 86
 
87
-        return $content;
88
-    }
87
+		return $content;
88
+	}
89 89
 }
Please login to merge, or discard this patch.
Switch Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -67,12 +67,12 @@
 block discarded – undo
67 67
 
68 68
         $mode = trim($params['mode'], '"\'');
69 69
         switch ($mode) {
70
-            case 'js':
71
-            case 'javascript':
72
-                $content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
70
+        case 'js':
71
+        case 'javascript':
72
+            $content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
73 73
 
74
-            case 'default':
75
-            default:
74
+        case 'default':
75
+        default:
76 76
         }
77 77
         $content = preg_replace(array(
78 78
             "/\n/",
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Processors/PluginSmartyCompatible.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -29,7 +29,7 @@
 block discarded – undo
29 29
     /**
30 30
      * @param string $input
31 31
      *
32
-     * @return mixed
32
+     * @return string
33 33
      */
34 34
     public function process($input)
35 35
     {
Please login to merge, or discard this patch.
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -26,69 +26,69 @@
 block discarded – undo
26 26
  */
27 27
 class PluginSmartyCompatible extends Processor
28 28
 {
29
-    /**
30
-     * @param string $input
31
-     *
32
-     * @return mixed
33
-     */
34
-    public function process($input)
35
-    {
36
-        list($l, $r) = $this->compiler->getDelimiters();
29
+	/**
30
+	 * @param string $input
31
+	 *
32
+	 * @return mixed
33
+	 */
34
+	public function process($input)
35
+	{
36
+		list($l, $r) = $this->compiler->getDelimiters();
37 37
 
38
-        $rl           = preg_quote($l, '/');
39
-        $rr           = preg_quote($r, '/');
40
-        $sectionParam = '(?:(name|loop|start|step|max|show)\s*=\s*(\S+))?\s*';
41
-        $input        = preg_replace_callback('/' . $rl . '\s*section ' . str_repeat($sectionParam, 6) . '\s*' . $rr . '(.+?)(?:' . $rl . '\s*sectionelse\s*' . $rr . '(.+?))?' . $rl . '\s*\/section\s*' . $rr . '/is', array(
42
-            $this,
43
-            'convertSection'
44
-        ), $input);
45
-        $input        = str_replace('$smarty.section.', '$smarty.for.', $input);
38
+		$rl           = preg_quote($l, '/');
39
+		$rr           = preg_quote($r, '/');
40
+		$sectionParam = '(?:(name|loop|start|step|max|show)\s*=\s*(\S+))?\s*';
41
+		$input        = preg_replace_callback('/' . $rl . '\s*section ' . str_repeat($sectionParam, 6) . '\s*' . $rr . '(.+?)(?:' . $rl . '\s*sectionelse\s*' . $rr . '(.+?))?' . $rl . '\s*\/section\s*' . $rr . '/is', array(
42
+			$this,
43
+			'convertSection'
44
+		), $input);
45
+		$input        = str_replace('$smarty.section.', '$smarty.for.', $input);
46 46
 
47
-        $smarty = array(
48
-            '/' . $rl . '\s*ldelim\s*' . $rr . '/',
49
-            '/' . $rl . '\s*rdelim\s*' . $rr . '/',
50
-            '/' . $rl . '\s*\$smarty\.ldelim\s*' . $rr . '/',
51
-            '/' . $rl . '\s*\$smarty\.rdelim\s*' . $rr . '/',
52
-            '/\$smarty\./',
53
-            '/' . $rl . '\s*php\s*' . $rr . '/',
54
-            '/' . $rl . '\s*\/php\s*' . $rr . '/',
55
-            '/\|(@?)strip(\||' . $rr . ')/',
56
-            '/' . $rl . '\s*sectionelse\s*' . $rr . '/',
57
-        );
47
+		$smarty = array(
48
+			'/' . $rl . '\s*ldelim\s*' . $rr . '/',
49
+			'/' . $rl . '\s*rdelim\s*' . $rr . '/',
50
+			'/' . $rl . '\s*\$smarty\.ldelim\s*' . $rr . '/',
51
+			'/' . $rl . '\s*\$smarty\.rdelim\s*' . $rr . '/',
52
+			'/\$smarty\./',
53
+			'/' . $rl . '\s*php\s*' . $rr . '/',
54
+			'/' . $rl . '\s*\/php\s*' . $rr . '/',
55
+			'/\|(@?)strip(\||' . $rr . ')/',
56
+			'/' . $rl . '\s*sectionelse\s*' . $rr . '/',
57
+		);
58 58
 
59
-        $dwoo = array(
60
-            '\\' . $l,
61
-            $r,
62
-            '\\' . $l,
63
-            $r,
64
-            '$dwoo.',
65
-            '<?php ',
66
-            ' ?>',
67
-            '|$1whitespace$2',
68
-            $l . 'else' . $r,
69
-        );
59
+		$dwoo = array(
60
+			'\\' . $l,
61
+			$r,
62
+			'\\' . $l,
63
+			$r,
64
+			'$dwoo.',
65
+			'<?php ',
66
+			' ?>',
67
+			'|$1whitespace$2',
68
+			$l . 'else' . $r,
69
+		);
70 70
 
71
-        if (preg_match('{\|@([a-z][a-z0-9_]*)}i', $input, $matches)) {
72
-            trigger_error('The Smarty Compatibility Module has detected that you use |@' . $matches[1] . ' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
73
-        }
71
+		if (preg_match('{\|@([a-z][a-z0-9_]*)}i', $input, $matches)) {
72
+			trigger_error('The Smarty Compatibility Module has detected that you use |@' . $matches[1] . ' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
73
+		}
74 74
 
75
-        return preg_replace($smarty, $dwoo, $input);
76
-    }
75
+		return preg_replace($smarty, $dwoo, $input);
76
+	}
77 77
 
78
-    /**
79
-     * @param array $matches
80
-     *
81
-     * @return mixed
82
-     */
83
-    protected function convertSection(array $matches)
84
-    {
85
-        $params = array();
86
-        $index  = 1;
87
-        while (!empty($matches[$index]) && $index < 13) {
88
-            $params[$matches[$index]] = $matches[$index + 1];
89
-            $index += 2;
90
-        }
78
+	/**
79
+	 * @param array $matches
80
+	 *
81
+	 * @return mixed
82
+	 */
83
+	protected function convertSection(array $matches)
84
+	{
85
+		$params = array();
86
+		$index  = 1;
87
+		while (!empty($matches[$index]) && $index < 13) {
88
+			$params[$matches[$index]] = $matches[$index + 1];
89
+			$index += 2;
90
+		}
91 91
 
92
-        return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
93
-    }
92
+		return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
93
+	}
94 94
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -38,38 +38,38 @@  discard block
 block discarded – undo
38 38
         $rl           = preg_quote($l, '/');
39 39
         $rr           = preg_quote($r, '/');
40 40
         $sectionParam = '(?:(name|loop|start|step|max|show)\s*=\s*(\S+))?\s*';
41
-        $input        = preg_replace_callback('/' . $rl . '\s*section ' . str_repeat($sectionParam, 6) . '\s*' . $rr . '(.+?)(?:' . $rl . '\s*sectionelse\s*' . $rr . '(.+?))?' . $rl . '\s*\/section\s*' . $rr . '/is', array(
41
+        $input        = preg_replace_callback('/'.$rl.'\s*section '.str_repeat($sectionParam, 6).'\s*'.$rr.'(.+?)(?:'.$rl.'\s*sectionelse\s*'.$rr.'(.+?))?'.$rl.'\s*\/section\s*'.$rr.'/is', array(
42 42
             $this,
43 43
             'convertSection'
44 44
         ), $input);
45
-        $input        = str_replace('$smarty.section.', '$smarty.for.', $input);
45
+        $input = str_replace('$smarty.section.', '$smarty.for.', $input);
46 46
 
47 47
         $smarty = array(
48
-            '/' . $rl . '\s*ldelim\s*' . $rr . '/',
49
-            '/' . $rl . '\s*rdelim\s*' . $rr . '/',
50
-            '/' . $rl . '\s*\$smarty\.ldelim\s*' . $rr . '/',
51
-            '/' . $rl . '\s*\$smarty\.rdelim\s*' . $rr . '/',
48
+            '/'.$rl.'\s*ldelim\s*'.$rr.'/',
49
+            '/'.$rl.'\s*rdelim\s*'.$rr.'/',
50
+            '/'.$rl.'\s*\$smarty\.ldelim\s*'.$rr.'/',
51
+            '/'.$rl.'\s*\$smarty\.rdelim\s*'.$rr.'/',
52 52
             '/\$smarty\./',
53
-            '/' . $rl . '\s*php\s*' . $rr . '/',
54
-            '/' . $rl . '\s*\/php\s*' . $rr . '/',
55
-            '/\|(@?)strip(\||' . $rr . ')/',
56
-            '/' . $rl . '\s*sectionelse\s*' . $rr . '/',
53
+            '/'.$rl.'\s*php\s*'.$rr.'/',
54
+            '/'.$rl.'\s*\/php\s*'.$rr.'/',
55
+            '/\|(@?)strip(\||'.$rr.')/',
56
+            '/'.$rl.'\s*sectionelse\s*'.$rr.'/',
57 57
         );
58 58
 
59 59
         $dwoo = array(
60
-            '\\' . $l,
60
+            '\\'.$l,
61 61
             $r,
62
-            '\\' . $l,
62
+            '\\'.$l,
63 63
             $r,
64 64
             '$dwoo.',
65 65
             '<?php ',
66 66
             ' ?>',
67 67
             '|$1whitespace$2',
68
-            $l . 'else' . $r,
68
+            $l.'else'.$r,
69 69
         );
70 70
 
71 71
         if (preg_match('{\|@([a-z][a-z0-9_]*)}i', $input, $matches)) {
72
-            trigger_error('The Smarty Compatibility Module has detected that you use |@' . $matches[1] . ' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
72
+            trigger_error('The Smarty Compatibility Module has detected that you use |@'.$matches[1].' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
73 73
         }
74 74
 
75 75
         return preg_replace($smarty, $dwoo, $input);
@@ -85,10 +85,10 @@  discard block
 block discarded – undo
85 85
         $params = array();
86 86
         $index  = 1;
87 87
         while (!empty($matches[$index]) && $index < 13) {
88
-            $params[$matches[$index]] = $matches[$index + 1];
88
+            $params[$matches[$index]] = $matches[$index+1];
89 89
             $index += 2;
90 90
         }
91 91
 
92
-        return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
92
+        return str_replace('['.trim($params['name'], '"\'').']', '[$'.trim($params['name'], '"\'').']', $matches[0]);
93 93
     }
94 94
 }
Please login to merge, or discard this patch.
lib/Dwoo/Smarty/Adapter.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -312,7 +312,7 @@
 block discarded – undo
312 312
 
313 313
     /**
314 314
      * @param mixed $_tpl
315
-     * @param array $data
315
+     * @param Data $data
316 316
      * @param null  $_compiler
317 317
      * @param bool  $_output
318 318
      *
Please login to merge, or discard this patch.
Indentation   +657 added lines, -657 removed lines patch added patch discarded remove patch
@@ -26,14 +26,14 @@  discard block
 block discarded – undo
26 26
 use Dwoo\Smarty\Processor\Adapter as ProcessorAdapter;
27 27
 
28 28
 if (!defined('DIR_SEP')) {
29
-    define('DIR_SEP', DIRECTORY_SEPARATOR);
29
+	define('DIR_SEP', DIRECTORY_SEPARATOR);
30 30
 }
31 31
 
32 32
 if (!defined('SMARTY_PHP_PASSTHRU')) {
33
-    define('SMARTY_PHP_PASSTHRU', 0);
34
-    define('SMARTY_PHP_QUOTE', 1);
35
-    define('SMARTY_PHP_REMOVE', 2);
36
-    define('SMARTY_PHP_ALLOW', 3);
33
+	define('SMARTY_PHP_PASSTHRU', 0);
34
+	define('SMARTY_PHP_QUOTE', 1);
35
+	define('SMARTY_PHP_REMOVE', 2);
36
+	define('SMARTY_PHP_ALLOW', 3);
37 37
 }
38 38
 
39 39
 /**
@@ -43,656 +43,656 @@  discard block
 block discarded – undo
43 43
  */
44 44
 class Adapter extends Core
45 45
 {
46
-    /**
47
-     * Magic get/set/call functions that handle unsupported features
48
-     *
49
-     * @param string $p
50
-     * @param string $v
51
-     */
52
-    public function __set($p, $v)
53
-    {
54
-        if ($p === 'scope') {
55
-            $this->scope = $v;
56
-
57
-            return;
58
-        }
59
-        if ($p === 'data') {
60
-            $this->data = $v;
61
-
62
-            return;
63
-        }
64
-        if (array_key_exists($p, $this->compat['properties']) !== false) {
65
-            if ($this->show_compat_errors) {
66
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
67
-            }
68
-            $this->compat['properties'][$p] = $v;
69
-        } else {
70
-            if ($this->show_compat_errors) {
71
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
72
-            }
73
-        }
74
-    }
75
-
76
-    /**
77
-     * @param $p
78
-     *
79
-     * @return mixed
80
-     */
81
-    public function __get($p)
82
-    {
83
-        if (array_key_exists($p, $this->compat['properties']) !== false) {
84
-            if ($this->show_compat_errors) {
85
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
86
-            }
87
-
88
-            return $this->compat['properties'][$p];
89
-        } else {
90
-            if ($this->show_compat_errors) {
91
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
92
-            }
93
-        }
94
-    }
95
-
96
-    /**
97
-     * @param string $m
98
-     * @param array  $a
99
-     *
100
-     * @return mixed|void
101
-     */
102
-    public function __call($m, $a)
103
-    {
104
-        if (method_exists($this->dataProvider, $m)) {
105
-            call_user_func_array(
106
-                array(
107
-                $this->dataProvider,
108
-                $m
109
-                ), $a
110
-            );
111
-        } elseif ($this->show_compat_errors) {
112
-            if (array_search($m, $this->compat['methods']) !== false) {
113
-                $this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
114
-            } else {
115
-                $this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
116
-            }
117
-        }
118
-    }
119
-
120
-    /**
121
-     * List of unsupported properties and methods
122
-     */
123
-    protected $compat = array(
124
-        'methods'    => array(
125
-            'register_resource',
126
-            'unregister_resource',
127
-            'load_filter',
128
-            'clear_compiled_tpl',
129
-            'clear_config',
130
-            'get_config_vars',
131
-            'config_load',
132
-        ),
133
-        'properties' => array(
134
-            'cache_handler_func'            => null,
135
-            'debugging'                     => false,
136
-            'error_reporting'               => null,
137
-            'debugging_ctrl'                => 'NONE',
138
-            'request_vars_order'            => 'EGPCS',
139
-            'request_use_auto_globals'      => true,
140
-            'use_sub_dirs'                  => false,
141
-            'autoload_filters'              => array(),
142
-            'default_template_handler_func' => '',
143
-            'debug_tpl'                     => '',
144
-            'cache_modified_check'          => false,
145
-            'default_modifiers'             => array(),
146
-            'default_resource_type'         => 'file',
147
-            'config_overwrite'              => true,
148
-            'config_booleanize'             => true,
149
-            'config_read_hidden'            => false,
150
-            'config_fix_newlines'           => true,
151
-            'config_class'                  => 'Config_File',
152
-        ),
153
-    );
154
-
155
-    /**
156
-     * Security vars
157
-     */
158
-    public $security          = false;
159
-    public $trusted_dir       = array();
160
-    public $secure_dir        = array();
161
-    public $php_handling      = SMARTY_PHP_PASSTHRU;
162
-    public $security_settings = array(
163
-        'PHP_HANDLING'    => false,
164
-        'IF_FUNCS'        => array(
165
-            'list',
166
-            'empty',
167
-            'count',
168
-            'sizeof',
169
-            'in_array',
170
-            'is_array',
171
-        ),
172
-        'INCLUDE_ANY'     => false,
173
-        'PHP_TAGS'        => false,
174
-        'MODIFIER_FUNCS'  => array(),
175
-        'ALLOW_CONSTANTS' => false,
176
-    );
177
-
178
-    /**
179
-     * Paths
180
-     */
181
-    public $template_dir = 'templates';
182
-    public $compile_dir  = 'templates_c';
183
-    public $config_dir   = 'configs';
184
-    public $cache_dir    = 'cache';
185
-    public $plugins_dir  = array();
186
-
187
-    /**
188
-     * Misc options
189
-     */
190
-    public $left_delimiter  = '{';
191
-    public $right_delimiter = '}';
192
-    public $compile_check   = true;
193
-    public $force_compile   = false;
194
-    public $caching         = 0;
195
-    public $cache_lifetime  = 3600;
196
-    public $compile_id      = null;
197
-    public $compiler_file   = null;
198
-    public $compiler_class  = null;
199
-
200
-    /**
201
-     * Dwoo/Smarty compat layer
202
-     */
203
-    public           $show_compat_errors = false;
204
-    protected        $dataProvider;
205
-    protected        $_filters           = array(
206
-        'pre'    => array(),
207
-        'post'   => array(),
208
-        'output' => array()
209
-    );
210
-    protected static $tplCache           = array();
211
-    protected        $compiler           = null;
212
-
213
-    /**
214
-     * Adapter constructor.
215
-     */
216
-    public function __construct()
217
-    {
218
-        parent::__construct();
219
-        $this->charset      = 'iso-8859-1';
220
-        $this->dataProvider = new Data();
221
-        $this->compiler     = new Compiler();
222
-    }
223
-
224
-    /**
225
-     * @param      $filename
226
-     * @param null $cacheId
227
-     * @param null $compileId
228
-     */
229
-    public function display($filename, $cacheId = null, $compileId = null)
230
-    {
231
-        $this->fetch($filename, $cacheId, $compileId, true);
232
-    }
233
-
234
-    /**
235
-     * @param      $filename
236
-     * @param null $cacheId
237
-     * @param null $compileId
238
-     * @param bool $display
239
-     *
240
-     * @return string|void
241
-     */
242
-    public function fetch($filename, $cacheId = null, $compileId = null, $display = false)
243
-    {
244
-        $this->setCacheDir($this->cache_dir);
245
-        $this->setCompileDir($this->compile_dir);
246
-
247
-        if ($this->security) {
248
-            $policy = new SecurityPolicy();
249
-            $policy->addPhpFunction(array_merge($this->security_settings['IF_FUNCS'], $this->security_settings['MODIFIER_FUNCS']));
250
-
251
-            $phpTags = $this->security_settings['PHP_HANDLING'] ? SMARTY_PHP_ALLOW : $this->php_handling;
252
-            if ($this->security_settings['PHP_TAGS']) {
253
-                $phpTags = SMARTY_PHP_ALLOW;
254
-            }
255
-            switch ($phpTags) {
256
-            case SMARTY_PHP_ALLOW:
257
-            case SMARTY_PHP_PASSTHRU:
258
-                $phpTags = SecurityPolicy::PHP_ALLOW;
259
-                break;
260
-            case SMARTY_PHP_QUOTE:
261
-                $phpTags = SecurityPolicy::PHP_ENCODE;
262
-                break;
263
-            case SMARTY_PHP_REMOVE:
264
-            default:
265
-                $phpTags = SecurityPolicy::PHP_REMOVE;
266
-                break;
267
-            }
268
-            $policy->setPhpHandling($phpTags);
269
-
270
-            $policy->setConstantHandling($this->security_settings['ALLOW_CONSTANTS']);
271
-
272
-            if ($this->security_settings['INCLUDE_ANY']) {
273
-                $policy->allowDirectory(preg_replace('{^((?:[a-z]:)?[\\\\/]).*}i', '$1', __FILE__));
274
-            } else {
275
-                $policy->allowDirectory($this->secure_dir);
276
-            }
277
-
278
-            $this->setSecurityPolicy($policy);
279
-        }
280
-
281
-        if (!empty($this->plugins_dir)) {
282
-            foreach ($this->plugins_dir as $dir) {
283
-                $this->getLoader()->addDirectory(rtrim($dir, '\\/'));
284
-            }
285
-        }
286
-
287
-        $tpl = $this->makeTemplate($filename, $cacheId, $compileId);
288
-        if ($this->force_compile) {
289
-            $tpl->forceCompilation();
290
-        }
291
-
292
-        if ($this->caching > 0) {
293
-            $this->cacheTime = $this->cache_lifetime;
294
-        } else {
295
-            $this->cacheTime = 0;
296
-        }
297
-
298
-        if ($this->compiler_class !== null) {
299
-            if ($this->compiler_file !== null && !class_exists($this->compiler_class)) {
300
-                include $this->compiler_file;
301
-            }
302
-            $this->compiler = new $this->compiler_class();
303
-        } else {
304
-            $this->compiler->addPreProcessor('PluginSmartyCompatible', true);
305
-            $this->compiler->setLooseOpeningHandling(true);
306
-        }
307
-
308
-        $this->compiler->setDelimiters($this->left_delimiter, $this->right_delimiter);
309
-
310
-        return $this->get($tpl, $this->dataProvider, $this->compiler, $display === true);
311
-    }
312
-
313
-    /**
314
-     * @param mixed $_tpl
315
-     * @param array $data
316
-     * @param null  $_compiler
317
-     * @param bool  $_output
318
-     *
319
-     * @return string|void
320
-     */
321
-    public function get($_tpl, $data = array(), $_compiler = null, $_output = false)
322
-    {
323
-        if ($_compiler === null) {
324
-            $_compiler = $this->compiler;
325
-        }
326
-
327
-        return parent::get($_tpl, $data, $_compiler, $_output);
328
-    }
329
-
330
-    /**
331
-     * @param      $name
332
-     * @param      $callback
333
-     * @param bool $cacheable
334
-     * @param null $cache_attrs
335
-     *
336
-     * @throws Exception
337
-     */
338
-    public function register_function($name, $callback, $cacheable = true, $cache_attrs = null)
339
-    {
340
-        if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_FUNCTION) {
341
-            throw new Exception('Multiple plugins of different types can not share the same name');
342
-        }
343
-        $this->plugins[$name] = array(
344
-            'type'     => self::SMARTY_FUNCTION,
345
-            'callback' => $callback
346
-        );
347
-    }
348
-
349
-    /**
350
-     * @param $name
351
-     */
352
-    public function unregister_function($name)
353
-    {
354
-        unset($this->plugins[$name]);
355
-    }
356
-
357
-    /**
358
-     * @param      $name
359
-     * @param      $callback
360
-     * @param bool $cacheable
361
-     * @param null $cache_attrs
362
-     *
363
-     * @throws Exception
364
-     */
365
-    public function register_block($name, $callback, $cacheable = true, $cache_attrs = null)
366
-    {
367
-        if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_BLOCK) {
368
-            throw new Exception('Multiple plugins of different types can not share the same name');
369
-        }
370
-        $this->plugins[$name] = array(
371
-            'type'     => self::SMARTY_BLOCK,
372
-            'callback' => $callback
373
-        );
374
-    }
375
-
376
-    /**
377
-     * @param $name
378
-     */
379
-    public function unregister_block($name)
380
-    {
381
-        unset($this->plugins[$name]);
382
-    }
383
-
384
-    /**
385
-     * @param $name
386
-     * @param $callback
387
-     *
388
-     * @throws Exception
389
-     */
390
-    public function register_modifier($name, $callback)
391
-    {
392
-        if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_MODIFIER) {
393
-            throw new Exception('Multiple plugins of different types can not share the same name');
394
-        }
395
-        $this->plugins[$name] = array(
396
-            'type'     => self::SMARTY_MODIFIER,
397
-            'callback' => $callback
398
-        );
399
-    }
400
-
401
-    /**
402
-     * @param $name
403
-     */
404
-    public function unregister_modifier($name)
405
-    {
406
-        unset($this->plugins[$name]);
407
-    }
408
-
409
-    /**
410
-     * @param $callback
411
-     */
412
-    public function register_prefilter($callback)
413
-    {
414
-        $processor = new ProcessorAdapter($this->compiler);
415
-        $processor->registerCallback($callback);
416
-        $this->_filters['pre'][] = $processor;
417
-        $this->compiler->addPreProcessor($processor);
418
-    }
419
-
420
-    /**
421
-     * @param $callback
422
-     */
423
-    public function unregister_prefilter($callback)
424
-    {
425
-        foreach ($this->_filters['pre'] as $index => $processor) {
426
-            if ($processor->callback === $callback) {
427
-                $this->compiler->removePostProcessor($processor);
428
-                unset($this->_filters['pre'][$index]);
429
-            }
430
-        }
431
-    }
432
-
433
-    /**
434
-     * @param $callback
435
-     */
436
-    public function register_postfilter($callback)
437
-    {
438
-        $processor = new ProcessorAdapter($this->compiler);
439
-        $processor->registerCallback($callback);
440
-        $this->_filters['post'][] = $processor;
441
-        $this->compiler->addPostProcessor($processor);
442
-    }
443
-
444
-    /**
445
-     * @param $callback
446
-     */
447
-    public function unregister_postfilter($callback)
448
-    {
449
-        foreach ($this->_filters['post'] as $index => $processor) {
450
-            if ($processor->callback === $callback) {
451
-                $this->compiler->removePostProcessor($processor);
452
-                unset($this->_filters['post'][$index]);
453
-            }
454
-        }
455
-    }
456
-
457
-    /**
458
-     * @param $callback
459
-     */
460
-    public function register_outputfilter($callback)
461
-    {
462
-        $filter = new FilterAdapter($this);
463
-        $filter->registerCallback($callback);
464
-        $this->_filters['output'][] = $filter;
465
-        $this->addFilter($filter);
466
-    }
467
-
468
-    /**
469
-     * @param $callback
470
-     */
471
-    public function unregister_outputfilter($callback)
472
-    {
473
-        foreach ($this->_filters['output'] as $index => $filter) {
474
-            if ($filter->callback === $callback) {
475
-                $this->removeOutputFilter($filter);
476
-                unset($this->_filters['output'][$index]);
477
-            }
478
-        }
479
-    }
480
-
481
-    /**
482
-     * @param       $object
483
-     * @param       $object_impl
484
-     * @param array $allowed
485
-     * @param bool  $smarty_args
486
-     * @param array $block_methods
487
-     */
488
-    public function register_object($object, $object_impl, $allowed = array(), $smarty_args = false, $block_methods = array())
489
-    {
490
-        settype($allowed, 'array');
491
-        settype($block_methods, 'array');
492
-        settype($smarty_args, 'boolean');
493
-
494
-        if (!empty($allowed) && $this->show_compat_errors) {
495
-            $this->triggerError('You can register objects but can not restrict the method/properties used, this is PHP5, you have proper OOP access restrictions so use them.', E_USER_NOTICE);
496
-        }
497
-
498
-        if ($smarty_args) {
499
-            $this->triggerError('You can register objects but methods will be called using method($arg1, $arg2, $arg3), not as an argument array like smarty did.', E_USER_NOTICE);
500
-        }
501
-
502
-        if (!empty($block_methods)) {
503
-            $this->triggerError('You can register objects but can not use methods as being block methods, you have to build a plugin for that.', E_USER_NOTICE);
504
-        }
505
-
506
-        $this->dataProvider->assign($object, $object_impl);
507
-    }
508
-
509
-    /**
510
-     * @param $object
511
-     */
512
-    public function unregister_object($object)
513
-    {
514
-        $this->dataProvider->clear($object);
515
-    }
516
-
517
-    /**
518
-     * @param $name
519
-     *
520
-     * @return mixed
521
-     */
522
-    public function get_registered_object($name)
523
-    {
524
-        $data = $this->dataProvider->getData();
525
-        if (isset($data[$name]) && is_object($data[$name])) {
526
-            return $data[$name];
527
-        } else {
528
-            trigger_error('Dwoo_Compiler: object "' . $name . '" was not registered or is not an object', E_USER_ERROR);
529
-        }
530
-    }
531
-
532
-    /**
533
-     * @param $filename
534
-     *
535
-     * @return bool
536
-     */
537
-    public function template_exists($filename)
538
-    {
539
-        if (!is_array($this->template_dir)) {
540
-            return file_exists($this->template_dir . DIRECTORY_SEPARATOR . $filename);
541
-        } else {
542
-            foreach ($this->template_dir as $tpl_dir) {
543
-                if (file_exists($tpl_dir . DIRECTORY_SEPARATOR . $filename)) {
544
-                    return true;
545
-                }
546
-            }
547
-
548
-            return false;
549
-        }
550
-    }
551
-
552
-    /**
553
-     * @param      $tpl
554
-     * @param null $cacheId
555
-     * @param null $compileId
556
-     *
557
-     * @return bool
558
-     */
559
-    public function is_cached($tpl, $cacheId = null, $compileId = null)
560
-    {
561
-        return $this->isCached($this->makeTemplate($tpl, $cacheId, $compileId));
562
-    }
563
-
564
-    /**
565
-     * @param      $var
566
-     * @param      $value
567
-     * @param bool $merge
568
-     */
569
-    public function append_by_ref($var, &$value, $merge = false)
570
-    {
571
-        $this->dataProvider->appendByRef($var, $value, $merge);
572
-    }
573
-
574
-    /**
575
-     * @param $name
576
-     * @param $val
577
-     */
578
-    public function assign_by_ref($name, &$val)
579
-    {
580
-        $this->dataProvider->assignByRef($name, $val);
581
-    }
582
-
583
-    /**
584
-     * @param $var
585
-     */
586
-    public function clear_assign($var)
587
-    {
588
-        $this->dataProvider->clear($var);
589
-    }
590
-
591
-    /**
592
-     *
593
-     */
594
-    public function clear_all_assign()
595
-    {
596
-        $this->dataProvider->clear();
597
-    }
598
-
599
-    /**
600
-     * @param null $name
601
-     *
602
-     * @return array|null
603
-     */
604
-    public function get_template_vars($name = null)
605
-    {
606
-        if ($this->show_compat_errors) {
607
-            trigger_error('get_template_vars does not return values by reference, if you try to modify the data that way you should modify your code.', E_USER_NOTICE);
608
-        }
609
-
610
-        $data = $this->dataProvider->getData();
611
-        if ($name === null) {
612
-            return $data;
613
-        } elseif (isset($data[$name])) {
614
-            return $data[$name];
615
-        }
616
-
617
-        return null;
618
-    }
619
-
620
-    /**
621
-     * @param int $olderThan
622
-     */
623
-    public function clear_all_cache($olderThan = 0)
624
-    {
625
-        $this->clearCache($olderThan);
626
-    }
627
-
628
-    /**
629
-     * @param      $template
630
-     * @param null $cacheId
631
-     * @param null $compileId
632
-     * @param int  $olderThan
633
-     */
634
-    public function clear_cache($template, $cacheId = null, $compileId = null, $olderThan = 0)
635
-    {
636
-        $this->makeTemplate($template, $cacheId, $compileId)->clearCache($olderThan);
637
-    }
638
-
639
-    /**
640
-     * @param     $error_msg
641
-     * @param int $error_type
642
-     */
643
-    public function trigger_error($error_msg, $error_type = E_USER_WARNING)
644
-    {
645
-        $this->triggerError($error_msg, $error_type);
646
-    }
647
-
648
-    /**
649
-     *
650
-     */
651
-    protected function initGlobals()
652
-    {
653
-        parent::initGlobals();
654
-        $this->globals['ldelim'] = '{';
655
-        $this->globals['rdelim'] = '}';
656
-    }
657
-
658
-    /**
659
-     * @param $file
660
-     * @param $cacheId
661
-     * @param $compileId
662
-     *
663
-     * @return mixed
664
-     * @throws Exception
665
-     */
666
-    protected function makeTemplate($file, $cacheId, $compileId)
667
-    {
668
-        if ($compileId === null) {
669
-            $compileId = $this->compile_id;
670
-        }
671
-
672
-        $hash = bin2hex(md5($file . $cacheId . $compileId, true));
673
-        if (!isset(self::$tplCache[$hash])) {
674
-            // abs path
675
-            if (substr($file, 0, 1) === '/' || substr($file, 1, 1) === ':') {
676
-                self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId);
677
-            } elseif (is_string($this->template_dir) || is_array($this->template_dir)) {
678
-                self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId, $this->template_dir);
679
-            } else {
680
-                throw new Exception('Unable to load "' . $file . '", check the template_dir');
681
-            }
682
-        }
683
-
684
-        return self::$tplCache[$hash];
685
-    }
686
-
687
-    /**
688
-     * @param string $message
689
-     * @param int    $level
690
-     */
691
-    public function triggerError($message, $level = E_USER_NOTICE)
692
-    {
693
-        if (is_object($this->template)) {
694
-            parent::triggerError($message, $level);
695
-        }
696
-        trigger_error('Dwoo error : ' . $message, $level);
697
-    }
46
+	/**
47
+	 * Magic get/set/call functions that handle unsupported features
48
+	 *
49
+	 * @param string $p
50
+	 * @param string $v
51
+	 */
52
+	public function __set($p, $v)
53
+	{
54
+		if ($p === 'scope') {
55
+			$this->scope = $v;
56
+
57
+			return;
58
+		}
59
+		if ($p === 'data') {
60
+			$this->data = $v;
61
+
62
+			return;
63
+		}
64
+		if (array_key_exists($p, $this->compat['properties']) !== false) {
65
+			if ($this->show_compat_errors) {
66
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
67
+			}
68
+			$this->compat['properties'][$p] = $v;
69
+		} else {
70
+			if ($this->show_compat_errors) {
71
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
72
+			}
73
+		}
74
+	}
75
+
76
+	/**
77
+	 * @param $p
78
+	 *
79
+	 * @return mixed
80
+	 */
81
+	public function __get($p)
82
+	{
83
+		if (array_key_exists($p, $this->compat['properties']) !== false) {
84
+			if ($this->show_compat_errors) {
85
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
86
+			}
87
+
88
+			return $this->compat['properties'][$p];
89
+		} else {
90
+			if ($this->show_compat_errors) {
91
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
92
+			}
93
+		}
94
+	}
95
+
96
+	/**
97
+	 * @param string $m
98
+	 * @param array  $a
99
+	 *
100
+	 * @return mixed|void
101
+	 */
102
+	public function __call($m, $a)
103
+	{
104
+		if (method_exists($this->dataProvider, $m)) {
105
+			call_user_func_array(
106
+				array(
107
+				$this->dataProvider,
108
+				$m
109
+				), $a
110
+			);
111
+		} elseif ($this->show_compat_errors) {
112
+			if (array_search($m, $this->compat['methods']) !== false) {
113
+				$this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
114
+			} else {
115
+				$this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
116
+			}
117
+		}
118
+	}
119
+
120
+	/**
121
+	 * List of unsupported properties and methods
122
+	 */
123
+	protected $compat = array(
124
+		'methods'    => array(
125
+			'register_resource',
126
+			'unregister_resource',
127
+			'load_filter',
128
+			'clear_compiled_tpl',
129
+			'clear_config',
130
+			'get_config_vars',
131
+			'config_load',
132
+		),
133
+		'properties' => array(
134
+			'cache_handler_func'            => null,
135
+			'debugging'                     => false,
136
+			'error_reporting'               => null,
137
+			'debugging_ctrl'                => 'NONE',
138
+			'request_vars_order'            => 'EGPCS',
139
+			'request_use_auto_globals'      => true,
140
+			'use_sub_dirs'                  => false,
141
+			'autoload_filters'              => array(),
142
+			'default_template_handler_func' => '',
143
+			'debug_tpl'                     => '',
144
+			'cache_modified_check'          => false,
145
+			'default_modifiers'             => array(),
146
+			'default_resource_type'         => 'file',
147
+			'config_overwrite'              => true,
148
+			'config_booleanize'             => true,
149
+			'config_read_hidden'            => false,
150
+			'config_fix_newlines'           => true,
151
+			'config_class'                  => 'Config_File',
152
+		),
153
+	);
154
+
155
+	/**
156
+	 * Security vars
157
+	 */
158
+	public $security          = false;
159
+	public $trusted_dir       = array();
160
+	public $secure_dir        = array();
161
+	public $php_handling      = SMARTY_PHP_PASSTHRU;
162
+	public $security_settings = array(
163
+		'PHP_HANDLING'    => false,
164
+		'IF_FUNCS'        => array(
165
+			'list',
166
+			'empty',
167
+			'count',
168
+			'sizeof',
169
+			'in_array',
170
+			'is_array',
171
+		),
172
+		'INCLUDE_ANY'     => false,
173
+		'PHP_TAGS'        => false,
174
+		'MODIFIER_FUNCS'  => array(),
175
+		'ALLOW_CONSTANTS' => false,
176
+	);
177
+
178
+	/**
179
+	 * Paths
180
+	 */
181
+	public $template_dir = 'templates';
182
+	public $compile_dir  = 'templates_c';
183
+	public $config_dir   = 'configs';
184
+	public $cache_dir    = 'cache';
185
+	public $plugins_dir  = array();
186
+
187
+	/**
188
+	 * Misc options
189
+	 */
190
+	public $left_delimiter  = '{';
191
+	public $right_delimiter = '}';
192
+	public $compile_check   = true;
193
+	public $force_compile   = false;
194
+	public $caching         = 0;
195
+	public $cache_lifetime  = 3600;
196
+	public $compile_id      = null;
197
+	public $compiler_file   = null;
198
+	public $compiler_class  = null;
199
+
200
+	/**
201
+	 * Dwoo/Smarty compat layer
202
+	 */
203
+	public           $show_compat_errors = false;
204
+	protected        $dataProvider;
205
+	protected        $_filters           = array(
206
+		'pre'    => array(),
207
+		'post'   => array(),
208
+		'output' => array()
209
+	);
210
+	protected static $tplCache           = array();
211
+	protected        $compiler           = null;
212
+
213
+	/**
214
+	 * Adapter constructor.
215
+	 */
216
+	public function __construct()
217
+	{
218
+		parent::__construct();
219
+		$this->charset      = 'iso-8859-1';
220
+		$this->dataProvider = new Data();
221
+		$this->compiler     = new Compiler();
222
+	}
223
+
224
+	/**
225
+	 * @param      $filename
226
+	 * @param null $cacheId
227
+	 * @param null $compileId
228
+	 */
229
+	public function display($filename, $cacheId = null, $compileId = null)
230
+	{
231
+		$this->fetch($filename, $cacheId, $compileId, true);
232
+	}
233
+
234
+	/**
235
+	 * @param      $filename
236
+	 * @param null $cacheId
237
+	 * @param null $compileId
238
+	 * @param bool $display
239
+	 *
240
+	 * @return string|void
241
+	 */
242
+	public function fetch($filename, $cacheId = null, $compileId = null, $display = false)
243
+	{
244
+		$this->setCacheDir($this->cache_dir);
245
+		$this->setCompileDir($this->compile_dir);
246
+
247
+		if ($this->security) {
248
+			$policy = new SecurityPolicy();
249
+			$policy->addPhpFunction(array_merge($this->security_settings['IF_FUNCS'], $this->security_settings['MODIFIER_FUNCS']));
250
+
251
+			$phpTags = $this->security_settings['PHP_HANDLING'] ? SMARTY_PHP_ALLOW : $this->php_handling;
252
+			if ($this->security_settings['PHP_TAGS']) {
253
+				$phpTags = SMARTY_PHP_ALLOW;
254
+			}
255
+			switch ($phpTags) {
256
+			case SMARTY_PHP_ALLOW:
257
+			case SMARTY_PHP_PASSTHRU:
258
+				$phpTags = SecurityPolicy::PHP_ALLOW;
259
+				break;
260
+			case SMARTY_PHP_QUOTE:
261
+				$phpTags = SecurityPolicy::PHP_ENCODE;
262
+				break;
263
+			case SMARTY_PHP_REMOVE:
264
+			default:
265
+				$phpTags = SecurityPolicy::PHP_REMOVE;
266
+				break;
267
+			}
268
+			$policy->setPhpHandling($phpTags);
269
+
270
+			$policy->setConstantHandling($this->security_settings['ALLOW_CONSTANTS']);
271
+
272
+			if ($this->security_settings['INCLUDE_ANY']) {
273
+				$policy->allowDirectory(preg_replace('{^((?:[a-z]:)?[\\\\/]).*}i', '$1', __FILE__));
274
+			} else {
275
+				$policy->allowDirectory($this->secure_dir);
276
+			}
277
+
278
+			$this->setSecurityPolicy($policy);
279
+		}
280
+
281
+		if (!empty($this->plugins_dir)) {
282
+			foreach ($this->plugins_dir as $dir) {
283
+				$this->getLoader()->addDirectory(rtrim($dir, '\\/'));
284
+			}
285
+		}
286
+
287
+		$tpl = $this->makeTemplate($filename, $cacheId, $compileId);
288
+		if ($this->force_compile) {
289
+			$tpl->forceCompilation();
290
+		}
291
+
292
+		if ($this->caching > 0) {
293
+			$this->cacheTime = $this->cache_lifetime;
294
+		} else {
295
+			$this->cacheTime = 0;
296
+		}
297
+
298
+		if ($this->compiler_class !== null) {
299
+			if ($this->compiler_file !== null && !class_exists($this->compiler_class)) {
300
+				include $this->compiler_file;
301
+			}
302
+			$this->compiler = new $this->compiler_class();
303
+		} else {
304
+			$this->compiler->addPreProcessor('PluginSmartyCompatible', true);
305
+			$this->compiler->setLooseOpeningHandling(true);
306
+		}
307
+
308
+		$this->compiler->setDelimiters($this->left_delimiter, $this->right_delimiter);
309
+
310
+		return $this->get($tpl, $this->dataProvider, $this->compiler, $display === true);
311
+	}
312
+
313
+	/**
314
+	 * @param mixed $_tpl
315
+	 * @param array $data
316
+	 * @param null  $_compiler
317
+	 * @param bool  $_output
318
+	 *
319
+	 * @return string|void
320
+	 */
321
+	public function get($_tpl, $data = array(), $_compiler = null, $_output = false)
322
+	{
323
+		if ($_compiler === null) {
324
+			$_compiler = $this->compiler;
325
+		}
326
+
327
+		return parent::get($_tpl, $data, $_compiler, $_output);
328
+	}
329
+
330
+	/**
331
+	 * @param      $name
332
+	 * @param      $callback
333
+	 * @param bool $cacheable
334
+	 * @param null $cache_attrs
335
+	 *
336
+	 * @throws Exception
337
+	 */
338
+	public function register_function($name, $callback, $cacheable = true, $cache_attrs = null)
339
+	{
340
+		if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_FUNCTION) {
341
+			throw new Exception('Multiple plugins of different types can not share the same name');
342
+		}
343
+		$this->plugins[$name] = array(
344
+			'type'     => self::SMARTY_FUNCTION,
345
+			'callback' => $callback
346
+		);
347
+	}
348
+
349
+	/**
350
+	 * @param $name
351
+	 */
352
+	public function unregister_function($name)
353
+	{
354
+		unset($this->plugins[$name]);
355
+	}
356
+
357
+	/**
358
+	 * @param      $name
359
+	 * @param      $callback
360
+	 * @param bool $cacheable
361
+	 * @param null $cache_attrs
362
+	 *
363
+	 * @throws Exception
364
+	 */
365
+	public function register_block($name, $callback, $cacheable = true, $cache_attrs = null)
366
+	{
367
+		if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_BLOCK) {
368
+			throw new Exception('Multiple plugins of different types can not share the same name');
369
+		}
370
+		$this->plugins[$name] = array(
371
+			'type'     => self::SMARTY_BLOCK,
372
+			'callback' => $callback
373
+		);
374
+	}
375
+
376
+	/**
377
+	 * @param $name
378
+	 */
379
+	public function unregister_block($name)
380
+	{
381
+		unset($this->plugins[$name]);
382
+	}
383
+
384
+	/**
385
+	 * @param $name
386
+	 * @param $callback
387
+	 *
388
+	 * @throws Exception
389
+	 */
390
+	public function register_modifier($name, $callback)
391
+	{
392
+		if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_MODIFIER) {
393
+			throw new Exception('Multiple plugins of different types can not share the same name');
394
+		}
395
+		$this->plugins[$name] = array(
396
+			'type'     => self::SMARTY_MODIFIER,
397
+			'callback' => $callback
398
+		);
399
+	}
400
+
401
+	/**
402
+	 * @param $name
403
+	 */
404
+	public function unregister_modifier($name)
405
+	{
406
+		unset($this->plugins[$name]);
407
+	}
408
+
409
+	/**
410
+	 * @param $callback
411
+	 */
412
+	public function register_prefilter($callback)
413
+	{
414
+		$processor = new ProcessorAdapter($this->compiler);
415
+		$processor->registerCallback($callback);
416
+		$this->_filters['pre'][] = $processor;
417
+		$this->compiler->addPreProcessor($processor);
418
+	}
419
+
420
+	/**
421
+	 * @param $callback
422
+	 */
423
+	public function unregister_prefilter($callback)
424
+	{
425
+		foreach ($this->_filters['pre'] as $index => $processor) {
426
+			if ($processor->callback === $callback) {
427
+				$this->compiler->removePostProcessor($processor);
428
+				unset($this->_filters['pre'][$index]);
429
+			}
430
+		}
431
+	}
432
+
433
+	/**
434
+	 * @param $callback
435
+	 */
436
+	public function register_postfilter($callback)
437
+	{
438
+		$processor = new ProcessorAdapter($this->compiler);
439
+		$processor->registerCallback($callback);
440
+		$this->_filters['post'][] = $processor;
441
+		$this->compiler->addPostProcessor($processor);
442
+	}
443
+
444
+	/**
445
+	 * @param $callback
446
+	 */
447
+	public function unregister_postfilter($callback)
448
+	{
449
+		foreach ($this->_filters['post'] as $index => $processor) {
450
+			if ($processor->callback === $callback) {
451
+				$this->compiler->removePostProcessor($processor);
452
+				unset($this->_filters['post'][$index]);
453
+			}
454
+		}
455
+	}
456
+
457
+	/**
458
+	 * @param $callback
459
+	 */
460
+	public function register_outputfilter($callback)
461
+	{
462
+		$filter = new FilterAdapter($this);
463
+		$filter->registerCallback($callback);
464
+		$this->_filters['output'][] = $filter;
465
+		$this->addFilter($filter);
466
+	}
467
+
468
+	/**
469
+	 * @param $callback
470
+	 */
471
+	public function unregister_outputfilter($callback)
472
+	{
473
+		foreach ($this->_filters['output'] as $index => $filter) {
474
+			if ($filter->callback === $callback) {
475
+				$this->removeOutputFilter($filter);
476
+				unset($this->_filters['output'][$index]);
477
+			}
478
+		}
479
+	}
480
+
481
+	/**
482
+	 * @param       $object
483
+	 * @param       $object_impl
484
+	 * @param array $allowed
485
+	 * @param bool  $smarty_args
486
+	 * @param array $block_methods
487
+	 */
488
+	public function register_object($object, $object_impl, $allowed = array(), $smarty_args = false, $block_methods = array())
489
+	{
490
+		settype($allowed, 'array');
491
+		settype($block_methods, 'array');
492
+		settype($smarty_args, 'boolean');
493
+
494
+		if (!empty($allowed) && $this->show_compat_errors) {
495
+			$this->triggerError('You can register objects but can not restrict the method/properties used, this is PHP5, you have proper OOP access restrictions so use them.', E_USER_NOTICE);
496
+		}
497
+
498
+		if ($smarty_args) {
499
+			$this->triggerError('You can register objects but methods will be called using method($arg1, $arg2, $arg3), not as an argument array like smarty did.', E_USER_NOTICE);
500
+		}
501
+
502
+		if (!empty($block_methods)) {
503
+			$this->triggerError('You can register objects but can not use methods as being block methods, you have to build a plugin for that.', E_USER_NOTICE);
504
+		}
505
+
506
+		$this->dataProvider->assign($object, $object_impl);
507
+	}
508
+
509
+	/**
510
+	 * @param $object
511
+	 */
512
+	public function unregister_object($object)
513
+	{
514
+		$this->dataProvider->clear($object);
515
+	}
516
+
517
+	/**
518
+	 * @param $name
519
+	 *
520
+	 * @return mixed
521
+	 */
522
+	public function get_registered_object($name)
523
+	{
524
+		$data = $this->dataProvider->getData();
525
+		if (isset($data[$name]) && is_object($data[$name])) {
526
+			return $data[$name];
527
+		} else {
528
+			trigger_error('Dwoo_Compiler: object "' . $name . '" was not registered or is not an object', E_USER_ERROR);
529
+		}
530
+	}
531
+
532
+	/**
533
+	 * @param $filename
534
+	 *
535
+	 * @return bool
536
+	 */
537
+	public function template_exists($filename)
538
+	{
539
+		if (!is_array($this->template_dir)) {
540
+			return file_exists($this->template_dir . DIRECTORY_SEPARATOR . $filename);
541
+		} else {
542
+			foreach ($this->template_dir as $tpl_dir) {
543
+				if (file_exists($tpl_dir . DIRECTORY_SEPARATOR . $filename)) {
544
+					return true;
545
+				}
546
+			}
547
+
548
+			return false;
549
+		}
550
+	}
551
+
552
+	/**
553
+	 * @param      $tpl
554
+	 * @param null $cacheId
555
+	 * @param null $compileId
556
+	 *
557
+	 * @return bool
558
+	 */
559
+	public function is_cached($tpl, $cacheId = null, $compileId = null)
560
+	{
561
+		return $this->isCached($this->makeTemplate($tpl, $cacheId, $compileId));
562
+	}
563
+
564
+	/**
565
+	 * @param      $var
566
+	 * @param      $value
567
+	 * @param bool $merge
568
+	 */
569
+	public function append_by_ref($var, &$value, $merge = false)
570
+	{
571
+		$this->dataProvider->appendByRef($var, $value, $merge);
572
+	}
573
+
574
+	/**
575
+	 * @param $name
576
+	 * @param $val
577
+	 */
578
+	public function assign_by_ref($name, &$val)
579
+	{
580
+		$this->dataProvider->assignByRef($name, $val);
581
+	}
582
+
583
+	/**
584
+	 * @param $var
585
+	 */
586
+	public function clear_assign($var)
587
+	{
588
+		$this->dataProvider->clear($var);
589
+	}
590
+
591
+	/**
592
+	 *
593
+	 */
594
+	public function clear_all_assign()
595
+	{
596
+		$this->dataProvider->clear();
597
+	}
598
+
599
+	/**
600
+	 * @param null $name
601
+	 *
602
+	 * @return array|null
603
+	 */
604
+	public function get_template_vars($name = null)
605
+	{
606
+		if ($this->show_compat_errors) {
607
+			trigger_error('get_template_vars does not return values by reference, if you try to modify the data that way you should modify your code.', E_USER_NOTICE);
608
+		}
609
+
610
+		$data = $this->dataProvider->getData();
611
+		if ($name === null) {
612
+			return $data;
613
+		} elseif (isset($data[$name])) {
614
+			return $data[$name];
615
+		}
616
+
617
+		return null;
618
+	}
619
+
620
+	/**
621
+	 * @param int $olderThan
622
+	 */
623
+	public function clear_all_cache($olderThan = 0)
624
+	{
625
+		$this->clearCache($olderThan);
626
+	}
627
+
628
+	/**
629
+	 * @param      $template
630
+	 * @param null $cacheId
631
+	 * @param null $compileId
632
+	 * @param int  $olderThan
633
+	 */
634
+	public function clear_cache($template, $cacheId = null, $compileId = null, $olderThan = 0)
635
+	{
636
+		$this->makeTemplate($template, $cacheId, $compileId)->clearCache($olderThan);
637
+	}
638
+
639
+	/**
640
+	 * @param     $error_msg
641
+	 * @param int $error_type
642
+	 */
643
+	public function trigger_error($error_msg, $error_type = E_USER_WARNING)
644
+	{
645
+		$this->triggerError($error_msg, $error_type);
646
+	}
647
+
648
+	/**
649
+	 *
650
+	 */
651
+	protected function initGlobals()
652
+	{
653
+		parent::initGlobals();
654
+		$this->globals['ldelim'] = '{';
655
+		$this->globals['rdelim'] = '}';
656
+	}
657
+
658
+	/**
659
+	 * @param $file
660
+	 * @param $cacheId
661
+	 * @param $compileId
662
+	 *
663
+	 * @return mixed
664
+	 * @throws Exception
665
+	 */
666
+	protected function makeTemplate($file, $cacheId, $compileId)
667
+	{
668
+		if ($compileId === null) {
669
+			$compileId = $this->compile_id;
670
+		}
671
+
672
+		$hash = bin2hex(md5($file . $cacheId . $compileId, true));
673
+		if (!isset(self::$tplCache[$hash])) {
674
+			// abs path
675
+			if (substr($file, 0, 1) === '/' || substr($file, 1, 1) === ':') {
676
+				self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId);
677
+			} elseif (is_string($this->template_dir) || is_array($this->template_dir)) {
678
+				self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId, $this->template_dir);
679
+			} else {
680
+				throw new Exception('Unable to load "' . $file . '", check the template_dir');
681
+			}
682
+		}
683
+
684
+		return self::$tplCache[$hash];
685
+	}
686
+
687
+	/**
688
+	 * @param string $message
689
+	 * @param int    $level
690
+	 */
691
+	public function triggerError($message, $level = E_USER_NOTICE)
692
+	{
693
+		if (is_object($this->template)) {
694
+			parent::triggerError($message, $level);
695
+		}
696
+		trigger_error('Dwoo error : ' . $message, $level);
697
+	}
698 698
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -63,12 +63,12 @@  discard block
 block discarded – undo
63 63
         }
64 64
         if (array_key_exists($p, $this->compat['properties']) !== false) {
65 65
             if ($this->show_compat_errors) {
66
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
66
+                $this->triggerError('Property '.$p.' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
67 67
             }
68 68
             $this->compat['properties'][$p] = $v;
69 69
         } else {
70 70
             if ($this->show_compat_errors) {
71
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
71
+                $this->triggerError('Property '.$p.' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
72 72
             }
73 73
         }
74 74
     }
@@ -82,13 +82,13 @@  discard block
 block discarded – undo
82 82
     {
83 83
         if (array_key_exists($p, $this->compat['properties']) !== false) {
84 84
             if ($this->show_compat_errors) {
85
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
85
+                $this->triggerError('Property '.$p.' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
86 86
             }
87 87
 
88 88
             return $this->compat['properties'][$p];
89 89
         } else {
90 90
             if ($this->show_compat_errors) {
91
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
91
+                $this->triggerError('Property '.$p.' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
92 92
             }
93 93
         }
94 94
     }
@@ -110,9 +110,9 @@  discard block
 block discarded – undo
110 110
             );
111 111
         } elseif ($this->show_compat_errors) {
112 112
             if (array_search($m, $this->compat['methods']) !== false) {
113
-                $this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
113
+                $this->triggerError('Method '.$m.' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
114 114
             } else {
115
-                $this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
115
+                $this->triggerError('Method '.$m.' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
116 116
             }
117 117
         }
118 118
     }
@@ -525,7 +525,7 @@  discard block
 block discarded – undo
525 525
         if (isset($data[$name]) && is_object($data[$name])) {
526 526
             return $data[$name];
527 527
         } else {
528
-            trigger_error('Dwoo_Compiler: object "' . $name . '" was not registered or is not an object', E_USER_ERROR);
528
+            trigger_error('Dwoo_Compiler: object "'.$name.'" was not registered or is not an object', E_USER_ERROR);
529 529
         }
530 530
     }
531 531
 
@@ -537,10 +537,10 @@  discard block
 block discarded – undo
537 537
     public function template_exists($filename)
538 538
     {
539 539
         if (!is_array($this->template_dir)) {
540
-            return file_exists($this->template_dir . DIRECTORY_SEPARATOR . $filename);
540
+            return file_exists($this->template_dir.DIRECTORY_SEPARATOR.$filename);
541 541
         } else {
542 542
             foreach ($this->template_dir as $tpl_dir) {
543
-                if (file_exists($tpl_dir . DIRECTORY_SEPARATOR . $filename)) {
543
+                if (file_exists($tpl_dir.DIRECTORY_SEPARATOR.$filename)) {
544 544
                     return true;
545 545
                 }
546 546
             }
@@ -669,7 +669,7 @@  discard block
 block discarded – undo
669 669
             $compileId = $this->compile_id;
670 670
         }
671 671
 
672
-        $hash = bin2hex(md5($file . $cacheId . $compileId, true));
672
+        $hash = bin2hex(md5($file.$cacheId.$compileId, true));
673 673
         if (!isset(self::$tplCache[$hash])) {
674 674
             // abs path
675 675
             if (substr($file, 0, 1) === '/' || substr($file, 1, 1) === ':') {
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
             } elseif (is_string($this->template_dir) || is_array($this->template_dir)) {
678 678
                 self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId, $this->template_dir);
679 679
             } else {
680
-                throw new Exception('Unable to load "' . $file . '", check the template_dir');
680
+                throw new Exception('Unable to load "'.$file.'", check the template_dir');
681 681
             }
682 682
         }
683 683
 
@@ -693,6 +693,6 @@  discard block
 block discarded – undo
693 693
         if (is_object($this->template)) {
694 694
             parent::triggerError($message, $level);
695 695
         }
696
-        trigger_error('Dwoo error : ' . $message, $level);
696
+        trigger_error('Dwoo error : '.$message, $level);
697 697
     }
698 698
 }
Please login to merge, or discard this patch.
lib/Dwoo/Smarty/Filter/Adapter.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -23,23 +23,23 @@
 block discarded – undo
23 23
  */
24 24
 class Adapter extends Filter
25 25
 {
26
-    public $callback;
26
+	public $callback;
27 27
 
28
-    /**
29
-     * @param string $input
30
-     *
31
-     * @return mixed
32
-     */
33
-    public function process($input)
34
-    {
35
-        return call_user_func($this->callback, $input);
36
-    }
28
+	/**
29
+	 * @param string $input
30
+	 *
31
+	 * @return mixed
32
+	 */
33
+	public function process($input)
34
+	{
35
+		return call_user_func($this->callback, $input);
36
+	}
37 37
 
38
-    /**
39
-     * @param $callback
40
-     */
41
-    public function registerCallback($callback)
42
-    {
43
-        $this->callback = $callback;
44
-    }
38
+	/**
39
+	 * @param $callback
40
+	 */
41
+	public function registerCallback($callback)
42
+	{
43
+		$this->callback = $callback;
44
+	}
45 45
 }
46 46
\ No newline at end of file
Please login to merge, or discard this patch.
lib/Dwoo/Smarty/Processor/Adapter.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -23,23 +23,23 @@
 block discarded – undo
23 23
  */
24 24
 class Adapter extends Processor
25 25
 {
26
-    public $callback;
26
+	public $callback;
27 27
 
28
-    /**
29
-     * @param string $input
30
-     *
31
-     * @return mixed
32
-     */
33
-    public function process($input)
34
-    {
35
-        return call_user_func($this->callback, $input);
36
-    }
28
+	/**
29
+	 * @param string $input
30
+	 *
31
+	 * @return mixed
32
+	 */
33
+	public function process($input)
34
+	{
35
+		return call_user_func($this->callback, $input);
36
+	}
37 37
 
38
-    /**
39
-     * @param $callback
40
-     */
41
-    public function registerCallback($callback)
42
-    {
43
-        $this->callback = $callback;
44
-    }
38
+	/**
39
+	 * @param $callback
40
+	 */
41
+	public function registerCallback($callback)
42
+	{
43
+		$this->callback = $callback;
44
+	}
45 45
 }
46 46
\ No newline at end of file
Please login to merge, or discard this patch.
lib/Dwoo/IPluginProxy.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -23,52 +23,52 @@
 block discarded – undo
23 23
  */
24 24
 interface IPluginProxy
25 25
 {
26
-    /**
27
-     * Returns true or false to say whether the given plugin is handled by this proxy or not.
28
-     *
29
-     * @param string $name the plugin name
30
-     *
31
-     * @return bool true if the plugin is known and usable, otherwise false
32
-     */
33
-    public function handles($name);
26
+	/**
27
+	 * Returns true or false to say whether the given plugin is handled by this proxy or not.
28
+	 *
29
+	 * @param string $name the plugin name
30
+	 *
31
+	 * @return bool true if the plugin is known and usable, otherwise false
32
+	 */
33
+	public function handles($name);
34 34
 
35
-    /**
36
-     * Returns the code (as a string) to call the plugin
37
-     * (this will be executed at runtime inside the Dwoo class).
38
-     *
39
-     * @param string $name   the plugin name
40
-     * @param array  $params a parameter array, array key "*" is the rest array
41
-     *
42
-     * @return string
43
-     */
44
-    public function getCode($name, $params);
35
+	/**
36
+	 * Returns the code (as a string) to call the plugin
37
+	 * (this will be executed at runtime inside the Dwoo class).
38
+	 *
39
+	 * @param string $name   the plugin name
40
+	 * @param array  $params a parameter array, array key "*" is the rest array
41
+	 *
42
+	 * @return string
43
+	 */
44
+	public function getCode($name, $params);
45 45
 
46
-    /**
47
-     * Returns a callback to the plugin, this is used with the reflection API to
48
-     * find out about the plugin's parameter names etc.
49
-     * should you need a rest array without the possibility to edit the
50
-     * plugin's code, you can provide a callback to some
51
-     * other function with the correct parameter signature, i.e. :
52
-     * <code>
53
-     * return array($this, "callbackHelper");
54
-     * // and callbackHelper would be as such:
55
-     * public function callbackHelper(array $rest=array()){}
56
-     * </code>
57
-     *
58
-     * @param string $name the plugin name
59
-     *
60
-     * @return callback
61
-     */
62
-    public function getCallback($name);
46
+	/**
47
+	 * Returns a callback to the plugin, this is used with the reflection API to
48
+	 * find out about the plugin's parameter names etc.
49
+	 * should you need a rest array without the possibility to edit the
50
+	 * plugin's code, you can provide a callback to some
51
+	 * other function with the correct parameter signature, i.e. :
52
+	 * <code>
53
+	 * return array($this, "callbackHelper");
54
+	 * // and callbackHelper would be as such:
55
+	 * public function callbackHelper(array $rest=array()){}
56
+	 * </code>
57
+	 *
58
+	 * @param string $name the plugin name
59
+	 *
60
+	 * @return callback
61
+	 */
62
+	public function getCallback($name);
63 63
 
64
-    /**
65
-     * Returns some code that will check if the plugin is loaded and if not load it
66
-     * this is optional, if your plugins are autoloaded or whatever, just return an
67
-     * empty string.
68
-     *
69
-     * @param string $name the plugin name
70
-     *
71
-     * @return string
72
-     */
73
-    public function getLoader($name);
64
+	/**
65
+	 * Returns some code that will check if the plugin is loaded and if not load it
66
+	 * this is optional, if your plugins are autoloaded or whatever, just return an
67
+	 * empty string.
68
+	 *
69
+	 * @param string $name the plugin name
70
+	 *
71
+	 * @return string
72
+	 */
73
+	public function getLoader($name);
74 74
 }
Please login to merge, or discard this patch.
lib/Dwoo/Filter.php 1 patch
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -23,30 +23,30 @@
 block discarded – undo
23 23
  */
24 24
 abstract class Filter
25 25
 {
26
-    /**
27
-     * The dwoo instance that runs this filter.
28
-     *
29
-     * @var Core
30
-     */
31
-    protected $dwoo;
26
+	/**
27
+	 * The dwoo instance that runs this filter.
28
+	 *
29
+	 * @var Core
30
+	 */
31
+	protected $dwoo;
32 32
 
33
-    /**
34
-     * Constructor, if you override it, call parent::__construct($dwoo); or assign
35
-     * the dwoo instance yourself if you need it.
36
-     *
37
-     * @param Core $dwoo the dwoo instance that runs this plugin
38
-     */
39
-    public function __construct(Core $dwoo)
40
-    {
41
-        $this->dwoo = $dwoo;
42
-    }
33
+	/**
34
+	 * Constructor, if you override it, call parent::__construct($dwoo); or assign
35
+	 * the dwoo instance yourself if you need it.
36
+	 *
37
+	 * @param Core $dwoo the dwoo instance that runs this plugin
38
+	 */
39
+	public function __construct(Core $dwoo)
40
+	{
41
+		$this->dwoo = $dwoo;
42
+	}
43 43
 
44
-    /**
45
-     * Processes the input and returns it filtered.
46
-     *
47
-     * @param string $input the template to process
48
-     *
49
-     * @return string
50
-     */
51
-    abstract public function process($input);
44
+	/**
45
+	 * Processes the input and returns it filtered.
46
+	 *
47
+	 * @param string $input the template to process
48
+	 *
49
+	 * @return string
50
+	 */
51
+	abstract public function process($input);
52 52
 }
Please login to merge, or discard this patch.