HTML_QuickForm_Renderer_Array(true, $staticLabels); $this->_tpl =& $tpl; } // end constructor /** * Called when visiting a header element * * @param HTML_QuickForm_header header element being visited * @access public * @return void */ function renderHeader(&$header) { if ($name = $header->getName()) { $this->_ary['header'][$name] = $header->toHtml(); } else { $this->_ary['header'][$this->_sectionCount] = $header->toHtml(); } $this->_currentSection = $this->_sectionCount++; } // end func renderHeader /** * Called when visiting a group, before processing any group elements * * @param HTML_QuickForm_group group being visited * @param bool Whether a group is required * @param string An error message associated with a group * @access public * @return void */ function startGroup(&$group, $required, $error) { parent::startGroup($group, $required, $error); $this->_groupElementIdx = 1; } // end func startGroup /** * Creates an array representing an element containing * the key for storing this * * @access private * @param HTML_QuickForm_element form element being visited * @param bool Whether an element is required * @param string Error associated with the element * @return array */ function _elementToArray(&$element, $required, $error) { $ret = parent::_elementToArray($element, $required, $error); if ('group' == $ret['type']) { $ret['html'] = $element->toHtml(); // we don't need the elements, see the array structure unset($ret['elements']); } if (($required || $error) && !empty($this->_required)){ $this->_renderRequired($ret['label'], $ret['html'], $required, $error); } if ($error && !empty($this->_error)) { $this->_renderError($ret['label'], $ret['html'], $error); $ret['error'] = $error; } // create keys for elements grouped by native group or name if (strstr($ret['name'], '[') or $this->_currentGroup) { // Fix for bug #8123: escape backslashes and quotes to prevent errors // in eval(). The code below seems to handle the case where element // name has unbalanced square brackets. Dunno whether we really // need this after the fix for #8123, but I'm wary of making big // changes to this code. preg_match('/([^]]*)\\[([^]]*)\\]/', $ret['name'], $matches); if (isset($matches[1])) { $sKeysSub = substr_replace($ret['name'], '', 0, strlen($matches[1])); $sKeysSub = str_replace( array('\\', '\'', '[' , ']', '[\'\']'), array('\\\\', '\\\'', '[\'', '\']', '[]' ), $sKeysSub ); $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $matches[1]) . '\']' . $sKeysSub; } else { $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['name']) . '\']'; } // special handling for elements in native groups if ($this->_currentGroup) { // skip unnamed group items unless radios: no name -> no static access // identification: have the same key string as the parent group if ($this->_currentGroup['keys'] == $sKeys and 'radio' != $ret['type']) { return false; } // reduce string of keys by remove leading group keys if (0 === strpos($sKeys, $this->_currentGroup['keys'])) { $sKeys = substr_replace($sKeys, '', 0, strlen($this->_currentGroup['keys'])); } } // element without a name } elseif ($ret['name'] == '') { $sKeys = '[\'element_' . $this->_elementIdx . '\']'; // other elements } else { $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['name']) . '\']'; } // for radios: add extra key from value if ('radio' == $ret['type'] and substr($sKeys, -2) != '[]') { $sKeys .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['value']) . '\']'; } $this->_elementIdx++; $ret['keys'] = $sKeys; return $ret; } // end func _elementToArray /** * Stores an array representation of an element in the form array * * @access private * @param array Array representation of an element * @return void */ function _storeArray($elAry) { if ($elAry) { $sKeys = $elAry['keys']; unset($elAry['keys']); // where should we put this element... if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) { $toEval = '$this->_currentGroup' . $sKeys . ' = $elAry;'; } else { $toEval = '$this->_ary' . $sKeys . ' = $elAry;'; } eval($toEval); } return; } /** * Called when an element is required * * This method will add the required tag to the element label and/or the element html * such as defined with the method setRequiredTemplate. * * @param string The element label * @param string The element html rendering * @param boolean The element required * @param string The element error * @see setRequiredTemplate() * @access private * @return void */ function _renderRequired(&$label, &$html, &$required, &$error) { $this->_tpl->assign(array( 'label' => $label, 'html' => $html, 'required' => $required, 'error' => $error )); if (!empty($label) && strpos($this->_required, $this->_tpl->left_delimiter . '$label') !== false) { $label = $this->_tplFetch($this->_required); } if (!empty($html) && strpos($this->_required, $this->_tpl->left_delimiter . '$html') !== false) { $html = $this->_tplFetch($this->_required); } $this->_tpl->clear_assign(array('label', 'html', 'required')); } // end func _renderRequired /** * Called when an element has a validation error * * This method will add the error message to the element label or the element html * such as defined with the method setErrorTemplate. If the error placeholder is not found * in the template, the error will be displayed in the form error block. * * @param string The element label * @param string The element html rendering * @param string The element error * @see setErrorTemplate() * @access private * @return void */ function _renderError(&$label, &$html, &$error) { $this->_tpl->assign(array('label' => '', 'html' => '', 'error' => $error)); $error = $this->_tplFetch($this->_error); $this->_tpl->assign(array('label' => $label, 'html' => $html)); if (!empty($label) && strpos($this->_error, $this->_tpl->left_delimiter . '$label') !== false) { $label = $this->_tplFetch($this->_error); } elseif (!empty($html) && strpos($this->_error, $this->_tpl->left_delimiter . '$html') !== false) { $html = $this->_tplFetch($this->_error); } $this->_tpl->clear_assign(array('label', 'html', 'error')); } // end func _renderError /** * Process an template sourced in a string with Smarty * * Smarty has no core function to render a template given as a string. * So we use the smarty eval plugin function to do this. * * @param string The template source * @access private * @return void */ function _tplFetch($tplSource) { if (!function_exists('smarty_function_eval')) { require SMARTY_DIR . '/plugins/function.eval.php'; } return smarty_function_eval(array('var' => $tplSource), $this->_tpl); }// end func _tplFetch /** * Sets the way required elements are rendered * * You can use {$label} or {$html} placeholders to let the renderer know where * where the element label or the element html are positionned according to the * required tag. They will be replaced accordingly with the right value. You * can use the full smarty syntax here, especially a custom modifier for I18N. * For example: * {if $required}*{/if}{$label|translate} * will put a red star in front of the label if the element is required and * translate the label. * * * @param string The required element template * @access public * @return void */ function setRequiredTemplate($template) { $this->_required = $template; } // end func setRequiredTemplate /** * Sets the way elements with validation errors are rendered * * You can use {$label} or {$html} placeholders to let the renderer know where * where the element label or the element html are positionned according to the * error message. They will be replaced accordingly with the right value. * The error message will replace the {$error} placeholder. * For example: * {if $error}{$error}{/if}
{$html} * will put the error message in red on top of the element html. * * If you want all error messages to be output in the main error block, use * the {$form.errors} part of the rendered array that collects all raw error * messages. * * If you want to place all error messages manually, do not specify {$html} * nor {$label}. * * Groups can have special layouts. With this kind of groups, you have to * place the formated error message manually. In this case, use {$form.group.error} * where you want the formated error message to appear in the form. * * @param string The element error template * @access public * @return void */ function setErrorTemplate($template) { $this->_error = $template; } // end func setErrorTemplate } ?>