Extension:RandomInclude/RandomInclude.php

From MediaWiki.org

Jump to: navigation, search

This is part of the source code for the RandomInclude extension.

Instructions

  • To download, select the text in the box below and save it in a file named RandomInclude.php in the extensions directory of your wiki.
  • Suggest patches on the extension discussion page.

[edit] RandomInclude.php

<?php
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# http://www.gnu.org/copyleft/gpl.html

// RandomInclude MediaWiki extension.
// Includes a random text.
 
// Copyright (C) 2007 - Benner Sistemas, 2008 - John Erling Blad.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
#----------------------------------------------------------------------------
#    Extension initialization
#----------------------------------------------------------------------------
 
$wgRandomInclude = array();
$RandomIncludeVersion = '1.3.5';
$wgExtensionCredits['parserhook'][] = array(
	'name'=>'RandomInclude',
	'version'=>$RandomIncludeVersion,
	'author'=>'Fernando Correia, John Erling Blad',
	'url'=>'http://www.mediawiki.org/wiki/Extension:RandomInclude',
	'description' => 'Includes a random text'
    );
 
$wgExtensionFunctions[] = "wfRandomIncludeExtension";
$wgExtensionFunctions[] = 'wfRandomIncludeParserFunctionSetup';
$wgHooks['LanguageGetMagic'][] = 'wfRandomIncludeMagic';
 
function wfRandomIncludeExtension() {
	global $wgParser;
	$wgParser->setHook( "random", "wfRenderRandomInclude" );
}
 
function wfRandomIncludeParserFunctionSetup() {
	global $wgParser;
	$wgParser->setFunctionHook( 'random', 'wfRenderRandomIncludeParserFunction' );
}
 
function wfRandomIncludeMagic( &$magicWords, $langCode ) {
	$magicWords['random'] = array( 0, 'random' );
	return true;
}
 
#----------------------------------------------------------------------------
#    Rendering
#----------------------------------------------------------------------------
 
// Processes the {{#random:}} parser function.
function wfRenderRandomIncludeParserFunction( &$parser, $argv ) {
	$attr = array();
	$cont = array();
	$mypat = isset($wgRandomInclude['pattern']) ? $wgRandomInclude['pattern'] : "\n";
	$a = func_get_args();
	array_shift($a);
	foreach ($a as $item) {
		$t = explode('=', $item);
		switch ($t[0]) {
		case 'pattern':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			$mypat = $t[1];
			$mypat = str_replace(array('\n', '¶'), array("\n", "\n"), $mypat);
			break;
		case 'separator':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'count':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'limit':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'period':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'hash':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'seed':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'cache':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'mode':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		case 'format':
			$attr[] = $t[0] . '="' . $t[1] . '"';
			break;
		default:
			$cont[] = $item;
			break;
		}
	}
	$cont2 = array();
	foreach ($cont as $item) {
		$t = explode($mypat, $item);
		foreach ($t as $i) {
			$i = trim($i);
			if (strlen($i)) $cont2[] = $i;
		}
	}
 
	$result = '<random ' . join(' ', $attr) . '>' . join($mypat, $cont2) . '</random>';
	return $result;
}
 
// Local digest, can be reimplemented
// MD5 is quite heavy, and can probably be replaced by a simpler digest
function wfRenderRandomDigest( $any ) {
	$acc = 0;
	if (is_int($any)) $any = dechex($any + 0);
	foreach (str_split(md5("" . $any), 4) as $h) {
		$acc ^= hexdec($h);
	}
	return $acc;
}
 
// Processes the <random> extension tag.
function wfRenderRandomInclude( $input, $argv, $parser ) {
	global $wgUser;
	global $wgMessageCache;
	global $wgRandomInclude;
	$sStartList = '<ul>';
	$sEndList = '</ul>';
	$sStartItem = '<li>';
	$sEndItem = '</li>';
	$sk =& $wgUser->getSkin();
	$retries = 0;
	$pattern = $argv['pattern'] ? $argv['pattern'] : (isset($wgRandomInclude['pattern']) ? $wgRandomInclude['pattern'] : "\n");
	$pattern = str_replace(array('\n', '¶'), array("\n", "\n"), $pattern);
	$separator = $argv['separator'] ? $argv['separator'] : (isset($wgRandomInclude['separator']) ? $wgRandomInclude['separator'] : '');
	$count = $argv['count'] ? $argv['count'] : (isset($wgRandomInclude['count']) ? $wgRandomInclude['count'] : 1);
	$limit = $argv['limit'] ? $argv['limit'] : (isset($wgRandomInclude['limit']) ? $wgRandomInclude['limit'] : 20);
	$cache = $argv['cache'] ? $argv['cache'] : (isset($wgRandomInclude['cache']) ? $wgRandomInclude['cache'] : 'none');
	$seed = $argv['seed'] ? $argv['seed'] : (isset($wgRandomInclude['seed']) ? $wgRandomInclude['seed'] : 'none');
	if ($seed != 'none') {
		srand($seed = intval($seed));
		if ('disable' == $cache) $parser->disableCache();
	}
	$hash = $argv['hash'] ? $argv['hash'] : (isset($wgRandomInclude['hash']) ? $wgRandomInclude['hash'] : 'none');
	if ($hash != 'none') {
		$hash = wfRenderRandomDigest($hash);
		if ('disable' == $cache) $parser->disableCache();
	}
	$period = $argv['period'] ? $argv['period'] : (isset($wgRandomInclude['period']) ? $wgRandomInclude['period'] : 'none');
	if ($period != 'none') {
		$now = time();
		switch ($period) {
		case 'minute':
			$hash = $now - $now%60; // 60 seconds in a minute
			break;
		case 'hour':
			$hash = $now - $now%3600; // 60*60 seconds in a hour
			break;
		case 'day':
			$hash = $now - $now%86400; // 24*60*60 seconds in a day
			break;
		case 'week':
			$hash = $now - $now%604800; // 7*24*60*60 seconds in a week
			break;
		default:
			$hash = $now - $now%intval($period);
			break;
		}
		if ('disable' == $cache) $parser->disableCache();
	}
	$mode = $argv['mode'] ? $argv['mode'] : (isset($wgRandomInclude['mode']) ? $wgRandomInclude['mode'] : ($count == 1 ? 'none' : 'unordered'));
	switch ($mode) {
	case 'none':
		$sStartList = '';
		$sEndList = '';
		$sStartItem = '';
		$sEndItem = '';
		break;
	case 'ordered':
		$sStartList = "<ol>\n";
		$sEndList = "</ol>\n";
		$sStartItem = "<li>\n";
		$sEndItem = "</li>\n";
		$separator = '';
		break;
	case 'unordered':
		$sStartList = "<ul>\n";
		$sEndList = "</ul>\n";
		$sStartItem = "<li>\n";
		$sEndItem = "</li>\n";
		$separator = '';
		break;
	default:
		$tpl = $wgMessageCache->getMsgFromNamespace('Random-' . $mode);
		if (!$tpl) $tpl = '&lt;' . $mode . '&gt;';
		$sStartList = '';
		$sEndList = '';
		$sStartItem = '{{' . $tpl . '|';
		$sEndItem = '}}';
		break;
	}
	$format = $argv['format'] ? $argv['format'] : (isset($wgRandomInclude['format']) ? $wgRandomInclude['format'] : 'none');
	if ($format != 'none') {
		$f = explode(',', $format);
		$sStartList = htmlspecialchars($f[0]);
		$sStartItem = htmlspecialchars($f[1]);
		$sEndItem = htmlspecialchars($f[2]);
		$sEndList = htmlspecialchars($f[3]);
	}
	$values = explode($pattern, $input);
	$keep = array();
	$idxs = array();
	while (count($keep) < $count && count($values) && (++$retries <= $limit)) {
		if ($hash == 'none') {
			$idx = rand(0, count($values) - 1);
		}
		else {
			$idx = wfRenderRandomDigest($hash + count($keep) + $retries) % count($values);
			$idxs[] = $hash + count($keep) + $retries;
			$idxs[] = $idx;
		}
		$randomText = trim($values[$idx]);
		if ($randomText) {
			$keep[] = $randomText;
			$retries = 0;
			$values[$idx] = '';
		}
	}
 
	//process results of request, outputing equivalent of <li>[[Article]]</li> for each result,
	//or something similar if the list uses other startlist/endlist
	$n = 0;
	$separator = htmlspecialchars($separator);
	$output = $sStartList;
	foreach ($keep as $item) {
		$item = htmlspecialchars($item);
		if ($n++) $output .= $separator;
		$tmp = $sStartItem;
		$tmp .= $item;
		$tmp .= $sEndItem;
		$output .= str_replace(array('%ITEM%', '%COUNT%'), array($item, $n), $tmp);
	}
	$output .= $sEndList;
	$output = str_replace(array('²{', '}²', '²[', ']²', '¦', '\n', '¶'), array('{{', '}}', '[[', ']]', '|', "\n", "\n"), $output);
 
	return $parser->internalParse($output . " __NOEDITSECTION__");
 
}