/**
  * Process an argument string to return an array of argments
  * @param I2CE_Page $page
  * @param DOMNode $node
  * @param string $arg
  * @param boolean $templatefunction.  Defaults to false.  If true we preend the $node, and $template to the argument list for the funciton.
  * @returns array
  */
 public static function getArguments($page, $node, $arg, $templatefunction = false)
 {
     self::$page = $page;
     self::$node = $node;
     return self::callModuleFunction(false, false, $arg, $templatefunction);
 }
 /**
  * Process any form elements on the page.
  * 
  * This method will parse all form elements on the page to replace the values if they are known.
  * There are three type of form directives for a span.  The first two are as follows
  * <span type='form' name='form_name:form_field_name'></span>
  * and <span type='form' name='form_name->method_name(args)'></span>
  * In each case we find the form with form name 'form_name'.
  * In the first case, we  call the processDom() method for the form field identified by form_field_name.
  * For the seconcd case we call the method_name method of the form with the arguments specified by args.
  *
  * The last case is for 
  *   <span type='form' name='form_field_name'></span>
  * In this case is like the first case except that the form used is the default form for this page.
  *
  */
 public function processForms($page)
 {
     if (!$page instanceof I2CE_Page) {
         I2CE::raiseError("Did not receive expected page");
         return false;
     }
     $template = $page->getTemplate();
     $user = $page->getUser();
     $qry = '//span[@type=\'form\']';
     $results = $template->query($qry);
     for ($i = 0; $i < $results->length; $i++) {
         $node = $results->item($i);
         $node->removeAttribute('type');
         if (!$node->hasAttribute('name')) {
             continue;
         }
         $name = trim($node->getAttribute("name"));
         if (!$name) {
             continue;
         }
         //the following regular expression matches any valid PHP function or label: http://us3.php.net/functions
         $phpfunc = '[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*';
         if (preg_match("/^({$phpfunc}):({$phpfunc})\$/", $name, $matches)) {
             $form = $template->getData('FORM', $matches[1], $node, false, true);
             if ($form instanceof I2CE_Form && $form->getName() != $matches[1]) {
                 I2CE::raiseError("Form name mismatch " . $form->getName() . '!=' . $matches[1]);
                 $form = null;
             }
             $method = 'displayField';
             if (!array_key_exists(3, $matches)) {
                 $matches[3] = null;
             }
             $args = array($matches[2], substr($matches[3], 1, -1));
         } else {
             if (preg_match("/^({$phpfunc})\$/", $name, $matches)) {
                 $form = $template->getDefaultData('FORM');
                 $method = 'displayField';
                 if (!array_key_exists(2, $matches)) {
                     $matches[2] = null;
                 }
                 $args = array($matches[1], substr($matches[2], 1, -1));
             } else {
                 if (preg_match("/^({$phpfunc})->({$phpfunc})(\\(.*\\))\$/", $name, $matches)) {
                     $node->removeAttribute('name');
                     $form = $template->getData('FORM', $matches[1], $node, false, true);
                     if (!$form instanceof I2CE_Form) {
                         continue;
                     }
                     if (!$form->_hasMethod($matches[2])) {
                         continue;
                     }
                     $args = I2CE_Module_Tags::getArguments($page, $node, $matches[3], true);
                     if (count($args) < 2) {
                         continue;
                     }
                     @call_user_func_array(array($form, $matches[2]), $args);
                     continue;
                 } else {
                     continue;
                 }
             }
         }
         if ($form instanceof I2CE_Form) {
             $form->processDOM($node, $template, $method, $args);
         } else {
             $node->parentNode->removeChild($node);
         }
     }
     $results = $template->query('//*[@form]');
     for ($i = 0; $i < $results->length; $i++) {
         $node = $results->item($i);
         $form = $node->getAttribute('form');
         $orig_form = $form;
         $node->removeAttribute('form');
         if (!$form) {
             continue;
         }
         try {
             //example <span form='$user->displayField("surname")'/> is the same as <span type='form' name='user:surname'>
             //which is the same as <span form='$user->surname->processDOM()'/>
             I2CE_Module_Tags::callModuleFunction('', false, $form, true, 'FORM');
             //try to call a template function
         } catch (Exception $e) {
             I2CE::raiseError("Could not evaluate {$orig_form}:\n" . $e->getMessage());
             continue;
         }
     }
     //now we fix up any <form> tags that have a file input
     $forms = $template->query('//form');
     for ($i = 0; $i < $forms->length; $i++) {
         $form = $forms->item($i);
         $file_inputs = $template->query('.//input[@type="file"]', $form);
         if ($file_inputs->length == 0) {
             continue;
         }
         $form->setAttribute('enctype', 'multipart/form-data');
     }
 }