Merge "Add MessagesBi.php"
[lhc/web/wiklou.git] / includes / htmlform / fields / HTMLMultiSelectField.php
index 0d5eeba..e9ecc40 100644 (file)
@@ -22,8 +22,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
                        $this->mParams['disabled-options'] = [];
                }
 
-               // For backwards compatibility, also handle the old way with 'cssclass' => 'mw-chosen'
-               if ( isset( $params['dropdown'] ) || strpos( $this->mClass, 'mw-chosen' ) !== false ) {
+               if ( isset( $params['dropdown'] ) ) {
                        $this->mClass .= ' mw-htmlform-dropdown';
                }
 
@@ -102,10 +101,10 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
                if ( $this->mParent instanceof OOUIHTMLForm ) {
                        throw new MWException( 'HTMLMultiSelectField#getOneCheckbox() is not supported' );
                } else {
-                       $elementFunc = [ 'Html', $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
+                       $elementFunc = [ Html::class, $this->mOptionsLabelsNotFromMessage ? 'rawElement' : 'element' ];
                        $checkbox =
                                Xml::check( "{$this->mName}[]", $checked, $attribs ) .
-                               ' ' .
+                               "\u{00A0}" .
                                call_user_func( $elementFunc,
                                        'label',
                                        [ 'for' => $attribs['id'] ],
@@ -125,45 +124,87 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
         * @return array Options for inclusion in a select or whatever.
         */
        public function getOptionsOOUI() {
-               $options = parent::getOptionsOOUI();
-               foreach ( $options as &$option ) {
-                       $option['disabled'] = in_array( $option['data'], $this->mParams['disabled-options'], true );
-               }
-               return $options;
+               // Sections make this difficult. See getInputOOUI().
+               throw new MWException( 'HTMLMultiSelectField#getOptionsOOUI() is not supported' );
        }
 
        /**
         * Get the OOUI version of this field.
         *
+        * Returns OOUI\CheckboxMultiselectInputWidget for fields that only have one section,
+        * string otherwise.
+        *
         * @since 1.28
         * @param string[] $value
-        * @return OOUI\CheckboxMultiselectInputWidget
+        * @return string|OOUI\CheckboxMultiselectInputWidget
         */
        public function getInputOOUI( $value ) {
                $this->mParent->getOutput()->addModules( 'oojs-ui-widgets' );
 
-               $attr = [];
-               $attr['id'] = $this->mID;
-               $attr['name'] = "{$this->mName}[]";
+               $hasSections = false;
+               $optionsOouiSections = [];
+               $options = $this->getOptions();
+               // If the options are supposed to be split into sections, each section becomes a separate
+               // CheckboxMultiselectInputWidget.
+               foreach ( $options as $label => $section ) {
+                       if ( is_array( $section ) ) {
+                               $optionsOouiSections[ $label ] = Xml::listDropDownOptionsOoui( $section );
+                               unset( $options[$label] );
+                               $hasSections = true;
+                       }
+               }
+               // If anything remains in the array, they are sectionless options. Put them in a separate widget
+               // at the beginning.
+               if ( $options ) {
+                       $optionsOouiSections = array_merge(
+                               [ '' => Xml::listDropDownOptionsOoui( $options ) ],
+                               $optionsOouiSections
+                       );
+               }
+
+               $out = [];
+               foreach ( $optionsOouiSections as $sectionLabel => $optionsOoui ) {
+                       $attr = [];
+                       $attr['name'] = "{$this->mName}[]";
 
-               $attr['value'] = $value;
-               $attr['options'] = $this->getOptionsOOUI();
+                       $attr['value'] = $value;
+                       $attr['options'] = $optionsOoui;
 
-               if ( $this->mOptionsLabelsNotFromMessage ) {
                        foreach ( $attr['options'] as &$option ) {
-                               $option['label'] = new OOUI\HtmlSnippet( $option['label'] );
+                               $option['disabled'] = in_array( $option['data'], $this->mParams['disabled-options'], true );
+                       }
+                       if ( $this->mOptionsLabelsNotFromMessage ) {
+                               foreach ( $attr['options'] as &$option ) {
+                                       $option['label'] = new OOUI\HtmlSnippet( $option['label'] );
+                               }
+                       }
+
+                       $attr += OOUI\Element::configFromHtmlAttributes(
+                               $this->getAttributes( [ 'disabled', 'tabindex' ] )
+                       );
+
+                       if ( $this->mClass !== '' ) {
+                               $attr['classes'] = [ $this->mClass ];
                        }
-               }
 
-               $attr += OOUI\Element::configFromHtmlAttributes(
-                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
-               );
+                       $widget = new OOUI\CheckboxMultiselectInputWidget( $attr );
+                       if ( $sectionLabel ) {
+                               $out[] = new OOUI\FieldsetLayout( [
+                                       'items' => [ $widget ],
+                                       'label' => new OOUI\HtmlSnippet( $sectionLabel ),
+                               ] );
+                       } else {
+                               $out[] = $widget;
+                       }
+               }
 
-               if ( $this->mClass !== '' ) {
-                       $attr['classes'] = [ $this->mClass ];
+               if ( !$hasSections ) {
+                       // Directly return the only OOUI\CheckboxMultiselectInputWidget.
+                       // This allows it to be made infusable and later tweaked by JS code.
+                       return $out[ 0 ];
                }
 
-               return new OOUI\CheckboxMultiselectInputWidget( $attr );
+               return implode( '', $out );
        }
 
        /**
@@ -172,10 +213,14 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
         * @return string|array
         */
        public function loadDataFromRequest( $request ) {
-               if ( $this->isSubmitAttempt( $request ) ) {
+               $fromRequest = $request->getArray( $this->mName, [] );
+               // Fetch the value in either one of the two following case:
+               // - we have a valid submit attempt (form was just submitted)
+               // - we have a value (an URL manually built by the user, or GET form with no wpFormIdentifier)
+               if ( $this->isSubmitAttempt( $request ) || $fromRequest ) {
                        // Checkboxes are just not added to the request arrays if they're not checked,
                        // so it's perfectly possible for there not to be an entry at all
-                       return $request->getArray( $this->mName, [] );
+                       return $fromRequest;
                } else {
                        // That's ok, the user has not yet submitted the form, so show the defaults
                        return $this->getDefault();