Wikipedia:WikiProjekt Vorlagen/MediaWiki-Features
Die MediaWiki-Software entwickelt sich ständig weiter und wird dabei immer besser und technisch trickreicher. Jüngste, großartige Erneuerung, ist die Möglichkeit der Vorlagenprogrammierung. Hier sollen neue Features erdacht, ersonnen, diskutiert, ... werden, die die Vorlagenprogrammierung noch effizienter gestalten können.
Daher mein Aufruf an alle die das hier lesen: Besorgt euch MediaZilla-Accounts und votet für die Bugs! |
for
BearbeitenIch habe neulich einen Bug gefiled der direkt mit einem Patch daherkam. Dieser führt eine neue Funktion {{#for:}}
ein. Bisher scheint der Bug keine große Beachtung gefunden zu haben, insbesondere steht die Frage nach der verlangten Rechenkapazität zur Diskussion. Ich habe daher auch Vorschläge gepostet, wie man diese einschränken kann.
Anbei kopiere ich die Beschreibung des Patch und den Quelltext:
Bug #6794: ParserFunction: {{#for: }}
Der Bug
BearbeitenThe syntax is {{#for: loopcount | text to loop | join-character | initial value | step size }} each parameter can be ommited, but ommiting the first 2 ones won't make any sense. Examples: <wikitext>List of some Years: {{subst:#for: 9 | * [[19$i]] | $n | 10 | 10}}</wikitext> will be <wikitext>* [[1910]] * [[1920]] * [[1930]] * [[1940]] * [[1950]] * [[1960]] * [[1970]] * [[1980]] * [[1990]]</wikitext> $n is a magic string in join-string cause it is not possible to insert a normal new line there. simpler example: Let'c count: {{#for 9 | $i!}} You can also go backwards: {{#for: 9 | Value: $i | $b | 0 | -1}} ($b is another magic thing for >>|<< (vertical bar)) Countdown: {{#for: 10 | $i, || 10 | -1}} '''Lift off!'''
Der Patch
BearbeitenDies ist die neue ParserFunctions.php (latest snapshots: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/ParserFunctions/ http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/ParserFunctions/ParserFunctions.php)
<?php if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, it is not a valid entry point' ); } $wgExtensionFunctions[] = 'wfSetupParserFunctions'; $wgExtensionCredits['parserhook'][] = array( 'name' => 'ParserFunctions', 'url' => 'http://meta.wikimedia.org/wiki/ParserFunctions', 'author' => 'Tim Starling' ); $wgHooks['LanguageGetMagic'][] = 'wfParserFunctionsLanguageGetMagic'; class ExtParserFunctions { var $mExprParser; function &getExprParser() { if ( !isset( $this->mExpr ) ) { if ( !class_exists( 'ExprParser' ) ) { require( dirname( __FILE__ ) . '/Expr.php' ); ExprParser::addMessages(); } $this->mExprParser = new ExprParser; } return $this->mExprParser; } function expr( &$parser, $expr = '' ) { $exprParser =& $this->getExprParser(); $result = $exprParser->doExpression( $expr ); if ( $result === false ) { return $exprParser->lastErrorMessage; } else { return $result; } } function ifexpr( &$parser, $expr = '', $then = '', $else = '' ) { $exprParser =& $this->getExprParser(); $result = $exprParser->doExpression( $expr ); if ( $result === false ) { return $exprParser->lastErrorMessage; } elseif ( $result ) { return $then; } else { return $else; } } function ifHook( &$parser, $test = '', $then = '', $else = '' ) { if ( $test !== '' ) { return $then; } else { return $else; } } function ifeq( &$parser, $left = '', $right = '', $then = '', $else = '' ) { if ( $left == $right ) { return $then; } else { return $else; } } function switchHook( &$parser /*,...*/ ) { $args = func_get_args(); array_shift( $args ); $value = trim(array_shift($args)); $found = false; $parts = null; $default = null; foreach( $args as $arg ) { $parts = array_map( 'trim', explode( '=', $arg, 2 ) ); if ( count( $parts ) == 2 ) { if ( $found || $parts[0] == $value ) { return $parts[1]; } else { $mwDefault =& MagicWord::get( 'default' ); if ( $mwDefault->matchStartAndRemove( $parts[0] ) ) { $default = $parts[1]; } # else wrong case, continue } } elseif ( count( $parts ) == 1 ) { # Multiple input, single output # If the value matches, set a flag and continue if ( $parts[0] == $value ) { $found = true; } } # else RAM corruption due to cosmic ray? } # Default case # Check if the last item had no = sign, thus specifying the default case if ( count( $parts ) == 1) { return $parts[0]; } elseif ( !is_null( $default ) ) { return $default; } else { return ''; } } function ifexist( &$parser, $title = '', $then = '', $else = '' ) { $title = Title::newFromText( $title ); return is_object( $title ) && $title->exists() ? $then : $else; } /** * @author <Warhog aka Julian Fleischer (mediazilla@warhog.net)> * @date 2006-07-23 16:57 */ function forHook( &$parser, $loopcount = 0, $text = '', $joinby = '', $init = 1, $step = 1 ) { // when there is no text to loop the whole loop is useless if (strlen($text) < 1) { return ''; // no error needs to be printed, it's simply nothing } // convert arguments to integers so what we don't have to worry about texts etc $loopcount = (int) $loopcount; $init = (int) $init; $step = (int) $step; // Check for the sense of the given parameters if ($loopcount < 1) { // a loop which will not be looped is senseless return ''; // maybe print an error-message here? } if ($step == 0) { // a loop that does not progress is also senseless return ''; // maybe print an error-message here? } // if the function has not exited due to senseless parameters yet // then do the action here // calculate the min/max value for $i according to loopcount $max = $init + $loopcount * $step; $rows = array(); // does the loop count upwards or downwards? if ($step > 0) { // the loop counts upwards, so we have an upper limit for ($i = $init; $i < $max; $i = $i + $step) { // replace '$i' with $i so that we can access the iterator and the loop makes sense $rows[] = str_replace('$i', "$i", $text); } } else { // the loop counts downwards, so we have a lower limit for ($i = $init; $i > $max; $i = $i + $step) { // same thing here $rows[] = str_replace('$i', "$i", $text); } } // prepare glue string $joinby = (string) $joinby; // do some magic: new line, this is regarded as whitespace by the parser // so we would not have a chance to add new-lines via parameters // important for e.g. {{for: 3 | * List Item $i | $n }} $joinby = str_replace('$n', "\n", $joinby); $joinby = str_replace('$b', "|", $joinby); // return the generated rows joint by the glue-string $joinby return join($joinby, $rows); } } function wfSetupParserFunctions() { global $wgParser, $wgMessageCache, $wgExtParserFunctions; $wgExtParserFunctions = new ExtParserFunctions; $wgParser->setFunctionHook( 'expr', array( &$wgExtParserFunctions, 'expr' ) ); $wgParser->setFunctionHook( 'if', array( &$wgExtParserFunctions, 'ifHook' ) ); $wgParser->setFunctionHook( 'ifeq', array( &$wgExtParserFunctions, 'ifeq' ) ); $wgParser->setFunctionHook( 'ifexpr', array( &$wgExtParserFunctions, 'ifexpr' ) ); $wgParser->setFunctionHook( 'switch', array( &$wgExtParserFunctions, 'switchHook' ) ); $wgParser->setFunctionHook( 'ifexist', array( &$wgExtParserFunctions, 'ifexist' ) ); $wgParser->setFunctionHook( 'for', array( &$wgExtParserFunctions, 'forHook' ) ); } function wfParserFunctionsLanguageGetMagic( &$magicWords, $langCode ) { switch ( $langCode ) { case 'he': $magicWords['expr'] = array( 0, '×ש×', 'expr' ); $magicWords['if'] = array( 0, '×ª× ××', 'if' ); $magicWords['ifeq'] = array( 0, 'ש×××', 'ifeq' ); $magicWords['ifexpr'] = array( 0, '××©× ×ª× ××', 'ifexpr' ); $magicWords['switch'] = array( 0, '××ר', 'switch' ); $magicWords['default'] = array( 0, '#×ר×רת ××××', '#default' ); $magicWords['ifexist'] = array( 0, 'ק×××', 'ifexist' ); $magicWords['for'] = array( 0, '-tobedone-', 'for' ); // DONT KNOW ABOUT HEBREW !? break; default: $magicWords['expr'] = array( 0, 'expr' ); $magicWords['if'] = array( 0, 'if' ); $magicWords['ifeq'] = array( 0, 'ifeq' ); $magicWords['ifexpr'] = array( 0, 'ifexpr' ); $magicWords['switch'] = array( 0, 'switch' ); $magicWords['default'] = array( 0, '#default' ); $magicWords['ifexist'] = array( 0, 'ifexist' ); $magicWords['for'] = array( 0, 'for' ); } return true; } ?>
Bekannte Fehler / Konzeptschwächen
Bearbeiten- Ich möchte gar nicht wissen was passiert wenn man {{#for:}}-Schleifen schachtelt.
- Die Schleifen könnten von Vandalen bösartig ausgenutzt werden (obgleich ich bezweifle dass diese entsprechend tief sich in die Materie hineinlesen)
Eure Meinungen dazu
BearbeitenIch mache damit mal den Anfang: Ich fände eine solche Vorlage, und wenn es nur für subst:-Zwecke wäre, enorm praktisch. Da es im Normalfall keine Listen gibt die man erstellen müsste die über 100 Einträge lang sind gäbe es auch keine "unglaubliche Serverbelastung". Die Babel-X Vorlage ist mit 100 If-Abfragen da schon fast rechenintensiver. (Meine Meinung - aber ich bin als Autor des Patch wohl wenig objektiv ;-D )--Warhog (???, +/-) 04:19, 25. Jul 2006 (CEST)
- Ich verstehe nicht ganz, soll diese Funktion denn schon implementiert sein? Ein
#for:
kann ich nämlich nicht verwenden. - Prizipiell ist die Idee jedoch gut, da diese Funktionalität notwendig ist. Einen Iterator habe ich bereits auf rekursive Weise implementiert. Die Anwendung ist jedoch leider umständlich. Ein fertig implementierter Iterator wie dieses "for-statement" ist daher in jedem Falle vorzuziehen. Die Bedenken die Du aufgeführt hast teile ich jedoch. Gruß, -- zOiDberg (Δ | Α & Ω) 13:33, 14. Sep 2006 (CEST)
ROOTPAGENAME
BearbeitenSiehe Wikipedia:WikiProjekt_Vorlagen/Projekt:Optimierung_durch_Programmierung#Vorlage:Archiv.
Bug 6747: Feature-Request: Introduce a new Variable {{ROOTPAGENAME}} (similar to {{BASEPAGENAME}}
Strings
BearbeitenWir benötigen dringend den Einbau dieser Stringfunktionen derart, dass man damit Vorlagen programmieren kann. Augiasstallputzer 10:37, 2. Aug 2006 (CEST)
- Tut diese Seite überhaupt noch? Würde StringFunctions auch sehr begrüßen, da #expr in Vorlage:nts grad dabei ist, einige Listen grauslich zu verunstalten und sich das wohl damit lösen ließe. --Cointel 16:03, 22. Mai 2008 (CEST)