Merge "Allow providing 'notices' for OOUI HTMLForm fields"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 25 Jul 2016 10:58:45 +0000 (10:58 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 25 Jul 2016 10:58:45 +0000 (10:58 +0000)
1  2 
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php

   *    'help-messages'       -- array of message keys/objects. As above, each item can
   *                             be an array of msg key and then parameters.
   *                             Overwrites 'help'.
+  *    'notice'              -- message text for a message to use as a notice in the field.
+  *                             Currently used by OOUI form fields only.
+  *    'notice-messages'     -- array of message keys/objects to use for notice.
+  *                             Overrides 'notice'.
+  *    'notice-message'      -- message key or object to use as a notice.
   *    'required'            -- passed through to the object, indicating that it
   *                             is a required field.
   *    'size'                -- the length of text fields
@@@ -169,8 -174,6 +174,8 @@@ class HTMLForm extends ContextSource 
        protected $mShowReset = false;
        protected $mShowSubmit = true;
        protected $mSubmitFlags = [ 'constructive', 'primary' ];
 +      protected $mShowCancel = false;
 +      protected $mCancelTarget;
  
        protected $mSubmitCallback;
        protected $mValidationErrorMessage;
        protected $mSubmitText;
        protected $mSubmitTooltip;
  
 +      protected $mFormIdentifier;
        protected $mTitle;
        protected $mMethod = 'post';
        protected $mWasSubmitted = false;
                }
  
                # Load data from the request.
 -              $this->loadData();
 +              if (
 +                      $this->mFormIdentifier === null ||
 +                      $this->getRequest()->getVal( 'wpFormIdentifier' ) === $this->mFormIdentifier
 +              ) {
 +                      $this->loadData();
 +              } else {
 +                      $this->mFieldData = [];
 +              }
  
                return $this;
        }
        public function tryAuthorizedSubmit() {
                $result = false;
  
 -              $submit = false;
 +              $identOkay = false;
 +              if ( $this->mFormIdentifier === null ) {
 +                      $identOkay = true;
 +              } else {
 +                      $identOkay = $this->getRequest()->getVal( 'wpFormIdentifier' ) === $this->mFormIdentifier;
 +              }
 +
 +              $tokenOkay = false;
                if ( $this->getMethod() !== 'post' ) {
 -                      $submit = true; // no session check needed
 +                      $tokenOkay = true; // no session check needed
                } elseif ( $this->getRequest()->wasPosted() ) {
                        $editToken = $this->getRequest()->getVal( 'wpEditToken' );
                        if ( $this->getUser()->isLoggedIn() || $editToken !== null ) {
                                // Session tokens for logged-out users have no security value.
                                // However, if the user gave one, check it in order to give a nice
                                // "session expired" error instead of "permission denied" or such.
 -                              $submit = $this->getUser()->matchEditToken( $editToken, $this->mTokenSalt );
 +                              $tokenOkay = $this->getUser()->matchEditToken( $editToken, $this->mTokenSalt );
                        } else {
 -                              $submit = true;
 +                              $tokenOkay = true;
                        }
                }
  
 -              if ( $submit ) {
 +              if ( $tokenOkay && $identOkay ) {
                        $this->mWasSubmitted = true;
                        $result = $this->trySubmit();
                }
         *  - id: (string, optional) DOM id for the button.
         *  - attribs: (array, optional) Additional HTML attributes.
         *  - flags: (string|string[], optional) OOUI flags.
 +       *  - framed: (boolean=true, optional) OOUI framed attribute.
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
        public function addButton( $data ) {
                        'id' => null,
                        'attribs' => null,
                        'flags' => null,
 +                      'framed' => true,
                ];
  
                return $this;
         */
        public function getHiddenFields() {
                $html = '';
 +              if ( $this->mFormIdentifier !== null ) {
 +                      $html .= Html::hidden(
 +                              'wpFormIdentifier',
 +                              $this->mFormIdentifier
 +                      ) . "\n";
 +              }
                if ( $this->getMethod() === 'post' ) {
                        $html .= Html::hidden(
                                'wpEditToken',
                        ) . "\n";
                }
  
 +              if ( $this->mShowCancel ) {
 +                      $target = $this->mCancelTarget ?: Title::newMainPage();
 +                      if ( $target instanceof Title ) {
 +                              $target = $target->getLocalURL();
 +                      }
 +                      $buttons .= Html::element(
 +                                      'a',
 +                                      [
 +                                              'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button' : null,
 +                                              'href' => $target,
 +                                      ],
 +                                      $this->msg( 'cancel' )->text()
 +                              ) . "\n";
 +              }
 +
                // IE<8 has bugs with <button>, so we'll need to avoid them.
                $isBadIE = preg_match( '/MSIE [1-7]\./i', $this->getRequest()->getHeader( 'User-Agent' ) );
  
                return $this;
        }
  
 +      /**
 +       * Set an internal identifier for this form. It will be submitted as a hidden form field, allowing
 +       * HTMLForm to determine whether the form was submitted (or merely viewed). Setting this serves
 +       * two purposes:
 +       *
 +       * - If you use two or more forms on one page, it allows HTMLForm to identify which of the forms
 +       *   was submitted, and not attempt to validate the other ones.
 +       * - If you use checkbox or multiselect fields inside a form using the GET method, it allows
 +       *   HTMLForm to distinguish between the initial page view and a form submission with all
 +       *   checkboxes or select options unchecked.
 +       *
 +       * @since 1.28
 +       * @param string $ident
 +       * @return $this
 +       */
 +      public function setFormIdentifier( $ident ) {
 +              $this->mFormIdentifier = $ident;
 +
 +              return $this;
 +      }
 +
        /**
         * Stop a default submit button being shown for this form. This implies that an
         * alternate submit method must be provided manually.
                return $this;
        }
  
 +      /**
 +       * Show a cancel button (or prevent it). The button is not shown by default.
 +       * @param bool $show
 +       * @return HTMLForm $this for chaining calls
 +       * @since 1.27
 +       */
 +      public function showCancel( $show = true ) {
 +              $this->mShowCancel = $show;
 +              return $this;
 +      }
 +
 +      /**
 +       * Sets the target where the user is redirected to after clicking cancel.
 +       * @param Title|string $target Target as a Title object or an URL
 +       * @return HTMLForm $this for chaining calls
 +       * @since 1.27
 +       */
 +      public function setCancelTarget( $target ) {
 +              $this->mCancelTarget = $target;
 +              return $this;
 +      }
 +
        /**
         * Set the id of the \<table\> or outermost \<div\> element.
         *
@@@ -349,20 -349,6 +349,20 @@@ abstract class HTMLFormField 
                $this->mShowEmptyLabels = $show;
        }
  
 +      /**
 +       * Can we assume that the request is an attempt to submit a HTMLForm, as opposed to an attempt to
 +       * just view it? This can't normally be distinguished for e.g. checkboxes.
 +       *
 +       * Returns true if the request has a field for a CSRF token (wpEditToken) or a form identifier
 +       * (wpFormIdentifier).
 +       *
 +       * @param WebRequest $request
 +       * @return boolean
 +       */
 +      protected function isSubmitAttempt( WebRequest $request ) {
 +              return $request->getCheck( 'wpEditToken' ) || $request->getCheck( 'wpFormIdentifier' );
 +      }
 +
        /**
         * Get the value that this input has been set to from a posted form,
         * or the input's default value if it has not been set.
                        $error = new OOUI\HtmlSnippet( $error );
                }
  
+               $notices = $this->getNotices();
+               foreach ( $notices as &$notice ) {
+                       $notice = new OOUI\HtmlSnippet( $notice );
+               }
                $config = [
                        'classes' => [ "mw-htmlform-field-$fieldType", $this->mClass ],
                        'align' => $this->getLabelAlignOOUI(),
                        'help' => $helpText !== null ? new OOUI\HtmlSnippet( $helpText ) : null,
                        'errors' => $errors,
+                       'notices' => $notices,
                        'infusable' => $infusable,
                ];
  
                return $errors;
        }
  
+       /**
+        * Determine notices to display for the field.
+        *
+        * @since 1.28
+        * @return string[]
+        */
+       function getNotices() {
+               $notices = [];
+               if ( isset( $this->mParams['notice-message'] ) ) {
+                       $notices[] = $this->getMessage( $this->mParams['notice-message'] )->parse();
+               }
+               if ( isset( $this->mParams['notice-messages'] ) ) {
+                       foreach ( $this->mParams['notice-messages'] as $msg ) {
+                               $notices[] = $this->getMessage( $msg )->parse();
+                       }
+               } elseif ( isset( $this->mParams['notice'] ) ) {
+                       $notices[] = $this->mParams['notice'];
+               }
+               return $notices;
+       }
        /**
         * @return string HTML
         */