[ Index ]

PHP Cross Reference of Web Application Component Toolkit

title

Body

[close]

/framework/template/components/form/ -> form.inc.php (source)

   1  <?php
   2  //--------------------------------------------------------------------------------
   3  // Copyright 2003 Procata, Inc.
   4  // Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html)
   5  //--------------------------------------------------------------------------------
   6  /**
   7  * @package WACT_COMPONENT
   8  * @version $Id: form.inc.php,v 1.19 2004/11/17 00:41:37 jeffmoore Exp $
   9  */
  10  
  11  /**
  12  * The FormComponent provide a runtime API for control the behavior of a form
  13  * @see http://wact.sourceforge.net/index.php/FormComponent
  14  * @access public
  15  * @package WACT_COMPONENT
  16  */
  17  class FormComponent extends TagComponent {
  18      /**
  19      * An ErrorList object
  20      * @var ErrorList
  21      * @access private
  22      */
  23      var $ErrorList;
  24  
  25      /**
  26      * Switch to identify whether the form has errors or not
  27      * @var boolean TRUE means no errors
  28      * @access private
  29      */
  30      var $IsValid = TRUE;
  31  
  32      /**
  33      * An indexed array of variable names used to build hidden form fields which
  34      * are passed on in the next POST request
  35      * @var array
  36      * @access private
  37      */
  38      var $StateVars = array();
  39  
  40      /**
  41      * DataSource object that we delegate to
  42      * @var array
  43      * @access private
  44      */
  45      var $_datasource;
  46  
  47      /**
  48      * @access private
  49      */
  50  	function ensureDataSourceAvailable() {
  51          if (!isset($this->_datasource)) {
  52              $this->registerDataSource(new DataSpace());
  53          }
  54      }
  55  
  56      /**
  57      * Get the named property from the form DataSource
  58      * @param string variable name
  59      * @return mixed value or void if not found
  60      * @access public
  61      * @deprecated will probablybe removed in a future reorganization of
  62      *   how form elements become associated with their values
  63      */
  64  	function _getValue($name) {
  65          $this->ensureDataSourceAvailable();
  66          return $this->_datasource->get($name);
  67      }
  68  
  69      /**
  70      * Set a named property in the form DataSource
  71      * @param string variable name
  72      * @param mixed variable value
  73      * @return void
  74      * @access public
  75      * @deprecated will probablybe removed in a future reorganization of
  76      *   how form elements become associated with their values
  77      */
  78  	function _setValue($name, $value) {
  79          $this->ensureDataSourceAvailable();
  80          $this->_datasource->set($name, $value);
  81      }
  82  
  83      /**
  84      * Initializes the form DataSource
  85      * (typically this is called for you by controllers)
  86      * @return void
  87      * @access public
  88      */
  89  	function prepare() {
  90          $this->ensureDataSourceAvailable();
  91          $this->_datasource->prepare();
  92      }
  93  
  94      /**
  95      * Registers a DataSource with this component
  96      * (typically this is called for you by controllers)
  97      * @param object implementing DataSource interface
  98      * @return void
  99      * @access public
 100      */
 101  	function registerDataSource(&$datasource) {
 102          $this->_datasource =& $datasource;
 103      }
 104  
 105      /**
 106      * Return the DataSource
 107      * (typically this is called for you by controllers)    
 108      * @return object implementing DataSource
 109      * @access public
 110      */
 111      function &getDataSource() {
 112          return $this->_datasource;
 113      }
 114  
 115      /**
 116      * Finds the LabelComponent associated with a form field, allowing 
 117      * an error message to be displayed next to the field. Called by this
 118      * setErrors.
 119      * @param string server id of the form field where the error occurred
 120      * @param object component below which the LabelComponent can be found
 121      * @return mixed either a LabelComponent or false if not found
 122      * @access private
 123      */
 124      function &findLabel($FieldId, &$Component) {
 125          foreach( array_keys($Component->children) as $key) {
 126              $Child =& $Component->children[$key];
 127              if (is_a($Child, 'LabelComponent') && $Child->getAttribute('for') == $FieldId) {
 128                  return $Child;
 129              } else {
 130                  $result =& $this->findLabel($FieldId, $Child);
 131                  if ($result) {
 132                      return $result;
 133                  }
 134              }
 135          }
 136          return FALSE;
 137      }
 138  
 139      /**
 140      * If errors occur, use this method to identify them to the FormComponent.
 141      * (typically this is called for you by controllers)
 142      * @see FormController
 143      * @param ErrorList
 144      * @return void
 145      * @access public
 146      */
 147  	function setErrors(&$ErrorList) {
 148          
 149          // Sets the human readable dictionary corresponding to form fields.
 150          // Entries in the dictionary defined by displayname attribute of tag
 151          $ErrorList->setFieldNameDictionary(new FormFieldNameDictionary($this));        
 152          
 153          $ErrorList->reset();
 154          
 155          while ($ErrorList->next()) {
 156              $this->IsValid = FALSE;
 157              
 158              $Error =& $ErrorList->getError();
 159              
 160              // Find the component(s) that the error applies to and tell
 161              // them there was an error (using their setError() method)
 162              // as well as notifying related label components if found
 163              foreach ($Error->FieldList as $tokenName => $fieldName) {
 164                  $Field =& $this->findChild($fieldName);
 165                  if (is_object($Field)) {
 166                      $Field->setError();
 167                      if ($Field->hasAttribute('id')) {
 168                          $Label =& $this->findLabel($Field->getAttribute('id'), $this);
 169                          if ($Label) {
 170                              $Label->setError();
 171                          }
 172                      }
 173                  }
 174              }
 175              
 176          }
 177          
 178          $this->ErrorList =& $ErrorList;
 179      }
 180  
 181      /**
 182      * Determine whether the form has errors.
 183      * (typically this is called for you by controllers)
 184      * @return boolean TRUE if the form has errros
 185      * @access public
 186      */
 187  	function hasErrors() {
 188          return !$this->IsValid;
 189      }
 190  
 191      /**
 192      * Returns the ErrorList if it exists or an EmptyErrorList if not
 193      * (typically this is called for you by controllers)
 194      * @return object ErrorList or EmptyErrorList
 195      * @access public
 196      */
 197      function &getErrorDataSet() {
 198          if (!isset($this->ErrorList)) {
 199              require_once WACT_ROOT . 'validation/emptyerrorlist.inc.php';
 200              $this->ErrorList =& new EmptyErrorList();
 201          }
 202          return $this->ErrorList;
 203      }
 204  
 205      /**
 206      * Identify a property stored in the DataSource of the component, which
 207      * should be passed as a hidden input field in the form post. The name
 208      * attribute of the hidden input field will be the name of the property.
 209      * Use this to have properties persist between form submits
 210      * @see renderState()
 211      * @param string name of property
 212      * @return void
 213      * @access public
 214      */
 215  	function preserveState($variable) {
 216          $this->StateVars[] = $variable;
 217      }
 218  
 219      /**
 220      * Renders the hidden fields for variables which should be preserved.
 221      * Called from within a compiled template render function.
 222      * @todo XHTML: Input fields should be closed
 223      * @see preserveState()
 224      * @return void
 225      * @access public
 226      */
 227  	function renderState() {
 228          foreach ($this->StateVars as $var) {
 229              echo '<input type="hidden" name="';
 230              echo $var;
 231              echo '" value="';
 232              echo htmlspecialchars($this->_getValue($var), ENT_QUOTES);
 233              echo '">';
 234          }
 235      }
 236      
 237  }
 238  
 239  //--------------------------------------------------------------------------------
 240  /**
 241  * Translates between form name attributes and tag displayname
 242  * attributes (human reabable). Created in FormComponent::setErrors.
 243  * (typically this is handled for you by controllers / form component)
 244  * @see FormComponent::setErrors()
 245  * @see http://wact.sourceforge.net/index.php/FieldNameDictionary
 246  * @access protected
 247  * @package WACT_VALIDATION
 248  */
 249  class FormFieldNameDictionary {
 250  
 251      /**
 252      * @var FormComponent
 253      * @access private
 254      */
 255      var $form;
 256  
 257      /**
 258      * @param FormComponent
 259      * @access protected
 260      */
 261  	function FormFieldNameDictionary(&$form) {
 262          $this->form =& $form;
 263      }
 264  
 265      /**
 266      * @param string name attribute of the field
 267      * @return string displayname attribute of the field
 268      * @access protected
 269      */
 270  	function getFieldName($fieldName) {
 271          $Field =& $this->form->findChild($fieldName);
 272          if (is_object($Field)) {
 273              return $Field->getDisplayName();
 274          } else {
 275              return $fieldName;
 276          }
 277      }
 278  }
 279  
 280  
 281  //--------------------------------------------------------------------------------
 282  /**
 283  * Base class for concrete form elements
 284  * @see http://wact.sourceforge.net/index.php/FormElement
 285  * @access public
 286  * @abstract
 287  * @package WACT_COMPONENT
 288  */
 289  class FormElement extends TagComponent {
 290  
 291      /**
 292      * Whether the form element has validated successfully (default TRUE)
 293      * @var boolean
 294      * @access private
 295      */
 296      var $IsValid = TRUE;
 297  
 298      /**
 299      * Human reable name of the form element determined by
 300      * tag displayname attribute
 301      * @var string
 302      * @access protected
 303      */
 304      var $displayname;
 305  
 306      /**
 307      * CSS class attribute the element should display if there is an error
 308      * Determined by tag errorclass attribute
 309      * @var string
 310      * @access private
 311      */
 312      var $errorclass;
 313  
 314      /**
 315      * CSS style attribute the element should display if there is an error
 316      * Determined by tag errorstyle attribute
 317      * @var string
 318      * @access private
 319      */
 320      var $errorstyle;
 321  
 322      /**
 323      * Returns a value for the name attribute. If $this->displayname is not
 324      * set, returns either the title, alt or name attribute (in that order
 325      * of preference, defined for the tag
 326      * (typically this is called for you by controllers)
 327      * @return string
 328      * @access protected
 329      */
 330  	function getDisplayName() {
 331          if (isset($this->displayname)) {
 332              return $this->displayname;
 333          } else if ($this->hasAttribute('title')) {
 334              return $this->getAttribute('title');
 335          } else if ($this->hasAttribute('alt')) {
 336              return $this->getAttribute('alt');
 337          } else {
 338              return str_replace("_", " ", $this->getAttribute('name'));
 339          }
 340      }
 341  
 342      /**
 343      * Returns true if the form element is in an error state
 344      * (typically this is called for you by controllers)
 345      * @return boolean
 346      * @access protected
 347      */
 348  	function hasErrors() {
 349          return !$this->IsValid;
 350      }
 351  
 352      /**
 353      * Puts the element into the error state and assigns the error class or
 354      * style attributes, if the corresponding member vars have a value
 355      * (typically you shouldn't need to call this)
 356      * @see FormComponent::setErrors()
 357      * @return boolean
 358      * @access protected
 359      */
 360  	function setError() {
 361          $this->IsValid = FALSE;
 362          if (isset($this->errorclass)) {
 363              $this->setAttribute('class', $this->errorclass);
 364          }
 365          if (isset($this->errorstyle)) {
 366              $this->setAttribute('style', $this->errorstyle);
 367          }
 368      }
 369  
 370      /**
 371      * Returns the value of the form element  (it's value in the form DataSource)
 372      * @return string
 373      * @access public
 374      */
 375  	function getValue() {
 376          $FormComponent =& $this->findParentByClass('FormComponent');
 377          return $FormComponent->_getValue($this->getAttribute('name'));
 378      }
 379      
 380      /**
 381      * Sets the value of the form element  (it's value in the form DataSource)
 382      * @param string value
 383      * @return void
 384      * @access public
 385      */
 386  	function setValue($value) {
 387          $FormComponent =& $this->findParentByClass('FormComponent');
 388          return $FormComponent->_setValue($this->getAttribute('name'),$value);
 389      }
 390  
 391      /**
 392      * Overrides TagComponent method so that requests for the value of
 393      * the attribute named "value" return the value from the FormComponent
 394      * DataSource, if it exists. This implementation is overridden itself
 395      * in CheckableFormElement
 396      * @param string attribute name
 397      * @return string attribute value
 398      * @access public
 399      */
 400  	function getAttribute($name) {
 401          if ( strcasecmp($name,'value') == 0 ) {
 402              if ( !is_null($value = $this->getValue()) ) {
 403                  return $value;
 404              }
 405          }
 406          return parent::getAttribute($name);
 407      }
 408      
 409      /**
 410      * Overrides TagComponent method so keep value attribute and value
 411      * in form DataSource in sync
 412      * @param string attribute name
 413      * @param string attribute value
 414      * @return void
 415      * @access public
 416      */
 417  	function setAttribute($name,$value) {
 418          if ( strcasecmp($name,'value') == 0 ) {
 419              $this->setValue($value);
 420          }
 421          parent::setAttribute($name,$value);
 422      }
 423  
 424  }
 425  
 426  //--------------------------------------------------------------------------------
 427  /**
 428  * Inherited by InputTextComponent to make sure they
 429  * have a value attribute
 430  * @see http://wact.sourceforge.net/index.php/InputFormElement
 431  * @access public
 432  * @abstract
 433  * @package WACT_COMPONENT
 434  */
 435  class InputFormElement extends FormElement {
 436  
 437      /**
 438      * Overrides then calls with the parent renderAttributes() method. Makes
 439      * sure there is always a value attribute, even if it's empty.
 440      * Called from within a compiled template render function.
 441      * @todo XHTML: Null attributes need a value
 442      * @return void
 443      * @access protected
 444      */
 445  	function renderAttributes() {
 446          $value = $this->getValue();
 447          if (!is_null($value)) {
 448              $this->setAttribute('value', $value);
 449          } else {
 450              $this->setAttribute('value', '');
 451          }
 452          parent::renderAttributes();
 453      }
 454      
 455  }
 456  
 457  //--------------------------------------------------------------------------------
 458  /**
 459  * Represents an HTML label tag
 460  * @see http://wact.sourceforge.net/index.php/LabelComponent
 461  * @access public
 462  * @package WACT_COMPONENT
 463  */
 464  class LabelComponent extends TagComponent {
 465  
 466      /**
 467      * CSS class attribute to display on error
 468      * Determined by tag errorclass attribute
 469      * @var string
 470      * @access private
 471      */
 472      var $errorclass;
 473      
 474      /**
 475      * CSS style attribute to display on error
 476      * Determined by tag errorstyle attribute
 477      * @var string
 478      * @access private
 479      */
 480      var $errorstyle;
 481  
 482      /**
 483      * If either are set, assigns the attributes for error class or style
 484      * @see FormComponent::setErrors
 485      * @return void
 486      * @access protected
 487      */
 488  	function setError() {
 489          if (isset($this->errorclass)) {
 490              $this->setAttribute('class', $this->errorclass);
 491          }
 492          if (isset($this->errorstyle)) {
 493              $this->setAttribute('style', $this->errorstyle);
 494          }
 495      }
 496  
 497  }
 498  
 499  //--------------------------------------------------------------------------------
 500  /**
 501  * Represents an HTML input type="radio" tag
 502  * Represents an HTML input type="checkbox" tag
 503  * @see http://wact.sourceforge.net/index.php/CheckableFormElement
 504  * @access public
 505  * @package WACT_COMPONENT
 506  */
 507  class CheckableFormElement extends FormElement {
 508  
 509      /**
 510      * Routes call to TagComponent::getAttribute
 511      * @param string attribute name
 512      * @return string attribute value
 513      * @access public
 514      */
 515  	function getAttribute($name) {
 516          // Can't think of a smarter way do this. Would be nice if TagComponent
 517          // wasnt hard coded but rather we skip FormElement
 518          return TagComponent::getAttribute($name);
 519      }
 520      
 521      /**
 522      * Routes call to TagComponent::setAttribute
 523      * @param string attribute name
 524      * @param string attribute value
 525      * @return void
 526      * @access public
 527      */
 528  	function setAttribute($name,$value) {
 529          TagComponent::setAttribute($name,$value);
 530      }
 531  
 532      /**
 533      * Overrides then calls with the parent renderAttributes() method dealing
 534      * with the special case of the checked attribute
 535      * Called from compiled template
 536      * @todo XHTML: Need checked="checked"
 537      * @return void
 538      * @access public
 539      */
 540  	function renderAttributes() {
 541          $value = $this->getValue();
 542          if ($value == $this->getAttribute('value')) {
 543              $this->setAttribute('checked', NULL);
 544          } else {
 545              $this->removeAttribute('checked');
 546          }
 547          parent::renderAttributes();
 548      }
 549      
 550  }
 551  
 552  //--------------------------------------------------------------------------------
 553  /**
 554  * Represents an HTML textarea tag
 555  * @see http://wact.sourceforge.net/index.php/TextAreaComponent
 556  * @access public
 557  * @package WACT_COMPONENT
 558  */
 559  class TextAreaComponent extends FormElement {
 560  
 561      /**
 562      * Output the contents of the textarea, passing through htmlspecialchars().
 563      * Called from within a compiled template's render function
 564      * @return void
 565      * @access protected
 566      */
 567  	function renderContents() {
 568          echo htmlspecialchars($this->getValue(), ENT_QUOTES);
 569      }
 570      
 571  }
 572  ?>


Generated: Sun Nov 28 19:36:09 2004 Cross-referenced by PHPXref 0.5