Handboek:Parserfuncties
Een parserfunctie, toegevoegd in MediaWiki 1.7, is een soort extensie die nauw integreert met de parser. De uitdrukking "parserfunctie" moet niet worden verward met Extension:ParserFunctions , wat een verzameling eenvoudige parserfuncties is. (Zie voor die Help extension ParserFunctions .)
Beschrijving
Terwijl van een tag extensie wordt verwacht dat die onbewerkte tekst neemt en HTML terugstuurt naar de browser, kan een parserfunctie 'samenwerken' met andere wiki-elementen op de pagina. De uitvoer van een parserfunctie kan bijvoorbeeld worden gebruikt als een sjabloon-parameter of bij de constructie van een link.
De typische syntaxis voor een parserfunctie is:
{{ #functionname: param1 | param2 | param3 }}
Zie de documentatie voor meer informatie voor Parser::setFunctionHook ( $id, $callback, $flags = 0 )
. In deze documentatie staat:
- De functie callback moet de vorm hebben:
function myParserFunction( $parser, $arg1, $arg2, $arg3 ) { ... }
- Of met
SFH_OBJECT_ARGS
:function myParserFunction( $parser, $frame, $args ) { ... }
De eerste variant van de aanroep geeft alle argumenten door als gewone tekst.
De tweede geeft alle argumenten door als een array van PPNode s, behalve de eerste ($args[0]
), die nu tekst is, hoewel dit in de toekomst kan veranderen.
Deze vertegenwoordigen de niet uitgebreide wikitext.
De parameter $frame
kan worden gebruikt om deze argumenten naar behoefte te vergroten.
Dit wordt vaak gebruikt voor voorwaardelijke verwerking zodat alleen het geval true
wordt geëvalueerd met een if-
of switch-like
parserfunctie.
Het frame-object kan ook de documentboom doornemen om informatie over de caller te krijgen en heeft functies om de call depth, time-to-live, en of het resultaat van de parserfunctie vluchtig is te bepalen en te beheren.
Het maken van een parserfunctie is iets ingewikkelder dan het maken van een nieuwe tag, omdat de functienaam een magisch woord moet zijn, een trefwoord dat aliassen en lokalisatie ondersteunt.
Eenvoudig voorbeeld
Hieronder is een voorbeeld van een extensie die een parserfunctie creëert.
De registratie gaat respectievelijk in extension.json en de code in src/ExampleExtensionHooks.php:
Standard: | Using the HookHandler interface: |
---|---|
extension.json | |
{
"name": "ExampleExtension",
"author": "Me",
"version": "1.0.0",
"url": "https://www.mediawiki.org/wiki/Extension:ExampleExtension",
"descriptionmsg": "exampleextension-desc",
"license-name": "GPL-2.0-or-later",
"type": "parserhook",
"MessagesDirs": {
"ExampleExtension": [
"i18n"
]
},
"AutoloadClasses": {
"ExampleExtensionHooks": "src/ExampleExtensionHooks.php"
},
"ExtensionMessagesFiles": {
"ExampleExtensionMagic": "ExampleExtension.i18n.php"
},
"Hooks": {
"ParserFirstCallInit": "ExampleExtensionHooks::onParserFirstCallInit"
},
"manifest_version": 1
}
|
{
"name": "ExampleExtension",
"author": "Me",
"version": "1.0.0",
"url": "https://www.mediawiki.org/wiki/Extension:ExampleExtension",
"descriptionmsg": "exampleextension-desc",
"license-name": "GPL-2.0-or-later",
"type": "parserhook",
"MessagesDirs": {
"ExampleExtension": [
"i18n"
]
},
"AutoloadClasses": {
"ExampleExtensionHooks": "src/ExampleExtensionHooks.php"
},
"ExtensionMessagesFiles": {
"ExampleExtensionMagic": "ExampleExtension.i18n.php"
},
"Hooks": {
"ParserFirstCallInit": "onParserFirstCallInit"
},
"HookHandlers": {
"ExampleExtensionHooks": {
"class": "MediaWiki\\Extension\\ExampleExtension\\Hooks"
}
},
"manifest_version": 1
}
|
ExampleExtensionHooks.php | |
<?php
class ExampleExtensionHooks {
// Registreer alle callbacks met de parser
public static function onParserFirstCallInit( Parser $parser ) {
// Maak een functie hook die het magische woord <code>example</code> associeert met renderExample()
$parser->setFunctionHook( 'example', [ self::class, 'renderExample' ] );
}
// De uitvoer van {{#example:}} opbouwen.
public static function renderExample( Parser $parser, $param1 = '', $param2 = '', $param3 = '' ) {
// De invoerparameters zijn wikitext met uitgebreide sjablonen.
// De uitvoer moet ook wikitext zijn.
$output = "param1 is $param1 and param2 is $param2 and param3 is $param3";
return $output;
}
}
|
<?php
class ExampleExtensionHooks implements ParserFirstCallInitHook {
// Register any render callbacks with the parser
public function onParserFirstCallInit( $parser ) {
// Create a function hook associating the <code>example</code> magic word with renderExample()
$parser->setFunctionHook( 'example', [ $this, 'renderExample' ] );
}
// Render the output of {{#example:}}.
public function renderExample( $parser, $param1 = '', $param2 = '', $param3 = '' ) {
// The input parameters are wikitext with templates expanded.
// The output should be wikitext too.
$output = "param1 is $param1 and param2 is $param2 and param3 is $param3";
return $output;
}
}
|
Een ander bestand, ExampleExtension.i18n.php, in uw map extension (Niet in de submap src/) moet bevatten:
<?php
/**
* @license GPL-2.0-or-later
* @author Uw naam (YourUserName)
*/
$magicWords = [];
/** English
* @author Uw naam (YourUserName)
*/
$magicWords['en'] = [
'example' => [ 0, 'example' ],
];
Met deze extension ingeschakeld,
- {{#example: hello | hi | hey}}
resultaat:
- param1 is hello en param2 is hi en param3 is hey
LocalSettings.php
MediaWiki\MediaWikiServices::getInstance()->getContentLanguage()->mMagicExtensions['wikicodeToHtml'] = ['MAG_CUSTOM', 'custom'];
Binnen LocalSettings.php
Magische woorden en hun parserfuncties voor afhandeling kunnen volledig worden gedefinieerd in LocalSettings.php.
$wgHooks['ParserFirstCallInit'][] = function ( Parser $parser )
{
MediaWiki\MediaWikiServices::getInstance()->getContentLanguage()->mMagicExtensions['wikicodeToHtml'] = ['wikicodeToHtml', 'wikicodeToHtml'];
$parser->setFunctionHook( 'wikicodeToHtml', 'wikicodeToHtml' );
};
function wikicodeToHtml( Parser $parser, $code = '' )
{
$title = $parser->getTitle();
$options = $parser->Options();
$options->enableLimitReport(false);
$parser = $parser->getFreshParser();
return [$parser->parse($code, $title, $options)->getText(), 'isHTML' => true];
}
Langere functies
Voor langere functies, kunt u de hook functies opdelen naar een _body.php of .hooks.php bestand en ze statische functies van een class maken. Dan kunt u de class laden met $wgAutoloadClasses en de statische functies in de hooks aanroepen; bijvoorbeeld:
Zet dit in uw extension.json
bestand:
"Hooks": {
"ParserFirstCallInit": "ExampleExtensionHooks::onParserFirstCallInit"
},
"AutoloadClasses": {
"ExampleExtensionHooks": "src/ExampleExtensionHooks.php"
}
- Zie: een event-handler schrijven voor andere stijlen.
Zet dan dit in uw src/ExampleExtensionHooks.php
bestand:
class ExampleExtensionHooks {
public static function onParserFirstCallInit( Parser $parser ) {
$parser->setFunctionHook( 'example', [ self::class, 'renderExample' ] );
}
}
Parser interface
Het parsen van de uitvoer controleren
Om de wikitext die door uw parserfunctie wordt teruggestuurd volledig te laten analyseren (inclusief extensie van sjablonen), stel de optie noparse
op false
bij het retourneren:
return [ $output, 'noparse' => false ];
Het lijkt erop dat de standaardwaarde voor noparse
veranderde van false
naar true
, in sommige situaties, ergens rond versie 1.12.
Omgekeerd, om uw parserfunctie HTML terug te laten geven die niet is verwerkt, in plaats van wikitext, gebruik dit:
return [ $output, 'noparse' => true, 'isHTML' => true ];
Naamgeving
Standaard voegt MediaWiki een hash-teken (nummerteken, #
) toe aan de naam van elke parserfunctie.
Als u die toevoeging wilt onderdrukken (en een parserfunctie zonder voorvoegsel #
wilt verkrijgen), neemt u de constante SFH_NO_HASH op in het argument flags voor setFunctionHook, zoals hieronder beschreven.
Bij het kiezen van een naam zonder een hashprefix, is het niet langer mogelijk om een pagina met een naam die begint met die functienaam gevolgd door een dubbele punt te transcluderen. Vermijd met name functienamen die gelijk zijn aan een namespace. In het geval dat interwiki transclusion [1] is ingeschakeld, vermijdt u ook functienamen die gelijk zijn aan een interwiki prefix.
De hook setFunctionHook
Voor meer informatie over de interface in de parser, zie de documentatie over setFunctionHook in includes/Parser.php. Hier is een (mogelijk gedateerde) kopie van die opmerkingen:
functie setFunctionHook( $id, $callback, $flags = 0 )
Parameters:
- string $id - Het magische woord ID
- mixed $callback - De te gebruiken functie met object (na de aanroep, callback)
- integer $flags - Optioneel. Waarden:
- SFH_NO_HASH (1) constante, als de functie wordt aangeroepen zonder de
#
. - SFH_OBJECT_ARGS (2) als u een PPFrame-object en array van argumenten doorgeeft in plaats van een reeks functieargumenten, [#Description|zie daarvoor hierboven]].
- De standaard is 0 (geen flags).
- SFH_NO_HASH (1) constante, als de functie wordt aangeroepen zonder de
Returnwaarde: De eventuele oude callback functie voor deze naam
Een functie maken, bijvoorbeeld {{#sum:1|2|3}}
. De callback-functie moet de volgende vorm hebben:
function myParserFunction( $parser, $arg1, $arg2, $arg3 ) { ... }
Het resultaat kan het tekstresultaat van de functie zijn of een matrix met de tekst in element 0 en een aantal flags in de andere elementen. De namen van de flags staan in de keys. Geldige flags zijn:
Naam | Type | Standaard | Beschrijving |
---|---|---|---|
found | Boolean | true
|
true als de teruggegeven tekst geldig is en het verwerken van het sjabloon moet worden gestopt.
|
text | ? | ? | De tekst om terug te geven door de functie. Als isChildObj of isLocalObj worden gespecificeerd, moet dit in plaats daarvan een DOM-node zijn. |
noparse | Boolean | true
|
true als tekst niet vooraf moet worden verwerkt naar een DOM-tree, bijvoorbeeld als onveilige HTML-tags niet moeten worden verwijderd, enz.
|
isHTML | Boolean | ? | true als de teruggegeven tekst HTML is en moet worden beschermd tegen wikitext-transformatie. Maar bekijk de discussie
|
nowiki | Boolean | meestal false
|
true als de wiki-opmaak in de returnwaarde (tekst) moet worden beschermd (escaped).
|
isChildObj | Boolean | ? | true als de tekst een DOM-node is die uitbreiding nodig heeft in een subframe.
|
isLocalObj | Boolean | ? | true als de tekst een DOM-node is die uitbreiding nodig heeft in het huidige frame. De standaardwaarde is afhankelijk van andere waarden en resultaten.
|
preprocessFlags | ? | false
|
Optionele flags PPFrame om te gebruiken bij het analyseren van de ontvangen tekst. Dit geldt alleen als noparse false is.
|
title | ? | false
|
Het object Title waar de tekst vandaan kwam. |
forceRawInterwiki | Boolean | ? | true als de transclusion tussen wiki's in de raw-modus moet worden uitgevoerd en er geen opbouw nodig is.
|
Dure parserfuncties
Sommige parserfuncties zorgen voor een significant gebruik van de middelen van een wiki en moeten als "duur" worden gezien. Het aantal dure parserfuncties op een bepaalde pagina wordt beperkt door de instelling $wgExpensiveParserFunctionLimit . Wat als duur telt, wordt overgelaten aan de functie zelf, maar meestal moet alles worden overwogen dat waarschijnlijk een vertraging veroorzaakt die verder gaat dan een eenvoudige verwerking van gegevens. Dit omvat zaken als een database lezen / schrijven, een shellscript synchroon lanceren of bestandsmanipulatie. Aan de andere kant moeten niet al zulke functies noodzakelijkerwijs worden getagged. Semantische MediaWiki, bijvoorbeeld, geeft slechts een percentage van de database leesopdrachten als duur aan. Dit komt doordat op bepaalde data-intensive pagina's het gemakkelijk de normale limiet voor dure parserfuncties overschrijdt. In gevallen als deze is het potentieel voor een merkbaar langzamere prestaties die niet als duur worden gemarkeerd, een compromis met het hebben van de functionaliteit die Semantische MediaWiki biedt.
Om uw parserfunctie te markeren als duur, vanuit de code van de functie, gebruik $result = $parser->incrementExpensiveFunctionCount();
.
De returnwaarde zal false
zijn als de limiet voor dure functies is bereikt of is overschreden.
Parameters met een naam
Parserfuncties ondersteunen benoemde parameters niet zoals sjablonen en tag-extensies dat doen, maar het is af en toe handig om ze te vervalsen. Gebruikers zijn vaak gewend om verticale balken ( |
) te gebruiken om argumenten van elkaar te scheiden, dus het is fijn om dat ook te kunnen doen in de context van de parserfunctie. Hier is een eenvoudig voorbeeld van hoe u dit kunt bereiken:
function ExampleExtensionRenderParserFunction( &$parser ) {
// Stel dat de gebruiker de parserfunctie als volgt heeft aangeroepen:
// {{#myparserfunction: foo=bar | apple=orange | banana }}
$options = extractOptions( array_slice( func_get_args(), 1 ) );
// Nu heeft u een array dat er als volgt uitziet:
// [foo] => 'bar'
// [apple] => 'orange'
// [banana] => true
// Doorgaan met het schrijven van code...
}
/**
* Converteert een array met waarden in vorm [0] => "name=value"
* in een associatief array in vorm [name] => waarde
* Als er geen = wordt opgegeven, wordt waar als volgt verondersteld: [naam] => true
*
* @param array string $options
* @return array $results
*/
function extractOptions( array $options ) {
$results = [];
foreach ( $options as $option ) {
$pair = array_map( 'trim', explode( '=', $option, 2 ) );
if ( count( $pair ) === 2 ) {
$results[ $pair[0] ] = $pair[1];
}
if ( count( $pair ) === 1 ) {
$results[ $pair[0] ] = true;
}
}
return $results;
}
Zie ook
Algemene en gerelateerde gidsen:
- Handleiding: Extensies ontwikkelen , of voor meer algemene informatie over extensies, zie Handleiding:Extensies en Extensions FAQ .
- Manual:Tag extensions
- Handleiding:Magische woorden
Code:
- Handboek:Parser.php
- Manual:Hooks/ParserFirstCallInit
- Parser function hooks - een (onvolledige) lijst van parserfuncties die worden aangeboden door core en extensies
- De Parser Hooks PHP-bibliotheek, die een objectgerichte interface biedt voor declaratieve parser hooks
- Manual:Extension data
Voorbeelden:
- De extensie ParserFunctions is een bekende verzameling van parserfuncties.
- Help extension ParserFunctions