Overview

Packages

  • Form
  • None

Classes

  • Horde_Form
  • Horde_Form_Action
  • Horde_Form_Action_conditional_enable
  • Horde_Form_Action_conditional_setvalue
  • Horde_Form_Action_ConditionalEnable
  • Horde_Form_Action_ConditionalSetValue
  • Horde_Form_Action_reload
  • Horde_Form_Action_setcursorpos
  • Horde_Form_Action_submit
  • Horde_Form_Action_sum_fields
  • Horde_Form_Action_updatefield
  • Horde_Form_Renderer
  • Horde_Form_Translation
  • Horde_Form_Type
  • Horde_Form_Type_address
  • Horde_Form_Type_addresslink
  • Horde_Form_Type_assign
  • Horde_Form_Type_boolean
  • Horde_Form_Type_captcha
  • Horde_Form_Type_category
  • Horde_Form_Type_cellphone
  • Horde_Form_Type_colorpicker
  • Horde_Form_Type_countedtext
  • Horde_Form_Type_country
  • Horde_Form_Type_creditcard
  • Horde_Form_Type_date
  • Horde_Form_Type_datetime
  • Horde_Form_Type_dblookup
  • Horde_Form_Type_description
  • Horde_Form_Type_email
  • Horde_Form_Type_emailConfirm
  • Horde_Form_Type_enum
  • Horde_Form_Type_figlet
  • Horde_Form_Type_file
  • Horde_Form_Type_header
  • Horde_Form_Type_hourminutesecond
  • Horde_Form_Type_image
  • Horde_Form_Type_int
  • Horde_Form_Type_intlist
  • Horde_Form_Type_invalid
  • Horde_Form_Type_ip6address
  • Horde_Form_Type_ipaddress
  • Horde_Form_Type_keyval_multienum
  • Horde_Form_Type_link
  • Horde_Form_Type_longtext
  • Horde_Form_Type_matrix
  • Horde_Form_Type_mlenum
  • Horde_Form_Type_monthdayyear
  • Horde_Form_Type_monthyear
  • Horde_Form_Type_multienum
  • Horde_Form_Type_number
  • Horde_Form_Type_obrowser
  • Horde_Form_Type_octal
  • Horde_Form_Type_password
  • Horde_Form_Type_passwordconfirm
  • Horde_Form_Type_pgp
  • Horde_Form_Type_phone
  • Horde_Form_Type_radio
  • Horde_Form_Type_selectfiles
  • Horde_Form_Type_set
  • Horde_Form_Type_smime
  • Horde_Form_Type_sorter
  • Horde_Form_Type_sound
  • Horde_Form_Type_spacer
  • Horde_Form_Type_stringarray
  • Horde_Form_Type_stringlist
  • Horde_Form_Type_tableset
  • Horde_Form_Type_text
  • Horde_Form_Type_time
  • Horde_Form_Variable
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Horde_Form_Renderer class provides HTML and other renderings of
  4:  * forms for the Horde_Form:: package.
  5:  *
  6:  * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
  7:  *
  8:  * See the enclosed file COPYING for license information (LGPL). If you
  9:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 10:  *
 11:  * @author  Robert E. Coyle <robertecoyle@hotmail.com>
 12:  * @package Form
 13:  */
 14: class Horde_Form_Renderer {
 15: 
 16:     var $_name;
 17:     var $_requiredLegend = false;
 18:     var $_requiredMarker = '*';
 19:     var $_helpMarker = '?';
 20:     var $_showHeader = true;
 21:     var $_cols = 2;
 22:     var $_varRenderer = null;
 23:     var $_firstField = null;
 24:     var $_stripedRows = true;
 25: 
 26:     /**
 27:      * Does the title of the form contain HTML? If so, you are responsible for
 28:      * doing any needed escaping/sanitization yourself. Otherwise the title
 29:      * will be run through htmlspecialchars() before being output.
 30:      *
 31:      * @var boolean
 32:      */
 33:     var $_encodeTitle = true;
 34: 
 35:     /**
 36:      * Width of the attributes column.
 37:      *
 38:      * @access private
 39:      * @var string
 40:      */
 41:     var $_attrColumnWidth = '15%';
 42: 
 43:     /**
 44:      * Construct a new Horde_Form_Renderer::.
 45:      *
 46:      * @param array $params  This is a hash of renderer-specific parameters.
 47:      *                       Possible keys:
 48:      *                       - 'varrenderer_driver': specifies the driver
 49:      *                         parameter to Horde_Core_Ui_VarRenderer::factory().
 50:      *                       - 'encode_title': @see $_encodeTitle
 51:      */
 52:     function Horde_Form_Renderer($params = array())
 53:     {
 54:         global $registry;
 55:         if (isset($registry) && is_a($registry, 'Registry')) {
 56:             /* Registry available, so use a pretty image. */
 57:             $this->_requiredMarker = Horde::img('required.png', '*');
 58:         } else {
 59:             /* No registry available, use something plain. */
 60:             $this->_requiredMarker = '*';
 61:         }
 62: 
 63:         if (isset($params['encode_title'])) {
 64:             $this->encodeTitle($params['encode_title']);
 65:         }
 66: 
 67:         $driver = 'html';
 68:         if (isset($params['varrenderer_driver'])) {
 69:             $driver = $params['varrenderer_driver'];
 70:         }
 71:         $this->_varRenderer = Horde_Core_Ui_VarRenderer::factory($driver, $params);
 72:     }
 73: 
 74:     function showHeader($bool)
 75:     {
 76:         $this->_showHeader = $bool;
 77:     }
 78: 
 79:     /**
 80:      * Sets or returns whether the form title should be encoded with
 81:      * htmlspecialchars().
 82:      *
 83:      * @param boolean $encode  If true, the form title gets encoded.  If false
 84:      *                         the title can contain HTML, but the class user
 85:      *                         is responsible to encode any special characters.
 86:      *
 87:      * @return boolean  Whether the form title should be encoded.
 88:      */
 89:     function encodeTitle($encode = null)
 90:     {
 91:         if (!is_null($encode)) {
 92:             $this->_encodeTitle = $encode;
 93:         }
 94:         return $this->_encodeTitle = $encode;
 95:     }
 96: 
 97:     /**
 98:      * @deprecated
 99:      */
100:     function setAttrColumnWidth($width)
101:     {
102:     }
103: 
104:     function open($action, $method, $name, $enctype = null)
105:     {
106:         $this->_name = $name;
107:         $name = htmlspecialchars($name);
108:         $action = htmlspecialchars($action);
109:         $method = htmlspecialchars($method);
110:         echo "<form action=\"$action\" method=\"$method\"" . (empty($name) ? '' : " name=\"$name\" id=\"$name\"") . (is_null($enctype) ? '' : " enctype=\"$enctype\"") . ">\n";
111:         Horde_Util::pformInput();
112:     }
113: 
114:     function beginActive($name, $extra = null)
115:     {
116:         $this->_renderBeginActive($name, $extra);
117:     }
118: 
119:     function beginInactive($name, $extra = null)
120:     {
121:         $this->_renderBeginInactive($name, $extra);
122:     }
123: 
124:     function _renderSectionTabs(&$form)
125:     {
126:         /* If javascript is not available, do not render tabs. */
127:         if (!$GLOBALS['browser']->hasFeature('javascript')) {
128:             return;
129:         }
130: 
131:         $open_section = $form->getOpenSection();
132: 
133:         /* Add the javascript for the toggling the sections. */
134:         Horde::addScriptFile('form_sections.js', 'horde');
135:         echo '<script type="text/javascript">' . "\n";
136:         printf('var sections_%1$s = new Horde_Form_Sections(\'%1$s\', \'%2$s\');',
137:                $form->getName(),
138:                $open_section);
139:         echo "\n" . '</script>';
140: 
141:         /* Loop through the sections and print out a tab for each. */
142:         echo "<div class=\"tabset\"><ul>\n";
143:         foreach ($form->_sections as $section => $val) {
144:             $class = ($section == $open_section) ? ' class="activeTab"' : '';
145:             $js = sprintf('onclick="sections_%s.toggle(\'%s\'); return false;"',
146:                           $form->getName(),
147:                           $section);
148:             printf('<li%s id="%s"><a href="#" %s>%s%s</a> </li>' . "\n",
149:                    $class, htmlspecialchars($form->getName() . '_tab_' . $section), $js,
150:                    $form->getSectionImage($section),
151:                    $form->getSectionDesc($section));
152:         }
153:         echo "</ul></div><br class=\"clear\" />\n";
154:     }
155: 
156:     function _renderSectionBegin(&$form, $section)
157:     {
158:         // Stripe alternate rows if that option is turned on.
159:         if ($this->_stripedRows && class_exists('Horde')) {
160:             Horde::addScriptFile('stripe.js', 'horde');
161:             $class = ' class="striped"';
162:         } else {
163:             $class = '';
164:         }
165: 
166:         $open_section = $form->getOpenSection();
167:         if (is_null($open_section)) {
168:             $open_section = '__base';
169:         }
170:         printf('<div id="%s" style="display:%s;"><table%s cellspacing="0">',
171:                htmlspecialchars($form->getName() . '_section_' . $section),
172:                ($open_section == $section ? 'block' : 'none'),
173:                $class);
174:     }
175: 
176:     function _renderSectionEnd()
177:     {
178:         echo '</table></div>';
179:     }
180: 
181:     function end()
182:     {
183:         $this->_renderEnd();
184:     }
185: 
186:     function close($focus = true)
187:     {
188:         echo "</form>\n";
189:         if ($focus && !empty($this->_firstField)) {
190:             echo '<script type="text/javascript">
191: <!--
192: try {
193:     document.getElementById("' . $this->_firstField . '").focus();
194: } catch(e) {}
195: //-->
196: </script>
197: ';
198:         }
199:     }
200: 
201:     function listFormVars(&$form)
202:     {
203:         $variables = &$form->getVariables(true, true);
204:         $vars = array();
205:         if ($variables) {
206:             foreach ($variables as $var) {
207:                 if (is_object($var)) {
208:                     if (!$var->isReadonly()) {
209:                         $vars[$var->getVarName()] = 1;
210:                     }
211:                 } else {
212:                     $vars[$var] = 1;
213:                 }
214:             }
215:         }
216:         echo '<input type="hidden" name="_formvars" value="' . htmlspecialchars(serialize($vars)) . '" />';
217:     }
218: 
219:     function renderFormActive(&$form, &$vars)
220:     {
221:         $this->_renderForm($form, $vars, true);
222:     }
223: 
224:     function renderFormInactive(&$form, &$vars)
225:     {
226:         $this->_renderForm($form, $vars, false);
227:     }
228: 
229:     function _renderForm(&$form, &$vars, $active)
230:     {
231:         /* If help is present 3 columns are needed. */
232:         $this->_cols = $form->hasHelp() ? 3 : 2;
233: 
234:         $variables = &$form->getVariables(false);
235: 
236:         /* Check for a form token error. */
237:         if (($tokenError = $form->getError('_formToken')) !== null) {
238:             echo '<p class="form-error">' . htmlspecialchars($tokenError) . '</p>';
239:         }
240: 
241:         /* Check for a form secret error. */
242:         if (($secretError = $form->getError('_formSecret')) !== null) {
243:             echo '<p class="form-error">' . htmlspecialchars($secretError) . '</p>';
244:         }
245: 
246:         if (count($form->_sections)) {
247:             $this->_renderSectionTabs($form);
248:         }
249: 
250:         $error_section = null;
251:         foreach ($variables as $section_id => $section) {
252:             $this->_renderSectionBegin($form, $section_id);
253:             foreach ($section as $var) {
254:                 $type = $var->getTypeName();
255: 
256:                 switch ($type) {
257:                 case 'header':
258:                     $this->_renderHeader($var->getHumanName(), $form->getError($var->getVarName()));
259:                     break;
260: 
261:                 case 'description':
262:                     $this->_renderDescription($var->getHumanName());
263:                     break;
264: 
265:                 case 'spacer':
266:                     $this->_renderSpacer();
267:                     break;
268: 
269:                 default:
270:                     $isInput = ($active && !$var->isReadonly());
271:                     $format = $isInput ? 'Input' : 'Display';
272:                     $begin = "_renderVar${format}Begin";
273:                     $end = "_renderVar${format}End";
274: 
275:                     $this->$begin($form, $var, $vars);
276:                     echo $this->_varRenderer->render($form, $var, $vars, $isInput);
277: 
278:                     /* Print any javascript if actions present. */
279:                     if ($var->hasAction()) {
280:                         $var->_action->printJavaScript();
281:                     }
282: 
283:                     $this->$end($form, $var, $vars);
284: 
285:                     /* Keep first field. */
286:                     if ($active && empty($this->_firstField) && !$var->isReadonly() && !$var->isHidden()) {
287:                         $this->_firstField = $var->getVarName();
288:                     }
289: 
290:                     /* Keep section with first error. */
291:                     if (is_null($error_section) && $form->getError($var)) {
292:                         $error_section = $section_id;
293:                     }
294:                 }
295:             }
296: 
297:             $this->_renderSectionEnd();
298:         }
299: 
300:         if (!is_null($error_section) && $form->_sections) {
301:             echo '<script type="text/javascript">' .
302:                 "\n" . sprintf('sections_%s.toggle(\'%s\');',
303:                                $form->getName(),
304:                                $error_section) .
305:                 "\n</script>";
306:         }
307:     }
308: 
309:     function submit($submit = null, $reset = false)
310:     {
311:         if (is_null($submit) || empty($submit)) {
312:             $submit = Horde_Form_Translation::t("Submit");
313:         }
314:         if ($reset === true) {
315:             $reset = Horde_Form_Translation::t("Reset");
316:         }
317:         $this->_renderSubmit($submit, $reset);
318:     }
319: 
320:     /**
321:      * Implementation specific begin function.
322:      */
323:     function _renderBeginActive($name, $extra)
324:     {
325:         echo '<div class="form" id="' . htmlspecialchars($this->_name) . '_active">';
326:         if ($this->_showHeader) {
327:             $this->_sectionHeader($name, $extra);
328:         }
329:         if ($this->_requiredLegend) {
330:             echo '<span class="form-error">' . $this->_requiredMarker . '</span> = ' . Horde_Form_Translation::t("Required Field");
331:         }
332:     }
333: 
334:     /**
335:      * Implementation specific begin function.
336:      */
337:     function _renderBeginInactive($name, $extra)
338:     {
339:         echo '<div class="form" id="' . htmlspecialchars($this->_name) . '_inactive">';
340:         if ($this->_showHeader) {
341:             $this->_sectionHeader($name, $extra);
342:         }
343:     }
344: 
345:     /**
346:      * Implementation specific end function.
347:      */
348:     function _renderEnd()
349:     {
350:         echo '</div>' . $this->_varRenderer->renderEnd();
351:     }
352: 
353:     function _renderHeader($header, $error = '')
354:     {
355: ?><tr><td class="control" width="100%" colspan="<?php echo $this->_cols ?>" valign="bottom"><strong><?php echo $header ?></strong><?php
356:         if (!empty($error)) {
357: ?><br /><span class="form-error"><?php echo $error ?></span><?php
358:         }
359: ?></td></tr>
360: <?php
361:     }
362: 
363:     function _renderDescription($text)
364:     {
365: ?><tr><td width="100%" colspan="<?php echo $this->_cols ?>"><p style="padding:8px"><?php echo $text ?></p></td></tr>
366: <?php
367:     }
368: 
369:     function _renderSpacer()
370:     {
371: ?><tr><td colspan="<?php echo $this->_cols ?>">&nbsp;</td></tr>
372: <?php
373:     }
374: 
375:     function _renderSubmit($submit, $reset)
376:     {
377: ?><div class="control">
378:   <?php if (!is_array($submit)) $submit = array($submit); foreach ($submit as $submitbutton): ?>
379:     <input class="button" name="submitbutton" type="submit" value="<?php echo $submitbutton ?>" />
380:   <?php endforeach; ?>
381:   <?php if (!empty($reset)): ?>
382:     <input class="button" name="resetbutton" type="reset" value="<?php echo $reset ?>" />
383:   <?php endif; ?>
384: </div>
385: <?php
386:     }
387: 
388:     // Implementation specifics -- input variables.
389:     function _renderVarInputBegin(&$form, &$var, &$vars)
390:     {
391:         $message = $form->getError($var);
392:         $isvalid = empty($message);
393:         echo "<tr valign=\"top\">\n";
394:         printf('  <td%s align="right">%s%s%s%s</td>' . "\n",
395:                empty($this->_attrColumnWidth) ? '' : ' width="' . $this->_attrColumnWidth . '"',
396:                $isvalid ? '' : '<span class="form-error">',
397:                $var->isRequired() ? '<span class="form-error">' . $this->_requiredMarker . '</span>&nbsp;' : '',
398:                $var->getHumanName(),
399:                $isvalid ? '' : '<br />' . $message . '</span>');
400:         printf('  <td%s%s>',
401:                ((!$var->hasHelp() && $form->hasHelp()) ? ' colspan="2"' : ''),
402:                ($var->isDisabled() ? ' class="form-disabled"' : ''));
403:     }
404: 
405:     function _renderVarInputEnd(&$form, &$var, &$vars)
406:     {
407:         /* Display any description for the field. */
408:         if ($var->hasDescription()) {
409:             echo '<br />' . $var->getDescription();
410:         }
411: 
412:         /* Display any help for the field. */
413:         if ($var->hasHelp()) {
414:             global $registry;
415:             if (isset($registry) && $registry instanceof Horde_Registry) {
416:                 $link = Horde_Help::link($GLOBALS['registry']->getApp(), $var->getHelp());
417:             } else {
418:                 $link = '<a href="#" onclick="alert(\'' . addslashes(@htmlspecialchars($var->getHelp())) . '\');return false;">' . $this->_helpMarker . '</a>';
419:             }
420:             echo "</td>\n  <td style=\"text-align:right\">$link&nbsp;";
421:         }
422: 
423:         echo "</td>\n</tr>\n";
424:     }
425: 
426:     // Implementation specifics -- display variables.
427:     function _renderVarDisplayBegin(&$form, &$var, &$vars)
428:     {
429:         $message = $form->getError($var);
430:         $isvalid = empty($message);
431:         echo "<tr valign=\"top\">\n";
432:         printf('  <td%s align="right">%s<strong>%s</strong>%s</td>' . "\n",
433:                empty($this->_attrColumnWidth) ? '' : ' width="' . $this->_attrColumnWidth . '"',
434:                $isvalid ? '' : '<span class="form-error">',
435:                $var->getHumanName(),
436:                $isvalid ? '' : '<br />' . $message . '</span>');
437:         echo '  <td>';
438:     }
439: 
440:     function _renderVarDisplayEnd(&$form, &$var, &$vars)
441:     {
442:         if ($var->hasHelp()) {
443:             echo '</td><td>&nbsp;';
444:         }
445:         echo "</td>\n</tr>\n";
446:     }
447: 
448:     function _sectionHeader($title, $extra = '')
449:     {
450:         if (strlen($title)) {
451:             echo '<div class="header">';
452:             if (!empty($extra)) {
453:                 echo '<span class="rightFloat">' . $extra . '</span>';
454:             }
455:             echo $this->_encodeTitle ? htmlspecialchars($title) : $title;
456:             echo '</div>';
457:         }
458:     }
459: 
460:     /**
461:      * Attempts to return a concrete Horde_Form_Renderer instance based on
462:      * $renderer.
463:      *
464:      * @param mixed $renderer  The type of concrete Horde_Form_Renderer
465:      *                         subclass to return. The code is dynamically
466:      *                         included. If $renderer is an array, then we will
467:      *                         look in $renderer[0]/lib/Form/Renderer/ for the
468:      *                         subclass implementation named $renderer[1].php.
469:      * @param array $params    A hash containing any additional configuration a
470:      *                         form might need.
471:      *
472:      * @return Horde_Form_Renderer  The concrete Horde_Form_Renderer reference,
473:      *                              or false on an error.
474:      */
475:     function factory($renderer = '', $params = null)
476:     {
477:         if (is_array($renderer)) {
478:             $app = $renderer[0];
479:             $renderer = $renderer[1];
480:         }
481: 
482:         /* Return a base Horde_Form_Renderer object if no driver is
483:          * specified. */
484:         $renderer = basename($renderer);
485:         if (!empty($renderer) && $renderer != 'none') {
486:             $class = 'Horde_Form_Renderer_' . $renderer;
487:         } else {
488:             $class = 'Horde_Form_Renderer';
489:         }
490: 
491:         if (!class_exists($class)) {
492:             if (!empty($app)) {
493:                 include $GLOBALS['registry']->get('fileroot', $app) . '/lib/Form/Renderer/' . $renderer . '.php';
494:             } else {
495:                 include 'Horde/Form/Renderer/' . $renderer . '.php';
496:             }
497:         }
498: 
499:         if (class_exists($class)) {
500:             return new $class($params);
501:         } else {
502:             return PEAR::raiseError('Class definition of ' . $class . ' not found.');
503:         }
504:     }
505: 
506:     /**
507:      * Attempts to return a reference to a concrete Horde_Form_Renderer
508:      * instance based on $renderer. It will only create a new instance if no
509:      * Horde_Form_Renderer instance with the same parameters currently exists.
510:      *
511:      * This should be used if multiple types of form renderers (and,
512:      * thus, multiple Horde_Form_Renderer instances) are required.
513:      *
514:      * This method must be invoked as: $var = &Horde_Form_Renderer::singleton()
515:      *
516:      * @param mixed $renderer  The type of concrete Horde_Form_Renderer
517:      *                         subclass to return. The code is dynamically
518:      *                         included. If $renderer is an array, then we will
519:      *                         look in $renderer[0]/lib/Form/Renderer/ for the
520:      *                         subclass implementation named $renderer[1].php.
521:      * @param array $params  A hash containing any additional configuration a
522:      *                       form might need.
523:      *
524:      * @return Horde_Form_Renderer  The concrete Horde_Form_Renderer reference,
525:      *                              or false on an error.
526:      */
527:     function &singleton($renderer, $params = null)
528:     {
529:         static $instances = array();
530: 
531:         $signature = serialize(array($renderer, $params));
532:         if (!isset($instances[$signature])) {
533:             $instances[$signature] = Horde_Form_Renderer::factory($renderer, $params);
534:         }
535: 
536:         return $instances[$signature];
537:     }
538: 
539: }
540: 
API documentation generated by ApiGen