title: Dynamically add functions to PHP class as plugins
body: <p>I'm working with a PHP class for exporting templates, and there is a tag for calling functions which should be loaded dynamically from plugin-scripts. The scripts are stored in a directory and named after the name of the function in the tag. The dynamically loaded functions' names are then stored in an array so they are only loaded once. This works fine, so my question isn't how to solve this, but rather I'd ask for input on whether this is a stable and secure solution, if there is a better way to solve this, or something I've overseen?</p>
  
  <p>Neither the <a href="http://en.wikipedia.org/wiki/Observer_pattern" rel="nofollow">Observer</a> nor the <a href="http://en.wikipedia.org/wiki/Decorator_pattern" rel="nofollow">Decorator</a> patterns works with this design, and I want it to remain minimalistic; and in this particular case I won't use classes, only functions. Also, if this, in your opinion, is a working solution, or if you suggest something better; I'll probably implement it in other similar classes as well - therefore I'd like to get it right from the beginning. So, please be strict and critical.</p>
  
  <p>The class looks something like this:</p>
  
  <pre><code>&lt;?php
  // TemplateEngine.php
  class TemplateEngine {
      private static $functions = array();
      private $vars = array();
      ...
      public function &amp;getVars() { return $this-&gt;vars; }
      ...
      private function call(&amp;$tag) {
          $name = strtr(strtolower($tag-&gt;id),'-','_');
          $value = $tag-&gt;value;
          $func = false;
          if(preg_match('/^[\w\_]+$/',$name)) {
              if(isset(self::$functions[$name])) {
                  $func = &amp;self::$functions[$name];
              } else {
                  $script = __DIR__.'/functions/'.$name.'.php';
                  if(file_exists($script)) $func = require_once $script;
                  self::$functions[$key] = &amp;$func;
              }
          }
          $ret = '';
          if(is_callable($func)) $ret = $func($this,$value);
          return $ret;
      }
  ...
  }
  </code></pre>
  
  <p>Then the function script to iterate an array and parse a string with it's values looks something like this:</p>
  
  <pre><code>&lt;?php
  // functions/iterate.php
  return function(&amp;$templ,$param) {
      $vars = &amp;$templ-&gt;getVars();
      list($key,$value) = $param;
      if(!isset($vars[$key])) return '';
      $var = $vars[$key];
      if(!is_array($var)) $var = array($key=&gt;$var);
      $value = stripcslashes($value);
      $ret = '';
      foreach($var as $k=&gt;$v) {
          $vars['key'] = $k;
          $vars['value'] = $v;
          $ret .= $templ-&gt;parse($value);
      }
      return $ret;
  }
  </code></pre>
  
  <p>In the template a tag may look something like this:</p>
  
  <pre><code>{call iterate|js-files|&lt;script src="{value}"&gt;\n}
  </code></pre>
  
  <p>Such a tag will call the function "iterate" and look for the index "js-files" in the template variables array (which is read from a configurations file), and parse the string "&lt;script ...&gt;".</p>