Merge "Pass __METHOD__ to ping query in JobRunner::commitMasterChanges()"
[lhc/web/wiklou.git] / includes / htmlform / HTMLForm.php
index dc73522..ce14003 100644 (file)
@@ -207,9 +207,41 @@ class HTMLForm extends ContextSource {
                'table',
                'div',
                'raw',
+               'inline',
+       );
+
+       /**
+        * Available formats in which to display the form
+        * @var array
+        */
+       protected $availableSubclassDisplayFormats = array(
                'vform',
        );
 
+       /**
+        * Construct a HTMLForm object for given display type. May return a HTMLForm subclass.
+        *
+        * @throws MWException When the display format requested is not known
+        * @param string $displayFormat
+        * @param mixed $arguments... Additional arguments to pass to the constructor.
+        * @return HTMLForm
+        */
+       public static function factory( $displayFormat/*, $arguments...*/ ) {
+               $arguments = func_get_args();
+               array_shift( $arguments );
+
+               switch ( $displayFormat ) {
+                       case 'vform':
+                               $reflector = new ReflectionClass( 'VFormHTMLForm' );
+                               return $reflector->newInstanceArgs( $arguments );
+                       default:
+                               $reflector = new ReflectionClass( 'HTMLForm' );
+                               $form = $reflector->newInstanceArgs( $arguments );
+                               $form->setDisplayFormat( $displayFormat );
+                               return $form;
+               }
+       }
+
        /**
         * Build a new HTMLForm from an array of field attributes
         *
@@ -233,6 +265,11 @@ class HTMLForm extends ContextSource {
                        $this->mMessagePrefix = $context;
                }
 
+               // Evil hack for mobile :(
+               if ( !$this->getConfig()->get( 'HTMLFormAllowTableFormat' ) && $this->displayFormat === 'table' ) {
+                       $this->displayFormat = 'div';
+               }
+
                // Expand out into a tree.
                $loadedDescriptor = array();
                $this->mFlatFields = array();
@@ -246,12 +283,7 @@ class HTMLForm extends ContextSource {
                                $this->mUseMultipart = true;
                        }
 
-                       $field = self::loadInputFromParameters( $fieldname, $info, $this );
-
-                       // vform gets too much space if empty labels generate HTML.
-                       if ( $this->isVForm() ) {
-                               $field->setShowEmptyLabel( false );
-                       }
+                       $field = static::loadInputFromParameters( $fieldname, $info, $this );
 
                        $setSection =& $loadedDescriptor;
                        if ( $section ) {
@@ -286,10 +318,24 @@ class HTMLForm extends ContextSource {
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
        public function setDisplayFormat( $format ) {
+               if (
+                       in_array( $format, $this->availableSubclassDisplayFormats ) ||
+                       in_array( $this->displayFormat, $this->availableSubclassDisplayFormats )
+               ) {
+                       throw new MWException( 'Cannot change display format after creation, ' .
+                               'use HTMLForm::factory() instead' );
+               }
+
                if ( !in_array( $format, $this->availableDisplayFormats ) ) {
                        throw new MWException( 'Display format must be one of ' .
                                print_r( $this->availableDisplayFormats, true ) );
                }
+
+               // Evil hack for mobile :(
+               if ( !$this->getConfig()->get( 'HTMLFormAllowTableFormat' ) && $format === 'table' ) {
+                       $format = 'div';
+               }
+
                $this->displayFormat = $format;
 
                return $this;
@@ -301,20 +347,18 @@ class HTMLForm extends ContextSource {
         * @return string
         */
        public function getDisplayFormat() {
-               $format = $this->displayFormat;
-               if ( !$this->getConfig()->get( 'HTMLFormAllowTableFormat' ) && $format === 'table' ) {
-                       $format = 'div';
-               }
-               return $format;
+               return $this->displayFormat;
        }
 
        /**
         * Test if displayFormat is 'vform'
         * @since 1.22
+        * @deprecated since 1.25
         * @return bool
         */
        public function isVForm() {
-               return $this->displayFormat === 'vform';
+               wfDeprecated( __METHOD__, '1.25' );
+               return false;
        }
 
        /**
@@ -337,7 +381,7 @@ class HTMLForm extends ContextSource {
                if ( isset( $descriptor['class'] ) ) {
                        $class = $descriptor['class'];
                } elseif ( isset( $descriptor['type'] ) ) {
-                       $class = self::$typeMappings[$descriptor['type']];
+                       $class = static::$typeMappings[$descriptor['type']];
                        $descriptor['class'] = $class;
                } else {
                        $class = null;
@@ -362,7 +406,7 @@ class HTMLForm extends ContextSource {
         * @return HTMLFormField Instance of a subclass of HTMLFormField
         */
        public static function loadInputFromParameters( $fieldname, $descriptor, HTMLForm $parent = null ) {
-               $class = self::getClassFromDescriptor( $fieldname, $descriptor );
+               $class = static::getClassFromDescriptor( $fieldname, $descriptor );
 
                $descriptor['fieldname'] = $fieldname;
                if ( $parent ) {
@@ -790,19 +834,6 @@ class HTMLForm extends ContextSource {
                # For good measure (it is the default)
                $this->getOutput()->preventClickjacking();
                $this->getOutput()->addModules( 'mediawiki.htmlform' );
-               if ( $this->isVForm() ) {
-                       // This is required for VForm HTMLForms that use that style regardless
-                       // of wgUseMediaWikiUIEverywhere (since they pre-date it).
-                       // When wgUseMediaWikiUIEverywhere is removed, this should be consolidated
-                       // with the addModuleStyles in SpecialPage->setHeaders.
-                       $this->getOutput()->addModuleStyles( array(
-                               'mediawiki.ui',
-                               'mediawiki.ui.button',
-                               'mediawiki.ui.input',
-                       ) );
-                       // @todo Should vertical form set setWrapperLegend( false )
-                       // to hide ugly fieldsets?
-               }
 
                $html = ''
                        . $this->getErrors( $submitResult )
@@ -818,18 +849,10 @@ class HTMLForm extends ContextSource {
        }
 
        /**
-        * Wrap the form innards in an actual "<form>" element
-        *
-        * @param string $html HTML contents to wrap.
-        *
-        * @return string Wrapped HTML.
+        * Get HTML attributes for the `<form>` tag.
+        * @return array
         */
-       function wrapForm( $html ) {
-
-               # Include a <fieldset> wrapper for style, if requested.
-               if ( $this->mWrapperLegend !== false ) {
-                       $html = Xml::fieldset( $this->mWrapperLegend, $html );
-               }
+       protected function getFormAttributes() {
                # Use multipart/form-data
                $encType = $this->mUseMultipart
                        ? 'multipart/form-data'
@@ -844,12 +867,23 @@ class HTMLForm extends ContextSource {
                if ( !empty( $this->mId ) ) {
                        $attribs['id'] = $this->mId;
                }
+               return $attribs;
+       }
 
-               if ( $this->isVForm() ) {
-                       array_push( $attribs['class'], 'mw-ui-vform', 'mw-ui-container' );
+       /**
+        * Wrap the form innards in an actual "<form>" element
+        *
+        * @param string $html HTML contents to wrap.
+        *
+        * @return string Wrapped HTML.
+        */
+       function wrapForm( $html ) {
+               # Include a <fieldset> wrapper for style, if requested.
+               if ( $this->mWrapperLegend !== false ) {
+                       $html = Xml::fieldset( $this->mWrapperLegend, $html );
                }
 
-               return Html::rawElement( 'form', $attribs, $html );
+               return Html::rawElement( 'form', $this->getFormAttributes(), $html );
        }
 
        /**
@@ -905,21 +939,10 @@ class HTMLForm extends ContextSource {
 
                        $attribs['class'] = array( 'mw-htmlform-submit' );
 
-                       if ( $this->isVForm() || $useMediaWikiUIEverywhere ) {
+                       if ( $useMediaWikiUIEverywhere ) {
                                array_push( $attribs['class'], 'mw-ui-button', $this->mSubmitModifierClass );
                        }
 
-                       if ( $this->isVForm() ) {
-                               // mw-ui-block is necessary because the buttons aren't necessarily in an
-                               // immediate child div of the vform.
-                               // @todo Let client specify if the primary submit button is progressive or destructive
-                               array_push(
-                                       $attribs['class'],
-                                       'mw-ui-big',
-                                       'mw-ui-block'
-                               );
-                       }
-
                        $buttons .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n";
                }
 
@@ -928,7 +951,8 @@ class HTMLForm extends ContextSource {
                                'input',
                                array(
                                        'type' => 'reset',
-                                       'value' => $this->msg( 'htmlform-reset' )->text()
+                                       'value' => $this->msg( 'htmlform-reset' )->text(),
+                                       'class' => ( $useMediaWikiUIEverywhere ? 'mw-ui-button' : null ),
                                )
                        ) . "\n";
                }
@@ -948,15 +972,9 @@ class HTMLForm extends ContextSource {
                                $attrs['id'] = $button['id'];
                        }
 
-                       if ( $this->isVForm() || $useMediaWikiUIEverywhere ) {
-                               if ( isset( $attrs['class'] ) ) {
-                                       $attrs['class'] .= ' mw-ui-button';
-                               } else {
-                                       $attrs['class'] = 'mw-ui-button';
-                               }
-                               if ( $this->isVForm() ) {
-                                       $attrs['class'] .= ' mw-ui-big mw-ui-block';
-                               }
+                       if ( $useMediaWikiUIEverywhere ) {
+                               $attrs['class'] = isset( $attrs['class'] ) ? (array)$attrs['class'] : array();
+                               $attrs['class'][] = 'mw-ui-button';
                        }
 
                        $buttons .= Html::element( 'input', $attrs ) . "\n";
@@ -965,13 +983,6 @@ class HTMLForm extends ContextSource {
                $html = Html::rawElement( 'span',
                        array( 'class' => 'mw-htmlform-submit-buttons' ), "\n$buttons" ) . "\n";
 
-               // Buttons are top-level form elements in table and div layouts,
-               // but vform wants all elements inside divs to get spaced-out block
-               // styling.
-               if ( $this->mShowSubmit && $this->isVForm() ) {
-                       $html = Html::rawElement( 'div', null, "\n$html" ) . "\n";
-               }
-
                return $html;
        }
 
@@ -1284,20 +1295,8 @@ class HTMLForm extends ContextSource {
                $subsectionHtml = '';
                $hasLabel = false;
 
-               switch ( $displayFormat ) {
-                       case 'table':
-                               $getFieldHtmlMethod = 'getTableRow';
-                               break;
-                       case 'vform':
-                               // Close enough to a div.
-                               $getFieldHtmlMethod = 'getDiv';
-                               break;
-                       case 'div':
-                               $getFieldHtmlMethod = 'getDiv';
-                               break;
-                       default:
-                               $getFieldHtmlMethod = 'get' . ucfirst( $displayFormat );
-               }
+               // Conveniently, PHP method names are case-insensitive.
+               $getFieldHtmlMethod = $displayFormat == 'table' ? 'getTableRow' : ( 'get' . $displayFormat );
 
                foreach ( $fields as $key => $value ) {
                        if ( $value instanceof HTMLFormField ) {
@@ -1369,7 +1368,9 @@ class HTMLForm extends ContextSource {
                                $html = Html::rawElement( 'table',
                                                $attribs,
                                                Html::rawElement( 'tbody', array(), "\n$html\n" ) ) . "\n";
-                       } elseif ( $displayFormat === 'div' || $displayFormat === 'vform' ) {
+                       } elseif ( $displayFormat === 'inline' ) {
+                               $html = Html::rawElement( 'span', $attribs, "\n$html\n" );
+                       } else {
                                $html = Html::rawElement( 'div', $attribs, "\n$html\n" );
                        }
                }