Extensions utiles
Native
Additional
To test
Création
Les dossiers et fichiers relatifs aux extensions doivent être placés dans /extensions.
extension.json
|
{
"@comment": "Tout ce qui commence par @ sera ignoré",
"name": "My Extension",
"version": "1.0",
"author": "Moi",
"license-name": "CC-BY-NC-SA-4.0",
"url": "https://www.mediawiki.org/wiki/Extension:MyExtension",
"description": "My message",
"type": "parserhook",
"require": {
"MediaWiki": ">= 1.27"
},
"Hooks": {
"ParserFirstCallInit": [
"MyExtensionClass::onParserFirstCallInit"
],
"BeforePageDisplay": [
"MyExtensionClass::onBeforePageDisplay"
]
},
"AutoloadClasses": {
"MyExtensionClass": "MyExtension.class.php"
},
"config": {
"configElement1": "valeur",
"configElement2": false
},
"manifest_version": 1
}
|
- name: nom affiché dans Spécial:Version
- license-name
- type : api, antispam, datavalues, media, parserhook, semantic, skin, specialpage, variable, other
- manifest_version: version du schema d'extension.json, seule la version 1 est supportée
MyExtension.class.php
MyExtension.class.php
|
<?php
class MyExtensionClass {
public static function onParserFirstCallInit( Parser &$parser ) {
global $configElement1, $configElement2;
if ( $configElement2 === false ) { /* ... */ }
return true;
}
public static function onBeforePageDisplay(OutputPage &$out, Skin &$skin) {
$out->addModules('...');
return true;
}
}
|
MyExtension.php
|
Fichier de compatibilité utilisé seulement si l'extension est chargée avec require_once "$IP/extensions/MyExtension/MyExtension.php"; |
MyExtension.php
|
<?php
if ( function_exists( 'wfLoadExtension' ) ) {
wfLoadExtension( 'MyExtension' );
// Keep i18n globals so mergeMessageFileList.php doesn't break
$wgMessagesDirs['MyExtension'] = __DIR__ . '/i18n';
return true;
} else {
die( 'This version of the MyExtension extension requires MediaWiki 1.25+' );
}
|
Ancienne méthode
MyExtension.php
|
<?php
// Check environment
if ( !defined( 'MEDIAWIKI' ) ) {
echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" );
die( -1 );
}
/*
code de l'extension
*/
// pas de fermeture de la balise php
|
Chargement de l'extension
LocalSettings.php
|
wfLoadExtension( 'MonExtension' );
# charge le fichier extensions/MonExtension/extension.json
|
ResourceLoader Features
extension.json
|
"ResourceModules": {
"ext.MyExtension": {
"scripts": [
"dossier/script.js",
"script.js"
],
"styles": "styles/style1.css"
}
},
"ResourceFileModulePaths": {
"localBasePath": "",
"remoteExtPath": "MyExtension",
"remoteSkinPath": "MyExtension"
},
|
- localBasePath: Important. Base path to prepend to all local paths, relative to current directory
- remoteExtPath: Optionnel. Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath ($wgScriptPath/extensions)
- remoteSkinPath: Optionnel. Base path to prepend to all remote paths, relative to $wgStylePath ($wgScriptPath/skins)
MyExtension.class.php
|
public static function onBeforePageDisplay(OutputPage &$out, Skin &$skin) {
$out->addModuleStyles( 'ext.MyExtension' );
// if the resource only contains style
$out->addModuleStyles( 'ext.MyExtension' );
return true;
}
|
Si des erreurs du type Fatal exception of type MWException apparaissent dans la Browser Console de Firefox,
forcer l'affichage du détail des erreurs dans MediaWiki:
LocalSettings.php
|
$wgShowExceptionDetails = true;
|
Cela peut être du à :
- des mauvais chemins
- des problèmes de droits en lecture
|
Built-in special pages are located in the includes/specials directory.
Source code: includes/specialpage/SpecialPage.php |
MySpecialPage/extension.json
|
{
"name": "MySpecialPage",
"version": "1.0",
"author": "Me",
"url": "https://www.mediawiki.org/wiki/Extension:MySpecialPage",
"descriptionmsg": "myspecialpage-desc",
"description": "My Special Page description.",
"license-name": "AGPL-3.0",
"type": "specialpage",
"SpecialPages": {
// key (MySpecialPage) has to match the name passed in the ctor
// value has to match the autoloaded class name
"MySpecialPage": "SpecialMySpecialPage"
},
"AutoloadClasses": {
// key (SpecialMySpecialPage) has to match the class name in the SpecialMySpecialPage.php file and the SpecialPages value above
"SpecialMySpecialPage": "SpecialMySpecialPage.php"
},
"MessagesDirs": {
// any key seems to work
// key (MySpecialPage) has to match the name passed in the ctor
"MySpecialPage": "i18n"
},
"ExtensionMessagesFiles": {
"MySpecialPageAlias": "MySpecialPage.alias.php"
},
"manifest_version": 2
|
MySpecialPage/src/Special.php
|
<?php
class SpecialMySpecialPage extends SpecialPage { // UnlistedSpecialPage, IncludableSpecialPage
public function __construct() {
// parent ctor parameters: $name = '', $restriction = '', $listed = true, $function = false, $file = '', $includable = false
parent::__construct( 'MySpecialPage' );
}
public function execute( $par ) {
$this->setHeaders();
$output = $this->getOutput();
# Get request data from, e.g.
$request = $this->getRequest();
$param = $request->getText( 'param' );
$output->addWikiTextAsInterface( '= Titre =' );
$output->addHTML( "<div>" );
|
MySpecialPage/i18n/fr.json
|
{
// doesn't seem to be used
"@metadata": {
"authors": "Me"
},
// key has to match the SpecialPages key
// value would be the page title
"myspecialpage": "Ma page spéciale",
"myspecialpage-desc": "Description de ma page spéciale.",
"myspecialpage-summary": "Sommaire de ma page spéciale."
|
|
// localize url
<?php
$specialPageAliases = [];
$specialPageAliases['en'] = [
'MySpecialPage' => [ 'MySpecialPage' ],
];
$specialPageAliases['fr'] = [
'MySpecialPage' => [ 'MaPageSpéciale' ],
];
|
LocalSettings.php
|
// has to match the folder name: extensions/MySpecialPage
wfLoadExtension( 'MySpecialPage' );
|
Parser un string Mediawiki
|
$output = $parser->recursiveTagParse("=Titre=", $frame );
// <h1>Titre</h1>
|
Créer des nouvelles balises
|
$wgHooks['ParserFirstCallInit'][] = 'newTags';
function newTags( Parser $parser ) {
$parser->setHook( 'nouvelleBalise', 'renduPourLaNouvelleBalise' );
return true;
}
function renduPourLaNouvelleBalise( $input, array $args, Parser $parser, PPFrame $frame ) {
$nb = 5;
if (array_key_exists('nb', $args) && is_numeric ($args['nb']) && $args['nb'] > 0) {
$nb = $args['nb'];
}
return '<strong>' . htmlspecialchars( $input ) . '</strong>';
}
|
<nouvelleBalise nb=5 />
Tag extensions
|
$res = $dbr->newSelectQueryBuilder()
->select( [ 'page_namespace', 'page_title', 'rev_timestamp' ] )
->from( 'page' )
->join( 'revision', null, [ 'page_latest = rev_id' ] )
->where( 'page_is_redirect = 0' )
->andWhere( 'page_namespace = 0' )
->orderBy( 'rev_timestamp', SelectQueryBuilder::SORT_DESC )
->limit( 12 )
->caller( __METHOD__ )
->fetchResultSet();
foreach($res as $row)
{}
// count
$res = $dbr->newSelectQueryBuilder()
->select( [ 'count(*)' ] )
->from( 'page' )
->leftJoin( 'categorylinks', null, [ 'cl_from = page_id' ] )
->where( 'cl_from is NULL' )
->andWhere( 'page_is_redirect = 0' )
->andWhere( 'page_namespace = 0' )
->caller( __METHOD__ )
->fetchResultSet();
$nb = $res->fetchRow()[0];
|
|
$querySQL = <<<EOD
select count(*)
from page
left join categorylinks
on cl_from = page_id
where cl_from is NULL
and page_is_redirect = 0
and page_namespace = 0
EOD;
$res = $dbr->query( $querySQL );
|
Formation du code HTML
|
// <p class="myclass">
Html::openElement('p', ['class' => 'myclass']);
// </p>
Html::closeElement('p');
// <p class="myclass">content</p>
Html::element('p', ['class' => 'myclass'], 'content' );
|
User
|
// in special page
if ( $this->getUser()->isAnon() ) {
$this->simpleCategoriesBlock();
}
|
|
function wfSomeHookFunction( $parser, $foo, $bar ) {
$parser->disableCache();
}
|
timestamp UTC → date locale
|
$timestamp = ... // timestamp UTC récupéré dans la BdD : 20120530111700
// récupération du context, utile pour connaitre la langue et l'utilisateur
$context = RequestContext::getMain();
// convertion du timestamp de la base de donnée vers le timestamp Mediawiki
$timestamp = wfTimestamp( TS_MW, $row->rev_timestamp );
// utilisation des préférences de l'utilisateur pour la conversion du timestamp en date
$date = $context->getLanguage()->userTimeAndDate( $timestamp, $context->getUser() );
// 30 mai 2012 à 13:17
|
Manipulation autour de timestamp et de date:
|
// convertion du timestamp Mediawiki en timestamp UNIX
$unixTimestamp = wfTimestamp( TS_UNIX, $timestamp); // 1338376620
// date en anglais
date("l j F Y - H:i", $unixTimestamp); // Wednesday 30 May 2012 - 13:17
// date suivant la locale
strftime("%A %e %B %G - %H:%M", $unixTimestamp);
// conversion en heure GMT + ajout du décalage du fuseau horaire
$offset = date("Z"); // 7200
gmstrftime("%A %e %B %G - %H:%M", $unixTimestamp + $offset);
|
wfTimestamp
date
strftime
Crédits
[1]
Hook
[2]
AJAX
|
## Abort if AJAX is not enabled
if ( !$wgUseAjax ) {
trigger_error( 'Please enable AJAX : «$wgUseAjax = true;» in LocalSettings.php', E_USER_WARNING );
return;
}
|
Page de l'extension sur mediawiki.org
Exemples
Compter le nombre de pages sans catégories
|
// jointure de categorylinks dans page avec cl_from = page_id
// résultat: cl_from IS NULL pour les pages sans catégories
// seulement les articles: page_namespace = 0
// pas les redirection: page_is_redirect = 0
$query = "select page_namespace, page_title, cl_from
from page left outer join categorylinks
on cl_from = page_id
where page_namespace = 0
and page_is_redirect = 0
and cl_from IS NULL;";
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->query( $query );
// liens vers les sans catégories
$output .= $dbr->numRows( $res ) . " pages";
|
|
Inspiré du fichier « includes/specials/SpecialUncategorizedpages.php » |
Liens interne
|
$output .= Linker::linkKnown( SpecialPage::getTitleFor( 'Allpages' ), "Toutes les pages !!!");
$title = Title::newFromText("Special:Uncategorizedpages");
$output .= "<a href=\"" . $title->getFullURL() . "\">Sans catégories</a>";
$output .= $parser->recursiveTagParse( "[[Special:Uncategorizedpages|Sans catégories]]", $frame );
|
|
// colonne ss_good_articles de la table site_stats
// An approximate count of pages matching the following criteria:
// in namespace 0
// not a redirect
// contains the text '[['
$nbPages = SiteStats::articles();
// {{NUMBEROFARTICLES}}
// colonne ss_total_pages de la table site_stats
// Total pages, theoretically equal to SELECT COUNT(*) FROM page; except faster
$nbPages = SiteStats::pages();
// {{NUMBEROFPAGES}}
// requête SQL pour un résultat précis mais peut poser un problème de performance
$query = "select count(*) from page
where page_namespace = 0
and page_is_redirect = 0";
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->query( $query );
$nbPages = $res->fetchRow()[0];
|
Fichiers:
- includes/specials/SpecialAllPages.php
- includes/SiteStats.php