r105609 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105608‎ | r105609 | r105610 >
Date:23:24, 8 December 2011
Author:danwe
Status:deferred
Tags:
Comment:
Tag for version 0.4
Modified paths:
  • /tags/extensions/Loops/REL_0_4 (added) (history)

Diff [purge]

Index: tags/extensions/Loops/REL_0_4/Loops.i18n.magic.php
@@ -0,0 +1,22 @@
 2+<?php
 3+#coding: utf-8
 4+
 5+/**
 6+ * Internationalization file for magic words of the 'Loops' extension.
 7+ *
 8+ * @since 0.4
 9+ *
 10+ * @file Loops.i18n.magic.php
 11+ * @ingroup Loops
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+
 15+$magicWords = array();
 16+
 17+$magicWords['en'] = array(
 18+ 'while' => array( 0, 'while' ),
 19+ 'dowhile' => array( 0, 'dowhile' ),
 20+ 'loop' => array( 0, 'loop' ),
 21+ 'forargs' => array( 0, 'forargs' ),
 22+ 'fornumargs' => array( 0, 'fornumargs' ),
 23+);
Property changes on: tags/extensions/Loops/REL_0_4/Loops.i18n.magic.php
___________________________________________________________________
Added: svn:eol-style
124 + native
Index: tags/extensions/Loops/REL_0_4/Loops.i18n.php
@@ -0,0 +1,101 @@
 2+<?php
 3+/**
 4+ * Internationalization file of the 'Loops' extension.
 5+ *
 6+ * @since 0.4
 7+ *
 8+ * @file Loops.i18n.php
 9+ * @ingroup Loops
 10+ * @author Daniel Werner < danweetz@web.de >
 11+ */
 12+
 13+$messages = array();
 14+
 15+/** English
 16+ * @author David M. Sledge
 17+ */
 18+$messages['en'] = array(
 19+ 'loops-desc' => 'Parser functions for performing loops',
 20+ 'loops_max' => 'Maximum number of loops have been performed'
 21+);
 22+
 23+/** German (Deutsch)
 24+ * @author Daniel Werner
 25+ */
 26+$messages['de'] = array(
 27+ 'loops-desc' => 'Parser-Funktionen zur Schleifen-Ausführung',
 28+ 'loops_max' => 'Die maximal erlaubte Anzahl an Schleifen wurde ausgeführt',
 29+);
 30+
 31+/** French (Français)
 32+ * @author DavidL
 33+ */
 34+$messages['fr'] = array(
 35+ 'loops-desc' => "Fonctions de l'interpréteur pour effectuer des boucles",
 36+ 'loops_max' => 'Le nombre maximal de boucles a été effectué',
 37+);
 38+
 39+/** Galician (Galego)
 40+ * @author Toliño
 41+ */
 42+$messages['gl'] = array(
 43+ 'loops-desc' => 'Funcións analíticas para levar a cabo bucles',
 44+ 'loops_max' => 'Levouse a cabo o número máximo de bucles',
 45+);
 46+
 47+/** Upper Sorbian (Hornjoserbsce)
 48+ * @author Michawiki
 49+ */
 50+$messages['hsb'] = array(
 51+ 'loops-desc' => 'Parserowe funkcije za wuwjedźenje seklow',
 52+ 'loops_max' => 'Maksimalna ličba seklow je so wuwjedła',
 53+);
 54+
 55+/** Interlingua (Interlingua)
 56+ * @author McDutchie
 57+ */
 58+$messages['ia'] = array(
 59+ 'loops-desc' => 'Functiones de analysator syntactic pro executar iterationes',
 60+ 'loops_max' => 'Le numero maxime de iterationes ha essite executate',
 61+);
 62+
 63+/** Japanese (日本語)
 64+ * @author Fryed-peach
 65+ */
 66+$messages['ja'] = array(
 67+ 'loops-desc' => 'ループを実行するためのパーサー関数',
 68+ 'loops_max' => 'ループの最大実行回数に達しました',
 69+);
 70+
 71+/** Luxembourgish (Lëtzebuergesch)
 72+ * @author Robby
 73+ */
 74+$messages['lb'] = array(
 75+ 'loops-desc' => 'Parser-Fonctioune fir Schleefen auszeféieren',
 76+ 'loops_max' => 'Déi maximal Zuel vun erlaabte Schleefe gouf ausgefouert',
 77+);
 78+
 79+/** Macedonian (Македонски)
 80+ * @author Bjankuloski06
 81+ */
 82+$messages['mk'] = array(
 83+ 'loops-desc' => 'Парсерски функции за вршење на повторувања (јамки)',
 84+ 'loops_max' => 'Извршен е максималниот број на повторувања',
 85+);
 86+
 87+/** Malay (Bahasa Melayu)
 88+ * @author Anakmalaysia
 89+ */
 90+$messages['ms'] = array(
 91+ 'loops-desc' => 'Fungsi parser untuk melakukan gelung',
 92+ 'loops_max' => 'Bilangan gelung maksimum telah dilakukan',
 93+);
 94+
 95+/** Dutch (Nederlands)
 96+ * @author Siebrand
 97+ */
 98+$messages['nl'] = array(
 99+ 'loops-desc' => 'Parserfuncties voor het uitvoeren van herhalingen',
 100+ 'loops_max' => 'Het maximum aantal herhalingen is uitgevoerd',
 101+);
 102+
Property changes on: tags/extensions/Loops/REL_0_4/Loops.i18n.php
___________________________________________________________________
Added: svn:eol-style
1103 + native
Index: tags/extensions/Loops/REL_0_4/Loops.php
@@ -0,0 +1,388 @@
 2+<?php
 3+
 4+/**
 5+ * 'Loops' is a MediaWiki extension expanding the parser with loops functions
 6+ *
 7+ * Documentation: http://www.mediawiki.org/wiki/Extension:Loops
 8+ * Support: http://www.mediawiki.org/wiki/Extension_talk:Loops
 9+ * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Loops
 10+ *
 11+ * @version: 0.4
 12+ * @license: GNU GPL v2 or higher
 13+ * @author: David M. Sledge
 14+ * @author: Daniel Werner < danweetz@web.de >
 15+ *
 16+ * @file Loops.php
 17+ * @ingroup Loops
 18+ */
 19+
 20+if ( ! defined( 'MEDIAWIKI' ) ) { die( ); }
 21+
 22+$wgExtensionCredits['parserhook'][] = array(
 23+ 'path' => __FILE__,
 24+ 'author' => array( 'David M. Sledge', '[http://www.mediawiki.org/wiki/User:Danwe Daniel Werner]' ),
 25+ 'name' => 'Loops',
 26+ 'version' => ExtLoops::VERSION,
 27+ 'descriptionmsg' => 'loops-desc',
 28+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Loops',
 29+);
 30+
 31+// language files:
 32+$wgExtensionMessagesFiles['Loops' ] = ExtLoops::getDir() . '/Loops.i18n.php';
 33+$wgExtensionMessagesFiles['LoopsMagic'] = ExtLoops::getDir() . '/Loops.i18n.magic.php';
 34+
 35+// hooks registration:
 36+$wgHooks['ParserFirstCallInit'][] = 'ExtLoops::init';
 37+$wgHooks['ParserLimitReport' ][] = 'ExtLoops::onParserLimitReport';
 38+$wgHooks['ParserClearState' ][] = 'ExtLoops::onParserClearState';
 39+
 40+// Include the settings file:
 41+require_once ExtLoops::getDir() . '/Loops_Settings.php';
 42+
 43+
 44+/**
 45+ * Class representing extension 'Loops', containing all parser functions and other
 46+ * extension logic stuff.
 47+ */
 48+class ExtLoops {
 49+
 50+ const VERSION = '0.4';
 51+
 52+ /**
 53+ * Configuration variable defining maximum allowed number of loops ('-1' => no limit).
 54+ * '#forargs' and '#fornumargs' are not limited by this.
 55+ *
 56+ * @var int
 57+ */
 58+ public static $maxLoops = 100;
 59+
 60+ /**
 61+ * Returns the extensions base installation directory.
 62+ *
 63+ * @since 0.4
 64+ *
 65+ * @return boolean
 66+ */
 67+ public static function getDir() {
 68+ static $dir = null;
 69+
 70+ if( $dir === null ) {
 71+ $dir = dirname( __FILE__ );
 72+ }
 73+ return $dir;
 74+ }
 75+
 76+ /**
 77+ * Sets up parser functions
 78+ *
 79+ * @since 0.4
 80+ */
 81+ public static function init( Parser &$parser ) {
 82+
 83+ if( ! class_exists( 'ExtVariables' ) ) {
 84+ /*
 85+ * If Variables extension not defined, we can't use certain functions.
 86+ * Make sure they are disabled:
 87+ */
 88+ global $egLoopsEnabledFunctions;
 89+ $disabledFunctions = array( 'loop', 'forargs', 'fornumargs' );
 90+ $egLoopsEnabledFunctions = array_diff( $egLoopsEnabledFunctions, $disabledFunctions );
 91+ }
 92+
 93+ /*
 94+ * store for loops count per parser object. This will solve several bugs related to
 95+ * 'ParserClearState' hook resetting the count early in combination with certain
 96+ * other extensions or special page inclusion. (since v0.4)
 97+ */
 98+ $parser->mExtLoopsCounter = 0;
 99+
 100+ self::initFunction( $parser, 'while' );
 101+ self::initFunction( $parser, 'dowhile' );
 102+ self::initFunction( $parser, 'loop' );
 103+ self::initFunction( $parser, 'forargs' );
 104+ self::initFunction( $parser, 'fornumargs' );
 105+
 106+ return true;
 107+ }
 108+ private static function initFunction( Parser &$parser, $name ) {
 109+ global $egLoopsEnabledFunctions;
 110+
 111+ // don't register parser function if disabled by configuration:
 112+ if( ! in_array( $name, $egLoopsEnabledFunctions ) ) {
 113+ return;
 114+ }
 115+
 116+ $functionCallback = array( __CLASS__, 'pfObj_' . $name );
 117+ $parser->setFunctionHook( $name, $functionCallback, SFH_OBJECT_ARGS );
 118+ }
 119+
 120+
 121+ ####################
 122+ # Parser Functions #
 123+ ####################
 124+
 125+ public static function pfObj_while( Parser &$parser, $frame, $args ) {
 126+ return self::perform_while( $parser, $frame, $args, false );
 127+ }
 128+
 129+ public static function pfObj_dowhile( Parser &$parser, $frame, $args ) {
 130+ return self::perform_while( $parser, $frame, $args, true );
 131+ }
 132+
 133+ /**
 134+ * Generic function handling '#while' and '#dowhile' as one
 135+ */
 136+ protected static function perform_while( Parser &$parser, $frame, $args, $dowhile = false ) {
 137+ // #(do)while: | condition | code
 138+ $rawCond = isset( $args[1] ) ? $args[1] : ''; // unexpanded condition
 139+ $rawCode = isset( $args[2] ) ? $args[2] : ''; // unexpanded loop code
 140+
 141+ if(
 142+ $dowhile === false
 143+ && trim( $frame->expand( $rawCond ) ) === ''
 144+ ) {
 145+ // while, but condition not fullfilled from the start
 146+ return '';
 147+ }
 148+
 149+ $output = '';
 150+
 151+ do {
 152+ // limit check:
 153+ if( ! self::incrCounter( $parser ) ) {
 154+ return self::msgLoopsLimit( $output );
 155+ }
 156+ $output .= trim( $frame->expand( $rawCode ) );
 157+
 158+ } while( trim( $frame->expand( $rawCond ) ) );
 159+
 160+ return $output;
 161+ }
 162+
 163+ public static function pfObj_loop( Parser &$parser, PPFrame $frame, $args ) {
 164+ // #loop: var | start | count | code
 165+ $varName = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
 166+ $startVal = isset( $args[1] ) ? (int)trim( $frame->expand( $args[1] ) ) : 0;
 167+ $loops = isset( $args[2] ) ? (int)trim( $frame->expand( $args[2] ) ) : 0;
 168+ $rawCode = isset( $args[3] ) ? $args[3] : ''; // unexpanded loop code
 169+
 170+ if( $loops === 0 ) {
 171+ // no loops to perform
 172+ return '';
 173+ }
 174+
 175+ $output = '';
 176+ $endVal = $startVal + $loops;
 177+ $i = $startVal;
 178+
 179+ while( $i !== $endVal ) {
 180+ // limit check:
 181+ if( ! self::incrCounter( $parser ) ) {
 182+ return self::msgLoopsLimit( $output );
 183+ }
 184+
 185+ // set current position as variable:
 186+ self::setVariable( $parser, $varName, (string)$i );
 187+
 188+ $output .= trim( $frame->expand( $rawCode ) );
 189+
 190+ // in-/decrease loop count (count can be negative):
 191+ ( $i < $endVal ) ? $i++ : $i--;
 192+ }
 193+ return $output;
 194+ }
 195+
 196+ /**
 197+ * #forargs: filter | keyVarName | valVarName | code
 198+ */
 199+ public static function pfObj_forargs( Parser &$parser, $frame, $args ) {
 200+ // The first arg is already expanded, but this is a good habit to have...
 201+ $filter = array_shift( $args );
 202+ $filter = $filter !== null ? trim( $frame->expand( $filter ) ) : '';
 203+
 204+ // if prefix contains numbers only or isn't set, get all arguments, otherwise just non-numeric
 205+ $tArgs = ( preg_match( '/^([1-9][0-9]*)?$/', $filter ) > 0 )
 206+ ? $frame->getArguments()
 207+ : $frame->getNamedArguments();
 208+
 209+ return self::perform_forargs( $parser, $frame, $args, $tArgs, $filter );
 210+ }
 211+
 212+ /**
 213+ * #fornumargs: keyVarName | valVarName | code
 214+ * or (since 0.4 for more consistency)
 215+ * #fornumargs: | keyVarName | valVarName | code
 216+ */
 217+ public static function pfObj_fornumargs( Parser &$parser, $frame, $args ) {
 218+ /*
 219+ * get numeric arguments, don't use PPFrame::getNumberedArguments because it would
 220+ * return explicitely numbered arguments only.
 221+ */
 222+ $tNumArgs = $frame->getArguments();
 223+ foreach( $tNumArgs as $argKey => $argVal ) {
 224+ // allow all numeric, including negative values!
 225+ if( is_string( $argKey ) ) {
 226+ unset( $tNumArgs[ $argKey ] );
 227+ }
 228+ }
 229+ ksort( $tNumArgs ); // sort from lowest to highest
 230+
 231+ if( count( $args ) > 3 ) {
 232+ // compatbility to pre 0.4 but consistency with other Loop functions.
 233+ // this way the first argument can be ommitted like '#fornumargs: |varKey |varVal |code'
 234+ array_shift( $args );
 235+ }
 236+
 237+ return self::perform_forargs( $parser, $frame, $args, $tNumArgs, '' );
 238+ }
 239+
 240+ /**
 241+ * Generic function handling '#forargs' and '#fornumargs' as one
 242+ */
 243+ protected static function perform_forargs( Parser &$parser, PPFrame $frame, array $funcArgs, array $templateArgs, $prefix = '' ) {
 244+ // if not called within template instance:
 245+ if( !( $frame->isTemplate() ) ) {
 246+ return '';
 247+ }
 248+
 249+ // name of the variable to store the argument name:
 250+ $keyVar = array_shift( $funcArgs );
 251+ $keyVar = $keyVar !== null ? trim( $frame->expand( $keyVar ) ) : '';
 252+ // name of the variable to store the argument value:
 253+ $valVar = array_shift( $funcArgs );
 254+ $valVar = $valVar !== null ? trim( $frame->expand( $valVar ) ) : '';
 255+ // unexpanded code:
 256+ $rawCode = array_shift( $funcArgs );
 257+ $rawCode = $rawCode !== null ? $rawCode : '';
 258+
 259+ $output = '';
 260+
 261+ // if prefix contains numbers only or isn't set, get all arguments, otherwise just non-numeric
 262+ $tArgs = preg_match( '/^([1-9][0-9]*)?$/', $prefix ) > 0
 263+ ? $frame->getArguments() : $frame->getNamedArguments();
 264+
 265+ foreach( $templateArgs as $argName => $argVal ) {
 266+ // if no filter or prefix in argument name:
 267+ if( $prefix !== '' && strpos( $argName, $prefix ) !== 0 ) {
 268+ continue;
 269+ }
 270+ if ( $keyVar !== $valVar ) {
 271+ // variable with the argument name without prefix as value:
 272+ self::setVariable( $parser, $keyVar, substr( $argName, strlen( $prefix ) ) );
 273+ }
 274+ // variable with the arguments value:
 275+ self::setVariable( $parser, $valVar, $argVal );
 276+
 277+ // expand current run:
 278+ $output .= trim( $frame->expand( $rawCode ) );
 279+ }
 280+
 281+ return $output;
 282+ }
 283+
 284+ /**
 285+ * Connects to 'Variables' extension and sets a variable. Handles different versions of
 286+ * 'Variables' extension since there have changed some things along the way.
 287+ *
 288+ * @param Parser $parser
 289+ * @param string $varName
 290+ * @param string $varValue
 291+ */
 292+ private static function setVariable( Parser &$parser, $varName, $varValue ) {
 293+ global $wgExtVariables;
 294+
 295+ static $newVersion = null;
 296+ if( $newVersion === null ) {
 297+ // find out whether local wiki is using variables extension 2.0 or higher
 298+ $newVersion = ( defined( 'ExtVariables::VERSION' ) && version_compare( ExtVariables::VERSION, '1.9999', '>' ) );
 299+ }
 300+
 301+ if( $newVersion ) {
 302+ // clean way since Variables 2.0:
 303+ ExtVariables::get( $parser )->setVarValue( $varName, $varValue );
 304+ }
 305+ else {
 306+ // make sure to trim values and convert them to string since old versions of Variables extension won't do this.
 307+ $wgExtVariables->vardefine( $parser, trim( $varName ), trim( $varValue ) );
 308+ }
 309+ }
 310+
 311+
 312+ ###############
 313+ # Loops Count #
 314+ ###############
 315+
 316+ /**
 317+ * Returns how many loops have been performed for a given Parser instance.
 318+ *
 319+ * @since 0.4
 320+ *
 321+ * @param Parser $parser
 322+ * @return int
 323+ */
 324+ public static function getLoopsCount( Parser &$parser ) {
 325+ return $parser->mExtLoopsCounter;
 326+ }
 327+
 328+ /**
 329+ * Returns whether the maximum number of loops for the given Parser instance have
 330+ * been performed already.
 331+ *
 332+ * @since 0.4
 333+ *
 334+ * @param Parser $parser
 335+ * @return bool
 336+ */
 337+ public static function maxLoopsPerformed( Parser &$parser ) {
 338+ $count = $parser->mExtLoopsCounter;
 339+ return $count > -1 && $count >= self::$maxLoops;
 340+ }
 341+
 342+ /**
 343+ * If limit has not been exceeded already, this will increase the counter. If
 344+ * exceeded false will be returned, otherwise the new counter value
 345+ *
 346+ * @return false|int
 347+ */
 348+ protected static function incrCounter( Parser &$parser ) {
 349+ if( self::maxLoopsPerformed( $parser ) ) {
 350+ return false;
 351+ }
 352+ return ++$parser->mExtLoopsCounter;
 353+ }
 354+
 355+ /**
 356+ * div wrapped error message stating maximum number of loops have been performed.
 357+ */
 358+ protected static function msgLoopsLimit( $output = '' ) {
 359+ if( trim( $output ) !== '' ) {
 360+ $output .= "\n";
 361+ }
 362+ return $output .= '<div class="error">' . wfMsgForContent( 'loops_max' ) . '</div>';
 363+ }
 364+
 365+
 366+ ##################
 367+ # Hooks handling #
 368+ ##################
 369+
 370+ public static function onParserClearState( Parser &$parser ) {
 371+ // reset loops counter since the parser process finished one page
 372+ $parser->mExtLoopsCounter = 0;
 373+ return true;
 374+ }
 375+
 376+ public static function onParserLimitReport( $parser, &$report ) {
 377+ // add performed loops to limit report:
 378+ $report .= 'ExtLoops count: ' . self::getLoopsCount( $parser );
 379+
 380+ if( self::$maxLoops > -1 ) {
 381+ // if limit is set, communicate the limit as well:
 382+ $report .= '/' . self::$maxLoops;
 383+ }
 384+ $report .= "\n";
 385+
 386+ return true;
 387+ }
 388+
 389+}
Property changes on: tags/extensions/Loops/REL_0_4/Loops.php
___________________________________________________________________
Added: svn:eol-style
1390 + native
Index: tags/extensions/Loops/REL_0_4/Loops_Settings.php
@@ -0,0 +1,31 @@
 2+<?php
 3+
 4+/**
 5+ * File defining the settings for the 'Loops' extension.
 6+ * More info can be found at http://www.mediawiki.org/wiki/Extension:Loops#Configuration
 7+ *
 8+ * NOTICE:
 9+ * =======
 10+ * Changing one of these settings can be done by copying and placing
 11+ * it in LocalSettings.php, AFTER the inclusion of 'Loops'.
 12+ *
 13+ * @file Loops_Settings.php
 14+ * @ingroup Loops
 15+ * @since 0.4
 16+ *
 17+ * @author Daniel Werner
 18+ */
 19+
 20+/**
 21+ * Allows to define which functionalities provided by 'Loops' should be enabled for the wiki.
 22+ * If extension 'Variables' is not installed, '#loop', '#forargs' and '#fornumargs' will be
 23+ * disabled automatically.
 24+ *
 25+ * @example
 26+ * # enable '#while' and '#dowhile' parser functions only:
 27+ * egLoopsEnabledFunctions = array( 'while', 'dowhile' );
 28+ *
 29+ * @since 0.4
 30+ * @var array
 31+ */
 32+$egLoopsEnabledFunctions = array( 'while', 'dowhile', 'loop', 'forargs', 'fornumargs' );
Property changes on: tags/extensions/Loops/REL_0_4/Loops_Settings.php
___________________________________________________________________
Added: svn:eol-style
133 + native
Index: tags/extensions/Loops/REL_0_4/RELEASE-NOTES
@@ -0,0 +1,43 @@
 2+ Post svn Changelog:
 3+ ===================
 4+
 5+ * November 16, 2011 -- Version 0.4 by Daniel Werner
 6+ - The loops count now counts per parser instance. Before there were several hacks to reset the
 7+ counter, for example a special-page inclusion. This has been solved now.
 8+ - 'Loops' is working with MW 1.18+ now. Should be compatible down to MW 1.14 or even further.
 9+ - Compatbility to Variables Version 2.0.
 10+ - Configuration variable '$egLoopsEnabledFunctions' to enable certain Loops parser functions only.
 11+ - If 'Variables' extension is not active, '#loop', '#forargs' and '#fornumargs' will be disabled.
 12+ - If loop limit exceeded, the error message will be part of the output wrapped inside a 'div'
 13+ with error class so it can be caught by '#iferror'.
 14+ - '#fornumargs' parameter 1 can be empty to make it more consistent with other Loop parser
 15+ functions. E.g. '{{#fornumargs: | keyVarName | valVarName | code }}' istead of
 16+ '{{#fornumargs: keyVarName | valVarName | code }}' (which still works as well).
 17+ - Language file clean-up.
 18+ - Internal structure changed, ExtLoops now works as a static class.
 19+
 20+ * November 15, 2011 -- Version 0.3.2 by Daniel Werner
 21+ - Bug solved where '#loop' didn't create variables with name or starting index '0'.
 22+ - minor '#forargs' and '#fornumargs' bug solved where unnamed numeric argument values
 23+ could have ended up as variable value with leading space.
 24+ - 'README' and 'RELEASE-NOTES' files added.
 25+ - Put into mediawiki.org svn repository.
 26+
 27+
 28+ Pre svn Changelog:
 29+ ==================
 30+
 31+ The following pre-svn changelog was composed after the extension has been moved into mediawiki.org
 32+ svn. All changes can still be retrace at:
 33+
 34+ http://www.mediawiki.org/w/index.php?title=Extension:Loops&action=history
 35+
 36+ * Version 0.3.0 by David M. Sledge
 37+ - '#loop' and '#fornumargs' parser functions were introduced.
 38+ - '#foreachnamedarg' renamed to '#forargs' and loops through indexed template arguments as well
 39+ as named arguments now.
 40+
 41+ * Version 0.2.0 by David M. Sledge
 42+ - '#foreachnamedarg' parser function introduced. Allows to loop through named template arguments.
 43+
 44+ * Version 0.1.0 (initial release) by David M. Sledge
Property changes on: tags/extensions/Loops/REL_0_4/RELEASE-NOTES
___________________________________________________________________
Added: svn:eol-style
145 + native
Index: tags/extensions/Loops/REL_0_4/README
@@ -0,0 +1,24 @@
 2+== About ==
 3+
 4+The 'Loops' extension Enhances the parser with parser functions to perform loops.
 5+It is not compatible with MediaWiki versions below 1.12.
 6+
 7+* Website: http://www.mediawiki.org/wiki/Extension:Loops
 8+* Authors: David M. Sledge, Daniel Werner < danweetz@web.de >
 9+* License: GNU GPL v2 or higher
 10+
 11+
 12+== Installation ==
 13+
 14+Once you have downloaded the code, place the 'Loops' directory within your
 15+MediaWiki 'extensions' directory. Then add the following code to your
 16+[[Manual:LocalSettings.php|LocalSettings.php]] file:
 17+
 18+ # Loops
 19+ require_once( "$IP/extensions/Loops/Loops.php" );
 20+
 21+
 22+== Contributing ==
 23+
 24+If you have bug reports or feature requests, please add them to the 'Loops'
 25+Talk page http://www.mediawiki.org/w/index.php?title=Extension_talk:Loops
Property changes on: tags/extensions/Loops/REL_0_4/README
___________________________________________________________________
Added: svn:eol-style
126 + native

Status & tagging log