MediaWiki
REL1_23
|
00001 <?php 00002 00100 class HTMLForm extends ContextSource { 00101 // A mapping of 'type' inputs onto standard HTMLFormField subclasses 00102 public static $typeMappings = array( 00103 'api' => 'HTMLApiField', 00104 'text' => 'HTMLTextField', 00105 'textarea' => 'HTMLTextAreaField', 00106 'select' => 'HTMLSelectField', 00107 'radio' => 'HTMLRadioField', 00108 'multiselect' => 'HTMLMultiSelectField', 00109 'check' => 'HTMLCheckField', 00110 'toggle' => 'HTMLCheckField', 00111 'int' => 'HTMLIntField', 00112 'float' => 'HTMLFloatField', 00113 'info' => 'HTMLInfoField', 00114 'selectorother' => 'HTMLSelectOrOtherField', 00115 'selectandother' => 'HTMLSelectAndOtherField', 00116 'submit' => 'HTMLSubmitField', 00117 'hidden' => 'HTMLHiddenField', 00118 'edittools' => 'HTMLEditTools', 00119 'checkmatrix' => 'HTMLCheckMatrix', 00120 // HTMLTextField will output the correct type="" attribute automagically. 00121 // There are about four zillion other HTML5 input types, like range, but 00122 // we don't use those at the moment, so no point in adding all of them. 00123 'email' => 'HTMLTextField', 00124 'password' => 'HTMLTextField', 00125 'url' => 'HTMLTextField', 00126 ); 00127 00128 public $mFieldData; 00129 00130 protected $mMessagePrefix; 00131 00133 protected $mFlatFields; 00134 00135 protected $mFieldTree; 00136 protected $mShowReset = false; 00137 protected $mShowSubmit = true; 00138 00139 protected $mSubmitCallback; 00140 protected $mValidationErrorMessage; 00141 00142 protected $mPre = ''; 00143 protected $mHeader = ''; 00144 protected $mFooter = ''; 00145 protected $mSectionHeaders = array(); 00146 protected $mSectionFooters = array(); 00147 protected $mPost = ''; 00148 protected $mId; 00149 protected $mTableId = ''; 00150 00151 protected $mSubmitID; 00152 protected $mSubmitName; 00153 protected $mSubmitText; 00154 protected $mSubmitTooltip; 00155 00156 protected $mTitle; 00157 protected $mMethod = 'post'; 00158 00164 protected $mAction = false; 00165 00166 protected $mUseMultipart = false; 00167 protected $mHiddenFields = array(); 00168 protected $mButtons = array(); 00169 00170 protected $mWrapperLegend = false; 00171 00179 protected $mSubSectionBeforeFields = true; 00180 00186 protected $displayFormat = 'table'; 00187 00192 protected $availableDisplayFormats = array( 00193 'table', 00194 'div', 00195 'raw', 00196 'vform', 00197 ); 00198 00207 public function __construct( $descriptor, /*IContextSource*/ $context = null, 00208 $messagePrefix = '' 00209 ) { 00210 if ( $context instanceof IContextSource ) { 00211 $this->setContext( $context ); 00212 $this->mTitle = false; // We don't need them to set a title 00213 $this->mMessagePrefix = $messagePrefix; 00214 } elseif ( is_null( $context ) && $messagePrefix !== '' ) { 00215 $this->mMessagePrefix = $messagePrefix; 00216 } elseif ( is_string( $context ) && $messagePrefix === '' ) { 00217 // B/C since 1.18 00218 // it's actually $messagePrefix 00219 $this->mMessagePrefix = $context; 00220 } 00221 00222 // Expand out into a tree. 00223 $loadedDescriptor = array(); 00224 $this->mFlatFields = array(); 00225 00226 foreach ( $descriptor as $fieldname => $info ) { 00227 $section = isset( $info['section'] ) 00228 ? $info['section'] 00229 : ''; 00230 00231 if ( isset( $info['type'] ) && $info['type'] == 'file' ) { 00232 $this->mUseMultipart = true; 00233 } 00234 00235 $field = self::loadInputFromParameters( $fieldname, $info ); 00236 // FIXME During field's construct, the parent form isn't available! 00237 // could add a 'parent' name-value to $info, could add a third parameter. 00238 $field->mParent = $this; 00239 00240 // vform gets too much space if empty labels generate HTML. 00241 if ( $this->isVForm() ) { 00242 $field->setShowEmptyLabel( false ); 00243 } 00244 00245 $setSection =& $loadedDescriptor; 00246 if ( $section ) { 00247 $sectionParts = explode( '/', $section ); 00248 00249 while ( count( $sectionParts ) ) { 00250 $newName = array_shift( $sectionParts ); 00251 00252 if ( !isset( $setSection[$newName] ) ) { 00253 $setSection[$newName] = array(); 00254 } 00255 00256 $setSection =& $setSection[$newName]; 00257 } 00258 } 00259 00260 $setSection[$fieldname] = $field; 00261 $this->mFlatFields[$fieldname] = $field; 00262 } 00263 00264 $this->mFieldTree = $loadedDescriptor; 00265 } 00266 00277 public function setDisplayFormat( $format ) { 00278 if ( !in_array( $format, $this->availableDisplayFormats ) ) { 00279 throw new MWException( 'Display format must be one of ' . 00280 print_r( $this->availableDisplayFormats, true ) ); 00281 } 00282 $this->displayFormat = $format; 00283 00284 return $this; 00285 } 00286 00292 public function getDisplayFormat() { 00293 return $this->displayFormat; 00294 } 00295 00301 public function isVForm() { 00302 return $this->displayFormat === 'vform'; 00303 } 00304 00310 static function addJS() { 00311 wfDeprecated( __METHOD__, '1.18' ); 00312 } 00313 00330 public static function getClassFromDescriptor( $fieldname, &$descriptor ) { 00331 if ( isset( $descriptor['class'] ) ) { 00332 $class = $descriptor['class']; 00333 } elseif ( isset( $descriptor['type'] ) ) { 00334 $class = self::$typeMappings[$descriptor['type']]; 00335 $descriptor['class'] = $class; 00336 } else { 00337 $class = null; 00338 } 00339 00340 if ( !$class ) { 00341 throw new MWException( "Descriptor with no class for $fieldname: " . print_r( $descriptor, true ) ); 00342 } 00343 return $class; 00344 } 00345 00355 public static function loadInputFromParameters( $fieldname, $descriptor ) { 00356 $class = self::getClassFromDescriptor( $fieldname, $descriptor ); 00357 00358 $descriptor['fieldname'] = $fieldname; 00359 00360 # @todo This will throw a fatal error whenever someone try to use 00361 # 'class' to feed a CSS class instead of 'cssclass'. Would be 00362 # great to avoid the fatal error and show a nice error. 00363 $obj = new $class( $descriptor ); 00364 00365 return $obj; 00366 } 00367 00377 function prepareForm() { 00378 # Check if we have the info we need 00379 if ( !$this->mTitle instanceof Title && $this->mTitle !== false ) { 00380 throw new MWException( "You must call setTitle() on an HTMLForm" ); 00381 } 00382 00383 # Load data from the request. 00384 $this->loadData(); 00385 00386 return $this; 00387 } 00388 00393 function tryAuthorizedSubmit() { 00394 $result = false; 00395 00396 $submit = false; 00397 if ( $this->getMethod() != 'post' ) { 00398 $submit = true; // no session check needed 00399 } elseif ( $this->getRequest()->wasPosted() ) { 00400 $editToken = $this->getRequest()->getVal( 'wpEditToken' ); 00401 if ( $this->getUser()->isLoggedIn() || $editToken != null ) { 00402 // Session tokens for logged-out users have no security value. 00403 // However, if the user gave one, check it in order to give a nice 00404 // "session expired" error instead of "permission denied" or such. 00405 $submit = $this->getUser()->matchEditToken( $editToken ); 00406 } else { 00407 $submit = true; 00408 } 00409 } 00410 00411 if ( $submit ) { 00412 $result = $this->trySubmit(); 00413 } 00414 00415 return $result; 00416 } 00417 00424 function show() { 00425 $this->prepareForm(); 00426 00427 $result = $this->tryAuthorizedSubmit(); 00428 if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) { 00429 return $result; 00430 } 00431 00432 $this->displayForm( $result ); 00433 00434 return false; 00435 } 00436 00445 function trySubmit() { 00446 # Check for validation 00447 foreach ( $this->mFlatFields as $fieldname => $field ) { 00448 if ( !empty( $field->mParams['nodata'] ) ) { 00449 continue; 00450 } 00451 if ( $field->validate( 00452 $this->mFieldData[$fieldname], 00453 $this->mFieldData ) 00454 !== true 00455 ) { 00456 return isset( $this->mValidationErrorMessage ) 00457 ? $this->mValidationErrorMessage 00458 : array( 'htmlform-invalid-input' ); 00459 } 00460 } 00461 00462 $callback = $this->mSubmitCallback; 00463 if ( !is_callable( $callback ) ) { 00464 throw new MWException( 'HTMLForm: no submit callback provided. Use ' . 00465 'setSubmitCallback() to set one.' ); 00466 } 00467 00468 $data = $this->filterDataForSubmit( $this->mFieldData ); 00469 00470 $res = call_user_func( $callback, $data, $this ); 00471 00472 return $res; 00473 } 00474 00486 function setSubmitCallback( $cb ) { 00487 $this->mSubmitCallback = $cb; 00488 00489 return $this; 00490 } 00491 00500 function setValidationErrorMessage( $msg ) { 00501 $this->mValidationErrorMessage = $msg; 00502 00503 return $this; 00504 } 00505 00513 function setIntro( $msg ) { 00514 $this->setPreText( $msg ); 00515 00516 return $this; 00517 } 00518 00527 function setPreText( $msg ) { 00528 $this->mPre = $msg; 00529 00530 return $this; 00531 } 00532 00540 function addPreText( $msg ) { 00541 $this->mPre .= $msg; 00542 00543 return $this; 00544 } 00545 00554 function addHeaderText( $msg, $section = null ) { 00555 if ( is_null( $section ) ) { 00556 $this->mHeader .= $msg; 00557 } else { 00558 if ( !isset( $this->mSectionHeaders[$section] ) ) { 00559 $this->mSectionHeaders[$section] = ''; 00560 } 00561 $this->mSectionHeaders[$section] .= $msg; 00562 } 00563 00564 return $this; 00565 } 00566 00576 function setHeaderText( $msg, $section = null ) { 00577 if ( is_null( $section ) ) { 00578 $this->mHeader = $msg; 00579 } else { 00580 $this->mSectionHeaders[$section] = $msg; 00581 } 00582 00583 return $this; 00584 } 00585 00594 function addFooterText( $msg, $section = null ) { 00595 if ( is_null( $section ) ) { 00596 $this->mFooter .= $msg; 00597 } else { 00598 if ( !isset( $this->mSectionFooters[$section] ) ) { 00599 $this->mSectionFooters[$section] = ''; 00600 } 00601 $this->mSectionFooters[$section] .= $msg; 00602 } 00603 00604 return $this; 00605 } 00606 00616 function setFooterText( $msg, $section = null ) { 00617 if ( is_null( $section ) ) { 00618 $this->mFooter = $msg; 00619 } else { 00620 $this->mSectionFooters[$section] = $msg; 00621 } 00622 00623 return $this; 00624 } 00625 00633 function addPostText( $msg ) { 00634 $this->mPost .= $msg; 00635 00636 return $this; 00637 } 00638 00646 function setPostText( $msg ) { 00647 $this->mPost = $msg; 00648 00649 return $this; 00650 } 00651 00661 public function addHiddenField( $name, $value, $attribs = array() ) { 00662 $attribs += array( 'name' => $name ); 00663 $this->mHiddenFields[] = array( $value, $attribs ); 00664 00665 return $this; 00666 } 00667 00678 public function addHiddenFields( array $fields ) { 00679 foreach ( $fields as $name => $value ) { 00680 $this->mHiddenFields[] = array( $value, array( 'name' => $name ) ); 00681 } 00682 00683 return $this; 00684 } 00685 00696 public function addButton( $name, $value, $id = null, $attribs = null ) { 00697 $this->mButtons[] = compact( 'name', 'value', 'id', 'attribs' ); 00698 00699 return $this; 00700 } 00701 00714 function displayForm( $submitResult ) { 00715 $this->getOutput()->addHTML( $this->getHTML( $submitResult ) ); 00716 } 00717 00725 function getHTML( $submitResult ) { 00726 # For good measure (it is the default) 00727 $this->getOutput()->preventClickjacking(); 00728 $this->getOutput()->addModules( 'mediawiki.htmlform' ); 00729 if ( $this->isVForm() ) { 00730 $this->getOutput()->addModuleStyles( array( 00731 'mediawiki.ui', 00732 'mediawiki.ui.button', 00733 ) ); 00734 // @todo Should vertical form set setWrapperLegend( false ) 00735 // to hide ugly fieldsets? 00736 } 00737 00738 $html = '' 00739 . $this->getErrors( $submitResult ) 00740 . $this->mHeader 00741 . $this->getBody() 00742 . $this->getHiddenFields() 00743 . $this->getButtons() 00744 . $this->mFooter; 00745 00746 $html = $this->wrapForm( $html ); 00747 00748 return '' . $this->mPre . $html . $this->mPost; 00749 } 00750 00758 function wrapForm( $html ) { 00759 00760 # Include a <fieldset> wrapper for style, if requested. 00761 if ( $this->mWrapperLegend !== false ) { 00762 $html = Xml::fieldset( $this->mWrapperLegend, $html ); 00763 } 00764 # Use multipart/form-data 00765 $encType = $this->mUseMultipart 00766 ? 'multipart/form-data' 00767 : 'application/x-www-form-urlencoded'; 00768 # Attributes 00769 $attribs = array( 00770 'action' => $this->getAction(), 00771 'method' => $this->getMethod(), 00772 'class' => array( 'visualClear' ), 00773 'enctype' => $encType, 00774 ); 00775 if ( !empty( $this->mId ) ) { 00776 $attribs['id'] = $this->mId; 00777 } 00778 00779 if ( $this->isVForm() ) { 00780 array_push( $attribs['class'], 'mw-ui-vform', 'mw-ui-container' ); 00781 } 00782 00783 return Html::rawElement( 'form', $attribs, $html ); 00784 } 00785 00790 function getHiddenFields() { 00791 global $wgArticlePath; 00792 00793 $html = ''; 00794 if ( $this->getMethod() == 'post' ) { 00795 $html .= Html::hidden( 00796 'wpEditToken', 00797 $this->getUser()->getEditToken(), 00798 array( 'id' => 'wpEditToken' ) 00799 ) . "\n"; 00800 $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n"; 00801 } 00802 00803 if ( strpos( $wgArticlePath, '?' ) !== false && $this->getMethod() == 'get' ) { 00804 $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n"; 00805 } 00806 00807 foreach ( $this->mHiddenFields as $data ) { 00808 list( $value, $attribs ) = $data; 00809 $html .= Html::hidden( $attribs['name'], $value, $attribs ) . "\n"; 00810 } 00811 00812 return $html; 00813 } 00814 00819 function getButtons() { 00820 $buttons = ''; 00821 00822 if ( $this->mShowSubmit ) { 00823 $attribs = array(); 00824 00825 if ( isset( $this->mSubmitID ) ) { 00826 $attribs['id'] = $this->mSubmitID; 00827 } 00828 00829 if ( isset( $this->mSubmitName ) ) { 00830 $attribs['name'] = $this->mSubmitName; 00831 } 00832 00833 if ( isset( $this->mSubmitTooltip ) ) { 00834 $attribs += Linker::tooltipAndAccesskeyAttribs( $this->mSubmitTooltip ); 00835 } 00836 00837 $attribs['class'] = array( 'mw-htmlform-submit' ); 00838 00839 if ( $this->isVForm() ) { 00840 // mw-ui-block is necessary because the buttons aren't necessarily in an 00841 // immediate child div of the vform. 00842 // @todo Let client specify if the primary submit button is progressive or destructive 00843 array_push( 00844 $attribs['class'], 00845 'mw-ui-button', 00846 'mw-ui-big', 00847 'mw-ui-constructive', 00848 'mw-ui-block' 00849 ); 00850 } 00851 00852 $buttons .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n"; 00853 } 00854 00855 if ( $this->mShowReset ) { 00856 $buttons .= Html::element( 00857 'input', 00858 array( 00859 'type' => 'reset', 00860 'value' => $this->msg( 'htmlform-reset' )->text() 00861 ) 00862 ) . "\n"; 00863 } 00864 00865 foreach ( $this->mButtons as $button ) { 00866 $attrs = array( 00867 'type' => 'submit', 00868 'name' => $button['name'], 00869 'value' => $button['value'] 00870 ); 00871 00872 if ( $button['attribs'] ) { 00873 $attrs += $button['attribs']; 00874 } 00875 00876 if ( isset( $button['id'] ) ) { 00877 $attrs['id'] = $button['id']; 00878 } 00879 00880 $buttons .= Html::element( 'input', $attrs ) . "\n"; 00881 } 00882 00883 $html = Html::rawElement( 'span', 00884 array( 'class' => 'mw-htmlform-submit-buttons' ), "\n$buttons" ) . "\n"; 00885 00886 // Buttons are top-level form elements in table and div layouts, 00887 // but vform wants all elements inside divs to get spaced-out block 00888 // styling. 00889 if ( $this->mShowSubmit && $this->isVForm() ) { 00890 $html = Html::rawElement( 'div', null, "\n$html" ) . "\n"; 00891 } 00892 00893 return $html; 00894 } 00895 00900 function getBody() { 00901 return $this->displaySection( $this->mFieldTree, $this->mTableId ); 00902 } 00903 00911 function getErrors( $errors ) { 00912 if ( $errors instanceof Status ) { 00913 if ( $errors->isOK() ) { 00914 $errorstr = ''; 00915 } else { 00916 $errorstr = $this->getOutput()->parse( $errors->getWikiText() ); 00917 } 00918 } elseif ( is_array( $errors ) ) { 00919 $errorstr = $this->formatErrors( $errors ); 00920 } else { 00921 $errorstr = $errors; 00922 } 00923 00924 return $errorstr 00925 ? Html::rawElement( 'div', array( 'class' => 'error' ), $errorstr ) 00926 : ''; 00927 } 00928 00936 public static function formatErrors( $errors ) { 00937 $errorstr = ''; 00938 00939 foreach ( $errors as $error ) { 00940 if ( is_array( $error ) ) { 00941 $msg = array_shift( $error ); 00942 } else { 00943 $msg = $error; 00944 $error = array(); 00945 } 00946 00947 $errorstr .= Html::rawElement( 00948 'li', 00949 array(), 00950 wfMessage( $msg, $error )->parse() 00951 ); 00952 } 00953 00954 $errorstr = Html::rawElement( 'ul', array(), $errorstr ); 00955 00956 return $errorstr; 00957 } 00958 00966 function setSubmitText( $t ) { 00967 $this->mSubmitText = $t; 00968 00969 return $this; 00970 } 00971 00980 public function setSubmitTextMsg( $msg ) { 00981 $this->setSubmitText( $this->msg( $msg )->text() ); 00982 00983 return $this; 00984 } 00985 00990 function getSubmitText() { 00991 return $this->mSubmitText 00992 ? $this->mSubmitText 00993 : $this->msg( 'htmlform-submit' )->text(); 00994 } 00995 01001 public function setSubmitName( $name ) { 01002 $this->mSubmitName = $name; 01003 01004 return $this; 01005 } 01006 01012 public function setSubmitTooltip( $name ) { 01013 $this->mSubmitTooltip = $name; 01014 01015 return $this; 01016 } 01017 01026 function setSubmitID( $t ) { 01027 $this->mSubmitID = $t; 01028 01029 return $this; 01030 } 01031 01042 function suppressDefaultSubmit( $suppressSubmit = true ) { 01043 $this->mShowSubmit = !$suppressSubmit; 01044 01045 return $this; 01046 } 01047 01057 public function setTableId( $id ) { 01058 $this->mTableId = $id; 01059 01060 return $this; 01061 } 01062 01068 public function setId( $id ) { 01069 $this->mId = $id; 01070 01071 return $this; 01072 } 01073 01084 public function setWrapperLegend( $legend ) { 01085 $this->mWrapperLegend = $legend; 01086 01087 return $this; 01088 } 01089 01099 public function setWrapperLegendMsg( $msg ) { 01100 $this->setWrapperLegend( $this->msg( $msg )->text() ); 01101 01102 return $this; 01103 } 01104 01114 function setMessagePrefix( $p ) { 01115 $this->mMessagePrefix = $p; 01116 01117 return $this; 01118 } 01119 01127 function setTitle( $t ) { 01128 $this->mTitle = $t; 01129 01130 return $this; 01131 } 01132 01137 function getTitle() { 01138 return $this->mTitle === false 01139 ? $this->getContext()->getTitle() 01140 : $this->mTitle; 01141 } 01142 01150 public function setMethod( $method = 'post' ) { 01151 $this->mMethod = $method; 01152 01153 return $this; 01154 } 01155 01156 public function getMethod() { 01157 return $this->mMethod; 01158 } 01159 01173 public function displaySection( $fields, 01174 $sectionName = '', 01175 $fieldsetIDPrefix = '', 01176 &$hasUserVisibleFields = false ) { 01177 $displayFormat = $this->getDisplayFormat(); 01178 01179 $html = ''; 01180 $subsectionHtml = ''; 01181 $hasLabel = false; 01182 01183 switch ( $displayFormat ) { 01184 case 'table': 01185 $getFieldHtmlMethod = 'getTableRow'; 01186 break; 01187 case 'vform': 01188 // Close enough to a div. 01189 $getFieldHtmlMethod = 'getDiv'; 01190 break; 01191 default: 01192 $getFieldHtmlMethod = 'get' . ucfirst( $displayFormat ); 01193 } 01194 01195 foreach ( $fields as $key => $value ) { 01196 if ( $value instanceof HTMLFormField ) { 01197 $v = empty( $value->mParams['nodata'] ) 01198 ? $this->mFieldData[$key] 01199 : $value->getDefault(); 01200 $html .= $value->$getFieldHtmlMethod( $v ); 01201 01202 $labelValue = trim( $value->getLabel() ); 01203 if ( $labelValue != ' ' && $labelValue !== '' ) { 01204 $hasLabel = true; 01205 } 01206 01207 if ( get_class( $value ) !== 'HTMLHiddenField' && 01208 get_class( $value ) !== 'HTMLApiField' 01209 ) { 01210 $hasUserVisibleFields = true; 01211 } 01212 } elseif ( is_array( $value ) ) { 01213 $subsectionHasVisibleFields = false; 01214 $section = 01215 $this->displaySection( $value, 01216 "mw-htmlform-$key", 01217 "$fieldsetIDPrefix$key-", 01218 $subsectionHasVisibleFields ); 01219 $legend = null; 01220 01221 if ( $subsectionHasVisibleFields === true ) { 01222 // Display the section with various niceties. 01223 $hasUserVisibleFields = true; 01224 01225 $legend = $this->getLegend( $key ); 01226 01227 if ( isset( $this->mSectionHeaders[$key] ) ) { 01228 $section = $this->mSectionHeaders[$key] . $section; 01229 } 01230 if ( isset( $this->mSectionFooters[$key] ) ) { 01231 $section .= $this->mSectionFooters[$key]; 01232 } 01233 01234 $attributes = array(); 01235 if ( $fieldsetIDPrefix ) { 01236 $attributes['id'] = Sanitizer::escapeId( "$fieldsetIDPrefix$key" ); 01237 } 01238 $subsectionHtml .= Xml::fieldset( $legend, $section, $attributes ) . "\n"; 01239 } else { 01240 // Just return the inputs, nothing fancy. 01241 $subsectionHtml .= $section; 01242 } 01243 } 01244 } 01245 01246 if ( $displayFormat !== 'raw' ) { 01247 $classes = array(); 01248 01249 if ( !$hasLabel ) { // Avoid strange spacing when no labels exist 01250 $classes[] = 'mw-htmlform-nolabel'; 01251 } 01252 01253 $attribs = array( 01254 'class' => implode( ' ', $classes ), 01255 ); 01256 01257 if ( $sectionName ) { 01258 $attribs['id'] = Sanitizer::escapeId( $sectionName ); 01259 } 01260 01261 if ( $displayFormat === 'table' ) { 01262 $html = Html::rawElement( 'table', 01263 $attribs, 01264 Html::rawElement( 'tbody', array(), "\n$html\n" ) ) . "\n"; 01265 } elseif ( $displayFormat === 'div' || $displayFormat === 'vform' ) { 01266 $html = Html::rawElement( 'div', $attribs, "\n$html\n" ); 01267 } 01268 } 01269 01270 if ( $this->mSubSectionBeforeFields ) { 01271 return $subsectionHtml . "\n" . $html; 01272 } else { 01273 return $html . "\n" . $subsectionHtml; 01274 } 01275 } 01276 01280 function loadData() { 01281 $fieldData = array(); 01282 01283 foreach ( $this->mFlatFields as $fieldname => $field ) { 01284 if ( !empty( $field->mParams['nodata'] ) ) { 01285 continue; 01286 } elseif ( !empty( $field->mParams['disabled'] ) ) { 01287 $fieldData[$fieldname] = $field->getDefault(); 01288 } else { 01289 $fieldData[$fieldname] = $field->loadDataFromRequest( $this->getRequest() ); 01290 } 01291 } 01292 01293 # Filter data. 01294 foreach ( $fieldData as $name => &$value ) { 01295 $field = $this->mFlatFields[$name]; 01296 $value = $field->filter( $value, $this->mFlatFields ); 01297 } 01298 01299 $this->mFieldData = $fieldData; 01300 } 01301 01310 function suppressReset( $suppressReset = true ) { 01311 $this->mShowReset = !$suppressReset; 01312 01313 return $this; 01314 } 01315 01325 function filterDataForSubmit( $data ) { 01326 return $data; 01327 } 01328 01337 public function getLegend( $key ) { 01338 return $this->msg( "{$this->mMessagePrefix}-$key" )->text(); 01339 } 01340 01351 public function setAction( $action ) { 01352 $this->mAction = $action; 01353 01354 return $this; 01355 } 01356 01364 public function getAction() { 01365 global $wgScript, $wgArticlePath; 01366 01367 // If an action is alredy provided, return it 01368 if ( $this->mAction !== false ) { 01369 return $this->mAction; 01370 } 01371 01372 // Check whether we are in GET mode and $wgArticlePath contains a "?" 01373 // meaning that getLocalURL() would return something like "index.php?title=...". 01374 // As browser remove the query string before submitting GET forms, 01375 // it means that the title would be lost. In such case use $wgScript instead 01376 // and put title in an hidden field (see getHiddenFields()). 01377 if ( strpos( $wgArticlePath, '?' ) !== false && $this->getMethod() === 'get' ) { 01378 return $wgScript; 01379 } 01380 01381 return $this->getTitle()->getLocalURL(); 01382 } 01383 }