X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FHTMLForm.php;h=2e7e3999bdce441fe8c76eeb415bdf855cea4d87;hb=8a6475bd704fd57c2207b20e1588134a742e3bb6;hp=0512043af650cae97f8f864809a11ed996b79818;hpb=82817746e680b422066e3b6e367aaffdd0d4be16;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/HTMLForm.php b/includes/HTMLForm.php index 0512043af6..2e7e3999bd 100644 --- a/includes/HTMLForm.php +++ b/includes/HTMLForm.php @@ -1,54 +1,1600 @@ $info, + * where $info is an Associative Array with any of the following: + * + * 'class' -- the subclass of HTMLFormField that will be used + * to create the object. *NOT* the CSS class! + * 'type' -- roughly translates into the \n"; + /** + * Prepare form for submission + */ + function prepareForm() { + # Check if we have the info we need + if ( ! $this->mTitle ) { + throw new MWException( "You must call setTitle() on an HTMLForm" ); + } + + // FIXME shouldn't this be closer to displayForm() ? + self::addJS(); + + # Load data from the request. + $this->loadData(); } - /* private */ function textbox( $varname, $value='', $size=20 ) { - $value = isset( $GLOBALS[$varname] ) ? $GLOBALS[$varname] : $value; - return "
\n"; + /** + * Try submitting, with edit token check first + * @return Status|boolean + */ + function tryAuthorizedSubmit() { + global $wgUser, $wgRequest; + $editToken = $wgRequest->getVal( 'wpEditToken' ); + + $result = false; + if ( $this->getMethod() != 'post' || $wgUser->matchEditToken( $editToken ) ) { + $result = $this->trySubmit(); + } + return $result; } - /* private */ function radiobox( $varname, $fields ) { - foreach ( $fields as $value => $checked ) { - $s .= "
\n"; + + /** + * The here's-one-I-made-earlier option: do the submission if + * posted, or display the form with or without funky valiation + * errors + * @return Bool or Status whether submission was successful. + */ + function show() { + $this->prepareForm(); + + $result = $this->tryAuthorizedSubmit(); + if ( $result === true || ( $result instanceof Status && $result->isGood() ) ){ + return $result; + } + + $this->displayForm( $result ); + return false; + } + + /** + * Validate all the fields, and call the submision callback + * function if everything is kosher. + * @return Mixed Bool true == Successful submission, Bool false + * == No submission attempted, anything else == Error to + * display. + */ + function trySubmit() { + # Check for validation + foreach ( $this->mFlatFields as $fieldname => $field ) { + if ( !empty( $field->mParams['nodata'] ) ) { + continue; + } + if ( $field->validate( + $this->mFieldData[$fieldname], + $this->mFieldData ) + !== true + ) { + return isset( $this->mValidationErrorMessage ) + ? $this->mValidationErrorMessage + : array( 'htmlform-invalid-input' ); + } } - return $this->fieldset( $this->mName.'-'.$varname, $s ); + + $callback = $this->mSubmitCallback; + + $data = $this->filterDataForSubmit( $this->mFieldData ); + + $res = call_user_func( $callback, $data ); + + return $res; + } + + /** + * Set a callback to a function to do something with the form + * once it's been successfully validated. + * @param $cb String function name. The function will be passed + * the output from HTMLForm::filterDataForSubmit, and must + * return Bool true on success, Bool false if no submission + * was attempted, or String HTML output to display on error. + */ + function setSubmitCallback( $cb ) { + $this->mSubmitCallback = $cb; + } + + /** + * Set a message to display on a validation error. + * @param $msg Mixed String or Array of valid inputs to wfMsgExt() + * (so each entry can be either a String or Array) + */ + function setValidationErrorMessage( $msg ) { + $this->mValidationErrorMessage = $msg; + } + + /** + * Set the introductory message, overwriting any existing message. + * @param $msg String complete text of message to display + */ + function setIntro( $msg ) { $this->mPre = $msg; } + + /** + * Add introductory text. + * @param $msg String complete text of message to display + */ + function addPreText( $msg ) { $this->mPre .= $msg; } + + /** + * Add header text, inside the form. + * @param $msg String complete text of message to display + */ + function addHeaderText( $msg ) { $this->mHeader .= $msg; } + + /** + * Add footer text, inside the form. + * @param $msg String complete text of message to display + */ + function addFooterText( $msg ) { $this->mFooter .= $msg; } + + /** + * Add text to the end of the display. + * @param $msg String complete text of message to display + */ + function addPostText( $msg ) { $this->mPost .= $msg; } + + /** + * Add a hidden field to the output + * @param $name String field name. This will be used exactly as entered + * @param $value String field value + * @param $attribs Array + */ + public function addHiddenField( $name, $value, $attribs = array() ) { + $attribs += array( 'name' => $name ); + $this->mHiddenFields[] = array( $value, $attribs ); + } + + public function addButton( $name, $value, $id = null, $attribs = null ) { + $this->mButtons[] = compact( 'name', 'value', 'id', 'attribs' ); + } + + /** + * Display the form (sending to wgOut), with an appropriate error + * message or stack of messages, and any validation errors, etc. + * @param $submitResult Mixed output from HTMLForm::trySubmit() + */ + function displayForm( $submitResult ) { + global $wgOut; + + # For good measure (it is the default) + $wgOut->preventClickjacking(); + + $html = '' + . $this->getErrors( $submitResult ) + . $this->mHeader + . $this->getBody() + . $this->getHiddenFields() + . $this->getButtons() + . $this->mFooter + ; + + $html = $this->wrapForm( $html ); + + $wgOut->addHTML( '' + . $this->mPre + . $html + . $this->mPost + ); + } + + /** + * Wrap the form innards in an actual
element + * @param $html String HTML contents to wrap. + * @return String wrapped HTML. + */ + function wrapForm( $html ) { + + # Include a
wrapper for style, if requested. + if ( $this->mWrapperLegend !== false ) { + $html = Xml::fieldset( $this->mWrapperLegend, $html ); + } + # Use multipart/form-data + $encType = $this->mUseMultipart + ? 'multipart/form-data' + : 'application/x-www-form-urlencoded'; + # Attributes + $attribs = array( + 'action' => $this->getTitle()->getFullURL(), + 'method' => $this->mMethod, + 'class' => 'visualClear', + 'enctype' => $encType, + ); + if ( !empty( $this->mId ) ) { + $attribs['id'] = $this->mId; + } + + return Html::rawElement( 'form', $attribs, $html ); + } + + /** + * Get the hidden fields that should go inside the form. + * @return String HTML. + */ + function getHiddenFields() { + global $wgUser; + + $html = ''; + + if( $this->getMethod() == 'post' ){ + $html .= Html::hidden( 'wpEditToken', $wgUser->editToken(), array( 'id' => 'wpEditToken' ) ) . "\n"; + $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n"; + } + + foreach ( $this->mHiddenFields as $data ) { + list( $value, $attribs ) = $data; + $html .= Html::hidden( $attribs['name'], $value, $attribs ) . "\n"; + } + + return $html; + } + + /** + * Get the submit and (potentially) reset buttons. + * @return String HTML. + */ + function getButtons() { + $html = ''; + $attribs = array(); + + if ( isset( $this->mSubmitID ) ) { + $attribs['id'] = $this->mSubmitID; + } + + if ( isset( $this->mSubmitName ) ) { + $attribs['name'] = $this->mSubmitName; + } + + if ( isset( $this->mSubmitTooltip ) ) { + global $wgUser; + $attribs += $wgUser->getSkin()->tooltipAndAccessKeyAttribs( $this->mSubmitTooltip ); + } + + $attribs['class'] = 'mw-htmlform-submit'; + + $html .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n"; + + if ( $this->mShowReset ) { + $html .= Html::element( + 'input', + array( + 'type' => 'reset', + 'value' => wfMsg( 'htmlform-reset' ) + ) + ) . "\n"; + } + + foreach ( $this->mButtons as $button ) { + $attrs = array( + 'type' => 'submit', + 'name' => $button['name'], + 'value' => $button['value'] + ); + + if ( $button['attribs'] ) { + $attrs += $button['attribs']; + } + + if ( isset( $button['id'] ) ) { + $attrs['id'] = $button['id']; + } + + $html .= Html::element( 'input', $attrs ); + } + + return $html; + } + + /** + * Get the whole body of the form. + */ + function getBody() { + return $this->displaySection( $this->mFieldTree ); + } + + /** + * Format and display an error message stack. + * @param $errors Mixed String or Array of message keys + * @return String + */ + function getErrors( $errors ) { + if ( $errors instanceof Status ) { + global $wgOut; + $errorstr = $wgOut->parse( $errors->getWikiText() ); + } elseif ( is_array( $errors ) ) { + $errorstr = $this->formatErrors( $errors ); + } else { + $errorstr = $errors; + } + + return $errorstr + ? Html::rawElement( 'div', array( 'class' => 'error' ), $errorstr ) + : ''; + } + + /** + * Format a stack of error messages into a single HTML string + * @param $errors Array of message keys/values + * @return String HTML, a