ParserFirstCallInit hook.
*
* Registers the related
parser function (see
* {@see Hooks::onFuncRelated}).
*
* @param Parser $parser
* @return boolean Always true
*/
public static function onParserFirstCallInit( Parser &$parser ) {
$parser->setFunctionHook( 'related', 'RelatedArticles\\Hooks::onFuncRelated' );
return true;
}
/**
* The related
parser function.
*
* Appends the arguments to the internal list so that it can be used
* more that once per page.
* We don't use setProperty here is there is no need
* to store it as a page prop in the database, only in the cache.
*
* @todo Test for uniqueness
* @param Parser $parser
*
* @return string Always ''
*/
public static function onFuncRelated( Parser $parser ) {
$parserOutput = $parser->getOutput();
$relatedArticles = $parserOutput->getExtensionData( 'RelatedArticles' );
if ( !$relatedArticles ) {
$relatedArticles = array();
}
$args = func_get_args();
array_shift( $args );
// Add all the related articles passed by the parser function
// {{#related:Test with read more|Foo|Bar}}
foreach ( $args as $relatedArticle ) {
$relatedArticles[] = $relatedArticle;
}
$parserOutput->setExtensionData( 'RelatedArticles', $relatedArticles );
return '';
}
/**
* Handler for the ParserClearState
hook.
*
* Empties the internal list so that related articles are not passed on to future
* ParserOutput's - note that {{#related:Foo}} appends and can be used multiple times
* in the page.
*
* @param Parser $parser
* @return boolean Always true
*/
public static function onParserClearState( Parser &$parser ) {
$parserOutput = $parser->getOutput();
$parserOutput->setExtensionData( 'RelatedArticles', array() );
// FIXME: Remove in 30 days (T115698)
$parserOutput->unsetProperty( 'RelatedArticles' );
return true;
}
/**
* Gets the global instance of the {@see CustomData} class for backwards compatibility.
*
* FIXME: This can be removed when cache clears. (T114915)
* If the instance isn't available, then an exception is thrown.
*
* @throws Exception When the CustomData extension isn't properly installed
* @deprecated
* @return CustomData
*/
public static function getCustomData() {
global $wgCustomData;
if ( !$wgCustomData instanceof CustomData ) {
throw new Exception(
'CustomData extension isn\'t properly installed and is needed to view pages in cache.'
);
}
return $wgCustomData;
}
/**
* Passes the related articles list from the cached parser output
* object to the output page for rendering.
*
* The list of related articles will be retrieved using
* ParserOutput#getExtensionData
and, if that fails,
* CustomData#getParserData
.
*
* @param OutputPage $out
* @param ParserOutput $parserOutput
* @return boolean Always true
*/
public static function onOutputPageParserOutput( OutputPage &$out, ParserOutput $parserOutput ) {
$related = $parserOutput->getExtensionData( 'RelatedArticles' );
// Backwards compatability with old cached pages. In cached pages, related articles will not be in
// ParserOutput but will still be in custom data so let's retrieve them from there.
// FIXME: Remove in 30 days (T114915)
if ( !$related ) {
$related = self::getCustomData()->getParserData( $out, 'RelatedArticles' );
}
if ( $related ) {
$out->setProperty( 'RelatedArticles', $related );
}
return true;
}
/**
* Generates anchor element attributes for each entry in list of articles.
*
* The attributes that are generated are: href
,
* text
, and class
, with the latter always
* set to "interwiki-relart"
.
*
* If the the article is of the form "Foo && Bar"
, then
* the text
attribute will be set to "Bar", otherwise the
* article's {@see Title::getPrefixedText prefixed text} will be used.
*
* @param array[string] $relatedArticles
* @return array An array of maps, each with href
,
* text
, and class
entries.
*/
private static function getRelatedArticlesUrls( array $relatedArticles ) {
$relatedArticlesUrls = array();
foreach ( $relatedArticles as $article ) {
// Tribute to Evan
$article = urldecode( $article );
$altText = '';
if ( preg_match( '/\&\&/', $article ) ) {
$parts = array_map( 'trim', explode( '&&', $article, 2 ) );
$article = $parts[0];
$altText = $parts[1];
}
$title = Title::newFromText( $article );
if ( $title ) {
$relatedArticlesUrls[] = array(
'href' => $title->getLocalURL(),
'text' => $altText ?: $title->getPrefixedText(),
'class' => 'interwiki-relart'
);
}
};
return $relatedArticlesUrls;
}
/**
* Handler for the SkinBuildSidebar
hook.
*
* Retrieves the list of related articles
* and adds its HTML representation to the sidebar.
*
* @param Skin $skin
* @param array $bar
* @return boolean Always true
*/
public static function onSkinBuildSidebar( Skin $skin, &$bar ) {
$out = $skin->getOutput();
$relatedArticles = $out->getProperty( 'RelatedArticles' );
if ( !$relatedArticles ) {
return true;
}
$relatedArticlesUrls = self::getRelatedArticlesUrls( $relatedArticles );
// build relatedarticles
SkinTemplateToolboxEnd
hook.
*
* Retrieves the list of related articles from the template and
* echo
s its HTML representation to the sidebar.
*
* @param SkinTemplate $skinTpl
* @return boolean Always true
*/
public static function onSkinTemplateToolboxEnd( BaseTemplate &$skinTpl ) {
$relatedArticles = $skinTpl->getSkin()->getOutput()->getProperty( 'RelatedArticles' );
if ( !$relatedArticles ) {
return true;
}
$relatedArticlesUrls = self::getRelatedArticlesUrls( $relatedArticles );
// build relatedarticles UnitTestsList
hook.
*
* Adds the path to this extension's PHPUnit test suite to the set of
* paths.
*
* @param array $paths
* @return boolean Always true
*/
public static function onUnitTestsList( array &$paths ) {
$paths[] = __DIR__ . '/../tests/phpunit';
return true;
}
}