Display permissions specific to the API (such as writeapi and apihighlimits) on actio...
[lhc/web/wiklou.git] / includes / Linker.php
index 5b95abe..b913ebf 100644 (file)
@@ -147,7 +147,8 @@ class Linker {
         *   change to support Images, literal URLs, etc.
         * @param $text          string The HTML contents of the <a> element, i.e.,
         *   the link text.  This is raw HTML and will not be escaped.  If null,
-        *   defaults to the page name of the Title.
+        *   defaults to the prefixed text of the Title; or if the Title is just a
+        *   fragment, the contents of the fragment.
         * @param $query         array  The query string to append to the URL
         *   you're linking to, in key => value array form.  Query keys and values
         *   will be URL-encoded.
@@ -159,25 +160,24 @@ class Linker {
         * @param $options       mixed  String or array of strings:
         *     'known': Page is known to exist, so don't check if it does.
         *     'broken': Page is known not to exist, so don't check if it does.
-        *     'noclasses': Don't add any classes automatically (includes "new", "stub", "mw-redirect").  Only use the class attribute provided, if any.
+        *     'noclasses': Don't add any classes automatically (includes "new",
+        *       "stub", "mw-redirect", "extiw").  Only use the class attribute
+        *       provided, if any, so you get a simple blue link with no funny i-
+        *       cons.
         * @return string HTML <a> attribute
         */
        public function link( $target, $text = null, $customAttribs = array(), $query = array(), $options = array() ) {
                wfProfileIn( __METHOD__ );
-               if( !($target instanceof Title) ) {
+               if( !$target instanceof Title ) {
                        throw new MWException( 'Linker::link passed invalid target' );
                }
                $options = (array)$options;
 
                # Normalize the Title if it's a special page
-               if( $target->getNamespace() == NS_SPECIAL ) {
-                       list( $name, $subpage ) = SpecialPage::resolveAliasWithSubpage( $target->getDBkey() );
-                       if( $name ) {
-                               $target = SpecialPage::getTitleFor( $name, $subpage );
-                       }
-               }
+               $target = $this->normaliseSpecialPage( $target );
 
                # If we don't know whether the page exists, let's find out.
+               wfProfileIn( __METHOD__ . '-checkPageExistence' );
                if( !in_array( 'known', $options ) and !in_array( 'broken', $options ) ) {
                        if( $target->getNamespace() == NS_SPECIAL ) {
                                if( SpecialPage::exists( $target->getDbKey() ) ) {
@@ -190,10 +190,10 @@ class Linker {
                        or $target->exists() ) {
                                $options []= 'known';
                        } else {
-                               # Either it exists
                                $options []= 'broken';
                        }
                }
+               wfProfileOut( __METHOD__ . '-checkPageExistence' );
 
                # Note: we want the href attribute first, for prettiness.
                $attribs = array( 'href' => $this->linkUrl( $target, $query, $options ) );
@@ -202,57 +202,71 @@ class Linker {
                        $this->linkAttribs( $target, $customAttribs, $options )
                );
                if( is_null( $text ) ) {
-                       $text = $this->linkText( $target, $options );
+                       $text = $this->linkText( $target );
                }
 
-               $ret = Xml::element( 'a', $attribs, $text, false );
+               $ret = Xml::openElement( 'a', $attribs )
+                       . $text
+                       . Xml::closeElement( 'a' );
 
                wfProfileOut( __METHOD__ );
                return $ret;
        }
 
        private function linkUrl( $target, $query, $options ) {
-               # If it's a broken link, add the appropriate query pieces.  This over-
-               # writes the default action!
-               if( in_array( 'broken', $options ) ) {
+               wfProfileIn( __METHOD__ );
+               # If it's a broken link, add the appropriate query pieces, unless
+               # there's already an action specified, or unless 'edit' makes no sense
+               # (i.e., for a nonexistent special page).
+               if( in_array( 'broken', $options ) and empty( $query['action'] )
+               and $target->getNamespace() != NS_SPECIAL ) {
                        $query['action'] = 'edit';
                        $query['redlink'] = '1';
                }
-
-               return $target->getLocalURL( wfArrayToCGI( $query ) );
+               $ret = $target->getLinkUrl( $query );
+               wfProfileOut( __METHOD__ );
+               return $ret;
        }
 
        private function linkAttribs( $target, $attribs, $options ) {
+               wfProfileIn( __METHOD__ );
                global $wgUser;
                $defaults = array();
 
-               # First get a default title attribute.
-               if( in_array( 'known', $options ) ) {
-                       $defaults['title'] = $target->getPrefixedText();
-               } else {
-                       $defaults['title'] = wfMsg( 'red-link-title', $target->getPrefixedText() );
-               }
-
                if( !in_array( 'noclasses', $options ) ) {
-                       # Now build the classes.  This is the bulk of what we're doing.
+                       wfProfileIn( __METHOD__ . '-getClasses' );
+                       # Build the classes.
                        $classes = array();
 
                        if( in_array( 'broken', $options ) ) {
-                               $classes []= 'new';
+                               $classes[] = 'new';
+                       }
+
+                       if( $target->isExternal() ) {
+                               $classes[] = 'extiw';
                        }
 
                        # Note that redirects never count as stubs here.
                        if ( $target->isRedirect() ) {
-                               $classes []= 'mw-redirect';
+                               $classes[] = 'mw-redirect';
                        } elseif( $target->isContentPage() ) {
+                               # Check for stub.
                                $threshold = $wgUser->getOption( 'stubthreshold' );
                                if( $threshold > 0 and $target->getLength() < $threshold ) {
-                                       $classes []= 'stub';
+                                       $classes[] = 'stub';
                                }
                        }
                        if( $classes != array() ) {
                                $defaults['class'] = implode( ' ', $classes );
                        }
+                       wfProfileOut( __METHOD__ . '-getClasses' );
+               }
+
+               # Get a default title attribute.
+               if( in_array( 'known', $options ) ) {
+                       $defaults['title'] = $target->getPrefixedText();
+               } else {
+                       $defaults['title'] = wfMsg( 'red-link-title', $target->getPrefixedText() );
                }
 
                # Finally, merge the custom attribs with the default ones, and iterate
@@ -266,10 +280,11 @@ class Linker {
                                $ret[$key] = $val;
                        }
                }
+               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
-       private function linkText( $target, $options ) {
+       private function linkText( $target ) {
                # If the target is just a fragment, with no title, we return the frag-
                # ment text.  Otherwise, we return the title text itself.
                if( $target->getPrefixedText() === '' and $target->getFragment() !== '' ) {
@@ -594,7 +609,9 @@ class Linker {
                if ( $title->getNamespace() == NS_SPECIAL ) {
                        list( $name, $subpage ) = SpecialPage::resolveAliasWithSubpage( $title->getDBkey() );
                        if ( !$name ) return $title;
-                       return SpecialPage::getTitleFor( $name, $subpage );
+                       $ret = SpecialPage::getTitleFor( $name, $subpage );
+                       $ret->mFragment = $title->getFragment();
+                       return $ret;
                } else {
                        return $title;
                }
@@ -1025,13 +1042,12 @@ class Linker {
         * @private
         */
        function userLink( $userId, $userText ) {
-               $encName = htmlspecialchars( $userText );
                if( $userId == 0 ) {
                        $page = SpecialPage::getTitleFor( 'Contributions', $userText );
                } else {
                        $page = Title::makeTitle( NS_USER, $userText );
                }
-               return $this->link( $page, $encName );
+               return $this->link( $page, htmlspecialchars( $userText ) );
        }
 
        /**
@@ -1197,7 +1213,7 @@ class Linker {
         *
         * @todo Document the $local parameter.
         */
-       private function formatAutocomments( $comment, $title = NULL, $local = false ) {
+       private function formatAutocomments( $comment, $title = null, $local = false ) {
                $match = array();
                while (preg_match('!(.*)/\*\s*(.*?)\s*\*/(.*)!', $comment,$match)) {
                        $pre=$match[1];
@@ -1216,12 +1232,14 @@ class Linker {
                                $section = str_replace( '[[', '', $section );
                                $section = str_replace( ']]', '', $section );
                                if ( $local ) {
-                                       $sectionTitle = Title::newFromText( '#' . $section);
+                                       $sectionTitle = Title::newFromText( '#' . $section );
                                } else {
-                                       $sectionTitle = wfClone( $title );
+                                       $sectionTitle = clone( $title );
                                        $sectionTitle->mFragment = $section;
                                }
-                               $link = $this->link( $sectionTitle, wfMsgForContent( 'sectionlink' ) );
+                               $link = $this->link( $sectionTitle,
+                                       wfMsgForContent( 'sectionlink' ), array(), array(),
+                                       'noclasses' );
                        }
                        $auto = $link . $auto;
                        if( $pre ) {
@@ -1542,14 +1560,17 @@ class Linker {
        public function buildRollbackLink( $rev ) {
                global $wgRequest, $wgUser;
                $title = $rev->getTitle();
-               $query = array( 'action' => 'rollback' );
+               $query = array(
+                       'action' => 'rollback',
+                       'from' => $rev->getUserText()
+               );
                if( $wgRequest->getBool( 'bot' ) ) {
                        $query['bot'] = '1';
                }
                $query['token'] = $wgUser->editToken( array( $title->getPrefixedText(),
                        $rev->getUserText() ) );
                return $this->link( $title, wfMsgHtml( 'rollbacklink' ), array(),
-                       $query, 'known' );
+                       $query, array( 'known', 'noclasses' ) );
        }
 
        /**