r57024 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r57023‎ | r57024 | r57025 >
Date:19:04, 28 September 2009
Author:happy-melon
Status:resolved
Tags:
Comment:
Recommit some of the 'backend' stuff from the Login branch, after talking with Brion:
* ExternalUser::getLocalUser() from r56683
* Documentation and style tweaks for HTMLForm from r56682
* HTMLForm::add{HiddenField|(Pre|Post|Header)Text|Button}() functions, from 56782 and r56896.
Frontend stuff will wait until after 1.16 is branched.
Modified paths:
  • /trunk/phase3/includes/ExternalUser.php (modified) (history)
  • /trunk/phase3/includes/HTMLForm.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/ExternalUser.php
@@ -282,7 +282,25 @@
283283 $dbw->replace( 'external_user',
284284 array( 'eu_wiki_id', 'eu_external_id' ),
285285 array( 'eu_wiki_id' => $id,
286 - 'eu_external_id' => $this->getId() ),
287 - __METHOD__ );
 286+ 'eu_external_id' => $this->getId() ),
 287+ __METHOD__ );
288288 }
289 -}
 289+
 290+ /**
 291+ * Check whether this external user id is already linked with
 292+ * a local user.
 293+ * @return Mixed User if the account is linked, Null otherwise.
 294+ */
 295+ public final function getLocalUser(){
 296+ $dbr = wfGetDb( DB_SLAVE );
 297+ $row = $dbr->selectRow(
 298+ 'external_user',
 299+ '*',
 300+ array( 'eu_external_id' => $this->getId() )
 301+ );
 302+ return $row
 303+ ? User::newFromId( $row->eu_wiki_id )
 304+ : null;
 305+ }
 306+
 307+}
\ No newline at end of file
Index: trunk/phase3/includes/HTMLForm.php
@@ -1,16 +1,54 @@
22 <?php
33
 4+/**
 5+ * Object handling generic submission, CSRF protection, layout and
 6+ * other logic for UI forms. in a reusable manner.
 7+ *
 8+ * In order to generate the form, the HTMLForm object takes an array
 9+ * structure detailing the form fields available. Each element of the
 10+ * array is a basic property-list, including the type of field, the
 11+ * label it is to be given in the form, callbacks for validation and
 12+ * 'filtering', and other pertinent information.
 13+ *
 14+ * Field types are implemented as subclasses of the generic HTMLFormField
 15+ * object, and typically implement at least getInputHTML, which generates
 16+ * the HTML for the input field to be placed in the table.
 17+ *
 18+ * The constructor input is an associative array of $fieldname => $info,
 19+ * where $info is an Associative Array with any of the following:
 20+ *
 21+ * 'class' -- the subclass of HTMLFormField that will be used
 22+ * to create the object. *NOT* the CSS class!
 23+ * 'type' -- roughly translates into the <select> type attribute.
 24+ * if 'class' is not specified, this is used as a map
 25+ * through HTMLForm::$typeMappings to get the class name.
 26+ * 'default' -- default value when the form is displayed
 27+ * 'id' -- HTML id attribute
 28+ * 'options' -- varies according to the specific object.
 29+ * 'label-message' -- message key for a message to use as the label.
 30+ * can be an array of msg key and then parameters to
 31+ * the message.
 32+ * 'label' -- alternatively, a raw text message. Overridden by
 33+ * label-message
 34+ * 'help-message' -- message key for a message to use as a help text.
 35+ * can be an array of msg key and then parameters to
 36+ * the message.
 37+ * 'required' -- passed through to the object, indicating that it
 38+ * is a required field.
 39+ * 'size' -- the length of text fields
 40+ * 'filter-callback -- a function name to give you the chance to
 41+ * massage the inputted value before it's processed.
 42+ * @see HTMLForm::filter()
 43+ * 'validation-callback' -- a function name to give you the chance
 44+ * to impose extra validation on the field input.
 45+ * @see HTMLForm::validate()
 46+ *
 47+ * TODO: Document 'section' / 'subsection' stuff
 48+ */
449 class HTMLForm {
550 static $jsAdded = false;
651
7 - /* The descriptor is an array of arrays.
8 - i.e. array(
9 - 'fieldname' => array( 'section' => 'section/subsection',
10 - properties... ),
11 - ...
12 - )
13 - */
14 -
 52+ # A mapping of 'type' inputs onto standard HTMLFormField subclasses
1553 static $typeMappings = array(
1654 'text' => 'HTMLTextField',
1755 'select' => 'HTMLSelectField',
@@ -22,14 +60,44 @@
2361 'float' => 'HTMLFloatField',
2462 'info' => 'HTMLInfoField',
2563 'selectorother' => 'HTMLSelectOrOtherField',
 64+ 'submit' => 'HTMLSubmitField',
 65+ 'hidden' => 'HTMLHiddenField',
 66+
2667 # HTMLTextField will output the correct type="" attribute automagically.
2768 # There are about four zillion other HTML 5 input types, like url, but
2869 # we don't use those at the moment, so no point in adding all of them.
2970 'email' => 'HTMLTextField',
3071 'password' => 'HTMLTextField',
3172 );
 73+
 74+ protected $mMessagePrefix;
 75+ protected $mFlatFields;
 76+ protected $mFieldTree;
 77+ protected $mShowReset = false;
 78+ public $mFieldData;
 79+
 80+ protected $mSubmitCallback;
 81+ protected $mValidationErrorMessage;
 82+
 83+ protected $mPre = '';
 84+ protected $mHeader = '';
 85+ protected $mPost = '';
 86+
 87+ protected $mSubmitID;
 88+ protected $mSubmitText;
 89+ protected $mTitle;
 90+
 91+ protected $mHiddenFields = array();
 92+ protected $mButtons = array();
 93+
 94+ protected $mWrapperLegend = false;
3295
33 - function __construct( $descriptor, $messagePrefix ) {
 96+ /**
 97+ * Build a new HTMLForm from an array of field attributes
 98+ * @param $descriptor Array of Field constructs, as described above
 99+ * @param $messagePrefix String a prefix to go in front of default messages
 100+ */
 101+ public function __construct( $descriptor, $messagePrefix='' ) {
34102 $this->mMessagePrefix = $messagePrefix;
35103
36104 // Expand out into a tree.
@@ -43,7 +111,7 @@
44112
45113 $info['name'] = $fieldname;
46114
47 - $field = $this->loadInputFromParameters( $info );
 115+ $field = self::loadInputFromParameters( $info );
48116 $field->mParent = $this;
49117
50118 $setSection =& $loadedDescriptor;
@@ -66,10 +134,12 @@
67135 }
68136
69137 $this->mFieldTree = $loadedDescriptor;
70 -
71 - $this->mShowReset = true;
72138 }
73139
 140+ /**
 141+ * Add the HTMLForm-specific JavaScript, if it hasn't been
 142+ * done already.
 143+ */
74144 static function addJS() {
75145 if( self::$jsAdded ) return;
76146
@@ -78,6 +148,11 @@
79149 $wgOut->addScriptClass( 'htmlform' );
80150 }
81151
 152+ /**
 153+ * Initialise a new Object for the field
 154+ * @param $descriptor input Descriptor, as described above
 155+ * @return HTMLFormField subclass
 156+ */
82157 static function loadInputFromParameters( $descriptor ) {
83158 if ( isset( $descriptor['class'] ) ) {
84159 $class = $descriptor['class'];
@@ -95,15 +170,21 @@
96171 return $obj;
97172 }
98173
 174+ /**
 175+ * The here's-one-I-made-earlier option: do the submission if
 176+ * posted, or display the form with or without funky valiation
 177+ * errors
 178+ * @return Bool whether submission was successful.
 179+ */
99180 function show() {
100181 $html = '';
101182
102183 self::addJS();
103184
104 - // Load data from the request.
 185+ # Load data from the request.
105186 $this->loadData();
106187
107 - // Try a submission
 188+ # Try a submission
108189 global $wgUser, $wgRequest;
109190 $editToken = $wgRequest->getVal( 'wpEditToken' );
110191
@@ -114,23 +195,31 @@
115196 if( $result === true )
116197 return $result;
117198
118 - // Display form.
 199+ # Display form.
119200 $this->displayForm( $result );
 201+ return false;
120202 }
121203
122 - /** Return values:
123 - * TRUE == Successful submission
124 - * FALSE == No submission attempted
125 - * Anything else == Error to display.
126 - */
 204+ /**
 205+ * Validate all the fields, and call the submision callback
 206+ * function if everything is kosher.
 207+ * @return Mixed Bool true == Successful submission, Bool false
 208+ * == No submission attempted, anything else == Error to
 209+ * display.
 210+ */
127211 function trySubmit() {
128 - // Check for validation
 212+ # Check for validation
129213 foreach( $this->mFlatFields as $fieldname => $field ) {
130 - if ( !empty( $field->mParams['nodata'] ) ) continue;
131 - if ( $field->validate( $this->mFieldData[$fieldname],
132 - $this->mFieldData ) !== true ) {
133 - return isset( $this->mValidationErrorMessage ) ?
134 - $this->mValidationErrorMessage : array( 'htmlform-invalid-input' );
 214+ if ( !empty( $field->mParams['nodata'] ) )
 215+ continue;
 216+ if ( $field->validate(
 217+ $this->mFieldData[$fieldname],
 218+ $this->mFieldData )
 219+ !== true )
 220+ {
 221+ return isset( $this->mValidationErrorMessage )
 222+ ? $this->mValidationErrorMessage
 223+ : array( 'htmlform-invalid-input' );
135224 }
136225 }
137226
@@ -143,18 +232,69 @@
144233 return $res;
145234 }
146235
 236+ /**
 237+ * Set a callback to a function to do something with the form
 238+ * once it's been successfully validated.
 239+ * @param $cb String function name. The function will be passed
 240+ * the output from HTMLForm::filterDataForSubmit, and must
 241+ * return Bool true on success, Bool false if no submission
 242+ * was attempted, or String HTML output to display on error.
 243+ */
147244 function setSubmitCallback( $cb ) {
148245 $this->mSubmitCallback = $cb;
149246 }
150247
 248+ /**
 249+ * Set a message to display on a validation error.
 250+ * @param $msg Mixed String or Array of valid inputs to wfMsgExt()
 251+ * (so each entry can be either a String or Array)
 252+ */
151253 function setValidationErrorMessage( $msg ) {
152254 $this->mValidationErrorMessage = $msg;
153255 }
 256+
 257+ /**
 258+ * Set the introductory message, overwriting any existing message.
 259+ * @param $msg String complete text of message to display
 260+ */
 261+ function setIntro( $msg ) { $this->mPre = $msg; }
154262
155 - function setIntro( $msg ) {
156 - $this->mIntro = $msg;
 263+ /**
 264+ * Add introductory text.
 265+ * @param $msg String complete text of message to display
 266+ */
 267+ function addPreText( $msg ) { $this->mPre .= $msg; }
 268+
 269+ /**
 270+ * Add header text, inside the form.
 271+ * @param $msg String complete text of message to display
 272+ */
 273+ function addHeaderText( $msg ) { $this->mHeader .= $msg; }
 274+
 275+ /**
 276+ * Add text to the end of the display.
 277+ * @param $msg String complete text of message to display
 278+ */
 279+ function addPostText( $msg ) { $this->mPost .= $msg; }
 280+
 281+ /**
 282+ * Add a hidden field to the output
 283+ * @param $name String field name
 284+ * @param $value String field value
 285+ */
 286+ public function addHiddenField( $name, $value ){
 287+ $this->mHiddenFields[ $name ] = $value;
157288 }
 289+
 290+ public function addButton( $name, $value, $id=null ){
 291+ $this->mButtons[] = compact( 'name', 'value', 'id' );
 292+ }
158293
 294+ /**
 295+ * Display the form (sending to wgOut), with an appropriate error
 296+ * message or stack of messages, and any validation errors, etc.
 297+ * @param $submitResult Mixed output from HTMLForm::trySubmit()
 298+ */
159299 function displayForm( $submitResult ) {
160300 global $wgOut;
161301
@@ -162,44 +302,67 @@
163303 $this->displayErrors( $submitResult );
164304 }
165305
166 - if ( isset( $this->mIntro ) ) {
167 - $wgOut->addHTML( $this->mIntro );
168 - }
 306+ $html = ''
 307+ . $this->mHeader
 308+ . $this->getBody()
 309+ . $this->getHiddenFields()
 310+ . $this->getButtons()
 311+ ;
169312
170 - $html = $this->getBody();
171 -
172 - // Hidden fields
173 - $html .= $this->getHiddenFields();
174 -
175 - // Buttons
176 - $html .= $this->getButtons();
177 -
178313 $html = $this->wrapForm( $html );
179314
180 - $wgOut->addHTML( $html );
 315+ $wgOut->addHTML( ''
 316+ . $this->mPre
 317+ . $html
 318+ . $this->mPost
 319+ );
181320 }
182321
 322+ /**
 323+ * Wrap the form innards in an actual <form> element
 324+ * @param $html String HTML contents to wrap.
 325+ * @return String wrapped HTML.
 326+ */
183327 function wrapForm( $html ) {
 328+
 329+ # Include a <fieldset> wrapper for style, if requested.
 330+ if( $this->mWrapperLegend !== false ){
 331+ $html = Xml::fieldset( $this->mWrapperLegend, $html );
 332+ }
 333+
184334 return Html::rawElement(
185335 'form',
186336 array(
187337 'action' => $this->getTitle()->getFullURL(),
188338 'method' => 'post',
 339+ 'class' => 'visualClear',
189340 ),
190341 $html
191342 );
192343 }
193344
 345+ /**
 346+ * Get the hidden fields that should go inside the form.
 347+ * @return String HTML.
 348+ */
194349 function getHiddenFields() {
195350 global $wgUser;
196351 $html = '';
197352
198353 $html .= Html::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n";
199354 $html .= Html::hidden( 'title', $this->getTitle() ) . "\n";
 355+
 356+ foreach( $this->mHiddenFields as $name => $value ){
 357+ $html .= Html::hidden( $name, $value ) . "\n";
 358+ }
200359
201360 return $html;
202361 }
203362
 363+ /**
 364+ * Get the submit and (potentially) reset buttons.
 365+ * @return String HTML.
 366+ */
204367 function getButtons() {
205368 $html = '';
206369
@@ -222,13 +385,31 @@
223386 ) . "\n";
224387 }
225388
 389+ foreach( $this->mButtons as $button ){
 390+ $attrs = array(
 391+ 'type' => 'submit',
 392+ 'name' => $button['name'],
 393+ 'value' => $button['value']
 394+ );
 395+ if( isset( $button['id'] ) )
 396+ $attrs['id'] = $button['id'];
 397+ $html .= Html::element( 'input', $attrs );
 398+ }
 399+
226400 return $html;
227401 }
228402
 403+ /**
 404+ * Get the whole body of the form.
 405+ */
229406 function getBody() {
230407 return $this->displaySection( $this->mFieldTree );
231408 }
232409
 410+ /**
 411+ * Format and display an error message stack.
 412+ * @param $errors Mixed String or Array of message keys
 413+ */
233414 function displayErrors( $errors ) {
234415 if ( is_array( $errors ) ) {
235416 $errorstr = $this->formatErrors( $errors );
@@ -242,6 +423,11 @@
243424 $wgOut->addHTML( $errorstr );
244425 }
245426
 427+ /**
 428+ * Format a stack of error messages into a single HTML string
 429+ * @param $errors Array of message keys/values
 430+ * @return String HTML, a <ul> list of errors
 431+ */
246432 static function formatErrors( $errors ) {
247433 $errorstr = '';
248434 foreach ( $errors as $error ) {
@@ -263,30 +449,70 @@
264450 return $errorstr;
265451 }
266452
 453+ /**
 454+ * Set the text for the submit button
 455+ * @param $t String plaintext.
 456+ */
267457 function setSubmitText( $t ) {
268458 $this->mSubmitText = $t;
269459 }
270460
 461+ /**
 462+ * Get the text for the submit button, either customised or a default.
 463+ * @return unknown_type
 464+ */
271465 function getSubmitText() {
272 - return isset( $this->mSubmitText ) ? $this->mSubmitText : wfMsg( 'htmlform-submit' );
 466+ return $this->mSubmitText
 467+ ? $this->mSubmitText
 468+ : wfMsg( 'htmlform-submit' );
273469 }
274470
 471+ /**
 472+ * Set the id for the submit button.
 473+ * @param $t String. FIXME: Integrity is *not* validated
 474+ */
275475 function setSubmitID( $t ) {
276476 $this->mSubmitID = $t;
277477 }
 478+
 479+ /**
 480+ * Prompt the whole form to be wrapped in a <fieldset>, with
 481+ * this text as its <legend> element.
 482+ * @param $legend String HTML to go inside the <legend> element.
 483+ * Will be escaped
 484+ */
 485+ public function setWrapperLegend( $legend ){ $this->mWrapperLegend = $legend; }
278486
 487+ /**
 488+ * Set the prefix for various default messages
 489+ * TODO: currently only used for the <fieldset> legend on forms
 490+ * with multiple sections; should be used elsewhre?
 491+ * @param $p String
 492+ */
279493 function setMessagePrefix( $p ) {
280494 $this->mMessagePrefix = $p;
281495 }
282496
 497+ /**
 498+ * Set the title for form submission
 499+ * @param $t Title of page the form is on/should be posted to
 500+ */
283501 function setTitle( $t ) {
284502 $this->mTitle = $t;
285503 }
286504
 505+ /**
 506+ * Get the title
 507+ * @return Title
 508+ */
287509 function getTitle() {
288510 return $this->mTitle;
289511 }
290512
 513+ /**
 514+ * TODO: Document
 515+ * @param $fields
 516+ */
291517 function displaySection( $fields ) {
292518 $tableHtml = '';
293519 $subsectionHtml = '';
@@ -295,8 +521,8 @@
296522 foreach( $fields as $key => $value ) {
297523 if ( is_object( $value ) ) {
298524 $v = empty( $value->mParams['nodata'] )
299 - ? $this->mFieldData[$key]
300 - : $value->getDefault();
 525+ ? $this->mFieldData[$key]
 526+ : $value->getDefault();
301527 $tableHtml .= $value->getTableRow( $v );
302528
303529 if( $value->getLabel() != '&nbsp;' )
@@ -319,6 +545,9 @@
320546 return $subsectionHtml . "\n" . $tableHtml;
321547 }
322548
 549+ /**
 550+ * Construct the form fields from the Descriptor array
 551+ */
323552 function loadData() {
324553 global $wgRequest;
325554
@@ -333,7 +562,7 @@
334563 }
335564 }
336565
337 - // Filter data.
 566+ # Filter data.
338567 foreach( $fieldData as $name => &$value ) {
339568 $field = $this->mFlatFields[$name];
340569 $value = $field->filter( $value, $this->mFlatFields );
@@ -342,33 +571,60 @@
343572 $this->mFieldData = $fieldData;
344573 }
345574
346 - function importData( $fieldData ) {
347 - // Filter data.
348 - foreach( $fieldData as $name => &$value ) {
349 - $field = $this->mFlatFields[$name];
350 - $value = $field->filter( $value, $this->mFlatFields );
351 - }
352 -
353 - foreach( $this->mFlatFields as $fieldname => $field ) {
354 - if ( !isset( $fieldData[$fieldname] ) )
355 - $fieldData[$fieldname] = $field->getDefault();
356 - }
357 -
358 - $this->mFieldData = $fieldData;
359 - }
360 -
 575+ /**
 576+ * Stop a reset button being shown for this form
 577+ * @param $suppressReset Bool set to false to re-enable the
 578+ * button again
 579+ */
361580 function suppressReset( $suppressReset = true ) {
362581 $this->mShowReset = !$suppressReset;
363582 }
364583
 584+ /**
 585+ * Overload this if you want to apply special filtration routines
 586+ * to the form as a whole, after it's submitted but before it's
 587+ * processed.
 588+ * @param $data
 589+ * @return unknown_type
 590+ */
365591 function filterDataForSubmit( $data ) {
366592 return $data;
367593 }
368594 }
369595
 596+/**
 597+ * The parent class to generate form fields. Any field type should
 598+ * be a subclass of this.
 599+ */
370600 abstract class HTMLFormField {
 601+
 602+ protected $mValidationCallback;
 603+ protected $mFilterCallback;
 604+ protected $mName;
 605+ public $mParams;
 606+ protected $mLabel; # String label. Set on construction
 607+ protected $mID;
 608+ protected $mDefault;
 609+ public $mParent;
 610+
 611+ /**
 612+ * This function must be implemented to return the HTML to generate
 613+ * the input object itself. It should not implement the surrounding
 614+ * table cells/rows, or labels/help messages.
 615+ * @param $value String the value to set the input to; eg a default
 616+ * text for a text input.
 617+ * @return String valid HTML.
 618+ */
371619 abstract function getInputHTML( $value );
372620
 621+ /**
 622+ * Override this function to add specific validation checks on the
 623+ * field input. Don't forget to call parent::validate() to ensure
 624+ * that the user-defined callback mValidationCallback is still run
 625+ * @param $value String the value the field was submitted with
 626+ * @param $alldata $all the data collected from the form
 627+ * @return Mixed Bool true on success, or String error to display.
 628+ */
373629 function validate( $value, $alldata ) {
374630 if ( isset( $this->mValidationCallback ) ) {
375631 return call_user_func( $this->mValidationCallback, $value, $alldata );
@@ -395,6 +651,12 @@
396652 return true;
397653 }
398654
 655+ /**
 656+ * Get the value that this input has been set to from a posted form,
 657+ * or the input's default value if it has not been set.
 658+ * @param $request WebRequest
 659+ * @return String the value
 660+ */
399661 function loadDataFromRequest( $request ) {
400662 if( $request->getCheck( $this->mName ) ) {
401663 return $request->getText( $this->mName );
@@ -403,9 +665,14 @@
404666 }
405667 }
406668
 669+ /**
 670+ * Initialise the object
 671+ * @param $params Associative Array. See HTMLForm doc for syntax.
 672+ */
407673 function __construct( $params ) {
408674 $this->mParams = $params;
409675
 676+ # Generate the label from a message, if possible
410677 if( isset( $params['label-message'] ) ) {
411678 $msgInfo = $params['label-message'];
412679
@@ -453,8 +720,14 @@
454721 }
455722 }
456723
 724+ /**
 725+ * Get the complete table row for the input, including help text,
 726+ * labels, and whatever.
 727+ * @param $value String the value to set the input to.
 728+ * @return String complete HTML table row.
 729+ */
457730 function getTableRow( $value ) {
458 - // Check for invalid data.
 731+ # Check for invalid data.
459732 global $wgRequest;
460733
461734 $errors = $this->validate( $value, $this->mParent->mFieldData );
@@ -517,7 +790,14 @@
518791 }
519792 }
520793
521 - static function flattenOptions( $options ) {
 794+ /**
 795+ * flatten an array of options to a single array, for instance,
 796+ * a set of <options> inside <optgroups>.
 797+ * @param $options Associative Array with values either Strings
 798+ * or Arrays
 799+ * @return Array flattened input
 800+ */
 801+ public static function flattenOptions( $options ) {
522802 $flatOpts = array();
523803
524804 foreach( $options as $key => $value ) {
@@ -533,11 +813,11 @@
534814 }
535815
536816 class HTMLTextField extends HTMLFormField {
537 - # Override in derived classes to use other Xml::... functions
538 - protected $mFunction = 'input';
539817
540818 function getSize() {
541 - return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45;
 819+ return isset( $this->mParams['size'] )
 820+ ? $this->mParams['size']
 821+ : 45;
542822 }
543823
544824 function getInputHTML( $value ) {
@@ -572,14 +852,11 @@
573853 $attribs[$param] = '';
574854 }
575855 }
576 - }
577 -
578 - # Implement tiny differences between some field variants
579 - # here, rather than creating a new class for each one which
580 - # is essentially just a clone of this one.
581 - if ( isset( $this->mParams['type'] ) ) {
582 - # Options that apply only to HTML5
583 - if( $wgHtml5 ){
 856+
 857+ # Implement tiny differences between some field variants
 858+ # here, rather than creating a new class for each one which
 859+ # is essentially just a clone of this one.
 860+ if ( isset( $this->mParams['type'] ) ) {
584861 switch ( $this->mParams['type'] ) {
585862 case 'email':
586863 $attribs['type'] = 'email';
@@ -591,23 +868,26 @@
592869 $attribs['type'] = 'number';
593870 $attribs['step'] = 'any';
594871 break;
 872+ case 'password':
 873+ $attribs['type'] = 'password';
 874+ break;
595875 }
596876 }
597 - # Options that apply to HTML4 as well
598 - switch( $this->mParams['type'] ){
599 - case 'password':
600 - $attribs['type'] = 'password';
601 - break;
602 - }
603877 }
604878
605879 return Html::element( 'input', $attribs );
606880 }
607881 }
608882
 883+/**
 884+ * A field that will contain a numeric value
 885+ */
609886 class HTMLFloatField extends HTMLTextField {
 887+
610888 function getSize() {
611 - return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 20;
 889+ return isset( $this->mParams['size'] )
 890+ ? $this->mParams['size']
 891+ : 20;
612892 }
613893
614894 function validate( $value, $alldata ) {
@@ -621,8 +901,8 @@
622902
623903 $in_range = true;
624904
625 - # The "int" part of these message names is rather confusing. They make
626 - # equal sense for all numbers.
 905+ # The "int" part of these message names is rather confusing.
 906+ # They make equal sense for all numbers.
627907 if ( isset( $this->mParams['min'] ) ) {
628908 $min = $this->mParams['min'];
629909 if ( $min > $value )
@@ -639,6 +919,9 @@
640920 }
641921 }
642922
 923+/**
 924+ * A field that must contain a number
 925+ */
643926 class HTMLIntField extends HTMLFloatField {
644927 function validate( $value, $alldata ) {
645928 $p = parent::validate( $value, $alldata );
@@ -653,6 +936,9 @@
654937 }
655938 }
656939
 940+/**
 941+ * A checkbox field
 942+ */
657943 class HTMLCheckField extends HTMLFormField {
658944 function getInputHTML( $value ) {
659945 if ( !empty( $this->mParams['invert'] ) )
@@ -667,8 +953,12 @@
668954 Html::rawElement( 'label', array( 'for' => $this->mID ), $this->mLabel );
669955 }
670956
 957+ /**
 958+ * For a checkbox, the label goes on the right hand side, and is
 959+ * added in getInputHTML(), rather than HTMLFormField::getRow()
 960+ */
671961 function getLabel() {
672 - return '&nbsp;'; // In the right-hand column.
 962+ return '&nbsp;';
673963 }
674964
675965 function loadDataFromRequest( $request ) {
@@ -692,6 +982,9 @@
693983 }
694984 }
695985
 986+/**
 987+ * A select dropdown field. Basically a wrapper for Xmlselect class
 988+ */
696989 class HTMLSelectField extends HTMLFormField {
697990
698991 function validate( $value, $alldata ) {
@@ -708,9 +1001,9 @@
7091002 function getInputHTML( $value ) {
7101003 $select = new XmlSelect( $this->mName, $this->mID, strval( $value ) );
7111004
712 - // If one of the options' 'name' is int(0), it is automatically selected.
713 - // because PHP sucks and things int(0) == 'some string'.
714 - // Working around this by forcing all of them to strings.
 1005+ # If one of the options' 'name' is int(0), it is automatically selected.
 1006+ # because PHP sucks and things int(0) == 'some string'.
 1007+ # Working around this by forcing all of them to strings.
7151008 $options = array_map( 'strval', $this->mParams['options'] );
7161009
7171010 if( !empty( $this->mParams['disabled'] ) ) {
@@ -723,6 +1016,9 @@
7241017 }
7251018 }
7261019
 1020+/**
 1021+ * Select dropdown field, with an additional "other" textbox.
 1022+ */
7271023 class HTMLSelectOrOtherField extends HTMLTextField {
7281024 static $jsAdded = false;
7291025
@@ -793,15 +1089,19 @@
7941090 }
7951091 }
7961092
 1093+/**
 1094+ * Multi-select field
 1095+ */
7971096 class HTMLMultiSelectField extends HTMLFormField {
 1097+
7981098 function validate( $value, $alldata ) {
7991099 $p = parent::validate( $value, $alldata );
8001100 if( $p !== true ) return $p;
8011101
8021102 if( !is_array( $value ) ) return false;
8031103
804 - // If all options are valid, array_intersect of the valid options and the provided
805 - // options will return the provided options.
 1104+ # If all options are valid, array_intersect of the valid options
 1105+ # and the provided options will return the provided options.
8061106 $validOptions = HTMLFormField::flattenOptions( $this->mParams['options'] );
8071107
8081108 $validValues = array_intersect( $value, $validOptions );
@@ -844,7 +1144,7 @@
8451145 }
8461146
8471147 function loadDataFromRequest( $request ) {
848 - // won't work with getCheck
 1148+ # won't work with getCheck
8491149 if( $request->getCheck( 'wpEditToken' ) ) {
8501150 $arr = $request->getArray( $this->mName );
8511151
@@ -870,6 +1170,9 @@
8711171 }
8721172 }
8731173
 1174+/**
 1175+ * Radio checkbox fields.
 1176+ */
8741177 class HTMLRadioField extends HTMLFormField {
8751178 function validate( $value, $alldata ) {
8761179 $p = parent::validate( $value, $alldata );
@@ -886,6 +1189,10 @@
8871190 return wfMsgExt( 'htmlform-select-badoption', 'parseinline' );
8881191 }
8891192
 1193+ /**
 1194+ * This returns a block of all the radio options, in one cell.
 1195+ * @see includes/HTMLFormField#getInputHTML()
 1196+ */
8901197 function getInputHTML( $value ) {
8911198 $html = $this->formatOptions( $this->mParams['options'], $value );
8921199
@@ -900,6 +1207,7 @@
9011208 $attribs['disabled'] = 'disabled';
9021209 }
9031210
 1211+ # TODO: should this produce an unordered list perhaps?
9041212 foreach( $options as $label => $info ) {
9051213 if( is_array( $info ) ) {
9061214 $html .= Html::rawElement( 'h1', array(), $label ) . "\n";
@@ -923,6 +1231,9 @@
9241232 }
9251233 }
9261234
 1235+/**
 1236+ * An information field (text blob), not a proper input.
 1237+ */
9271238 class HTMLInfoField extends HTMLFormField {
9281239 function __construct( $info ) {
9291240 $info['nodata'] = true;
@@ -946,3 +1257,29 @@
9471258 return false;
9481259 }
9491260 }
 1261+
 1262+class HTMLHiddenField extends HTMLFormField {
 1263+
 1264+ public function getTableRow( $value ){
 1265+ $this->mParent->addHiddenField(
 1266+ $this->mParams['name'],
 1267+ $this->mParams['default']
 1268+ );
 1269+ return '';
 1270+ }
 1271+
 1272+ public function getInputHTML( $value ){ return ''; }
 1273+}
 1274+
 1275+class HTMLSubmitField extends HTMLFormField {
 1276+
 1277+ public function getTableRow( $value ){
 1278+ $this->mParent->addButton(
 1279+ $this->mParams['name'],
 1280+ $this->mParams['default'],
 1281+ isset($this->mParams['id']) ? $this->mParams['id'] : null
 1282+ );
 1283+ }
 1284+
 1285+ public function getInputHTML( $value ){ return ''; }
 1286+}
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r57096Recommit r56947, partially overwritten in r57024.happy-melon09:46, 30 September 2009

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r56682Document and tidy HTMLForm.php. :Phappy-melon18:50, 20 September 2009
r56683New function for ExternalUser to get the local User corresponding to the exte...happy-melon18:53, 20 September 2009
r56896Improve HTMLForm's support for adding content in and around the form, to impr...happy-melon21:25, 24 September 2009

Status & tagging log