• 欢迎来到THBWiki!如果您是第一次来到这里,请点击右上角注册一个帐户
  • 有任何意见、建议、求助、反馈都可以在 讨论板 提出
  • THBWiki以专业性和准确性为目标,如果你发现了任何确定的错误或疏漏,可在登录后直接进行改正

帮助:扩展修改记录

来自THBWiki
跳到导航 跳到搜索

本页面用于记录一些对已有扩展的修改记录,Mediawiki本体的修改记录可以参看帮助:核心修改记录,其他扩展相关的信息可以参看帮助:编写扩展

CirrusSearch

\includes\Job\ElasticaWrite.php

ElasticaWrite::__construct

public function ElasticaWrite::__construct内修复php版本兼容性问题。

public function __construct( $title, $params ) {
	parent::__construct( $title, array_merge( [
		'createdAt' => time(),
		'errorCount' => 0,
		'retryCount' => 0,
		'cluster' => null,
	], $params ) );
}

\includes\Job\Job.php

Job::__construct

public function Job::__construct内修复php版本兼容性问题。

public function __construct( $title, $params ) {
	$params = array_merge( [ 'cluster' => null ], $params );
	// eg: DeletePages -> cirrusSearchDeletePages
	$jobName = 'cirrusSearch' . str_replace( 'CirrusSearch\\Job\\', '', static::class );
	parent::__construct( $jobName, $title, $params );

	// All CirrusSearch jobs are reasonably expensive.  Most involve parsing and it
	// is ok to remove duplicate _unclaimed_ cirrus jobs.  Once a cirrus job is claimed
	// it can't be deduplicated or else the search index will end up with out of date
	// data.  Luckily, this is how the JobQueue implementations work.
	$this->removeDuplicates = true;

	$this->searchConfig = MediaWikiServices::getInstance()
		->getConfigFactory()
		->makeConfig( 'CirrusSearch' );
	// When the 'cluster' parameter is provided the job must only operate on
	// the specified cluster, take special care to ensure nested jobs get the
	// correct cluster set.  When set to null all clusters should be written to.
	$this->connection = Connection::getPool( $this->searchConfig, $params['cluster'] );
}

\includes\Maintenance\AnalysisConfigBuilder.php

AnalysisConfigBuilder::$elasticsearchLanguageAnalyzersFromPlugins

private AnalysisConfigBuilder::$elasticsearchLanguageAnalyzersFromPlugins内更改zh使用的分词器。

private $elasticsearchLanguageAnalyzersFromPlugins = [
	'analysis-stempel' => [ 'pl' => 'polish' ],
	'analysis-kuromoji' => [ 'ja' => 'kuromoji' ],
	'analysis-ik' => [ 'zh-hans' => 'ik' ],
	// This hasn't had a release in a while and seems to not work with the
	// current version of elasticsearch:
	'elasticsearch-analysis-hebrew' => [ 'he' => 'hebrew' ],
	// TODO Hebrew requires some special query handling....
];

Echo

\Hooks.php

EchoHooks::onLinksUpdateAfterInsert

public static function EchoHooks::onLinksUpdateAfterInsert,禁用bug函数。

public static function onLinksUpdateAfterInsert( $linksUpdate, $table, $insertions ) {
	return true;
}

FlowThread

\assets\common.js

getAvatar

function getAvatar内增加使用用户ID获取头像的功能。

function getAvatar(id, username) {
  if (id === 0) {
    return config.AnonymousAvatar;
  } else {
    return config.Avatar.replace(/\$\{username\}/g, username).replace(/\$\{userid\}/g, id);
  }
}

\assets\flowthread.css

修改CSS样式

\assets\flowthread.js

getExtraThreadContent

增加函数function getExtraThreadContent,提供更改用户评论段落标题的功能。

function getExtraThreadContent ( name ) {
  var msg = mw.message( 'flowthread-ui-' + name );
  if ( !msg.exists() || msg.plain() === '' ) return '';
  var text = msg.escaped();
  return text.replace( /^(={1,6})(.+)\1\s*$/m, function (a,b,c) {
      return '<h'+b.length+'>'+c+'</h'+b.length+'>'
  } );
}
$('#bodyContent').after(getExtraThreadContent('header'), '<div class="comment-container-top" disabled></div>', '<div class="comment-container"></div>', pager.object, function() {
  if (canpost) return createReplyBox('');
  var noticeContainer = $('<div>').addClass('comment-bannotice');
  noticeContainer.html(config.CantPostNotice);
  return noticeContainer;
}(),getExtraThreadContent('footer'));

\extension.json

extension.json

让客户端自动加载用户评论段落标题字串。

"ResourceModules": {
	"ext.flowthread": {
		"dependencies": [
			"mediawiki.language",
			"moment",
			"mediawiki.user"
		],
		"scripts":[
			"assets/common.js",
			"assets/flowthread.js"
		],
		"styles":[
			"assets/common.css",
			"assets/flowthread.css"
		],
		"messages": [
			"flowthread-ui-header",
			"flowthread-ui-footer",
			"flowthread-ui-reply",
			"flowthread-ui-like",
			"flowthread-ui-report",
			"flowthread-ui-delete",
			"flowthread-ui-usewikitext",
			"flowthread-ui-preview",
			"flowthread-ui-placeholder",
			"flowthread-ui-submit",
			"flowthread-ui-nocontent",
			"flowthread-ui-popular",
			"flowthread-ui-networkerror"
		]
	},
	"ext.flowthread.mobile": {
		"dependencies": [
			"mediawiki.language",
			"moment",
			"mediawiki.user"
		],
		"scripts":[
			"assets/common.js",
			"assets/flowthread.js"
		],
		"styles":[
			"assets/common.css",
			"assets/mobile.css",
			"assets/flowthread.css"
		],
		"messages": [
			"flowthread-ui-reply",
			"flowthread-ui-like",
			"flowthread-ui-report",
			"flowthread-ui-delete",
			"flowthread-ui-usewikitext",
			"flowthread-ui-preview",
			"flowthread-ui-placeholder",
			"flowthread-ui-submit",
			"flowthread-ui-nocontent",
			"flowthread-ui-popular",
			"flowthread-ui-networkerror"
		],
		"targets": "mobile"
	},
	"ext.flowthread.manage": {
		"dependencies": [
			"mediawiki.language",
			"moment",
			"mediawiki.user"
		],
		"scripts": [
			"assets/common.js",
			"assets/manage.js"
		],
		"styles": [
			"assets/common.css",
			"assets/manage.css"
		],
		"messages": [
			"flowthread-ui-like",
			"flowthread-ui-report",
			"flowthread-ui-delete",
			"flowthread-ui-recover",
			"flowthread-ui-markchecked",
			"flowthread-ui-erase",
			"flowthread-ui-selectall",
			"flowthread-ui-unselectall",
			"flowthread-ui-user-post-on-page"
		]
	}
},

GraphViz

\GraphViz_body.php

GraphViz::initDummyFilePages

public static function GraphViz::initDummyFilePages内修复重复删除及上传范例图片的bug。

public static function initDummyFilePages() {
	global $wgParser;

	if ( $wgParser instanceof StubObject ) {
		$wgParser->_unstub();
	}

	foreach ( GraphRenderParms::$supportedDotImageTypes as $imageType ) {
		if ( !self::imageTypeAllowed( $imageType ) ) {
			wfDebug( __METHOD__ . ": skipping $imageType\n" );
			continue;
		}

		$imageFileName = self::IMAGE_DUMMY . '.' . $imageType;
		$imageTitle = Title::newFromText( $imageFileName, NS_FILE );

		if ( !$imageTitle->exists() ) {
			wfDebug( __METHOD__ . ": file page for $imageFileName does not exist\n" );
			self::createDummyImageFilePage( $wgParser, $imageType );
		}
		// Frequent upload and delete dummy file bug
		/* else if ( self::titleHasMultipleRevisions( $imageTitle ) ) {
			wfDebug( __METHOD__ . ": file page for $imageFileName has multiple revisions\n" );
			self::deleteFilePage( $imageTitle );

			self::createDummyImageFilePage( $wgParser, $imageType );
		} */
	}
}

HSTS

\HSTS.hooks.php

HSTSExtension::getPreferences

public static function HSTSExtension::getPreferences内更改https设定出现的逻辑。

public static function getPreferences( $user, &$preferences ) {
	global $wgHSTSBetaFeature, $wgHSTSForUsers;

	// If HSTS is activated as a Beta Feature, do not add it here
	if( $wgHSTSBetaFeature && class_exists( 'BetaFeatures' ) ) {
		return true;
	}

	// If HSTS is mandatory, do not display the choice
	//if( $wgHSTSForUsers ) {
	//	return true;
	//}

	// Add the checkbox in the 'basic informations' section
	$preferences['hsts'] = array(
		'type' => 'toggle',
		'label-message' => 'hsts-tog',
		'section' => 'personal/info'
	);

	// Enable this preference only if we are on HTTPS
	//if( $user->getRequest()->detectProtocol() !== 'https' ) {
	//	$preferences['hsts']['label-message'] = 'hsts-https-tog';
	//	$preferences['hsts']['disabled'] = true;
	//}

	return true;
}

HSTSExtension::addHeader

public static function HSTSExtension::addHeader内更改https头部的发送方式。

public static function addHeader( $output ) {
	global $wgHSTSForAnons, $wgHSTSForUsers, $wgHSTSIncludeSubdomains, $wgHSTSMaxAge;

	// Check if the user will get STS header
	if(
		( $output->getUser()->isAnon() && !$wgHSTSForAnons )
		|| ( $output->getUser()->isLoggedIn() && (!$wgHSTSForUsers || !$output->getUser()->getOption( 'hsts' )) )
	) {
		$header = 'Strict-Transport-Security: max-age=0'.
			( $wgHSTSIncludeSubdomains ? '; includeSubDomains' : '' );
		// Output the header
		$output->getRequest()->response()->header( $header );
		wfDebug( '[HSTS] ' . $header );
		return true;
	}

	// Compute the max-age property
	if( is_int( $wgHSTSMaxAge ) ) {
		$maxage = max( $wgHSTSMaxAge, 0 );
	} else {
		$maxage = wfTimestamp( TS_UNIX, $wgHSTSMaxAge );
		if( $maxage !== false ) {
			$maxage -= wfTimestamp();
		} else {
			wfDebug( '[HSTS] Bad value of the parameter $wgHSTSMaxAge: must be an integer or a date.' );
			return true;
		}
		if( $maxage < 0 ) {
			wfDebug( '[HSTS] Expired date; HSTS has been lost for all users, apart if externally added in the server configuration.' );
			return true;
		}
	}

	$header = 'Strict-Transport-Security: max-age=' . $maxage .
		( $wgHSTSIncludeSubdomains ? '; includeSubDomains' : '' );
	// Output the header
	$output->getRequest()->response()->header( $header );
	wfDebug( '[HSTS] ' . $header );

	return true;
}

LanguageSelector

\LanguageSelector.php

wfLanguageSelectorGetLanguageCode

function wfLanguageSelectorGetLanguageCode内修复语言逻辑bug。

function wfLanguageSelectorGetLanguageCode( $user, &$code ) {
	global $wgLanguageSelectorDetectLanguage,
		$wgCommandLineMode, $wgRequest, $wgContLang;

	if ( $wgCommandLineMode ) {
		return true;
	}

	$setlang = $wgRequest->getVal( 'setlang' );
	if ( $setlang && !in_array( $setlang, wfGetLanguageSelectorLanguages() ) ) {
		$setlang = null; // ignore invalid
	}

	if ( $setlang ) {
		$wgRequest->response()->setcookie( 'LanguageSelectorLanguage', $setlang );
		$requestedLanguage = $setlang;
	} else {
		$requestedLanguage = $wgRequest->getCookie( 'LanguageSelectorLanguage' );
	}

	if ( $setlang && !$user->isAnon() ) {
		if ( $setlang != $user->getOption( 'language' ) ) {
			$user->setOption( 'language', $requestedLanguage );
			$user->saveSettings();
			$code = $requestedLanguage;
		}
	}

	if ( !$wgRequest->getVal( 'uselang' ) && $user->isAnon() ) {
		if ( $wgLanguageSelectorDetectLanguage != LANGUAGE_SELECTOR_USE_CONTENT_LANG ) {
			if ( $requestedLanguage ) {
				$code = $requestedLanguage;
			} else {
				$languages = $wgRequest->getAcceptLang();

				// see if the content language is accepted by the client.
				if ( $wgLanguageSelectorDetectLanguage != LANGUAGE_SELECTOR_PREFER_CONTENT_LANG
					|| !array_key_exists( $wgContLang->getCode(), $languages ) )
				{

					$supported = wfGetLanguageSelectorLanguages();
					// look for a language that is acceptable to the client
					// and known to the wiki.
					foreach ( $languages as $reqCode => $q ) {
						if ( in_array( $reqCode, $supported ) ) {
							$code = $reqCode;
							break;
						}
					}

					// Apparently Safari sends stupid things like "de-de" only.
					// Try again with stripped codes.
					foreach ( $languages as $reqCode => $q ) {
						$stupidPHP = explode( '-', $reqCode, 2 );
						$bareCode = array_shift( $stupidPHP );
						if ( in_array( $bareCode, $supported ) ) {
							$code = $bareCode;
							break;
						}
					}
				}
			}
		} else {
			if ( $requestedLanguage ) {
				$code = $requestedLanguage;
			}
		}
	}

	return true;
}

LiquidThreads

设定管理员以外的用户只能编辑或删除自己发布的帖子。

Maintenance

禁用部分功能,增加generateSitemap脚本。

MultimediaViewer

修复一些Javascript兼容性错误,在新版本应该不需要了。

OAuth

改变样式,显示用户头像。

SemanticMediaWiki

\includes\datavalues\SMW_DV_Number.php

SMWNumberValue

class SMWNumberValue内增加一个函数,使用该DataValue的显示设定格式化任意数字,主要用于格式化format=sum之类的、数字处理后的结果。

public function getFormattedValue( $number, $unit = '' ) {
	$this->convertToMainUnit( $number, $unit );
	$this->makeUserValue();
	return $this->getShortText( SMW_OUTPUT_WIKI, null );
}

\includes\datavalues\SMW_DV_WikiPage.php

SMWWikiPageValue::parseUserValue

protected function SMWWikiPageValue::parseUserValue内增加高级页面重定向功能。

protected function parseUserValue( $value ) {
	global $wgContLang;

	// support inputs like " [[Test]] ";
	// note that this only works in pages if $smwgLinksInValues is set to true
	$value = ltrim( rtrim( $value, ' ]' ), ' [' );

	// #1066, Manipulate the output only for when the value has no caption
	// assigned and only if a single :Foo is being present, ::Foo is not permitted
	if ( $this->m_caption === false && isset( $value[2] ) && $value[0] === ':' && $value[1] !== ':' ) {
		$value = substr( $value, 1 );
	}

	if ( $this->m_caption === false ) {
		$this->m_caption = $value;
	}

	if ( $value === '' ) {
		return $this->addErrorMsg( array( 'smw-datavalue-wikipage-empty' ), Message::ESCAPED );
	}

	// #1701 If the DV is part of a Description and an approximate search
	// (e.g. ~foo* / ~Foo*) then use the value as-is and avoid being
	// transformed by the Title object
	// If the vaue contains a valid NS then use the Title to create a correct
	// instance to distinguish [[~Foo*]] from [[Help:~Foo*]]
	if ( $this->getOption( self::OPT_QUERY_COMP_CONTEXT ) ) {
		if ( ( $title = Title::newFromText( $value ) ) !== null && $title->getNamespace() !== NS_MAIN ) {
			return $this->m_dataitem = SMWDIWikiPage::newFromTitle( $title );
		} else {
			return $this->m_dataitem = new SMWDIWikiPage( $value, NS_MAIN );
		}
	}

	if ( $value[0] == '#' ) {
		if ( is_null( $this->m_contextPage ) ) {
			$this->addErrorMsg( array( 'smw-datavalue-wikipage-missing-fragment-context', $value ) );
			return;
		} else {
			$this->m_title = Title::makeTitle( $this->m_contextPage->getNamespace(),
				$this->m_contextPage->getDBkey(), substr( $value, 1 ),
				$this->m_contextPage->getInterwiki() );
		}
	} else {
		$this->m_title = Title::newFromText( $value, $this->m_fixNamespace );
		if ( class_exists( 'ApiPageExists' ) ) ApiPageExists::RawRedirect( $this->m_title );
	}

	/// TODO: Escape the text so users can see punctuation problems (bug 11666).
	if ( is_null( $this->m_title ) ) {
		$this->addErrorMsg( array( 'smw-datavalue-wikipage-invalid-title', $value ) );
	} elseif ( ( $this->m_fixNamespace != NS_MAIN ) &&
		 ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) {
		$this->addErrorMsg( array( 'smw_wrong_namespace', $wgContLang->getNsText( $this->m_fixNamespace ) ) );
	} else {
		$this->m_fragment = str_replace( ' ', '_', $this->m_title->getFragment() );
		$this->m_prefixedtext = '';
		$this->m_id = -1; // unset id
		$this->m_dataitem = SMWDIWikiPage::newFromTitle( $this->m_title, $this->m_typeid );
	}
}

SMWWikiPageValue::getShortWikiText

public function SMWWikiPageValue::getShortWikiText内增加输出页面ID的功能。

public function getShortWikiText( $linked = null ) {

	if ( is_null( $linked ) || $linked === false ||
		$this->m_outformat == '-' || !$this->isValid() ||
		$this->m_caption === '' ) {
		return $this->m_caption !== false ? $this->m_caption : $this->getWikiValue();
	} elseif ( $this->m_outformat == 'id' ) {
		return $this->m_caption !== false ? $this->m_caption : $this->getTitle()->getArticleID();
	}

	if ( $this->m_dataitem->getNamespace() == NS_FILE && $this->m_dataitem->getInterwiki() === '' ) {
		$linkEscape = '';
		$options = $this->m_outformat === false ? 'frameless|border|text-top|' : str_replace( ';', '|', \Sanitizer::removeHTMLtags( $this->m_outformat ) );
		$defaultCaption = '|' . $this->getShortCaptionText() . '|' . $options;
	} else {
		$linkEscape = ':';
		$defaultCaption = '|' . $this->getShortCaptionText();
	}

	if ( $this->m_caption === false ) {
		$link = '[[' . $linkEscape . $this->getWikiLinkTarget() . $defaultCaption . ']]';
	} else {
		$link = '[[' . $linkEscape . $this->getWikiLinkTarget() . '|' . $this->m_caption . ']]';
	}

	if ( $this->m_fragment !== '' ) {
		$this->linkAttributes['class'] = 'smw-subobject-entity';
	}

	if ( $this->linkAttributes !== array() ) {
		$link = \Html::rawElement(
			'span',
			$this->linkAttributes,
			$link
		);
	}

	return $link;
}

\includes\query\SMW_QueryParser.php

SMWQueryParser::getLinkDescription

protected function SMWQueryParser::getLinkDescription内修复当属性内含有以:或=开头的词条时(例如[[词条属性::=测试]])无法正确处理的bug。

private function getLinkDescription( &$setNS ) {
	// This method is called when we encountered an opening '[['. The following
	// block could be a Category-statement, fixed object, or property statement.
	$chunk = $this->readChunk( '', true, false ); // NOTE: untrimmed, initial " " escapes prop. chains

	if ( in_array( smwfNormalTitleText( $chunk ),
		array( $this->categoryPrefix, $this->conceptPrefix, $this->categoryPrefixCannonical, $this->conceptPrefixCannonical ) ) ) {
		return $this->getClassDescription( $setNS, (
			smwfNormalTitleText( $chunk ) == $this->categoryPrefix || smwfNormalTitleText( $chunk ) == $this->categoryPrefixCannonical
		) );
	} else { // fixed subject, namespace restriction, property query, or subquery
		$sep = $this->readChunk( '', false ); // do not consume hit, "look ahead"

		if ( ( $sep == '::' ) || ( $sep == ':=' ) ) {
			if ( $chunk{0} != ':' ) { // property statement
				return $this->getPropertyDescription( $chunk, $setNS );
			} else { // escaped article description, read part after :: to get full contents
				$chunk .= $this->readChunk( '\[\[|\]\]|\|\||\|' );
				return $this->getArticleDescription( trim( $chunk ), $setNS );
			}
		} elseif ( ( $chunk == '::' ) || ( $chunk == ':=' ) ) {
			$chunk .= $this->readChunk( '\[\[|\]\]|\|\||\|' );
			return $this->getArticleDescription( trim( $chunk ), $setNS );
		} else { // Fixed article/namespace restriction. $sep should be ]] or ||
			return $this->getArticleDescription( trim( $chunk ), $setNS );
		}
	}
}

\includes\query\SMW_QueryProcessor.php

SMWQueryProcessor::getComponentsFromFunctionParams

static public function SMWQueryProcessor::getComponentsFromFunctionParams内修复当以show单独获取内含有以特殊字符开头的词条的属性时(例如{{#show::测试|?属性}})无法正确处理的bug。

static public function getComponentsFromFunctionParams( array $rawParams, $showMode ) {
	$queryString = '';
	$parameters = array();
	$printouts = array();

	$lastprintout = null;
	$printRequestFactory = new PrintRequestFactory();

	if ( $showMode && isset( $rawParams[0] ) ) {
		$rawParams[0] = '[[:' . $rawParams[0] . ']]';
	}

	foreach ( $rawParams as $name => $rawParam ) {
		// special handling for arrays - this can happen if the
		// parameter came from a checkboxes input in Special:Ask:
		if ( is_array( $rawParam ) ) {
			$rawParam = implode( ',', array_keys( $rawParam ) );
		}

		// Bug 32955 / #640
		// Modify (e.g. replace `=`) a condition string only if enclosed by [[ ... ]]
		$rawParam = preg_replace_callback(
			'/\[\[(?:([^:][^]]*):[=:]|:)+([^\[\]]*)\]\]/xu',
			function( array $matches ) {
				return str_replace( array( '=' ), array( '-3D' ), $matches[0] );
			},
			$rawParam
		);

		// #1258 (named_args -> named args)
		// accept 'name' => 'value' just as '' => 'name=value':
		if ( is_string( $name ) && ( $name !== '' ) ) {
			$rawParam = str_replace( "_", " ", $name ) . '=' . $rawParam;
		}

		if ( $rawParam === '' ) {
		} elseif ( $rawParam { 0 } == '?' ) { // print statement
			$rawParam = substr( $rawParam, 1 );
			$lastprintout = $printRequestFactory->newPrintRequestFromText( $rawParam, $showMode );
			if ( !is_null( $lastprintout ) ) {
				$printouts[] = $lastprintout;
			}
		} elseif ( $rawParam[0] == '+' ) { // print request parameter
			if ( !is_null( $lastprintout ) ) {
				$rawParam = substr( $rawParam, 1 );
				$parts = explode( '=', $rawParam, 2 );
				if ( count( $parts ) == 2 ) {
					$lastprintout->setParameter( trim( $parts[0] ), $parts[1] );
				} else {
					$lastprintout->setParameter( trim( $parts[0] ), null );
				}
			}
		} else { // parameter or query

			// #1645
			$parts = $showMode && $name == 0 ? $rawParam : explode( '=', $rawParam, 2 );

			if ( count( $parts ) >= 2 ) {
				// don't trim here, some parameters care for " "
				$parameters[strtolower( trim( $parts[0] ) )] = $parts[1];
			} else {
				$queryString .= $rawParam;
			}
		}
	}

	$queryString = str_replace( array( '&lt;', '&gt;', '-3D' ), array( '<', '>', '=' ), $queryString );

	return array( $queryString, $parameters, $printouts);
}

\includes\queryprinters\ListResultPrinter.php

ListResultPrinter

class ListResultPrinter内增加5个变量。

class ListResultPrinter extends ResultPrinter {
	protected $mPropIntro;
	protected $mPropOutro;
	protected $manysep;
	protected $manyseplist = array();
	protected $fieldnamelist = array();
}

ListResultPrinter::handleParameters

protected function ListResultPrinter::handleParameters内增加获取及储存几个新参数的功能。

protected function handleParameters( array $params, $outputmode ) {
	parent::handleParameters( $params, $outputmode );

	$this->mTemplate = trim( $params['template'] );
	$this->mNamedArgs = $params['named args'];
	$this->mUserParam = trim( $params['userparam'] );
	$this->mColumns = !$this->isPlainlist() ? $params['columns'] : 1;
	$this->mIntroTemplate = $params['introtemplate'];
	$this->mOutroTemplate = $params['outrotemplate'];
	if ( $params['propintro'] !== '' || $params['propoutro'] !== '' ) {
		$this->mPropIntro = isset( $params['propintro'] ) ? $params['propintro'] : '';
		$this->mPropOutro = isset( $params['propoutro'] ) ? $params['propoutro'] : '';
	} else {
		list( $this->mPropIntro, $this->mPropOutro ) = explode( '||', $this->getContext()->msg( 'word-separator' )->text() . $this->getContext()->msg( 'parentheses', '||' )->text() );
	}
	$this->manysep = $this->params['many'];
}

ListResultPrinter::initializePrintingParameters

protected function ListResultPrinter::initializePrintingParameters内增加分隔符的判断。

protected function initializePrintingParameters( SMWQueryResult $queryResult ) {
	$this->numRows = 0;
	$this->numRowsInColumn = 0;
	$this->rowSortkey = '';

	$this->columnWidth = floor( 100 / $this->mColumns );
	$this->rowsPerColumn = ceil( $queryResult->getCount() / $this->mColumns );

	// Determine mark-up strings used around list items:
	if ( $this->mFormat == 'ul' || $this->mFormat == 'ol' ) {
		$this->header = "<" . $this->mFormat . ">\n";
		$this->footer = "</" . $this->mFormat . ">\n";
		$this->rowstart = "\t<li>";
		$this->rowend = "</li>\n";
	} else { // "list" and "template" format
		$this->header = '';
		$this->footer = '';
		$this->rowstart = '';
		$this->rowend = '';
	}

	// #2022, #2090 The system defines no default sep in order for it to decide
	// how to apply a separator and avoiding a regression for users who did
	// not choose a sep in the first place, if no separator is selected then
	// the list, ul, ol will use , as default
	$this->params['sep'] = str_replace( '\n', "\n", $this->params['sep'] );
	if ( $this->params['format'] === 'list' && $this->params['sep'] === ',' ) {
		// Make default list ", , , and "
		$this->listsep = ', ';
		$this->finallistsep = $this->getContext()->msg( 'smw_finallistconjunct' )->inContentLanguage()->text() . ' ';
	} elseif ( $this->params['format'] !== 'template' && $this->params['sep'] === '' ) {
		$this->listsep = ', ';
		$this->finallistsep = $this->listsep;
	} elseif ( $this->params['sep'] !== '' ) {
		// Allow "_" for encoding spaces, as documented
		$this->listsep = str_replace( '_', ' ', $this->params['sep'] );
		$this->finallistsep = $this->listsep;
	} else {
		$this->listsep = '';
		$this->finallistsep = '';
	}

	// #2329
	if ( $this->params['format'] === 'template' && !$this->isEnabledFeature( SMW_RF_TEMPLATE_OUTSEP ) ) {
		$this->listsep = '';
		$this->finallistsep = '';
	}
}

ListResultPrinter::getRowListContent

protected function ListResultPrinter::getRowListContent内增加manysep、propintro和propoutro功能。

protected function getRowListContent( array $row ) {

	$firstField = true; // is this the first entry in this row?
	$extraFields = false; // has anything but the first field been printed?
	$sep = $this->manysep;
	$seplist = $this->manyseplist;

	$result = '';
	$excluded = array( 'table', 'tr', 'th', 'td', 'dl', 'dd', 'ul', 'li', 'ol' );

	if ( $this->numRows == 0 ){
		foreach ( $row as $k => &$field ) {
			$seplist[$k] = ( ($sep2 = $field->getPrintRequest()->getParameter( 'many' )) === false ? $sep : $sep2 );
		}
		$this->manyseplist = $seplist;
	}
	foreach ( $row as $i => $field ) {
		$firstValue = true; // is this the first value in this field?

		while ( ( $dataValue = $field->getNextDataValue() ) !== false ) {

			// Add sortkey for all non-list formats
			if ( $firstField && $this->params['format'] !== 'list' &&
				$dataValue->getDataItem()->getDIType() === SMWDataItem::TYPE_WIKIPAGE  ) {
				$this->rowSortkey = StoreFactory::getStore()->getWikiPageSortKey( $dataValue->getDataItem() );
			}

			$text = $dataValue->getShortText( SMW_OUTPUT_WIKI, $this->getLinker( $firstField ) );

			if ( !$firstField && !$extraFields ) { // first values after first column
				$result .= $this->mPropIntro;
				$extraFields = true;
			} elseif ( $extraFields || !$firstValue ) {
				// any value after '(' or non-first values on first column
				$result .= $seplist[$i];
			}

			if ( $firstValue ) { // first value in any field, print header
				$firstValue = false;

				if ( ( $this->mShowHeaders != SMW_HEADERS_HIDE ) && ( $field->getPrintRequest()->getLabel() !== '' ) ) {
					$result .= $field->getPrintRequest()->getText( SMW_OUTPUT_WIKI, ( $this->mShowHeaders == SMW_HEADERS_PLAIN ? null:$this->mLinker ) ) . ' ';
				}
			}

			// Remove seleted tags to avoid lists are distorted by unresolved
			// in-text tags
			$result .= $this->isPlainlist() ? $text : Sanitizer::removeHTMLtags( $text, null, array(), array(), $excluded );
		}

		$firstField = false;
	}
	if ( $extraFields ) {
		$result .= $this->mPropOutro;
	}

	return $result;
}

ListResultPrinter::getTemplateContent

protected function ListResultPrinter::getTemplateContent内增加manysep功能及优化效率。

protected function addTemplateContentFields( $row ) {
	$sep = $this->manysep;
	$seplist = &$this->manyseplist;
	$fnamelist = &$this->fieldnamelist;

	foreach ( $row as $i => $field ) {
		if ( $this->numRows == 0 ){
			$seplist[$i] = ( ($sep2 = $field->getPrintRequest()->getParameter( 'many' )) === false ? $sep : $sep2 );
			$fnamelist[$i] = '';
			// {{{?Foo}}}
			if ( $this->mNamedArgs || $this->params['template arguments'] === 'legacy'  ) {
				$fnamelist[$i] = '?' . $field->getPrintRequest()->getLabel();
			}

			// {{{Foo}}}
			if ( $fnamelist[$i] === '' && $this->params['template arguments'] === 'named' ) {
				$fnamelist[$i] = $field->getPrintRequest()->getLabel();
			}

			// {{{1}}}
			if ( $fnamelist[$i] === '' || $fnamelist[$i] === '?' || $this->params['template arguments'] === 'numbered' ) {
				$fnamelist[$i] = intval( $i + 1 );
			}
		}
		$first_value = true;
		$value = '';
		$firstv = 'none';
		$many = $seplist[$i];

		while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getLinker( $i == 0 ) ) ) !== false ) {
			if ( $first_value ) {
				$first_value = false;
				$firstv = $text;
			} else {
				$value .= $many;
			}
			$value .= $text;
		}

		$this->templateRenderer->addField( $fnamelist[$i], $value );
	}

	$this->templateRenderer->addField( '#', $this->numRows );
}

ListResultPrinter::getParameters

public function ListResultPrinter::getParameters内增加几个新参数的定义。

public function getParameters() {
	$params = parent::getParameters();

	$params['sep'] = array(
		'message' => 'smw-paramdesc-sep',
		'default' => '',
	);

	if ( $this->mFormat === 'template' && $this->isEnabledFeature( SMW_RF_TEMPLATE_OUTSEP ) ) {
		$params['valuesep'] = array(
			'message' => 'smw-paramdesc-sep',
			'default' => '',
		);
	}

	$params['template'] = array(
		'message' => 'smw-paramdesc-template',
		'default' => '',
	);

	$params['template arguments'] = array(
		'message' => 'smw-paramdesc-template-arguments',
		'default' => '',
		'values' => array( 'numbered', 'named', 'legacy' ),
	);

	$params['named args'] = array(
		'type' => 'boolean',
		'message' => 'smw-paramdesc-named_args',
		'default' => false,
	);

	if ( !$this->isPlainlist() ) {
		$params['columns'] = array(
			'type' => 'integer',
			'message' => 'smw-paramdesc-columns',
			'default' => 1,
			'range' => array( 1, 10 ),
		);
	}

	$params['userparam'] = array(
		'message' => 'smw-paramdesc-userparam',
		'default' => '',
	);

	$params['introtemplate'] = array(
		'message' => 'smw-paramdesc-introtemplate',
		'default' => '',
	);

	$params['outrotemplate'] = array(
		'message' => 'smw-paramdesc-outrotemplate',
		'default' => '',
	);

	$params['import-annotation'] = array(
		'message' => 'smw-paramdesc-import-annotation',
		'type' => 'boolean',
		'default' => false
	);

	$params['propintro'] = array(
		'message' => 'smw-paramdesc-propintro',
		'default' => '',
	);
 
	$params['propoutro'] = array(
		'message' => 'smw-paramdesc-propoutro',
		'default' => '',
	);
 
	$params['many'] = array(
		'message' => 'smw-paramdesc-many',
		'default' => ', ',
	);

	return $params;
}

\includes\queryprinters\ResultPrinter.php

ResultPrinter::handleNonFileResult

protected function ResultPrinter::handleNonFileResult内去掉烦人的smw::off和smw::on。

protected function handleNonFileResult( $result, SMWQueryResult $results, $outputmode ) {
	/**
	 * @var \Parser $wgParser
	 */
	global $wgParser;

	$result .= $this->getErrorString( $results ); // append errors

	// MW 1.21+
	// Block recursive import of annotations unless otherwise specified for
	// a specific use case
	if ( method_exists( $wgParser->getOutput(), 'setExtensionData' ) ) {
		$wgParser->getOutput()->setExtensionData(
			'smw-blockannotation',
			$this->params['format'] === 'embedded'
		);
	}

	// Apply intro parameter
	if ( ( $this->mIntro ) && ( $results->getCount() > 0 ) ) {
		if ( $outputmode == SMW_OUTPUT_HTML ) {
			$result = Message::get( array( 'smw-parse', $this->mIntro ), Message::PARSE ) . $result;
		} else {
			$result = $this->mIntro . $result;
		}
	}

	// Apply outro parameter
	if ( ( $this->mOutro ) && ( $results->getCount() > 0 ) ) {
		if ( $outputmode == SMW_OUTPUT_HTML ) {
			$result = $result . Message::get( array( 'smw-parse', $this->mOutro ), Message::PARSE );
		} else {
			$result = $result . $this->mOutro;
		}
	}

	// Preprocess embedded templates if needed
	if ( ( !$this->isHTML ) && ( $this->hasTemplates ) ) {
		if ( ( $wgParser->getTitle() instanceof Title ) && ( $wgParser->getOptions() instanceof ParserOptions ) ) {
			self::$mRecursionDepth++;

			if ( self::$mRecursionDepth <= self::$maxRecursionDepth ) { // restrict recursion
				$result = isset( $this->params['import-annotation'] ) && $this->params['import-annotation'] ? $wgParser->recursivePreprocess( $result ) : $wgParser->replaceVariables( $result );
			} else {
				$result = ''; /// TODO: explain problem (too much recursive parses)
			}

			self::$mRecursionDepth--;
		} else { // not during parsing, no preprocessing needed, still protect the result
			
		}
	}

	if ( ( $this->isHTML ) && ( $outputmode == SMW_OUTPUT_WIKI ) ) {
		$result = array( $result, 'isHTML' => true );
	} elseif ( ( !$this->isHTML ) && ( $outputmode == SMW_OUTPUT_HTML ) ) {
		self::$mRecursionDepth++;

		// check whether we are in an existing parse, or if we should start a new parse for $wgTitle
		if ( self::$mRecursionDepth <= self::$maxRecursionDepth ) { // retrict recursion
			if ( ( $wgParser->getTitle() instanceof Title ) && ( $wgParser->getOptions() instanceof ParserOptions ) ) {
				$result = $wgParser->recursiveTagParse( $result );
			} else {
				global $wgTitle;

				$popt = new ParserOptions();
				$popt->setEditSection( false );
				$pout = $wgParser->parse( $result . '__NOTOC__', $wgTitle, $popt );

				/// NOTE: as of MW 1.14SVN, there is apparently no better way to hide the TOC
				\SMWOutputs::requireFromParserOutput( $pout );
				$result = $pout->getText();
			}
		} else {
			$result = ''; /// TODO: explain problem (too much recursive parses)
		}

		self::$mRecursionDepth--;
	}

	if ( method_exists( $wgParser->getOutput(), 'setExtensionData' ) ) {
		$wgParser->getOutput()->setExtensionData(
			'smw-blockannotation',
			false
		);
	}

	return $result;
}

\includes\queryprinters\TableResultPrinter.php

TableResultPrinter::getResultText

protected function TableResultPrinter::getResultText内为表格格式增加many、null、alter和add功能。

protected function getResultText( SMWQueryResult $res, $outputMode ) {
	$this->isHTML = ( $outputMode === SMW_OUTPUT_HTML );

	$this->htmlTableRenderer = ApplicationFactory::getInstance()->newMwCollaboratorFactory()->newHtmlTableRenderer();
	$this->htmlTableRenderer->setHtmlContext( $this->isHTML );

	$columnClasses = array();

	// Default cell value separator
	if ( !isset( $this->params['sep'] ) || $this->params['sep'] === '' ) {
		$manysep = $this->params['sep'] = '<br>';
	}
	$manysep = $this->params['many'];
	$null = ( !isset( $this->params['null'] ) || $this->params['null'] === '' ) ? null : $this->params['null'];
	$paramlist = array();
	$alter = trim( isset( $this->params['alter'] ) ? $this->params['alter'] : '' );
	if ( $alter === '' ) {
		$this->params['alter'] = false;
	} else {
		switch ( strtolower( $alter ) ) {
			case 'pagename': case 'fullpagename': case 'rootpagename': case 'basepagename': case 'subpagename': case 'subbasepagename':
				$this->params['alter'] = array( 1, strtolower( $alter ) );
				break;
			default:
				$this->params['alter'] = array( 2, $alter );
				break;
		}
	}

	foreach ( $res->getPrintRequests() as /* SMWPrintRequest */ $pr ) {
		if ( $this->mShowHeaders != SMW_HEADERS_HIDE ) { // building headers
			$attributes = array();
			$columnClass = str_replace( array( ' ', '_' ), '-', strip_tags( $pr->getText( SMW_OUTPUT_WIKI ) ) );
			$attributes['class'] = $columnClass;
			// Also add this to the array of classes, for
			// use in displaying each row.
			$columnClasses[] = $columnClass;
			$text = $pr->getText( $outputMode, ( $this->mShowHeaders == SMW_HEADERS_PLAIN ? null : $this->mLinker ) );

			$this->htmlTableRenderer->addHeader( ( $text === '' ? '&nbsp;' : $text ), $attributes );
		}
		$paramlist[] = array(
			'many' => ( ($sep2 = $pr->getParameter( 'many' ) ) === false ? $manysep : $sep2 ),
			'null' => ( ($nul2 = $pr->getParameter( 'null' ) ) === false ? array( false, $null ) : ( strlen( $nul2 ) == 0 ? array( false, null ) : array( ($nul3 = $pr->getParameter( 'isnull' )) === false ? null : $nul3, $nul2 ) ) ),
			'add' => ( ($t = trim( $pr->getParameter( 'add' ) )) === '' ? false : new DIProperty( $t ) ),
		);
	}

	$rowNumber = 0;

	while ( $subject = $res->getNext() ) {
		$rowNumber++;
		$this->getRowForSubject( $subject, $outputMode, $columnClasses, $paramlist );

		$this->htmlTableRenderer->addRow(
			array( 'data-row-number' => $rowNumber )
		);
	}

	// print further results footer
	if ( $this->linkFurtherResults( $res ) ) {
		$link = $this->getFurtherResultsLink( $res, $outputMode );

		$this->htmlTableRenderer->addCell(
				$link->getText( $outputMode, $this->mLinker ),
				array( 'class' => 'sortbottom', 'colspan' => $res->getColumnCount() )
		);
		$this->htmlTableRenderer->addRow( array( 'class' => 'smwfooter' ) );
	}

	$tableAttrs = array( 'class' => $this->params['class'] );

	if ( $this->mFormat == 'broadtable' ) {
		$tableAttrs['width'] = '100%';
	}

	$this->htmlTableRenderer->transpose( $this->mShowHeaders !== SMW_HEADERS_HIDE && $this->params['transpose'] );

	return $this->htmlTableRenderer->getHtml( $tableAttrs );
}

TableResultPrinter::getRowForSubject

protected function TableResultPrinter::getRowForSubject内把一些重要参数传递到下一级函数。

private function getRowForSubject( array $subject, $outputMode, array $columnClasses, $param ) {
	foreach ( $subject as $i => $field ) {
		// $columnClasses will be empty if "headers=hide"
		// was set.
		if ( array_key_exists( $i, $columnClasses ) ) {
			$columnClass = $columnClasses[$i];
		} else {
			$columnClass = null;
		}

		$this->getCellForPropVals( $field, $outputMode, $columnClass, $param[$i] );
	}
}

TableResultPrinter::getCellForPropVals

protected function TableResultPrinter::getCellForPropVals内应用many、null和add功能。

protected function getCellForPropVals( SMWResultArray $resultArray, $outputMode, $columnClass, $param ) {
	$dataValues = array();

	while ( ( $dv = $resultArray->getNextDataValue() ) !== false ) {
		$dataValues[] = $dv;
	}

	$attributes = array();
	$content = null;
	$isSubject = $resultArray->getPrintRequest()->getMode() == \SMWPrintRequest::PRINT_THIS;

	if ( count( $dataValues ) > 0 ) {
		$sortKey = $dataValues[0]->getDataItem()->getSortKey();
		$dataValueType = $dataValues[0]->getTypeID();

		if ( is_numeric( $sortKey ) ) {
			$attributes['data-sort-value'] = $sortKey;
		}

		$alignment = trim( $resultArray->getPrintRequest()->getParameter( 'align' ) );

		if ( in_array( $alignment, array( 'right', 'left', 'center' ) ) ) {
			$attributes['style'] = "text-align:$alignment;";
		}
		$attributes['class'] = $columnClass . ( $dataValueType !== '' ? ' smwtype' . $dataValueType : '' );

		$content = $this->getCellContent(
			$dataValues, $outputMode, $isSubject, $param
		);
	}
	if ( $content === $param['null'][0] ) $content = $param['null'][1];
	if ( $param['add'] ) {
		$addtext = '';
		foreach ( $resultArray->getStore()->getPropertyValues( $resultArray->getResultSubject(), $param['add'] ) as $v ) {
			$v = DataValueFactory::getInstance()->newDataItemValue( $v, $param['add'] );
			if ( ( $v = $v->getShortText( $outputMode, $this->getLinker( $isSubject ) ) ) !== '' ) $addtext .= ( $addtext === '' ? '' : $param['many'] ) . $v;
		}
		if ( $addtext !== '' ) {
			if ( is_null( $content ) || $content === '' ) $content = $addtext;
			else $content .= $param['many'] . $addtext;
		}
	}
	$this->htmlTableRenderer->addCell( $content, $attributes );
}

TableResultPrinter::getCellContent

protected function TableResultPrinter::getCellContent内应用alter功能。

protected function getCellContent( array $dataValues, $outputMode, $isSubject, $param ) {
	if ( $isSubject ){
		if ( $this->params['alter'] ){
			$value = $dataValues[0]->getShortText( $outputMode, null );
			switch( $this->params['alter'][0] ){
				case 1:
					$fn = $this->params['alter'][1];
					$t = \Title::newFromText( $value );
					switch ( strtolower( $fn ) ) {
						case 'pagename':
							$cap = wfEscapeWikiText( $t->getText() );
							break;
						case 'fullpagename':
							$cap = wfEscapeWikiText( $t->getPrefixedText() );
							break;
						case 'rootpagename':
							$cap = wfEscapeWikiText( strtok( $t->getText(), '/' ) );
							break;
						case 'basepagename':
							$cap = wfEscapeWikiText( substr( $t->getText(), 0, strrpos( $t->getText(), '/' ) ) );
							break;
						case 'subpagename':
							$cap = wfEscapeWikiText( substr( strrchr( '/' . $t->getText(), '/' ), 1 ) );
							break;
						case 'subbasepagename':
							$cap = wfEscapeWikiText( substr( strrchr( '/' . substr( $t->getText(), 0, strrpos( $t->getText(), '/' ) ), '/' ), 1 ) );
							break;
					}
					return '[[' . $value . '|' . $cap . ']]';
				case 2:
					return '[[' . $value . '|' . wfEscapeWikiText( $this->params['alter'][1] ) . ']]';
			}
 
		}
	}
	$values = array();

	foreach ( $dataValues as $dv ) {

		// Restore output in Special:Ask on:
		// - file/image parsing
		// - text formatting on string elements including italic, bold etc.
		if ( $outputMode === SMW_OUTPUT_HTML && $dv->getDataItem() instanceof DIWikiPage && $dv->getDataItem()->getNamespace() === NS_FILE ||
			$outputMode === SMW_OUTPUT_HTML && $dv->getDataItem() instanceof \SMWDIBlob ) {
			// Too lazy to handle the Parser object and besides the Message
			// parse does the job and ensures no other hook is executed
			$value = Message::get(
				array( 'smw-parse', $dv->getShortText( SMW_OUTPUT_WIKI, $this->getLinker( $isSubject ) ) ),
				Message::PARSE
			);
		} else {
			$value = $dv->getShortText( $outputMode, $this->getLinker( $isSubject ) );
		}


		$values[] = $value === '' ? '&nbsp;' : $value;
	}

	return implode( $param['many'], $values );
}

TableResultPrinter::getParamDefinitions

public function TableResultPrinter::getParamDefinitions内增加几个新参数的定义。

public function getParamDefinitions( array $definitions ) {
	$params = parent::getParamDefinitions( $definitions );

	$params['class'] = array(
		'name' => 'class',
		'message' => 'smw-paramdesc-table-class',
		'default' => 'sortable wikitable smwtable',
	);

	$params['transpose'] = array(
		'type' => 'boolean',
		'default' => false,
		'message' => 'smw-paramdesc-table-transpose',
	);

	$params['sep'] = array(
		'message' => 'smw-paramdesc-sep',
		'default' => '',
	);

	$params['many'] = array(
		'message' => 'smw-paramdesc-table-many',
		'default' => '<br />',
	);
 
	$params['alter'] = array(
		'message' => 'smw-paramdesc-table-alter',
		'default' => '',
	);

	return $params;
}

\src\DataValues\ValueFormatters\TimeValueFormatter.php

TimeValueFormatter::getPreferredCaption

protected function TimeValueFormatter::getPreferredCaption内把日期默认显示方式改为ISO。

protected function getPreferredCaption() {

	$dataItem = $this->dataValue->getDataItem();
	$format = strtoupper( $this->dataValue->getOutputFormat() );

	if ( $format == 'ISO' || $format === '' || $this->dataValue->getOutputFormat() == '-' ) {
		return $this->getISO8601Date();
	} elseif ( $format == 'MEDIAWIKI' ) {
		return $this->getMediaWikiDate();
	} elseif ( $format == 'SORTKEY' ) {
		return $dataItem->getSortKey();
	} elseif ( $format == 'JD' ) {
		return $dataItem->getJD();
	}

	// Does the formatting require calendar conversion?
	$model = $dataItem->getCalendarModel();

	if (
		( strpos( $format, 'JL' ) !== false ) ||
		( $dataItem->getJD() < TimeValue::J1582 && strpos( $format, 'GR' ) === false ) ) {
		$model = DITime::CM_JULIAN;
	} elseif ( strpos( $format, 'GR' ) !== false ) {
		$model = DITime::CM_GREGORIAN;
	}

	if ( strpos( $format, '-F[' ) !== false ) {
		return $this->getCaptionFromFreeFormat( $this->dataValue->getDataItemForCalendarModel( $model ) );
	} elseif ( strpos( $format, 'LOCL' ) !== false ) {
		return $this->getLocalizedFormat( $this->dataValue->getDataItemForCalendarModel( $model ) );
	} elseif ( $dataItem->getYear() > TimeValue::PREHISTORY && $dataItem->getPrecision() >= DITime::PREC_YM ) {
		// Do not convert between Gregorian and Julian if only
		// year is given (years largely overlap in history, but
		// assuming 1 Jan as the default date, the year number
		// would change in conversion).
		// Also do not convert calendars in prehistory: not
		// meaningful (getDataItemForCalendarModel may return null).
		return $this->getCaptionFromDataItem( $this->dataValue->getDataItemForCalendarModel( $model ) );
	}

	return $this->getCaptionFromDataItem( $dataItem );
}

\src\SQLStore\EntityStore\DataItemHandler.php

SMWDataItemHandler

class SMWDataItemHandler内移除函数SMWDataItemHandler::getWhereConds

//abstract public function getWhereConds( SMWDataItem $dataItem );

\src\SQLStore\EntityStore\DIHandlers\DINumberHandler.php

DINumberHandler::dataItemFromDBKeys

public function DINumberHandler::dataItemFromDBKeys内修改函数。

public function dataItemFromDBKeys( $dbkeys ) {

	if ( is_string( $dbkeys ) ) {
		return DINumber::doUnserialize( $dbkeys );
	} elseif ( is_array( $dbkeys ) ) {
		return DINumber::doUnserialize( $dbkeys[0] );
	}

	throw new DataItemHandlerException( 'Failed to create data item from DB keys.' );
}

\src\SQLStore\EntityStore\DataItemHandlerDispatcher.php

DataItemHandlerDispatcher::newHandlerByType

private function DataItemHandlerDispatcher::newHandlerByType内增加价格和链接类型。

private function newHandlerByType( $type ) {

	switch ( $type ) {
		case DataItem::TYPE_NUMBER:
			$handler = new DINumberHandler( $this->store );
			break;
		case DataItem::TYPE_BLOB:
			$handler = new DIBlobHandler( $this->store );
			break;
		case DataItem::TYPE_BOOLEAN:
			$handler = new DIBooleanHandler( $this->store );
			break;
		case DataItem::TYPE_URI:
			$handler = new DIUriHandler( $this->store );
			break;
		case \DurationExtSMW::TYPE_LINK:
			$handler = new \SMWDIHandlerLink( $this->store );
			break;
		case \DurationExtSMW::TYPE_PRICE:
			$handler = new \SMWDIHandlerPrice( $this->store );
			break;
		case DataItem::TYPE_TIME:
			$handler = new DITimeHandler( $this->store );
			break;
		case DataItem::TYPE_GEO:
			$handler = new DIGeoCoordinateHandler( $this->store );
			break;
		case DataItem::TYPE_WIKIPAGE:
			$handler = new DIWikiPageHandler( $this->store );
			break;
		case DataItem::TYPE_CONCEPT:
			$handler = new DIConceptHandler( $this->store );
			break;
		case DataItem::TYPE_PROPERTY:
			throw new DataItemHandlerException( "There is no DI handler for DataItem::TYPE_PROPERTY." );
		case DataItem::TYPE_CONTAINER:
			throw new DataItemHandlerException( "There is no DI handler for DataItem::TYPE_CONTAINER." );
		case DataItem::TYPE_ERROR:
			throw new DataItemHandlerException( "There is no DI handler for DataItem::TYPE_ERROR." );
		default:
			throw new DataItemHandlerException( "The value \"$type\" is not a valid dataitem ID." );
	}

	return $handler;
}

\src\SQLStore\PropertyTableInfoFetcher.php

PropertyTableInfoFetcher::$defaultDiTypeTableIdMap

private PropertyTableInfoFetcher::$defaultDiTypeTableIdMap内增加价格和链接类型。

private $defaultDiTypeTableIdMap = array(
	DataItem::TYPE_NUMBER     => 'smw_di_number',
	DataItem::TYPE_BLOB       => 'smw_di_blob',
	DataItem::TYPE_BOOLEAN    => 'smw_di_bool',
	DataItem::TYPE_URI        => 'smw_di_uri',
	\DurationExtSMW::TYPE_LINK       => 'smw_di_uri',
	\DurationExtSMW::TYPE_PRICE      => 'smw_di_number',
	DataItem::TYPE_TIME       => 'smw_di_time',
	DataItem::TYPE_GEO        => 'smw_di_coords', // currently created only if Semantic Maps are installed
	DataItem::TYPE_WIKIPAGE   => 'smw_di_wikipage',
	//DataItem::TYPE_CONCEPT    => '', // _CONC is the only property of this type
);

\src\InTextAnnotationParser.php

InTextAnnotationParser

class InTextAnnotationParser内清空两个常量。

	const OFF = '';
	const ON = '';

\src\IntlTimeFormatter.php

DataItemHandlerDispatcher::newHandlerByType

private function DataItemHandlerDispatcher::newHandlerByType内获取半年、季的信息。

/**
 * DateTime generally outputs English textual representation
 *
 * - D	A textual representation of a day, three letters
 * - l (lowercase 'L'), A full textual representation of the day of the week
 * - F	A full textual representation of a month, such as January or March
 * - M	A short textual representation of a month, three letters
 * - a	Lowercase Ante meridiem and Post meridiem am or pm
 * - A	Uppercase Ante meridiem and Post meridiem
 * - f	First half or Second half of the year, 1 or 2
 * - q	Quarter number of a year, 1 through 4
 */
private function formatWithLocalizedTextReplacement( $dateTime, $format ) {

	$output = $dateTime->format( $format );

	// (n) DateTime => 1 through 12
	$monthNumber = $dateTime->format( 'n' );

	// (N) DateTime => 1 (for Monday) through 7 (for Sunday)
	// (w) DateTime => 0 (for Sunday) through 6 (for Saturday)
	// MW => 1 (for Sunday) through 7 (for Saturday)
	$dayNumber = $dateTime->format( 'w' ) + 1;

	if ( strpos( $format, 'F' ) !== false ) {
		$output = str_replace(
			$dateTime->format( 'F' ),
			$this->language->getMonthName( $monthNumber ),
			$output
		);
	}

	if ( strpos( $format, 'M' ) !== false ) {
		$output = str_replace(
			$dateTime->format( 'M' ),
			$this->language->getMonthAbbreviation( $monthNumber ),
			$output
		);
	}

	if ( strpos( $format, 'l' ) !== false ) {
		$output = str_replace(
			$dateTime->format( 'l' ),
			$this->language->getWeekdayName( $dayNumber ),
			$output
		);
	}

	if ( strpos( $format, 'D' ) !== false ) {
		$output = str_replace(
			$dateTime->format( 'D' ),
			$this->language->getWeekdayAbbreviation( $dayNumber ),
			$output
		);
	}

	if ( strpos( $format, 'f' ) !== false ) {
		$output = str_replace(
			$dateTime->format( 'f' ),
			$monthNumber > 6 ? 2 : 1,
			$output
		);
	}

	if ( strpos( $format, 'q' ) !== false ) {
		$output = str_replace(
			$dateTime->format( 'q' ),
			floor( ( $monthNumber + 2 ) / 3 ),
			$output
		);
	}

	return $output;
}

\i18n\extra\en.json

en.json

"dataTypeLabels":{
	"_wpg": "Page",
	"_txt": "Text",
	"_cod": "Code",
	"_boo": "Boolean",
	"_num": "Number",
	"_geo": "Geographic coordinates",
	"_tem": "Temperature",
	"_dur": "Duration",
	"_dat": "Date",
	"_ema": "Email",
	"_uri": "URL",
	"_anu": "Annotation URI",
	"_tel": "Telephone number",
	"_rec": "Record",
	"_lin": "Link",
	"_qty": "Quantity",
	"_pri": "Price",
	"_shk": "Search Key",
	"_mlt_rec": "Monolingual text",
	"_eid": "External identifier",
	"_ref_rec": "Reference"
},
"dataTypeAliases":{
	"URL": "_uri",
	"URI": "_uri",
	"Page": "_wpg",
	"Text": "_txt",
	"Enumeration" : "_txt",
	"String": "_txt",
	"Code": "_cod",
	"Boolean": "_boo",
	"Number": "_num",
	"Float": "_num",
	"Integer": "_num",
	"Geographic coordinates": "_geo",
	"Geographic coordinate": "_geo",
	"Geographic polygon": "_gpo",
	"Temperature": "_tem",
	"Duration": "_dur",
	"Link": "_lin",
	"Quantity": "_qty",
	"Price": "_pri",
	"Search Key": "_shk",
	"Date": "_dat",
	"Email": "_ema",
	"E-mail": "_ema",
	"Annotation URI": "_anu",
	"Telephone number": "_tel",
	"Phone number": "_tel",
	"Record": "_rec",
	"Monolingual text": "_mlt_rec",
	"External identifier": "_eid",
	"Reference": "_ref_rec"
},

\i18n\extra\zh-cn.json

zh-cn.json

完全替换内容。

{
    "@metadata": {
        "authors": []
    },
    "fallbackLanguage": "en",
    "dataTypeLabels": {
        "_wpg": "页面",
        "_txt": "文字",
        "_cod": "代码",
        "_boo": "布尔",
        "_num": "数字",
        "_geo": "地理学的座标",
        "_tem": "温度",
		"_dur": "时长",
        "_dat": "日期",
        "_ema": "Email",
        "_uri": "URL",
		"_lin": "链接",
        "_anu": "URI的注解",
        "_tel": "电话号码",
        "_rec": "记录",
        "_qty": "数量",
        "_pri": "价格",
        "_shk": "搜索",
        "_mlt_rec": "Monolingual text",
        "_eid": "External identifier",
        "_ref_rec": "Reference"
    },
    "dataTypeAliases": {
        "浮点数": "_num",
        "整数": "_num",
        "枚举": "_txt",
        "字符串": "_txt",
        "Float": "_num",
        "Integer": "_num",
        "Enumeration": "_txt",
        "URI": "_uri"
    },
    "propertyLabels": {
        "_TYPE": "设有类型",
        "_URI": "对应的URI",
        "_SUBP": "所属的子属性",
        "_SUBC": "所属的子分类",
        "_UNIT": "显示单位",
        "_IMPO": "输入来源",
        "_CONV": "符合于",
        "_SERV": "提供服务",
        "_PVAL": "允许值",
        "_MDAT": "修改日期",
        "_CDAT": "创建日期",
        "_NEWP": "是否为新页面",
        "_LEDT": "最后编辑者是",
        "_ERRP": "有无不正确的值",
        "_LIST": "有无字段",
        "_SOBJ": "有无子对象",
        "_ASK": "有无查询",
        "_ASKST": "查询字符串",
        "_ASKFO": "查询格式",
        "_ASKSI": "查询大小",
        "_ASKDE": "查询深度",
        "_ASKDU": "查询时长",
        "_MEDIA": "媒体类型",
        "_MIME": "Mime类型",
        "_ERRC": "有无运行错误",
        "_ERRT": "有无运行错误说明",
        "_PREC": "显示精度",
        "_LCODE": "语言代号",
        "_TEXT": "文本",
        "_PDESC": "有无属性说明",
        "_PVAP": "允许格式",
        "_DTITLE": "显示标题",
        "_PVUC": "有无唯一限制",
        "_PEID": "External identifier",
        "_PEFU": "External formatter uri",
        "_ASKSC": "查询来源",
		"___EXCPUT": "处理时间",
		"___EXREDT": "重定向标题"
    },
    "propertyAliases": {
        "显示计量单位": "_UNIT"
    },
    "dateFormatsByPrecision": {
        "SMW_PREC_Y": "Y年",
        "SMW_PREC_YM": "Y年n月",
        "SMW_PREC_YMD": "Y年n月j日 (D)",
        "SMW_PREC_YMDT": "Y年n月j日 (D) H:i:s"
    },
    "namespaces": {
        "SMW_NS_PROPERTY": "属性",
        "SMW_NS_PROPERTY_TALK": "属性讨论",
        "SMW_NS_TYPE": "类型",
        "SMW_NS_TYPE_TALK": "类型讨论",
        "SMW_NS_CONCEPT": "概念",
        "SMW_NS_CONCEPT_TALK": "概念讨论"
    },
    "namespaceAliases": [],
    "dateFormats": [
        [
            "SMW_Y"
        ],
        [
            "SMW_MY",
            "SMW_YM"
        ],
        [
            "SMW_MDY",
            "SMW_DMY",
            "SMW_YMD",
            "SMW_YDM"
        ]
    ],
    "months": [
        [
            "1月",
            "1月"
        ],
        [
            "2月",
            "2月"
        ],
        [
            "3月",
            "3月"
        ],
        [
            "4月",
            "4月"
        ],
        [
            "5月",
            "5月"
        ],
        [
            "6月",
            "6月"
        ],
        [
            "7月",
            "7月"
        ],
        [
            "8月",
            "8月"
        ],
        [
            "9月",
            "9月"
        ],
        [
            "10月",
            "10月"
        ],
        [
            "11月",
            "11月"
        ],
        [
            "12月",
            "12月"
        ]
    ],
    "days": [
        [
            "星期一",
            "一"
        ],
        [
            "星期二",
            "二"
        ],
        [
            "星期三",
            "三"
        ],
        [
            "星期四",
            "四"
        ],
        [
            "星期五",
            "五"
        ],
        [
            "星期六",
            "六"
        ],
        [
            "星期日",
            "日"
        ]
    ]
}

\res\smw\data\ext.smw.dataItem.time.js

fn.getMediaWikiDate

var fn.getMediaWikiDate内修改函数。

getMediaWikiDate: function() {
	return this.date.getFullYear() + '年' +
		monthNames[this.date.getMonth()] + '月' +
		this.date.getDate() + '日' +
		( this.getTimeString() !== '00:00:00' ? ' ' + this.getTimeString() : '' );
}

SemanticResultFormats

\formats\math\SRF_Math.php

SRFMath

class SRFMath内增加变量$displaydatavalue。

class SRFMath extends SMWResultPrinter {
	protected $displaydatavalue;
}

SRFMath::getResultText

protected function SRFMath::getResultText内修改函数。

protected function getResultText( SMWQueryResult $res, $outputmode ) {
	$data = false;
	$numbers = $this->getNumbers( $res, $data );

	if ( count( $numbers ) == 0 ) return $this->params['default'];

	switch ( $this->mFormat ) {
		case 'max':
			$number = max( $numbers );
			break;
		case 'min':
			$number = min( $numbers );
			break;
		case 'sum':
			$number = array_sum( $numbers );
			break;
		case 'product':
			$number = array_product( $numbers );
			break;
		case 'average':
			$number = array_sum( $numbers ) / count( $numbers );
			break;
		case 'median':
			sort( $numbers, SORT_NUMERIC );
			$position = ( count( $numbers ) + 1 ) / 2 - 1;
			$number = ( $numbers[ceil( $position )] + $numbers[floor( $position )] ) / 2; 
			break;
	}

	if ( is_numeric( $number ) && $number !== '' && $data != false && method_exists( $data, 'getFormattedValue' ) ){
		return $data->getFormattedValue( $number );
	}
	return $number;
}

SRFMath::getNumbers

protected function SRFMath::getNumbers内修改函数。

protected function getNumbers( SMWQueryResult $res, &$data ) {
	$numbers = array();
	$isfirst = true;
	while ( $row = $res->getNext() ) {
		if( $isfirst ){
			foreach ( $row as &$field ) {
				while ( $dv = $field->getNextDataValue() ) {
					if ( $dv->getDataItem()->getDIType() == SMWDataItem::TYPE_NUMBER || $dv->getDataItem()->getDIType() == SMWDataItem::TYPE_PRICE ){
						$data = $dv;
						break 2;
					}
				}
			}
			$isfirst = false;
		}
		foreach( $row as /* SMWResultArray */ $resultArray ) {
			foreach ( $resultArray->getContent() as /* SMWDataItem */ $dataItem ) {
				self::addNumbersForDataItem( $dataItem, $numbers );
			}
		}
	}

	return $numbers;
}

SRFMath::addNumbersForDataItem

public static function SRFMath::addNumbersForDataItem内修改函数。

public static function addNumbersForDataItem( SMWDataItem $dataItem, array &$numbers ) {
	switch ( $dataItem->getDIType() ) {
		case SMWDataItem::TYPE_NUMBER: case SMWDataItem::TYPE_PRICE:
			$numbers[] = $dataItem->getNumber();
			break;
		case SMWDataItem::TYPE_CONTAINER:
			foreach ( $dataItem->getDataItems() as $di ) self::addNumbersForDataItem( $di, $numbers );
			break;
		default:
	}
}

SocialProfile

\UserProfile\SpecialUploadAvatar.php

UploadAvatar::createThumbnail

function UploadAvatar::createThumbnail内修复兼容性问题。

function createThumbnail( $imageSrc, $imageInfo, $imgDest, $thumbWidth ) {
	global $wgUseImageMagick, $wgImageMagickConvertCommand;

	if ( $wgUseImageMagick ) { // ImageMagick is enabled
		list( $origWidth, $origHeight, $typeCode ) = $imageInfo;

		if ( $origWidth < $thumbWidth ) {
			$thumbWidth = $origWidth;
		}
		$thumbHeight = ( $thumbWidth * $origHeight / $origWidth );
		$border = ' -bordercolor white  -border  0x';
		if ( $thumbHeight < $thumbWidth ) {
			$border = ' -bordercolor white  -border  0x' . ( ( $thumbWidth - $thumbHeight ) / 2 );
		}
		$pipes = null;
		if ( $typeCode == 2 ) {
			$proc = proc_open(
				$wgImageMagickConvertCommand . ' ' . $imageSrc .
				' -size ' . $thumbWidth . 'x' . $thumbWidth .
				' -resize ' . $thumbWidth . ' -crop ' . $thumbWidth . 'x' . $thumbWidth . '+0+0' .
				' -quality 100 ' . $border . ' ' . $this->avatarUploadDirectory . '/' . $imgDest . '.jpg',
				array(
					0 => array( 'file', 'php://stdin', 'r' ), // stdin is a pipe that the child will read from
					1 => array( 'pipe', 'w' ), // stdout is a pipe that the child will write to
					2 => array( 'file', 'php://stderr', 'w' ) // stderr is a file to write to
				),
				$pipes
			);
		}
		$pipes = null;
		if ( $typeCode == 1 ) {
			$proc = proc_open(
				$wgImageMagickConvertCommand . ' ' . $imageSrc .
				' -size ' . $thumbWidth . 'x' . $thumbWidth .
				' -resize ' . $thumbWidth . ' -crop ' . $thumbWidth . 'x' . $thumbWidth . '+0+0' .
				$border . ' ' . $this->avatarUploadDirectory . '/' . $imgDest . '.gif',
				array(
					0 => array( 'file', 'php://stdin', 'r' ), // stdin is a pipe that the child will read from
					1 => array( 'pipe', 'w' ), // stdout is a pipe that the child will write to
					2 => array( 'file', 'php://stderr', 'w' ) // stderr is a file to write to
				),
				$pipes
			);
		}
		$pipes = null;
		if ( $typeCode == 3 ) {
			$proc = proc_open(
				$wgImageMagickConvertCommand . ' ' . $imageSrc .
				' -size ' . $thumbWidth . 'x' . $thumbWidth .
				' -resize ' . $thumbWidth . ' -crop ' . $thumbWidth . 'x' . $thumbWidth . '+0+0' .
				$border . ' ' . $this->avatarUploadDirectory . '/' . $imgDest . '.png',
				array(
					0 => array( 'file', 'php://stdin', 'r' ), // stdin is a pipe that the child will read from
					1 => array( 'pipe', 'w' ), // stdout is a pipe that the child will write to
					2 => array( 'file', 'php://stderr', 'w' ) // stderr is a file to write to
				),
				$pipes
			);
		}
	} else { // ImageMagick is not enabled, so fall back to PHP's GD library
		// Get the image size, used in calculations later.
		list( $origWidth, $origHeight, $typeCode ) = getimagesize( $imageSrc );

		switch( $typeCode ) {
			case '1':
				$fullImage = imagecreatefromgif( $imageSrc );
				$ext = 'gif';
				break;
			case '2':
				$fullImage = imagecreatefromjpeg( $imageSrc );
				$ext = 'jpg';
				break;
			case '3':
				$fullImage = imagecreatefrompng( $imageSrc );
				$ext = 'png';
				break;
		}

		$scale = ( $thumbWidth / $origWidth );

		// Create our thumbnail size, so we can resize to this, and save it.
		$tnImage = imagecreatetruecolor(
			$origWidth * $scale,
			$origHeight * $scale
		);

		// Resize the image.
		imagecopyresampled(
			$tnImage,
			$fullImage,
			0, 0, 0, 0,
			$origWidth * $scale,
			$origHeight * $scale,
			$origWidth,
			$origHeight
		);

		// Create a new image thumbnail.
		if ( $typeCode == 1 ) {
			imagegif( $tnImage, $imageSrc );
		} elseif ( $typeCode == 2 ) {
			imagejpeg( $tnImage, $imageSrc );
		} elseif ( $typeCode == 3 ) {
			imagepng( $tnImage, $imageSrc );
		}

		// Clean up.
		imagedestroy( $fullImage );
		imagedestroy( $tnImage );

		// Copy the thumb
		copy(
			$imageSrc,
			$this->avatarUploadDirectory . '/' . $imgDest . '.' . $ext
		);
	}
}

UploadAvatar::performUpload

public function UploadAvatar::performUpload内修复兼容性问题。

public function performUpload( $comment, $pageText, $watch, $user, $tags = [] ) {
	global $wgUploadDirectory, $wgAvatarKey, $wgMemc;

	$this->avatarUploadDirectory = $wgUploadDirectory . '/avatars';

	$imageInfo = $this->mTempPath !== '' ? getimagesize( $this->mTempPath ) : null;
	if ( is_null( $imageInfo ) || empty( $imageInfo[2] ) ) {
		return Status::newFatal( 'empty-file' );
	}

	switch ( $imageInfo[2] ) {
		case 1:
			$ext = 'gif';
			break;
		case 2:
			$ext = 'jpg';
			break;
		case 3:
			$ext = 'png';
			break;
		default:
			return Status::newFatal( 'filetype-banned' );
	}

	$dest = $this->avatarUploadDirectory;

	$uid = $user->getId();
	$avatar = new wAvatar( $uid, 'l' );
	// If this is the user's first custom avatar, update statistics (in
	// case if we want to give out some points to the user for uploading
	// their first avatar)
	if ( $avatar->isDefault() ) {
		$stats = new UserStatsTrack( $uid, $user->getName() );
		$stats->incStatField( 'user_image' );
	}

	$this->createThumbnail( $this->mTempPath, $imageInfo, $wgAvatarKey . '_' . $uid . '_l', 75 );
	$this->createThumbnail( $this->mTempPath, $imageInfo, $wgAvatarKey . '_' . $uid . '_ml', 50 );
	$this->createThumbnail( $this->mTempPath, $imageInfo, $wgAvatarKey . '_' . $uid . '_m', 30 );
	$this->createThumbnail( $this->mTempPath, $imageInfo, $wgAvatarKey . '_' . $uid . '_s', 16 );

	if ( $ext != 'jpg' ) {
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_s.jpg' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_s.jpg' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_m.jpg' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_m.jpg' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_l.jpg' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_l.jpg' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_ml.jpg' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_ml.jpg' );
		}
	}
	if ( $ext != 'gif' ) {
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_s.gif' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_s.gif' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_m.gif' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_m.gif' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_l.gif' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_l.gif' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_ml.gif' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_ml.gif' );
		}
	}
	if ( $ext != 'png' ) {
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_s.png' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_s.png' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_m.png' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_m.png' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_l.png' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_l.png' );
		}
		if ( is_file( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_ml.png' ) ) {
			unlink( $this->avatarUploadDirectory . '/' . $wgAvatarKey . '_' . $uid . '_ml.png' );
		}
	}

	$key = wfMemcKey( 'user', 'profile', 'avatar', $uid, 's' );
	$data = $wgMemc->delete( $key );

	$key = wfMemcKey( 'user', 'profile', 'avatar', $uid, 'm' );
	$data = $wgMemc->delete( $key );

	$key = wfMemcKey( 'user', 'profile', 'avatar', $uid , 'l' );
	$data = $wgMemc->delete( $key );

	$key = wfMemcKey( 'user', 'profile', 'avatar', $uid, 'ml' );
	$data = $wgMemc->delete( $key );

	$this->mExtension = $ext;
	return Status::newGood();
}

\UserProfile\UserProfile.css

修改CSS样式。

\UserRelationship\UserRelationshipClass.php

UserRelationship::addRelationship

public function UserRelationship::addRelationship内修改hook的行为。

public function addRelationship( $relationshipRequestId, $email = true ) {
	global $wgMemc;

	$dbw = wfGetDB( DB_MASTER );
	$s = $dbw->selectRow(
		'user_relationship_request',
		array( 'ur_user_id_from', 'ur_user_name_from', 'ur_type' ),
		array( 'ur_id' => $relationshipRequestId ),
		__METHOD__
	);

	if ( $s == true ) {
		$ur_user_id_from = $s->ur_user_id_from;
		$ur_user_name_from = $s->ur_user_name_from;
		$ur_type = $s->ur_type;

		if ( self::getUserRelationshipByID( $this->user_id, $ur_user_id_from ) > 0 ) {
			return '';
		}

		$dbw->insert(
			'user_relationship',
			array(
				'r_user_id' => $this->user_id,
				'r_user_name' => $this->user_name,
				'r_user_id_relation' => $ur_user_id_from,
				'r_user_name_relation' => $ur_user_name_from,
				'r_type' => $ur_type,
				'r_date' => date( 'Y-m-d H:i:s' )
			),
			__METHOD__
		);

		$dbw->insert(
			'user_relationship',
			array(
				'r_user_id' => $ur_user_id_from,
				'r_user_name' => $ur_user_name_from,
				'r_user_id_relation' => $this->user_id,
				'r_user_name_relation' => $this->user_name,
				'r_type' => $ur_type,
				'r_date' => date( 'Y-m-d H:i:s' )
			),
			__METHOD__
		);

		$stats = new UserStatsTrack( $this->user_id, $this->user_name );
		if ( $ur_type == 1 ) {
			$stats->incStatField( 'friend' );
		} else {
			$stats->incStatField( 'foe' );
		}

		$stats = new UserStatsTrack( $ur_user_id_from, $ur_user_name_from );
		if ( $ur_type == 1 ) {
			$stats->incStatField( 'friend' );
		} else {
			$stats->incStatField( 'foe' );
		}

		if ( $email ) {
			$this->sendRelationshipAcceptEmail( $ur_user_id_from, $this->user_name, $ur_type );
		}

		// Purge caches
		$wgMemc->delete( wfMemcKey( 'relationship', 'profile', "{$this->user_id}-{$ur_type}" ) );
		$wgMemc->delete( wfMemcKey( 'relationship', 'profile', "{$ur_user_id_from}-{$ur_type}" ) );

		if ( class_exists( 'EchoEvent' ) ) {
			$userFrom = User::newFromId( $this->user_id );

			EchoEvent::create( array(
				'type' => 'social-rel-accept',
				'agent' => $userFrom,
				'title' => $userFrom->getUserPage(),
				'extra' => array(
					'target' => $ur_user_id_from,
					'from' => $this->user_id,
					'rel_type' => $ur_type
				)
			) );
		}

		// Hooks (for Semantic SocialProfile mostly)
		if ( $ur_type == 1 ) {
			Hooks::run( 'NewFriendAccepted', array( $ur_user_id_from, $this->user_id ) );
		} else {
			Hooks::run( 'NewFoeAccepted', array( $ur_user_id_from, $this->user_id ) );
		}

		return true;
	} else {
		return false;
	}
}

UserRelationship::removeRelationshipByUserID

public function UserRelationship::removeRelationshipByUserID内修改hook的行为。

public function removeRelationshipByUserID( $user1, $user2 ) {
	global $wgUser, $wgMemc;

	if ( $user1 != $wgUser->getID() && $user2 != $wgUser->getID() ) {
		return false; // only logged in user should be able to delete
	}

	// must delete record for each user involved in relationship
	$dbw = wfGetDB( DB_MASTER );
	$rel_type = (int)($dbw->selectField(
		'user_relationship',
		'r_type',
		array( 'r_user_id' => $user1, 'r_user_id_relation' => $user2 ),
		__METHOD__
	));
	$dbw->delete(
		'user_relationship',
		array( 'r_user_id' => $user1, 'r_user_id_relation' => $user2 ),
		__METHOD__
	);
	$dbw->delete(
		'user_relationship',
		array( 'r_user_id' => $user2, 'r_user_id_relation' => $user1 ),
		__METHOD__
	);

	$wgMemc->delete( wfMemcKey( 'relationship', 'profile', "{$user1}-1" ) );
	$wgMemc->delete( wfMemcKey( 'relationship', 'profile', "{$user2}-1" ) );

	$wgMemc->delete( wfMemcKey( 'relationship', 'profile', "{$user1}-2" ) );
	$wgMemc->delete( wfMemcKey( 'relationship', 'profile', "{$user2}-2" ) );

	// RelationshipRemovedByUserID hook
	Hooks::run( 'RelationshipRemovedByUserID', array( $user1, $user2, $rel_type ) );

	// Update social statistics for both users
	$stats = new UserStatsTrack( $user1, '' );
	$stats->updateRelationshipCount( 1 );
	$stats->updateRelationshipCount( 2 );
	$stats->clearCache();

	$stats = new UserStatsTrack( $user2, '' );
	$stats->updateRelationshipCount( 1 );
	$stats->updateRelationshipCount( 2 );
	$stats->clearCache();
}

\SocialProfile.namespaces.php

增加中文翻译。

/** 中文(简体) */
$namespaceNames['zh-hans'] = array(
	NS_USER_WIKI => '用户Wiki',
	NS_USER_WIKI_TALK => '用户Wiki讨论',
	NS_USER_PROFILE => '用户资料',
	NS_USER_PROFILE_TALK => '用户资料讨论',
);

$namespaceNames['zh-hant'] = array(
	NS_USER_WIKI => '用戶Wiki',
	NS_USER_WIKI_TALK => '用戶Wiki討論',
	NS_USER_PROFILE => '用戶資料',
	NS_USER_PROFILE_TALK => '用戶資料討論',
);

WikiEditor

\modules\jquery.wikiEditor.less

修改CSS样式。

\modules\jquery.wikiEditor.preview.less

修改CSS样式。