目次 Edit


関連 Edit

検索:MediaWiki

参考 Edit

Google:MediaWiki

MediaWiki Documentation
http://svn.wikimedia.org/doc/
The MediaWiki codebase
http://www.mediawiki.org/wiki/How_to_become_a_MediaWiki_hacker#The_MediaWiki_codebase

WikiEngine/MediaWiki/1.10 Edit

主処理への入り口 Edit

  • index.phpがエントリーポイント。
  • なぜかMediaWiki::initializeの中に主処理がある。
    index.php > MediaWiki::initialize > MediaWiki::performAction > (URLクエリーの'action'次第で分岐、それぞれの処理へ)
  • initialize直後にCleanup。

MediaWikiひとめぐり Edit

起動から終了までの主な処理を処理順に。

MediaWiki::performActionが処理の中心。
ここで何をするかはMediaWikiの外から与えられるクエリー次第。

  1. index.php
  2. includes/Wiki.php(41)
    MediaWiki::initialize
  3. includes/Wiki.php(365)
    MediaWiki::performAction
    クエリー'action'次第でいろいろ処理。またはOutputPage::redirectを呼び出すことでリダイレクトすることにする(実際の出力は後のOutputPage::outputで)。
  4. includes/Wiki.php(289)
    MediaWiki::finalCleanup
  5. includes/Wiki.php(305)
    MediaWiki::doUpdates
    $wgDeferredUpdateListに溜め込んだオブジェクト全て->doUpdates
    こうして処理タイミングを遅らせているのは、処理間の依存関係を解決するため?
  6. includes/OutputPage.php(553)
    OutputPage::output
    スキン適用、HTTPヘッダー・HTMLヘッダー生成、レスポンス出力

action Edit

'action'はほとんどMediaWiki(includes/Wiki.php)とArticle(includes/Article.php)で処理される。
それ以外には3つ程度のクラスしか関与しない。
処理の中心になっているのはこれらの数少ないクラスらしい。

'view'というactionは複数のクラスを通して処理される。
'view'はactionのデフォルト値。

MediaWikiが処理する'action' Edit

  • dublincore
  • creativecommons
  • credits

Articleが処理する'action' Edit

  • view *
  • watch
  • unwatch
  • delete
  • revert
  • rollback
  • protect
  • unprotect
  • info
  • markpatrolled
  • render
  • deletetrackback
  • purge
  • print

その他 Edit

  • submit *(editを含む)
  • edit *
  • history *
  • raw ?

action 'view' Edit

Articleが処理する。

includes/Article.php:
actionのデフォルト。
クエリーで指示されたページを表示する。

	$sk = $wgUser->getSkin();
	
	wfProfileIn( __METHOD__ );
	
	$parserCache =& ParserCache::singleton();
	$ns = $this->mTitle->getNamespace(); # shortcut
	
	# Get variables from query string
	$oldid = $this->getOldID();
	
	# getOldID may want us to redirect somewhere else
	if ( $this->mRedirectUrl ) {
		$wgOut->redirect( $this->mRedirectUrl );
		wfProfileOut( __METHOD__ );
		return;
	}
	
	$diff = $wgRequest->getVal( 'diff' );
	$rcid = $wgRequest->getVal( 'rcid' );
	$rdfrom = $wgRequest->getVal( 'rdfrom' );
	$diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
	
	$wgOut->setArticleFlag( true );
	
	# Discourage indexing of printable versions, but encourage following
	if( $wgOut->isPrintable() ) {
		$policy = 'noindex,follow';
	} elseif( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
		# Honour customised robot policies for this namespace
		$policy = $wgNamespaceRobotPolicies[$ns];
	} else {
		# Default to encourage indexing and following links
		$policy = 'index,follow';
	}
	$wgOut->setRobotPolicy( $policy );
	
	# If we got diff and oldid in the query, we want to see a
	# diff page instead of the article.
	
	if ( !is_null( $diff ) ) {
		$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
	
		$de = new DifferenceEngine( $this->mTitle, $oldid, $diff, $rcid );
		// DifferenceEngine directly fetched the revision:
		$this->mRevIdFetched = $de->mNewid;
		$de->showDiffPage( $diffOnly );
	
		// Needed to get the page's current revision
		$this->loadPageData();
		if( $diff == 0 || $diff == $this->mLatest ) {
			# Run view updates for current revision only
			$this->viewUpdates();
		}
		wfProfileOut( __METHOD__ );
		return;
	}
	
	if ( empty( $oldid ) && $this->checkTouched() ) {
		$wgOut->setETag($parserCache->getETag($this, $wgUser));
	
		if( $wgOut->checkLastModified( $this->mTouched ) ){
			wfProfileOut( __METHOD__ );
			return;
		} else if ( $this->tryFileCache() ) {
			# tell wgOut that output is taken care of
			$wgOut->disable();
			$this->viewUpdates();
			wfProfileOut( __METHOD__ );
			return;
		}
	}
	
	# Should the parser cache be used?
	$pcache = $wgEnableParserCache &&
		intval( $wgUser->getOption( 'stubthreshold' ) ) == 0 &&
		$this->exists() &&
		empty( $oldid );
	wfDebug( 'Article::view using parser cache: ' . ($pcache ? 'yes' : 'no' ) . "\n" );
	if ( $wgUser->getOption( 'stubthreshold' ) ) {
		wfIncrStats( 'pcache_miss_stub' );
	}
	
	$wasRedirected = false;
	if ( isset( $this->mRedirectedFrom ) ) {
		// This is an internally redirected page view.
		// We'll need a backlink to the source page for navigation.
		if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
			$sk = $wgUser->getSkin();
			$redir = $sk->makeKnownLinkObj( $this->mRedirectedFrom, '', 'redirect=no' );
			$s = wfMsg( 'redirectedfrom', $redir );
			$wgOut->setSubtitle( $s );
	
			// Set the fragment if one was specified in the redirect
			if ( strval( $this->mTitle->getFragment() ) != '' ) {
				$fragment = Xml::escapeJsString( $this->mTitle->getFragmentForURL() );
				$wgOut->addInlineScript( "redirectToFragment(\"$fragment\");" );
			}
			$wasRedirected = true;
		}
	} elseif ( !empty( $rdfrom ) ) {
		// This is an externally redirected view, from some other wiki.
		// If it was reported from a trusted site, supply a backlink.
		global $wgRedirectSources;
		if( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
			$sk = $wgUser->getSkin();
			$redir = $sk->makeExternalLink( $rdfrom, $rdfrom );
			$s = wfMsg( 'redirectedfrom', $redir );
			$wgOut->setSubtitle( $s );
			$wasRedirected = true;
		}
	}
	
	$outputDone = false;
	wfRunHooks( 'ArticleViewHeader', array( &$this ) );
	if ( $pcache ) {
		if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
			$outputDone = true;
		}
	}
	if ( !$outputDone ) {
		$text = $this->getContent();
		if ( $text === false ) {
			# Failed to load, replace text with error message
			$t = $this->mTitle->getPrefixedText();
			if( $oldid ) {
				$t .= ',oldid='.$oldid;
				$text = wfMsg( 'missingarticle', $t );
			} else {
				$text = wfMsg( 'noarticletext', $t );
			}
		}
	
		# Another whitelist check in case oldid is altering the title
		if ( !$this->mTitle->userCanRead() ) {
			$wgOut->loginToUse();
			$wgOut->output();
			exit;
		}
	
		# We're looking at an old revision
	
		if ( !empty( $oldid ) ) {
			$wgOut->setRobotpolicy( 'noindex,nofollow' );
			if( is_null( $this->mRevision ) ) {
				// FIXME: This would be a nice place to load the 'no such page' text.
			} else {
				$this->setOldSubtitle( isset($this->mOldId) ? $this->mOldId : $oldid );
				if( $this->mRevision->isDeleted( Revision::DELETED_TEXT ) ) {
					if( !$this->mRevision->userCan( Revision::DELETED_TEXT ) ) {
						$wgOut->addWikiText( wfMsg( 'rev-deleted-text-permission' ) );
						$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
						return;
					} else {
						$wgOut->addWikiText( wfMsg( 'rev-deleted-text-view' ) );
						// and we are allowed to see...
					}
				}
			}
	
		}
	}
	if( !$outputDone ) {
		$wgOut->setRevisionId( $this->getRevIdFetched() );
		# wrap user css and user js in pre and don't parse
		# XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is found
		if (
			$ns == NS_USER &&
			preg_match('/
/[
w]+
.(?:css|js)$/', $this->mTitle->getDBkey()) ) { $wgOut->addWikiText( wfMsg('clearyourcache')); $wgOut->addHTML( '<pre>'.htmlspecialchars($this->mContent)."\n</pre>" ); } else if ( $rt = Title::newFromRedirect( $text ) ) { # Display redirect $imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr'; $imageUrl = $wgStylePath.'/common/images/redirect' . $imageDir . '.png'; # Don't overwrite the subtitle if this was an old revision if( !$wasRedirected && $this->isCurrent() ) { $wgOut->setSubtitle( wfMsgHtml( 'redirectpagesub' ) ); } $link = $sk->makeLinkObj( $rt, $rt->getFullText() ); $wgOut->addHTML( '<img src="'.$imageUrl.'" alt="#REDIRECT " />' . '<span class="redirectText">'.$link.'</span>' ); $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser)); $wgOut->addParserOutputNoText( $parseout ); } else if ( $pcache ) { # Display content and save to parser cache $this->outputWikiText( $text ); } else { # Display content, don't attempt to save to parser cache # Don't show section-edit links on old revisions... this way lies madness. if( !$this->isCurrent() ) { $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false ); } # Display content and don't save to parser cache # With timing hack -- TS 2006-07-26 $time = -wfTime(); $this->outputWikiText( $text, false ); $time += wfTime(); # Timing hack if ( $time > 3 ) { wfDebugLog( 'slow-parse', sprintf( "%-5.2f %s", $time, $this->mTitle->getPrefixedDBkey())); } if( !$this->isCurrent() ) { $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting ); } } } /* title may have been set from the cache */ $t = $wgOut->getPageTitle(); if( empty( $t ) ) { $wgOut->setPageTitle( $this->mTitle->getPrefixedText() ); } # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page if( $ns == NS_USER_TALK && User::isIP( $this->mTitle->getText() ) ) { $wgOut->addWikiText( wfMsg('anontalkpagetext') ); } # If we have been passed an &rcid= parameter, we want to give the user a # chance to mark this new article as patrolled. if ( $wgUseRCPatrol && !is_null( $rcid ) && $rcid != 0 && $wgUser->isAllowed( 'patrol' ) ) { $wgOut->addHTML( "<div class='patrollink'>" . wfMsgHtml( 'markaspatrolledlink', $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml('markaspatrolledtext'), "action=markpatrolled&rcid=$rcid" ) ) . '</div>' ); } # Trackbacks if ($wgUseTrackbacks) $this->addTrackbacks(); $this->viewUpdates(); wfProfileOut( __METHOD__ );