Add Html::input() convenience function
authorAryeh Gregor <simetrical@users.mediawiki.org>
Tue, 11 Aug 2009 01:00:44 +0000 (01:00 +0000)
committerAryeh Gregor <simetrical@users.mediawiki.org>
Tue, 11 Aug 2009 01:00:44 +0000 (01:00 +0000)
Currently only used in SpecialResetpass.  Also added some whitespace to
the HTML output of SpecialResetpass, so that it's somewhat readable.

includes/Html.php
includes/specials/SpecialResetpass.php

index 7a75aef..0cbeb08 100644 (file)
@@ -46,6 +46,14 @@ class Html {
                'keygen', 'link', 'meta', 'param', 'source'
        );
 
+       # Boolean attributes, which may have the value omitted entirely.  Manually
+       # collected from the HTML 5 spec as of 2009-08-10.
+       private static $boolAttribs = array( 'async', 'autobuffer', 'autofocus',
+               'autoplay', 'checked', 'controls', 'defer', 'disabled',
+               'formnovalidate', 'hidden', 'ismap', 'loop', 'multiple', 'novalidate',
+               'open', 'readonly', 'required', 'reversed', 'scoped', 'seamless'
+       );
+
        /**
         * Returns an HTML element in a string.  The major advantage here over
         * manually typing out the HTML is that it will escape all attribute
@@ -62,7 +70,7 @@ class Html {
         *
         * One notable difference to Xml::element() is that $contents is *not*
         * escaped.  This means that Html::element() can be usefully nested, rather
-        * than using the rather clumsy Xml::openElement() and Xml::closeElement().  
+        * than using the rather clumsy Xml::openElement() and Xml::closeElement().
         *
         * @param $element  string The element's name, e.g., 'a'
         * @param $attribs  array  Associative array of attributes, e.g., array(
@@ -91,7 +99,8 @@ class Html {
         * 'http://www.mediawiki.org/' ) becomes something like
         * ' href="http://www.mediawiki.org"'.  Again, this is like
         * Xml::expandAttributes(), but it implements some HTML-specific logic.
-        * For instance, it will omit quotation marks if $wgWellFormedXml is false.
+        * For instance, it will omit quotation marks if $wgWellFormedXml is false,
+        * and will treat boolean attributes specially.
         *
         * @param $attribs array Associative array of attributes, e.g., array(
         *   'href' => 'http://www.mediawiki.org/' ).  Values will be HTML-escaped.
@@ -99,7 +108,7 @@ class Html {
         *   (starting with a space if at least one attribute is output)
         */
        public static function expandAttributes( $attribs ) {
-               global $wgWellFormedXml;
+               global $wgHtml5, $wgWellFormedXml;
 
                $ret = '';
                foreach ( $attribs as $key => $value ) {
@@ -115,18 +124,31 @@ class Html {
                                $quote = '';
                        }
 
-                       # Apparently we need to entity-encode \n, \r, \t, although the spec
-                       # doesn't mention that.  Since we're doing strtr() anyway, and we
-                       # don't need <> escaped here, we may as well not call
-                       # htmlspecialchars().  FIXME: verify that we actually need to 
-                       # escape \n\r\t here, and explain why, exactly.
-                       $ret .= " $key=$quote" . strtr( $value, array(
-                               '&' => '&amp;',
-                               '"' => '&quot;',
-                               "\n" => '&#10;',
-                               "\r" => '&#13;',
-                               "\t" => '&#9;'
-                       ) ) . $quote;
+                       if ( in_array( $key, self::$boolAttribs ) ) {
+                               # In XHTML 1.0 Transitional, the value needs to be equal to the
+                               # key.  In HTML 5, we can leave the value empty instead.  If we
+                               # don't need well-formed XML, we can omit the = entirely.
+                               if ( !$wgWellFormedXml ) {
+                                       $ret .= " $key";
+                               } elseif ( $wgHtml5 ) {
+                                       $ret .= " $key=\"\"";
+                               } else {
+                                       $ret .= " $key=\"$key\"";
+                               }
+                       } else {
+                               # Apparently we need to entity-encode \n, \r, \t, although the
+                               # spec doesn't mention that.  Since we're doing strtr() anyway,
+                               # and we don't need <> escaped here, we may as well not call
+                               # htmlspecialchars().  FIXME: verify that we actually need to
+                               # escape \n\r\t here, and explain why, exactly.
+                               $ret .= " $key=$quote" . strtr( $value, array(
+                                       '&' => '&amp;',
+                                       '"' => '&quot;',
+                                       "\n" => '&#10;',
+                                       "\r" => '&#13;',
+                                       "\t" => '&#9;'
+                               ) ) . $quote;
+                       }
                }
                return $ret;
        }
@@ -182,8 +204,8 @@ class Html {
 
                $attrs = array();
                if ( !$wgHtml5 ) {
-                       # Technically we should probably add CDATA stuff here like with 
-                       # scripts, but in practice, stylesheets tend not to have 
+                       # Technically we should probably add CDATA stuff here like with
+                       # scripts, but in practice, stylesheets tend not to have
                        # problematic characters anyway.
                        $attrs['type'] = 'text/css';
                }
@@ -214,4 +236,41 @@ class Html {
                }
                return self::element( 'link', $attrs );
        }
+
+       /**
+        * Convenience function to produce an <input> element.  This supports the
+        * new HTML 5 input types and attributes, and will silently strip them if
+        * $wgHtml5 is false.
+        *
+        * @param $name    string name attribute
+        * @param $value   mixed  value attribute (null = omit)
+        * @param $type    string type attribute
+        * @param $attribs array  Assocative array of miscellaneous extra attributes,
+        *   passed to Html::element()
+        * @return string Raw HTML
+        */
+       public static function input( $name, $value = null, $type = 'text', $attribs = array() ) {
+               global $wgHtml5;
+
+               if ( !$wgHtml5 ) {
+                       if ( !in_array( $type, array( 'hidden', 'text', 'password',
+                       'checkbox', 'radio', 'file', 'submit', 'image', 'reset', 'button'
+                       ) ) ) {
+                               $type = 'text';
+                       }
+                       foreach ( array( 'autocomplete', 'autofocus', 'max', 'min', 'multiple',
+                       'pattern', 'placeholder', 'required', 'step' ) as $badAttr ) {
+                               unset( $attribs[$badAttr] );
+                       }
+               }
+               if ( $type != 'text' ) {
+                       $attribs['type'] = $type;
+               }
+               if ( $value !== null ) {
+                       $attribs['value'] = $value;
+               }
+               $attribs['name'] = $name;
+
+               return self::element( 'input', $attribs );
+       }
 }
index 67e68b3..4aac1ee 100644 (file)
@@ -102,62 +102,58 @@ class SpecialResetpass extends SpecialPage {
                                array(
                                        'method' => 'post',
                                        'action' => $self->getLocalUrl(),
-                                       'id' => 'mw-resetpass-form' ) ) .       
-                       Xml::hidden( 'token', $wgUser->editToken() ) .
-                       Xml::hidden( 'wpName', $this->mUserName ) .
-                       Xml::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) .
-                       wfMsgExt( 'resetpass_text', array( 'parse' ) ) .
-                       Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) .
+                                       'id' => 'mw-resetpass-form' ) ) . "\n" .
+                       Xml::hidden( 'token', $wgUser->editToken() ) . "\n" .
+                       Xml::hidden( 'wpName', $this->mUserName ) . "\n" .
+                       Xml::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) . "\n" .
+                       wfMsgExt( 'resetpass_text', array( 'parse' ) ) . "\n" .
+                       Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) . "\n" .
                        $this->pretty( array(
                                array( 'wpName', 'username', 'text', $this->mUserName ),
                                array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass ),
                                array( 'wpNewPassword', 'newpassword', 'password', '' ),
                                array( 'wpRetype', 'retypenew', 'password', '' ),
-                       ) ) .
+                       ) ) . "\n" .
                        $rememberMe .
-                       '<tr>' .
-                               '<td></td>' .
+                       "<tr>\n" .
+                               "<td></td>\n" .
                                '<td class="mw-input">' .
                                        Xml::submitButton( wfMsg( $submitMsg ) ) .
-                               '</td>' .
-                       '</tr>' .
+                               "</td>\n" .
+                       "</tr>\n" .
                        Xml::closeElement( 'table' ) .
                        Xml::closeElement( 'form' ) .
-                       Xml::closeElement( 'fieldset' )
+                       Xml::closeElement( 'fieldset' ) . "\n"
                );
        }
 
        function pretty( $fields ) {
-               global $wgHtml5;
                $out = '';
-               foreach( $fields as $list ) {
+               foreach ( $fields as $list ) {
                        list( $name, $label, $type, $value ) = $list;
                        if( $type == 'text' ) {
                                $field = htmlspecialchars( $value );
                        } else {
-                               $attribs = array( 'id' => $name, 'type' => $type );
-                               if ( $wgHtml5 ) {
-                                       # All three fields are required, and we should focus the
-                                       # first (wpPassword)
-                                       $attribs['required'] = '';
-                                       if ( $name == 'wpPassword' ) {
-                                               $attribs['autofocus'] = '';
-                                       }
+                               $attribs = array( 'id' => $name );
+                               # All three fields are required, and we should focus the first
+                               # (wpPassword)
+                               $attribs['required'] = '';
+                               if ( $name == 'wpPassword' ) {
+                                       $attribs['autofocus'] = '';
                                }
-                               $field = Xml::input( $name, 20, $value,
-                                       $attribs );
+                               $field = Html::input( $name, $value, $type, $attribs );
                        }
-                       $out .= '<tr>';
-                       $out .= "<td class='mw-label'>";
+                       $out .= "<tr>\n";
+                       $out .= "\t<td class='mw-label'>";
                        if ( $type != 'text' )
                                $out .= Xml::label( wfMsg( $label ), $name );
                        else 
                                $out .=  wfMsgHtml( $label );
-                       $out .= '</td>';
-                       $out .= "<td class='mw-input'>";
+                       $out .= "</td>\n";
+                       $out .= "\t<td class='mw-input'>";
                        $out .= $field;
-                       $out .= '</td>';
-                       $out .= '</tr>';
+                       $out .= "</td>\n";
+                       $out .= "</tr>";
                }
                return $out;
        }