Difference between revisions of "MediaWiki/archive/extensions/Contributors"

from HTYP, the free directory anyone can edit if they can prove to me that they're not a spambot
Jump to navigation Jump to search
(→‎Contributors.php: more friendly URL)
(→‎Contributors.php: 11/15 suppression of selected usernames)
Line 23: Line 23:
 
* '''2007-11-14''' Oops, didn't mean to hog all the credit! Rob Church did most of the work. This version corrects the "author" data, and gives a more friendly URL.
 
* '''2007-11-14''' Oops, didn't mean to hog all the credit! Rob Church did most of the work. This version corrects the "author" data, and gives a more friendly URL.
 
<php><?php
 
<php><?php
 
 
/**
 
/**
 
  * Special page that lists the ten most prominent contributors to an article
 
  * Special page that lists the ten most prominent contributors to an article
 
  *
 
  *
 
  * @addtogroup Extensions
 
  * @addtogroup Extensions
  * @author Rob Church <robchur@gmail.com>, Nick (Woozle) Staddon
+
  * @author Rob Church <robchur@gmail.com>, Nick (Woozle) Staddon  
 
  */
 
  */
 
/*
 
/*
Line 34: Line 33:
 
$wgContributorsIncludeBefore, $wgContributorsIncludeBetween, $wgContributorsIncludeBeforeOthers,
 
$wgContributorsIncludeBefore, $wgContributorsIncludeBetween, $wgContributorsIncludeBeforeOthers,
 
$wgContributorsShowAnon, $wgContributorsShowOthers, $wgContributorsUseRealName
 
$wgContributorsShowAnon, $wgContributorsShowOthers, $wgContributorsUseRealName
 +
2007-11-15 (Woozle) Added ability to hide or alias certain usernames
 
*/
 
*/
 
   
 
   
 
if( defined( 'MEDIAWIKI' ) ) {
 
if( defined( 'MEDIAWIKI' ) ) {
 
+
 
$wgExtensionFunctions[] = 'efContributors';
 
$wgExtensionFunctions[] = 'efContributors';
 
$wgExtensionCredits['specialpage'][] = array(
 
$wgExtensionCredits['specialpage'][] = array(
Line 44: Line 44:
 
'description' => 'Summarises the main contributors to an article',
 
'description' => 'Summarises the main contributors to an article',
 
'url' => 'http://htyp.org/MediaWiki_Contributors_extension',
 
'url' => 'http://htyp.org/MediaWiki_Contributors_extension',
'version' => '2007-11-14.wzl',
+
'version' => '2007-11-15.wzl',
 
);
 
);
+
 
$wgAutoloadClasses['SpecialContributors'] = dirname( __FILE__ ) . '/Contributors.page.php';
 
$wgAutoloadClasses['SpecialContributors'] = dirname( __FILE__ ) . '/Contributors.page.php';
 
$wgSpecialPages['Contributors'] = 'SpecialContributors';
 
$wgSpecialPages['Contributors'] = 'SpecialContributors';
+
 
/**
 
/**
 
* Intelligent cut-off limit; see below
 
* Intelligent cut-off limit; see below
 
*/
 
*/
 
$wgContributorsLimit = 10;
 
$wgContributorsLimit = 10;
+
 
/**
 
/**
 
* After $wgContributorsLimit is reached, contributors with less than this
 
* After $wgContributorsLimit is reached, contributors with less than this
Line 60: Line 60:
 
*/
 
*/
 
$wgContributorsThreshold = 2;
 
$wgContributorsThreshold = 2;
+
 
/**
 
/**
 
* Some formatting specs for the included version of the contrib list:
 
* Some formatting specs for the included version of the contrib list:
Line 72: Line 72:
 
$wgContributorsShowOthers = false; // if FALSE, do not show "and n others" line
 
$wgContributorsShowOthers = false; // if FALSE, do not show "and n others" line
 
$wgContributorsUseRealName = true; // if TRUE, use real name if available
 
$wgContributorsUseRealName = true; // if TRUE, use real name if available
 
+
/**
 +
* Override to prevent certain users (e.g. internal authors) from being listed
 +
*/
 +
// $wgUsernameAliases['username'] = 'alias'; // add as many different aliases as needed
 +
/* Where multiple usernames map to one alias, each one is still listed individually -- but grouping should be
 +
easy enough to add if anyone actually wants it. Empty string suppresses listing of that name,
 +
including the separation string.
 +
*/
 +
 
/**
 
/**
 
* Extension initialisation function
 
* Extension initialisation function
Line 87: Line 95:
 
$wgHooks['MonoBookTemplateToolboxEnd'][] = 'efContributorsToolbox';
 
$wgHooks['MonoBookTemplateToolboxEnd'][] = 'efContributorsToolbox';
 
}
 
}
+
 
/**
 
/**
 
* Invalidate the cache we saved for a given title
 
* Invalidate the cache we saved for a given title
Line 96: Line 104:
 
global $wgMemc;
 
global $wgMemc;
 
$wgMemc->delete( wfMemcKey( 'contributors', $article->getId() ) );
 
$wgMemc->delete( wfMemcKey( 'contributors', $article->getId() ) );
+
 
return true;
 
return true;
 
}
 
}
+
 
/**
 
/**
 
* Prepare the toolbox link
 
* Prepare the toolbox link
Line 111: Line 119:
 
return true;
 
return true;
 
}
 
}
 
+
 
/**
 
/**
 
* Output the toolbox link
 
* Output the toolbox link
Line 128: Line 136:
 
return true;
 
return true;
 
}
 
}
 
+
 
} else {
 
} else {
 
echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
 
echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );

Revision as of 22:06, 15 November 2007

Navigation

{{#lst:MediaWiki extensions|navbar}}: Contributors

Overview

This is a modification of an extension originally posted on mediawiki.org. If anyone wants to integrate these changes into the official release of that extension, please feel free to do so.

It adds the following features:

  • link to user's page, if available (with standard edit link if page doesn't exist)
  • allows display of user's real name, if available (configurable option)
  • more flexible formatting via LocalSettings options

Installation instructions are unchanged from those in the official release, except for the following new LocalSettings options:

  • $wgContributorsIncludeBefore: string to include before each contributor listing
  • $wgContributorsIncludeBetween: string to include between contributors (not before first or after last)
  • $wgContributorsIncludeBeforeOthers: string to include before the optional "and n others" listing
    • (text for after the "others" listing is set at Mediawiki:contributors-others)
  • $wgContributorsShowAnon: if FALSE, do not show anonymous (IP address) contributors
  • $wgContributorsShowOthers: if FALSE, do not show "and n others" line
  • $wgContributorsUseRealName: if TRUE, use real name if available (as entered by user in their "my preferences" page)

Code

The Contributors.i18n.php file is unaltered; use the one linked from mediawiki.org.

Contributors.php

  • 2007-11-14 Oops, didn't mean to hog all the credit! Rob Church did most of the work. This version corrects the "author" data, and gives a more friendly URL.

<php><?php /**

* Special page that lists the ten most prominent contributors to an article
*
* @addtogroup Extensions
* @author Rob Church <robchur@gmail.com>, Nick (Woozle) Staddon 
*/

/*

2007-11-13 (Woozle) Better formatting for included contrib list; added some config options:

$wgContributorsIncludeBefore, $wgContributorsIncludeBetween, $wgContributorsIncludeBeforeOthers, $wgContributorsShowAnon, $wgContributorsShowOthers, $wgContributorsUseRealName

2007-11-15 (Woozle) Added ability to hide or alias certain usernames
  • /

if( defined( 'MEDIAWIKI' ) ) {

$wgExtensionFunctions[] = 'efContributors'; $wgExtensionCredits['specialpage'][] = array( 'name' => 'Contributors', 'author' => 'Rob Church, Nick (Woozle) Staddon', 'description' => 'Summarises the main contributors to an article', 'url' => 'http://htyp.org/MediaWiki_Contributors_extension', 'version' => '2007-11-15.wzl', );

$wgAutoloadClasses['SpecialContributors'] = dirname( __FILE__ ) . '/Contributors.page.php'; $wgSpecialPages['Contributors'] = 'SpecialContributors';

/** * Intelligent cut-off limit; see below */ $wgContributorsLimit = 10;

/** * After $wgContributorsLimit is reached, contributors with less than this * number of edits to a page won't be listed in normal or inclusion lists */ $wgContributorsThreshold = 2;

/** * Some formatting specs for the included version of the contrib list: */ $wgContributorsIncludeBefore = ; // include this string before each contributor // $wgContributorsIncludeBetween = '
'; // include this string after each contributor $wgContributorsIncludeBetween = ', '; // include this string after each contributor $wgContributorsIncludeBeforeOthers = '
... '; // include this string before "others" // text for *after* "others" is set at Mediawiki:contributors-others $wgContributorsShowAnon = false; // if FALSE, do not show anonymous contributors $wgContributorsShowOthers = false; // if FALSE, do not show "and n others" line $wgContributorsUseRealName = true; // if TRUE, use real name if available /** * Override to prevent certain users (e.g. internal authors) from being listed */ // $wgUsernameAliases['username'] = 'alias'; // add as many different aliases as needed /* Where multiple usernames map to one alias, each one is still listed individually -- but grouping should be easy enough to add if anyone actually wants it. Empty string suppresses listing of that name, including the separation string.

  • /

/** * Extension initialisation function */ function efContributors() { global $wgMessageCache, $wgHooks; require_once( dirname( __FILE__ ) . '/Contributors.i18n.php' ); foreach( efContributorsMessages() as $lang => $messages ) $wgMessageCache->addMessages( $messages, $lang ); $wgHooks['ArticleDeleteComplete'][] = 'efContributorsInvalidateCache'; $wgHooks['ArticleSaveComplete'][] = 'efContributorsInvalidateCache'; # Good god, this is ludicrous! $wgHooks['SkinTemplateBuildNavUrlsNav_urlsAfterPermalink'][] = 'efContributorsNavigation'; $wgHooks['MonoBookTemplateToolboxEnd'][] = 'efContributorsToolbox'; }

/** * Invalidate the cache we saved for a given title * * @param $article Article object that changed */ function efContributorsInvalidateCache( &$article ) { global $wgMemc; $wgMemc->delete( wfMemcKey( 'contributors', $article->getId() ) );

return true; }

/** * Prepare the toolbox link */ function efContributorsNavigation( &$skintemplate, &$nav_urls, &$oldid, &$revid ) { if ( $skintemplate->mTitle->getNamespace() === NS_MAIN && $revid !== 0 ) $nav_urls['contributors'] = array( 'text' => wfMsg( 'contributors-toolbox' ), 'href' => $skintemplate->makeSpecialUrl( 'Contributors', "target=" . wfUrlEncode( "{$skintemplate->thispage}" ) ) ); return true; }

/** * Output the toolbox link */ function efContributorsToolbox( &$monobook ) { if ( isset( $monobook->data['nav_urls']['contributors'] ) ) if ( $monobook->data['nav_urls']['contributors']['href'] == ) {

?>

  • <?php echo $monobook->msg( 'contributors-toolbox' ); ?>
  • <?php } else { ?>

  • <?php ?><a href="<?php echo htmlspecialchars( $monobook->data['nav_urls']['contributors']['href'] ) ?>"><?php echo $monobook->msg( 'contributors-toolbox' ); ?></a><?php ?>
  • <?php } return true; } } else { echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" ); exit( 1 ); } ?></php>

    Contributors.page.php

    <php><?php

    /**

    * Special page class for the Contributors extension
    *
    * @addtogroup Extensions
    * @author Rob Church <robchur@gmail.com>
    */
    
    

    class SpecialContributors extends IncludableSpecialPage {

    protected $target;

    public function __construct() { parent::__construct( 'Contributors' ); }

    public function execute( $target ) { wfProfileIn( __METHOD__ ); global $wgOut, $wgRequest; $this->setHeaders(); $this->determineTarget( $wgRequest, $target );

    # What are we doing? Different execution paths for inclusion, # direct access and raw access if( $this->including() ) { $this->showInclude(); } elseif( $wgRequest->getText( 'action' ) == 'raw' ) { $this->showRaw(); } else { $wgOut->addHtml( $this->makeForm() ); if( is_object( $this->target ) ) $this->showNormal(); }

    wfProfileOut( __METHOD__ ); }

    private function showInclude() { global $wgContributorsIncludeBefore, $wgContributorsIncludeBetween, $wgContributorsIncludeBeforeOthers, $wgContributorsShowAnon, $wgContributorsShowOthers, $wgContributorsUseRealName;

    wfProfileIn( __METHOD__ ); global $wgOut; if( is_object( $this->target ) ) { if( $this->target->exists() ) { $names = array(); list( $contributors, $others ) = $this->getMainContributors(); foreach( $contributors as $username => $info ) { $idUser = $info[0]; if ($idUser) { // logged-in user $objUser = User::newFromName($username); $strUserName = $username; if ($wgContributorsUseRealName) { $strUserFull = $objUser->getRealName(); if ($strUserFull) { $strUserName = $strUserFull; } } $objUserTitle = $objUser->getUserPage(); if ($objUserTitle->exists()) { $strUserURL = $objUserTitle->getLocalURL(); } else { $strUserURL = $objUserTitle->getEditURL(); $strClass = ' class="new"'; } $strUser = $wgContributorsIncludeBefore.'<a href="'.$strUserURL.'"'.$strClass.'>'.$strUserName.'</a>'; } else { if ($wgContributorsShowAnon) { $strUser = $wgContributorsIncludeBefore.$username; } else { $strUser = ; } } // $names[] = '[[User:'.$username.'|]]'; if ($strUser != ) { $names[] = $strUser; } } $output = implode( $wgContributorsIncludeBetween, $names ); if( ($others > 0) && $wgContributorsShowOthers) $output .= $wgContributorsIncludeBeforeOthers . wfMsgForContent( 'contributors-others', $others ); // $wgOut->addHtml( htmlspecialchars( $output ) ); $wgOut->addHtml( $output ); } else {

    $wgOut->addHtml( '

    ' . htmlspecialchars( wfMsgForContent( 'contributors-nosuchpage', $this->target->getPrefixedText() ) ) . '

    ' );

    } } else {

    $wgOut->addHtml( '

    ' . htmlspecialchars( wfMsgForContent( 'contributors-badtitle' ) ) . '

    ' );

    } wfProfileOut( __METHOD__ ); }

    /** * Output a machine-readable form of the raw information */ private function showRaw() { wfProfileIn( __METHOD__ ); global $wgOut; $wgOut->disable(); if( is_object( $this->target ) && $this->target->exists() ) { foreach( $this->getContributors() as $username => $info ) { list( $userid, $count ) = $info; header( 'Content-type: text/plain; charset=utf-8', true ); echo( htmlspecialchars( "{$username} = {$count}\n" ) ); } } else { header( 'Status: 404 Not Found', true, 404 ); echo( 'The requested target page does not exist.' ); } wfProfileOut( __METHOD__ ); }

    private function showNormal() { wfProfileIn( __METHOD__ ); global $wgOut, $wgUser, $wgLang; if( $this->target->exists() ) { $total = 0; $skin =& $wgUser->getSkin(); $link = $skin->makeKnownLinkObj( $this->target );

    $wgOut->addHtml( '

    ' . wfMsgHtml( 'contributors-subtitle', $link ) . '

    ' );

    list( $contributors, $others ) = $this->getMainContributors();

    $wgOut->addHtml( '

      ' ); foreach( $contributors as $username => $info ) { list( $id, $count ) = $info; $line = $skin->userLink( $id, $username ) . $skin->userToolLinks( $id, $username ); $line .= ' [' . $wgLang->formatNum( $count ) . ']'; $wgOut->addHtml( '
    • ' . $line . '
    • ' ); } $wgOut->addHtml( '

    ' );

    if( $others > 0 ) { $others = $wgLang->formatNum( $others ); $wgOut->addWikiText( wfMsgNoTrans( 'contributors-others-long', $others ) ); } } else {

    $wgOut->addHtml( '

    ' . htmlspecialchars( wfMsg( 'contributors-nosuchpage', $this->target->getPrefixedText() ) ) . '

    ' );

    } wfProfileOut( __METHOD__ ); }

    /** * Retrieve all contributors for the target page worth listing, at least * according to the limit and threshold defined in the configuration * * Also returns the number of contributors who weren't considered * "important enough" * * @return array */ protected function getMainContributors() { wfProfileIn( __METHOD__ ); global $wgContributorsLimit, $wgContributorsThreshold; $total = 0; $ret = array(); $all = $this->getContributors(); foreach( $all as $username => $info ) { list( $id, $count ) = $info; if( $total >= $wgContributorsLimit && $count < $wgContributorsThreshold ) break; $ret[$username] = array( $id, $count ); $total++; } $others = count( $all ) - count( $ret ); wfProfileOut( __METHOD__ ); return array( $ret, $others ); }

    /** * Retrieve the contributors for the target page with their contribution numbers * * @return array */ protected function getContributors() { wfProfileIn( __METHOD__ ); global $wgMemc; $k = wfMemcKey( 'contributors', $this->target->getArticleId() ); $contributors = $wgMemc->get( $k ); if( !$contributors ) { $contributors = array(); $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( 'revision', array( 'COUNT(*) AS count', 'rev_user', 'rev_user_text', ), $this->getConditions(), __METHOD__, array( 'GROUP BY' => 'rev_user_text', 'ORDER BY' => 'count DESC', ) ); if( $res && $dbr->numRows( $res ) > 0 ) { while( $row = $dbr->fetchObject( $res ) ) $contributors[ $row->rev_user_text ] = array( $row->rev_user, $row->count ); } $wgMemc->set( $k, $contributors, 84600 ); } wfProfileOut( __METHOD__ ); return $contributors; }

    /** * Get conditions for the main query * * @return array */ protected function getConditions() { global $wgVersion; $conds['rev_page'] = $this->target->getArticleId(); if( version_compare( $wgVersion, '1.11alpha', '>=' ) ) $conds[] = 'rev_deleted & ' . Revision::DELETED_USER . ' = 0'; return $conds; }

    /** * Given the web request, and a possible override from a subpage, work * out which we want to use * * @param $request WebRequest we're serving * @param $override Possible subpage override * @return string */ private function determineTarget( &$request, $override ) { $target = $request->getText( 'target', $override ); $this->target = Title::newFromUrl( $target ); }

    /** * Make a nice little form so the user can enter a title and so forth * in normal output mode * * @return string */ private function makeForm() { global $wgScript; $self = parent::getTitleFor( 'Contributors' ); $target = is_object( $this->target ) ? $this->target->getPrefixedText() : ; $form = '<form method="get" action="' . htmlspecialchars( $wgScript ) . '">'; $form .= Xml::hidden( 'title', $self->getPrefixedText() ); $form .= '<fieldset><legend>' . wfMsgHtml( 'contributors-legend' ) . '</legend>';

    $form .= '

    '; $form .= ''; $form .= ''; $form .= ''; $form .= ''; $form .= ''; $form .= '
    <label for="target">' . wfMsgHtml( 'contributors-target' ) . '</label>' . Xml::input( 'target', 40, $target, array( 'id' => 'target' ) ) . '
     ' . Xml::submitButton( wfMsg( 'contributors-submit' ) ) . '

    ';

    $form .= '</fieldset>'; $form .= '</form>'; return $form; }

    }</php>