Tools 是非官方社区Wiki。社区文档正在编写中,欢迎参与。 Wiki编辑答疑群:717421103
版本250722.2
全站通知:

帮助:解析函数/localurl

来自WIKI实验室WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

localurl是一个解析函数。帮助:解析函数页列出了所有解析函数的说明。

localurl

获取相对URL。MediaWiki原生支持。

指定页面获取其相对URL(不带域名),支持附加查询参数,自动进行URL编码。

语法

{{localurl: 页面 | 参数 }}

  • 页面:要生成URL的目标页面标题
  • 参数(可选):以key=value格式附加的查询字符串参数,多个参数用&分隔

生成的URL始终采用与当前wiki配置匹配的短URL格式(如/wiki/页面名)或index.php路径。

示例

  • 基础用法 {{localurl: 帮助:解析函数 }}/tools/%E5%B8%AE%E5%8A%A9:%E8%A7%A3%E6%9E%90%E5%87%BD%E6%95%B0
  • 基础用法 {{localurl: Test }}/tools/Test
  • 单个参数 {{localurl: Test | printable=yes }}/tools/index.php?title=Test&printable=yes
  • 多个参数 {{localurl: Test | action=raw&feed=atom }}/tools/index.php?title=Test&action=raw&feed=atom

底层代码

来自MediaWiki及其扩展的源代码,运行在服务端。此处仅供快速查阅,便于更充分的挖掘其“特性”。

// mediawiki-1.37.0\includes\parser\CoreParserFunctions.php
public static function localurl( $parser, $s = '', $arg = null ) {
	return self::urlFunction( 'getLocalURL', $s, $arg );
}

// mediawiki-1.37.0\includes\parser\CoreParserFunctions.php
public static function urlFunction( $func, $s = '', $arg = null ) {
	$title = Title::newFromText( $s );
	# Due to order of execution of a lot of bits, the values might be encoded
	# before arriving here; if that's true, then the title can't be created
	# and the variable will fail. If we can't get a decent title from the first
	# attempt, url-decode and try for a second.
	if ( $title === null ) {
		$title = Title::newFromURL( urldecode( $s ) );
	}
	if ( $title !== null ) {
		# Convert NS_MEDIA -> NS_FILE
		if ( $title->inNamespace( NS_MEDIA ) ) {
			$title = Title::makeTitle( NS_FILE, $title->getDBkey() );
		}
		if ( $arg !== null ) {
			$text = $title->$func( $arg );
		} else {
			$text = $title->$func();
		}
		return $text;
	} else {
		return [ 'found' => false ];
	}
}


/** mediawiki-1.37.0\includes\Title.php
 * Get a URL with no fragment or server name (relative URL) from a Title object.
 * If this page is generated with action=render, however,
 * $wgServer is prepended to make an absolute URL.
 *
 * @see self::getFullURL to always get an absolute URL.
 * @see self::getLinkURL to always get a URL that's the simplest URL that will be
 *  valid to link, locally, to the current Title.
 * @see self::newFromText to produce a Title object.
 *
 * @param string|array $query An optional query string,
 *   not used for interwiki links. Can be specified as an associative array as well,
 *   e.g., [ 'action' => 'edit' ] (keys and values will be URL-escaped).
 *   Some query patterns will trigger various shorturl path replacements.
 * @param string|string[]|bool $query2 An optional secondary query array. This one MUST
 *   be an array. If a string is passed it will be interpreted as a deprecated
 *   variant argument and urlencoded into a variant= argument.
 *   This second query argument will be added to the $query
 *   The second parameter is deprecated since 1.19. Pass it as a key,value
 *   pair in the first parameter array instead.
 *
 * @return string
 */
public function getLocalURL( $query = '', $query2 = false ) {
	global $wgArticlePath, $wgScript, $wgServer, $wgRequest, $wgMainPageIsDomainRoot;

	$query = self::fixUrlQueryArgs( $query, $query2 );

	$interwiki = self::getInterwikiLookup()->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->mDbkeyform );
		$url = wfAppendQuery( $url, $query );
	} else {
		$dbkey = wfUrlencode( $this->getPrefixedDBkey() );
		if ( $query == '' ) {
			if ( $wgMainPageIsDomainRoot && $this->isMainPage() ) {
				$url = '/';
			} else {
				$url = str_replace( '$1', $dbkey, $wgArticlePath );
			}
			Hooks::runner()->onGetLocalURL__Article( $this, $url );
		} else {
			global $wgVariantArticlePath, $wgActionPaths;
			$url = false;
			$matches = [];

			$articlePaths = PathRouter::getActionPaths( $wgActionPaths, $wgArticlePath );

			if ( $articlePaths
				&& preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches )
			) {
				$action = urldecode( $matches[2] );
				if ( isset( $articlePaths[$action] ) ) {
					$query = $matches[1];
					if ( isset( $matches[4] ) ) {
						$query .= $matches[4];
					}
					$url = str_replace( '$1', $dbkey, $articlePaths[$action] );
					if ( $query != '' ) {
						$url = wfAppendQuery( $url, $query );
					}
				}
			}

			if ( $url === false
				&& $wgVariantArticlePath
				&& preg_match( '/^variant=([^&]*)$/', $query, $matches )
				&& $this->getPageLanguage()->equals(
					MediaWikiServices::getInstance()->getContentLanguage() )
				&& $this->getPageLanguageConverter()->hasVariants()
			) {
				$variant = urldecode( $matches[1] );
				if ( $this->getPageLanguageConverter()->hasVariant( $variant ) ) {
					// Only do the variant replacement if the given variant is a valid
					// variant for the page's language.
					$url = str_replace( '$2', urlencode( $variant ), $wgVariantArticlePath );
					$url = str_replace( '$1', $dbkey, $url );
				}
			}

			if ( $url === false ) {
				if ( $query == '-' ) {
					$query = '';
				}
				$url = "{$wgScript}?title={$dbkey}&{$query}";
			}
		}
		Hooks::runner()->onGetLocalURL__Internal( $this, $url, $query );

		// @todo FIXME: This causes breakage in various places when we
		// actually expected a local URL and end up with dupe prefixes.
		if ( $wgRequest->getRawVal( 'action' ) == 'render' ) {
			LoggerFactory::getInstance( 'T263581' )
				->debug(
					"Title::getLocalURL called from render action",
					[
						'title' => $this->getPrefixedDBkey(),
						'exception' => new Exception()
					]
				);
			$url = $wgServer . $url;
		}
	}

	Hooks::runner()->onGetLocalURL( $this, $url, $query );
	return $url;
}
代码逻辑:
  • 调用MediaWiki核心的getLocalURL方法生成基础URL
  • 带参数时,URL:"{$wgScript}?title={$dbkey}&{$query}",其中wgScript为/tools,dbkey是页面名(tools是本wiki的路径,可在特殊:版本查看)
  • 无参数时,URL:str_replace( '$1', $dbkey, $wgArticlePath),其中wgArticlePath为/tools/$1

实际用例

一些Wiki使用了相关特性,如下所示这个静态列表可能在下列页面更改后过时仅供批判性参考