X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FTitle.php;h=274bd2556be23fd12f885b3be3bfd175cbc949ba;hb=ad39f2da8660219768f46db739be66a27c8eb651;hp=ed6e735b510e16c95e50341a6bfb0ede0240484a;hpb=d636fac2d8416fa8dcd5610bd2c932ab6bc147e1;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Title.php b/includes/Title.php index ed6e735b51..274bd2556b 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -757,6 +757,20 @@ class Title { return $this->mPrefixedText; } + /** + * Return the prefixed title with spaces _without_ the interwiki prefix + * + * @return \type{\string} the title, prefixed by the namespace but not by the interwiki prefix, with spaces + */ + public function getSemiPrefixedText() { + if ( !isset( $this->mSemiPrefixedText ) ){ + $s = ( $this->mNamespace === NS_MAIN ? '' : $this->getNsText() . ':' ) . $this->mTextform; + $s = str_replace( '_', ' ', $s ); + $this->mSemiPrefixedText = $s; + } + return $this->mSemiPrefixedText; + } + /** * Get the prefixed title with spaces, plus any fragment * (part beginning with '#') @@ -835,33 +849,13 @@ class Title { * @return String the URL */ public function getFullURL( $query = '', $variant = false ) { - global $wgServer, $wgRequest; - - if ( is_array( $query ) ) { - $query = wfArrayToCGI( $query ); - } - - $interwiki = Interwiki::fetch( $this->mInterwiki ); - if ( !$interwiki ) { - $url = $this->getLocalURL( $query, $variant ); - - // Ugly quick hack to avoid duplicate prefixes (bug 4571 etc) - // Correct fix would be to move the prepending elsewhere. - if ( $wgRequest->getVal( 'action' ) != 'render' ) { - $url = $wgServer . $url; - } - } else { - $baseUrl = $interwiki->getURL(); + # Hand off all the decisions on urls to getLocalURL + $url = $this->getLocalURL( $query, $variant ); - $namespace = wfUrlencode( $this->getNsText() ); - if ( $namespace != '' ) { - # Can this actually happen? Interwikis shouldn't be parsed. - # Yes! It can in interwiki transclusion. But... it probably shouldn't. - $namespace .= ':'; - } - $url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl ); - $url = wfAppendQuery( $url, $query ); - } + # Expand the url to make it a full url. Note that getLocalURL has the + # potential to output full urls for a variety of reasons, so we use + # wfExpandUrl instead of simply prepending $wgServer + $url = wfExpandUrl( $url, PROTO_RELATIVE ); # Finally, add the fragment. $url .= $this->getFragmentForURL(); @@ -889,15 +883,16 @@ class Title { $query = wfArrayToCGI( $query ); } - if ( $this->isExternal() ) { - $url = $this->getFullURL(); - if ( $query ) { - // This is currently only used for edit section links in the - // context of interwiki transclusion. In theory we should - // append the query to the end of any existing query string, - // but interwiki transclusion is already broken in that case. - $url .= "?$query"; + $interwiki = Interwiki::fetch( $this->mInterwiki ); + if ( $interwiki ) { + $namespace = $this->getNsText(); + if ( $namespace != '' ) { + # Can this actually happen? Interwikis shouldn't be parsed. + # Yes! It can in interwiki transclusion. But... it probably shouldn't. + $namespace .= ':'; } + $url = $interwiki->getURL( $namespace . $this->getDBkey() ); + $url = wfAppendQuery( $url, $query ); } else { $dbkey = wfUrlencode( $this->getPrefixedDBkey() ); if ( $query == '' ) { @@ -911,6 +906,7 @@ class Title { $url = str_replace( '$1', $dbkey, $url ); } else { $url = str_replace( '$1', $dbkey, $wgArticlePath ); + wfRunHooks( 'GetLocalURL::Article', array( &$this, &$url ) ); } } else { global $wgActionPaths; @@ -940,13 +936,15 @@ class Title { } } + wfRunHooks( 'GetLocalURL::Internal', array( &$this, &$url, $query, $variant ) ); + // @todo FIXME: This causes breakage in various places when we // actually expected a local URL and end up with dupe prefixes. if ( $wgRequest->getVal( 'action' ) == 'render' ) { $url = $wgServer . $url; } } - wfRunHooks( 'GetLocalURL', array( &$this, &$url, $query ) ); + wfRunHooks( 'GetLocalURL', array( &$this, &$url, $query, $variant ) ); return $url; } @@ -1001,24 +999,57 @@ class Title { public function escapeFullURL( $query = '' ) { return htmlspecialchars( $this->getFullURL( $query ) ); } + + /** + * HTML-escaped version of getCanonicalURL() + */ + public function escapeCanonicalURL( $query = '', $variant = false ) { + return htmlspecialchars( $this->getCanonicalURL( $query, $variant ) ); + } /** * Get the URL form for an internal link. * - Used in various Squid-related code, in case we have a different * internal hostname for the server from the exposed one. + * + * This uses $wgInternalServer to qualify the path, or $wgServer + * if $wgInternalServer is not set. If the server variable used is + * protocol-relative, the URL will be expanded to http:// * * @param $query String an optional query string * @param $variant String language variant of url (for sr, zh..) * @return String the URL */ public function getInternalURL( $query = '', $variant = false ) { - global $wgInternalServer, $wgServer; - $server = $wgInternalServer !== false ? $wgInternalServer : $wgServer; - $url = $server . $this->getLocalURL( $query, $variant ); + if ( $this->isExternal( ) ) { + $server = ''; + } else { + global $wgInternalServer, $wgServer; + $server = $wgInternalServer !== false ? $wgInternalServer : $wgServer; + } + $url = wfExpandUrl( $server . $this->getLocalURL( $query, $variant ), PROTO_HTTP ); wfRunHooks( 'GetInternalURL', array( &$this, &$url, $query ) ); return $url; } + /** + * Get the URL for a canonical link, for use in things like IRC and + * e-mail notifications. Uses $wgCanonicalServer and the + * GetCanonicalURL hook. + * + * NOTE: Unlike getInternalURL(), the canonical URL includes the fragment + * + * @param $query string An optional query string + * @param $variant string Language variant of URL (for sr, zh, ...) + * @return string The URL + */ + public function getCanonicalURL( $query = '', $variant = false ) { + global $wgCanonicalServer; + $url = wfExpandUrl( $this->getLocalURL( $query, $variant ) . $this->getFragmentForURL(), PROTO_CANONICAL ); + wfRunHooks( '', array( &$this, &$url, $query ) ); + return $url; + } + /** * Get the edit URL for this Title * @@ -1524,7 +1555,7 @@ class Title { $errors[] = array( 'immobile-source-namespace', $this->getNsText() ); } elseif ( !$this->isMovable() ) { // Less specific message for rarer cases - $errors[] = array( 'immobile-page' ); + $errors[] = array( 'immobile-source-page' ); } } elseif ( $action == 'move-target' ) { if ( !MWNamespace::isMovable( $this->mNamespace ) ) { @@ -1576,7 +1607,7 @@ class Title { if ( $reason == '' ) { $reason = wfMsg( 'blockednoreason' ); } - $ip = wfGetIP(); + $ip = $user->getRequest()->getIP(); if ( is_numeric( $id ) ) { $name = User::whoIs( $id ); @@ -1755,7 +1786,14 @@ class Title { * @return Bool TRUE or FALSE */ public function isMovable() { - return MWNamespace::isMovable( $this->getNamespace() ) && $this->getInterwiki() == ''; + if ( !MWNamespace::isMovable( $this->getNamespace() ) || $this->getInterwiki() != '' ) { + // Interwiki title or immovable namespace. Hooks don't get to override here + return false; + } + + $result = true; + wfRunHooks( 'TitleIsMovable', array( $this, &$result ) ); + return $result; } /** @@ -1944,7 +1982,7 @@ class Title { /** * Does that page contain wikitext, or it is JS, CSS or whatever? - * + * * @return Bool */ public function isWikitextPage() { @@ -2514,7 +2552,7 @@ class Title { */ public function resetArticleID( $newid ) { $linkCache = LinkCache::singleton(); - $linkCache->clearBadLink( $this->getPrefixedDBkey() ); + $linkCache->clearLink( $this ); if ( $newid === false ) { $this->mArticleID = -1; @@ -2823,6 +2861,10 @@ class Title { $this->mFragment = str_replace( '_', ' ', substr( $fragment, 1 ) ); } + public function setInterwiki( $interwiki ) { + $this->mInterwiki = $interwiki; + } + /** * Get a Title object associated with the talk page of this article * @@ -3127,6 +3169,8 @@ class Title { * @return Mixed true on success, getUserPermissionsErrors()-like array on failure */ public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true ) { + global $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase; + $err = $this->isValidMoveOperation( $nt, $auth, $reason ); if ( is_array( $err ) ) { return $err; @@ -3151,7 +3195,7 @@ class Title { $pageCountChange = ( $createRedirect ? 1 : 0 ) - ( $nt->exists() ? 1 : 0 ); // Do the actual move - $err = $this->moveToInternal( $nt, $reason, $createRedirect ); + $err = $this->moveOverExistingRedirect( $nt, $reason, $createRedirect ); if ( is_array( $err ) ) { # @todo FIXME: What about the File we have already moved? $dbw->rollback(); @@ -3183,6 +3227,15 @@ class Title { ); } + if ( $wgEnableInterwikiTemplatesTracking && $wgGlobalDatabase ) { + $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDatabase ); + $dbw2->update( 'globaltemplatelinks', + array( 'gtl_from_namespace' => $nt->getNamespace(), + 'gtl_from_title' => $nt->getText() ), + array ( 'gtl_from_page' => $pageid ), + __METHOD__ ); + } + if ( $protected ) { # Protect the redirect title as the title used to be... $dbw->insertSelect( 'page_restrictions', 'page_restrictions', @@ -3276,8 +3329,8 @@ class Title { * @param $createRedirect Bool Whether to leave a redirect at the old title. Ignored * if the user doesn't have the suppressredirect right */ - private function moveToInternal( &$nt, $reason = '', $createRedirect = true ) { - global $wgUser, $wgContLang; + private function moveOverExistingRedirect( &$nt, $reason = '', $createRedirect = true ) { + global $wgUser, $wgContLang, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase; $moveOverRedirect = $nt->exists(); @@ -3320,12 +3373,21 @@ class Title { $dbw->delete( 'externallinks', array( 'el_from' => $newid ), __METHOD__ ); $dbw->delete( 'langlinks', array( 'll_from' => $newid ), __METHOD__ ); $dbw->delete( 'redirect', array( 'rd_from' => $newid ), __METHOD__ ); + $dbw->delete( 'page_props', array( 'pp_page' => $newid ), __METHOD__ ); } // If the target page was recently created, it may have an entry in recentchanges still $dbw->delete( 'recentchanges', array( 'rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1 ), __METHOD__ ); + + if ( $wgEnableInterwikiTemplatesTracking && $wgGlobalDatabase ) { + $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDatabase ); + $dbw2->delete( 'globaltemplatelinks', + array( 'gtl_from_wiki' => wfGetID(), + 'gtl_from_page' => $newid ), + __METHOD__ ); + } } # Save a null revision in the page's history notifying of the move @@ -3798,6 +3860,18 @@ class Title { && $this->getDBkey() === $title->getDBkey(); } + /** + * Check if this title is a subpage of another title + * + * @param $title Title + * @return Bool + */ + public function isSubpageOf( Title $title ) { + return $this->getInterwiki() === $title->getInterwiki() + && $this->getNamespace() == $title->getNamespace() + && strpos( $this->getDBkey(), $title->getDBkey() . '/' ) === 0; + } + /** * Callback for usort() to do title sorts by (namespace, title) * @@ -4315,37 +4389,3 @@ class Title { return wfGetLangObj( $pageLang ); } } - -/** - * A BadTitle is generated in MediaWiki::parseTitle() if the title is invalid; the - * software uses this to display an error page. Internally it's basically a Title - * for an empty special page - */ -class BadTitle extends Title { - public function __construct(){ - $this->mTextform = ''; - $this->mUrlform = ''; - $this->mDbkeyform = ''; - $this->mNamespace = NS_SPECIAL; // Stops talk page link, etc, being shown - } - - public function exists(){ - return false; - } - - public function getPrefixedText(){ - return ''; - } - - public function getText(){ - return ''; - } - - public function getPrefixedURL(){ - return ''; - } - - public function getPrefixedDBKey(){ - return ''; - } -}