Mediawiki: Difference between revisions

From miki
Jump to navigation Jump to search
 
(68 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Install ==
=== Install on Debian ===
MediaWiki is available as a regular package. This is the recommendation way to keep security patches up-to-date:

<source lang=bash>
sudo apt install mediawiki
</source>

=== Install a 2nd wiki on Debian ===
On debian, the mediawiki installed with the package is installed in {{file|/var/lib/mediawiki}}. This folder contains many symlinks to the package files in {{file|/usr/share/mediawiki}} directories.

We can create a second mediawiki instance, but it needs some copy and clean up. Let's assume we want to create a second wiki instance at {{file|/var/lib/mediawiki-bis}}.

* We basically copy everything in {{file|/var/lib/mediawiki}}, preserving existing symlinks.
* We clean up folder {{cache}}.
* We clean up folder {{config}}.
* We clean up folder {{images}}.
* We clean up folder {{upload}}.
* We delete {{file|LocalSettings.php}}.
* We start installation again.
* Install {{file|LocalSettings.php}} in {{file|/etc/mediawiki}} and symlink to it

<source lang=bash>
mkdir /var/lib/mediawiki-bis
cd /var/lib/mediawiki-bis
cp -rp /var/lib/mediawiki/* .
rm -rf cache/*
rm -rf config/*
rm -rf images/*
rm -rf upload/*
cp /var/lib/mediawiki/images/README images/
rm LocalSettings.php
# ... Run install via browser, and copy LocalSettings to /etc/mediawiki/LocalSettings-bis.php
ln -sf /etc/mediawiki/LocalSettings-bis.php LocalSettings.php
</source>

;Troubleshoot
* If during install, script detects that a mediawiki instance is already running, just temporarily rename file {{file|/etc/mediawiki/LocalSettings.php}}.

== Hints and Tips ==
== Hints and Tips ==
; Purge wiki page cache
=== Purge wiki page cache ===
: When changing templates, purge the browser & mediawiki cache. To purge the cache of a single page, add '''<tt>&action=purge</tt>''' to the URL (see [http://meta.wikimedia.org/wiki/MediaWiki_FAQ#How_do_I_purge_cached_pages.3F] for more)
: When changing templates, purge the browser & mediawiki cache. To purge the cache of a single page, add '''<tt>&action=purge</tt>''' to the URL (see [http://meta.wikimedia.org/wiki/MediaWiki_FAQ#How_do_I_purge_cached_pages.3F] for more)

=== Increase default font size ===
The easiest way is to add the following to wiki common stylesheet ([[MediaWiki:Common.css]]):
<source lang=css>
/***** Increase default text size ****/
#content {font-size: 1.2em}
body.page-Main_Page #content {font-size: inherit}
</source>
The second line overrides effect of first line so that the new font size does not apply to the [[Main Page]].

There are in fact several ways to increase the font size. Using Opera's ''DragonFly'' debug environment ({{kb|Ctrl-Shift-I}}), it is easy to see how the font size of a normal wiki text is computed (css is filtered for property ''font-size''):

Computed Style
font-size: 15.36px;
Inherited from ''div''
#bodyContent {
font-size: 0.8em
}
Inherited from ''div''
<s>#content {
font-size: larger
}</s>
Inherited from ''body''
<s>body {
font-size: 1.0em
}</s>
Inherited from ''html''
<s>html {
font-size: 1.0em
}</s>

Note that '''em''' refers to the size of the current font, '''after''' application of all inherited styles. In the case above it means that the size of a standard wiki text is not 0.8em as given by div#bodyContent, but well 16px * 1.0 * 1.0 * 1.2 * 0.8 = 15.36px.

One can edit any CSS property above to change the default size of the wiki text. We choose to edit #content so that it only affects the wiki text part (including first header).

=== Make collapsible element ===
See https://www.mediawiki.org/wiki/Manual:Collapsible_elements.

Examples:
{| class="wikitable" width=100%
|-
| width=33% |
<!-- overflow:auto; to fix collapsed display, because the toggle link has float:right; -->
<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;">
* Some intro text ('''expand''' for details)
<div class="mw-collapsible-content">
A very long text<br/>
A very long text<br/>
A very long text<br/>
</div></div>
|
<source lang="xml">
<!-- overflow:auto; to fix collapsed display, because the toggle link has float:right; -->
<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;">
* Some intro text ('''expand''' for details)
<div class="mw-collapsible-content">
A very long text<br/>
A very long text<br/>
A very long text<br/>
</div></div>
</source>
|}


== Keyboard shortcuts ==
== Keyboard shortcuts ==
Line 7: Line 112:
* Reference page in [http://meta.wikimedia.org/wiki/Help:Keyboard_shortcuts wikipedia]
* Reference page in [http://meta.wikimedia.org/wiki/Help:Keyboard_shortcuts wikipedia]
* [http://meta.wikimedia.org/wiki/User_Styles#Changing_access_keys Page] explaining how to change keyboard shortcut using user custom stylesheet.
* [http://meta.wikimedia.org/wiki/User_Styles#Changing_access_keys Page] explaining how to change keyboard shortcut using user custom stylesheet.
* Most frequently-used HTML access keys (default access-key shortcut is <tt>alt+shift</tt> for ''Firefox'' and <tt>shift+Esc</tt> for ''Opera''):
* Most frequently-used HTML access keys (default access-key shortcut is {{kb|<Alt+Shift>}} for ''Firefox'' and {{kb|<shift+Esc>}} for ''Opera''):


{| class="wikitable"
{| class="wikitable"
! Action !! Key
! Action !! Key !! Firefox
|-
| accesskey-edit || e || {{kb|<Alt+Shift+e>}}
|-
|-
| accesskey-edit || e
| accesskey-mainpage || z || {{kb|<Alt+Shift+z>}}
|-
|-
| accesskey-preview || p
| accesskey-preview || p || {{kb|<Alt+Shift+p>}}
|-
|-
| accesskey-save || s
| accesskey-save || s || {{kb|<Alt+Shift+s>}}
|-
|-
| accesskey-search || f
| accesskey-search || f || {{kb|<Alt+Shift+f>}}
|}
|}


Line 34: Line 141:


== Miscellaneous ==
== Miscellaneous ==
* Page <tt>Special:Version</tt> produces a complete list of all extensions installed on the wiki.
; Page <tt>[[Special:Version]]</tt>: produces a complete list of all extensions installed on the wiki.


== Extensions ==
== Troubleshooting ==
=== Fix templates that always produce {{{1}}} ===
;Update
:No longer an issue on recent MW apparently (at least >=1.27).


Templates in Mediawiki will fail if the parameters contains an equal sign. Consider for instance the template '''nb''':
=== SyntaxHighlight GeSHi ===

This extension adds the <tt>&lt;source&gt;</tt> tag to present formatted source code.
See official [http://www.mediawiki.org/wiki/Extension:SyntaxHighlight_GeSHi page].

==== Restoring 1.0.7.# output - solving <tt>&lt;pre&gt;</tt> formatting problem ====
* Since at least version ''r24298 (July 21, 2007)'' (with ''GeSHi version 1.0.8''), <tt>&lt;source&gt;</tt> tag does not match usual formatting applied for <tt>&lt;pre&gt;</tt> tags. This is because the extension applies by default the new GeSHi header style <tt>[http://qbnz.com/highlighter/geshi-doc.html#the-code-container GESHI_HEADER_PRE_VALID]</tt>. The following patch allows to restore the old formatting when there is no attribute <tt>line</tt>. It also introduces a new option '''<tt>valid</tt>''' to attribute <tt>enclose</tt> to force application of header style <tt>GESHI_HEADER_PRE_VALID</tt>

<source lang="diff">
--- SyntaxHighlight_GeSHi.class.php.old 2008-09-07 23:24:37.000000000 +0200
+++ SyntaxHighlight_GeSHi.class.php 2008-09-07 23:33:15.000000000 +0200
@@ -39,7 +39,7 @@
// "Enclose" parameter
if ( isset( $args['enclose'] ) && $args['enclose'] == 'div' ) {
$enclose = GESHI_HEADER_DIV;
- } elseif ( defined('GESHI_HEADER_PRE_VALID') ) {
+ } elseif ( (isset( $args['line'] ) || isset( $args['enclose'] ) && $args['enclose'] == 'valid' ) && defined('GESHI_HEADER_PRE_VALID') ) {
// Since version 1.0.8 geshi can produce valid pre, but we need to check for it
$enclose = GESHI_HEADER_PRE_VALID;
} elseif( isset( $args['line'] ) ) {
</source>

* <u>Example</u>: the following code


<pre>
<pre>
<div class="noborder">
After the following command, <source lang="bash" enclose="valid"> % cat ~/hello.c</source> you'll get the following output
{{{1}}}</div>
<source lang="c">
#include <stdio.h>
int main(int,int)
{
printf("Hello, World!\n");
return 0;
}
</source>
</pre>
</pre>
gives:


Let's enclose a <code>&lt;source></code> tag:
{|

| || || ||
{| class=wikitable width=50%
After the following command, <source lang="bash" enclose="valid"> % cat ~/hello.c</source> you'll get the following output
|-
<source lang="c">
|<code><nowiki>{{nb|<source lang=bash>echo Hello</source>}}</nowiki></code>
#include <stdio.h>
|{{nb|<source lang=bash>echo Hello</source>}}
int main(int,int)
{
printf("Hello, World!\n");
return 0;
}
</source>
|}
|}


The fix is simply to prepend <code>1=</code> to the parameter value:
* Another solution is discussed [http://www.mediawiki.org/wiki/Extension_talk:SyntaxHighlight_GeSHi#Problem_with_CSS:_Default_style_for_pre_is_overwritten here]. The proposed solution is to edit file "SyntaxHighlight_GeSHi.class.php". Go to line 192, which should look like
<source lang="php">
$css[] = ".source-$lang {line-height: normal;}";
</source>
Change this to
<source lang="php">
$css[] = ".source-$lang {padding: 1em; border: 1px dashed #2f6fab; color: black; background-color: #f9f9f9; line-height: 1.1em;}";
</source>
and you have restored the pre css formatting.


{| class=wikitable width=50%
=== RawFile ===
|-
[http://wiki.yobi.be/wiki/Mediawiki_RawFile RawFile] is an extension made by Philippe Teuwen to allow downloading directly text in <tt>&lt;pre></tt> or <tt>&lt;source></tt> block as a file.
|<code><nowiki>{{nb|1=<source lang=bash>echo Hello</source>}}</nowiki></code>
|{{nb|1=<source lang=bash>echo Hello</source>}}
|}


=== Tag attributes not expanded in templates ===
==== Patch v0.2 &rarr; v0.3 ====
To have tag attributes expanded in wiki templates (in particular when these attributes contain template parameters), use the special construction <code><nowiki>{{#tag:tagname|content|attr1=val1|attr2=val2}}</nowiki></code>. See also [http://www.mediawiki.org/wiki/Help:Magic_words#Miscellaneous <code>#tag</code> magic word] and [https://bugzilla.wikimedia.org/show_bug.cgi?id=61341 bugzilla 61341] for more information.


This is used in template [[Template:Rawfiledownloadexample]]:
The patch below adds an optional parameter to hook <tt><nowiki>{{#filelink}}</nowiki></tt>. With 1 param, the file is fetched from the current page as usual:


<pre>
<pre>
You can download file "{{{name}}}" below, just click this link: {{#tag:file|{{{name}}}|name={{{name}}}|tag=pre}}.
Save [{{#filelink: fstab}} this file] in your <tt>/etc</tt> directory.
{{#tag:pre|{{{content}}}}}
</pre>
</pre>


The example
With 2 param, the 2nd param is telling which page to fetch the file from:

<pre>
<pre>
{{Rawfiledownloadexample|name=myfile.txt|content=Once upon a time
Save [{{#filelink: fstab|Config files - fstab}} this file] in your <tt>/etc</tt> directory.
There was a Tag
Tag was clickable
And clicked it was}}
</pre>
</pre>
expands into to the following with action <code>?action=raw&templates=expand</code>:

<source lang=xml>
{{hiddenSourceFile||RawFile-v0.2.patch|<source lang="diff" class="RawFile-v0.2.patch">
You can download file "myfile.sh" below, just click this link: <file|name="myfile.sh" tag="pre">myfile.sh</file>.
--- original/RawFile.php 2009-09-21 16:20:51.000000000 +0200
<pre>Once upon a time
+++ patched/RawFile.php 2009-09-21 18:07:06.000000000 +0200
There was a Tag
@@ -18,8 +18,12 @@
Tag was clickable
$magicWords['fileanchor'] = array( 0, 'fileanchor' );
And clicked it was</pre>
return true;
}
-function efRawFile_Render( &$parser, $filename = '') {
- return $parser->mTitle->getFullURL( 'action=raw&file='.urlencode( $filename ) );
+function efRawFile_Render( &$parser, $filename = '', $titleText = '') {
+ if( $titleText == '' ) {
+ $titleText = $parser->mTitle->getText();
+ }
+ $title=Title::newFromText( $titleText );
+ return $title->getFullURL( 'action=raw&file='.urlencode( $filename ) );
}
function efRawFile_Empty( &$parser, $filename = '') {
return '';
</source>
</source>
}}


====Patch v0.3 &rarr; v0.4====
=== Can't upload file ===
Error message:
Changes in '''v0.4'''
Could not create directory mwstore://local-backend/local-public/ when Uploading.
* '''Anchors''' can be specified using html '''class''' attribute
The problem is due to wrong ownership / permission in mediawiki folder [http://www.mediawiki.org/wiki/Thread:Project:Support_desk/Could_not_create_directory_mwstore://local-backend/local-public/_when_Uploading.]:
* New syntax for '''Links''' and '''Anchor-links''':
sudo chown -R www-data /var/www/mediawiki
:<code><nowiki><file [name="..."] [anchor="..."] [tag="..."] [title="..."] >Link text</file></nowiki></code>
* Support multiple files on the same page with same name.
* Can specify the tag name of the block to download (to skip some irrelevant blocks when using an '''anchor-link''').
* Ignore '''<code>&lt;br&gt;</code>''' tag.
* Some error reporting.


== MediaWiki for developers ==
The extension introduces 3 elements:
;References
;Anchor
* [https://www.mediawiki.org/wiki/Developer_hub '''Developer Hub'''].
: Used to flag that the next code block in the wiki text belongs to a specific file. The code block can be any wiki block (such as '''<code>&lt;pre&gt;</code>''', '''<code>&lt;code&gt;</code>''', '''<code>&lt;tt&gt;</code>''', '''<code>&lt;source&gt;</code>'''...). '''<code>&lt;br&gt;</code>''' tags are ignored. Note that anchors are invisible in the wiki display.
* [https://www.mediawiki.org/wiki/Manual:Extensions Manual:Extensions]
;Link
* [https://www.mediawiki.org/wiki/Manual:Developing_extensions Manual:Developing_extensions]
: They are transformed by the extension into links that allows for downloading all blocks attached to a given anchor name.
* [https://www.mediawiki.org/wiki/Manual:Tag_extensions Manual:Tag_extensions] (writing extensions that provides new wiki tags)
;Anchor-link
* [http://www.mediawiki.org/wiki/Manual:Parser_functions Parser functions]
: A shortcut notation mixing both an anchor and download link, handy for regular use, when a single code block is used and when the download link can be at the same position as the anchor.
* [http://www.mediawiki.org/wiki/Manual:Tag_extensions#How_do_I_render_wikitext_in_my_extension.3F How do I render wikitext in my extension ?]
* [https://www.mediawiki.org/wiki/Manual:RequestContext Manual:RequestContext]


;Tips
The syntax is as follows. The syntax using tag <code>&lt;file&gt;</code> and tag attribute <code>class</code> is new since v0.4. Note that elements of both syntaxes can be mixed in a same page.
* In 99% of cases, extensions just need to use the method <code>recursiveTagParse</code> of the parser instead of <code>Parser::parse</code> (apparently this function is not re-entrant).
{| border="2" cellspacing="4" cellpadding="3" style="margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaaaaa solid; border-collapse: collapse; empty-cells:show;"

!width="80em" style="background: #8da7d6;"|Element!!style="background: #8da7d6;"|Syntax and description
=== Debugging ===
* [https://www.mediawiki.org/wiki/Manual:How_to_debug Mediawiki - How to debug]

To see PHP errors, add to {{file|LocalSettings.php}} (or can also edit {{file|php.ini}} or {{file|.htaccess}} [https://www.mediawiki.org/wiki/Manual:How_to_debug Mediawiki - How to debug]):
<source lang=php>
error_reporting( -1 );
ini_set( 'display_errors', 1 );
</source>

=== Globals ===
Some global variables defined by Mediawiki. Note that to use these variables, we must first declare them as global:
<source lang=php>
global $wgExtensionAssetsPath;
</source>

{| class=wikitable
|-
!Name!!Default!!Description
|-
|-
|[https://www.mediawiki.org/wiki/Manual:$IP <code>$IP</code>]||<code>MW_INSTALL_PATH</code> env var||IP stands for Install Path. The variable holds the local file path to the base installation of your wiki.
|'''Anchor'''
|<pre><nowiki>
{{#fileAnchor: anchorname}}
<pre class='anchorname'>...&lt;/pre>
<code class="anchorname">...&lt;/code>
<code class="cssclass anchorname">...&lt;/code>
...
</nowiki></pre>
Indicates that the next wiki block is attached to an anchor ''anchorname''. The content of that block will be downloaded (possibly appended with other blocks if there are several blocks attached to the same ''anchorname'') when a file link is clicked on.<br/>
'''(since v0.4)''' To attach an anchor ''anchorname'' to a wiki block, simply add an attribute <code>class="anchorname"</code> to it. The extension supports multi-class specification, meaning that a same block can be associated to different files, and that the <code>class</code> attribute can still be used to specify custom CSS properties as in standard wiki text.
; ''anchorname''
; class="''anchorname''"
: The name of the anchor to which the wiki block is attached
|-
|-
|[https://www.mediawiki.org/wiki/Manual:$wgScriptPath <code>$wgScriptPath</code>]||<code>/wiki</code>||The base URL path (in relation to DOCUMENT ROOT).
|'''Link'''
|<pre><nowiki>
[{{#fileLink: anchorname}} link text]
[{{#fileLink: anchorname|pagetitle}} link text]
<file anchor="anchorname" [name="filename"] [title="pagetitle"]>link text</file>
</nowiki></pre>
Creates a link to download all blocks that are attached to an anchor ''anchorname''.
;''anchorname''
;anchor="''anchorname''"
: The name of the anchor to look for. All blocks attached to an anchor ''anchorname'' will be downloaded.
;name="''filename''"
:''Optional'' - Specifies the name of the file to download. If absent, ''anchorname'' is then used as the name of the downloaded file.
; ''pagetitle''
;tag="''pagetitle''"
: ''Optional'' - Indicates that the blocks to download are on the wiki page titled ''pagetitle''. If absent, blocks are looked for on the current page.
; ''link text''
: The text of the link to display.
|-
|-
|[https://www.mediawiki.org/wiki/Manual:$wgExtensionAssetsPath <code>$wgExtensionAssetsPath</code>]||<code>{$wgScriptPath}/extensions</code>||URL to extensions directory. Used to provide a base URL for extension assets like extension-specific images and scripts. Note the difference between
|'''Anchor-link'''
* <code>$IP/extensions</code> (points to the extensions directory on the server filesystem) and
|<pre><nowiki>
* <code>$wgScriptPath/extensions</code> (points to the URL of the extensions directory).
[{{#file: filename}} link text]
<file name="filename" [tag="''tagname''"]>link text</file>
</nowiki></pre>
Creates a link to download the next wiki block as a file named ''filename''.<br/>
'''(since v0.4)''' The attribute <code>tag</code> can be used to specify the ''tagname'' of the block to download.<br>
; ''filename''
; name="''filename''"
: The name of the file to download.
;tag="''tagname''"
:''Optional'' - When set, the extension only looks for blocks whose name matches the given ''tagname''. This attribute is particularly useful when there are some irrelevant blocks between the '''anchor-link''' and the block you want to download. If absent, the first encountered block following the anchor is downloaded.
; ''link text''
: The text of the link to display.
|}
|}


===== Examples =====
=== Modules ===
* [https://www.mediawiki.org/wiki/ResourceLoader/Modules ResourceLoader/Modules] &mdash; This page lists modules that ship with MediaWiki core by default.


=== ResourceLoader ===
<pre><nowiki>
;References:
* '''Method 1''': Returns the block that immediately follows. Save [{{#file: method1.txt}} this file]: <code>Hello, World!</code>
* [https://www.mediawiki.org/wiki/ResourceLoader ResourceLoader] on MediaWiki
: But this other example fails because of the &lt;br&gt; tag... So save [{{#file: method1-fail.txt}} this file]:<br>
* [https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader Developing with ResourceLoader]
:<code>Hello, World!</code>.
: Quick walkthrough, registering modules, etc.
* [https://www.mediawiki.org/wiki/Manual:$wgResourceModules <code>$wgResourceModules</code>]
* [https://doc.wikimedia.org/mediawiki-core/master/php/classResourceLoader.html ResourceLoader class reference]
* [https://www.mediawiki.org/wiki/ResourceLoader/Migration_guide_for_extension_developers Migration guide for extension developers]


;Add a CSS style module
* '''Method 2''': Indicates the block(s) with anchors. Save [{{#filelink: method2.txt}} this file] (but not this <code>code text</code>):<br>
:For instance, from Extension::Cite
:{{#fileanchor: method2.txt}}<code>We can then </code> very easily {{#fileanchor: method2.txt}}<code>interleave downloadable text with wiki comments</code>
<source lang=bash>
$wgHooks['BeforePageDisplay'][] = 'wfCiteBeforePageDisplay';
$wgResourceModules['ext.rtlcite'] = array(
'localBasePath' => __DIR__ . '/modules',
'remoteExtPath' => 'Cite/modules'
'styles' => 'ext.rtlcite.css',
'position' => 'top',
);


function wfCiteBeforePageDisplay( $out, &$sk ) {
* '''Method 3''': Same as above, but using html attribute 'class'. Save [{{#filelink: method3.txt}} this file] (but not this <code>code text</code>):<br>
$out->addModuleStyles( 'ext.rtlcite' );
:{{#fileanchor: method3.txt}}<code>We can still </code> very easily <code class="method3.txt">interleave downloadable text with wiki comments but with less typing</code>
return true;
<code class="method3.txt">
}
Obviously, there is absolutely
</source>
no limitation
:In the following example we add the module only if a tag is present
on the size of the
<source lang=bash>
text
$wgHooks['ParserFirstCallInit'][] = 'onParserSetup';
</code>
$wgResourceModules['ext.fentt'] = array(
// ...
);
static function onParserSetup( Parser $parser ) {
$parser->setHook( 'fentt', 'renderFenTT' );
}


$module_added = false;
* '''Method 4''': Same as method 1, but using new syntax (custom wiki tag). Save <file name="method4.txt">'''this''' file</file>: <code>Hello, World!</code>
function renderFenTT( $input, array $args, Parser $parser, PPFrame $frame ) {
global $module_added;
if( ! $module_added ) {
$parser->getOutput()->addModuleStyles('ext.fentt');
self::$module_added = true;
}
// ...
}
</source>


;Troubleshoot:
* '''Method 5''': Same as above, but specifying which tag to include. Save ''<file name="method5.txt" tag="code">this file</file>'':
* Module is listed in the <head> element, but corresponding CSS/JS does not appear in downloaded content
<source lang="text">This text is skipped.</source>
: Try to register the module (add to <code>$wgResourceModules</code>) at global level (i.e. not in the hook handle function that calls <code>$addModuleStyles</code>).
:<code>This is the text that will be returned...</code>


=== Hooks ===
* '''Method 6''': Same as method 2 / 3, but using new syntax (custom wiki tag). Save <file anchor="method6.txt">this file</file>. Of course the old syntax <code>{{#fileanchor}}</code> for anchor is still supported.<br>
* [https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay <code>$wgHooks['BeforePageDisplay'][]</code>] &mdash; Allows last minute changes to the output page, e.g. adding of CSS or JavaScript by extensions.
:{{#fileanchor: method6.txt}}<code>Again, we can </code>also very easily <code class="method6.txt">interleave downloadable code with wiki text while using the new syntax</code>
</nowiki></pre>


=== Javascript ===
This gives:
==== Modules ====
JavaScript files are, like CSS files, also evaluated in the order they are defined in the <code>scripts</code> array (file {{file|extension.json}}). [https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader#Passing_information_from_PHP_to_Javascript]


If a module must export a global object, do:
* '''Method 1''': Returns the block that immediately follows. Save [{{#file: method1.txt}} this file]: <code>Hello, World!</code>
<source lang=javascript>
: But this other example fails because of the &lt;br&gt; tag... So save [{{#file: method1-fail.txt}} this file]:<br>
// foo.js
:<code>Hello, World!</code>.
var Foo = {
sayHello: function ( $element ) {
$element.append( '<p>Hello Module!</p>' );
}
};
window.Foo = Foo;
</source>


If a module must wait that the document be completely loaded before executing, do:
* '''Method 2''': Indicates the block(s) with anchors. Save [{{#filelink: method2.txt}} this file] (but not this <code>code text</code>):<br>
<source lang=javascript>
:{{#fileanchor: method2.txt}}<code>We can then </code> very easily {{#fileanchor: method2.txt}}<code>interleave downloadable text with wiki comments</code>
// init.js
$( function () {
// This code must not be executed before the document is loaded.
Foo.sayHello( $( '#hello' ) );
});
</source>
==== Export javascript libraries ====
Some tips.
* Javascript libraries must be loaded with the ResourceLoader.
* JS libraries are loaded asynchronously. Moreover the global context is not the default global context, but the one of the ResourceLoader. If a library must export symbol to global context, they must attach it to the <code>window</code> object:
<source lang=javascript>
window.myjslib = myjslib;
</source>
* Some libraries don't export to window, but does so like in node.js (see [http://khan.io/2013/08/16/node-js-how-exports-and-module-exports-works/ node.js &mdash; how exports and module.exports works]). So they attach to an object <code>module.exports</code> If that's the case, we must export it ourselves.
: In {{file|extension.json}}, we have:
<source lang=javascript>
"ResourceModules": {
"scripts": [ "myjslib.js", "myjslib.export.js" ]
}
</source>
: assuming that {{file|myjslib.js}} export to <code>module.exports</code>, we fix that in library {{file|myjslib.export.js}}:
<source lang=javascript>
// Let's export i18next correctly
window.myjslib = window.myjslib || module.exports; // Don't export twice
$.myjslib = $.myjslib || module.exports; // Alternatively we can attach to jQuery context
myjslib = $.myjslib; // Export to default context
</source>
:We must do this '''immediately''' after loading the library, because another library could overwrite <code>module.exports</code>.


==== ResourceLoader Core Modules ====
* '''Method 3''': Same as above, but using html attribute 'class'. Save [{{#filelink: method3.txt}} this file] (but not this <code>code text</code>):<br>
See '''[https://www.mediawiki.org/wiki/ResourceLoader/Core_modules ResourceLoader Core Modules]'''.
:{{#fileanchor: method3.txt}}<code>We can still </code> very easily <code class="method3.txt">interleave downloadable text with wiki comments but with less typing</code>
<code class="method3.txt">s
Obviously, there is absolutely
no limitation
on the size of the
text
</code>


These contains
* '''Method 4''': Same as method 1, but using new syntax (custom wiki tag). Save <file name="method4.txt">'''this''' file</file>: <code>Hello, World!</code>
* The '''mediawiki''' module
* The '''OOjs''' module
* The '''jQuery''' module and plugins
:jQuery plugins are available as ResourceLoader module that can be added as a '''module dependency''' in {{file|extension.json}} (for instance module <code>jquery.ui.button</code>).


To make sure that a module is available, either add it as dependency, or use the code [https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader]:
* '''Method 5''': Same as above, but specifying which tag to include. Save ''<file name="method5.txt" tag="code">this file</file>'':
<source lang="text">This text is skipped.</source>
<source lang=javascript>
mw.loader.using( ['mediawiki.util','mediawiki.Title'] ).then( function () {
:<code>This is the text that will be returned...</code>
/* This callback is invoked as soon as the modules are available. */
} );
</source>
There is also an error callback:
<source lang=javascript>
mw.loader.using([ 'mediawiki.util', 'jquery.placeholder', 'jquery.spinner' ], function(){
console.warn( 'Ready callback was executed.', arguments );
}, function(){
console.warn( 'Error callback was executed.', arguments );
});
</source>


==== Passing information from PHP to Javascript ====
* '''Method 6''': Same as method 2 / 3, but using new syntax (custom wiki tag). Save <file anchor="method6.txt">this file</file>. Of course the old syntax <code>{{#fileanchor}}</code> for anchor is still supported.<br>
See https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader#Passing_information_from_PHP_to_Javascript.
:{{#fileanchor: method6.txt}}<code>Again, we can </code>also very easily <code class="method6.txt">interleave downloadable code with wiki text while using the new syntax</code>


* Store data in HTML.
References:
* Or use [https://www.mediawiki.org/wiki/Manual:OutputPage.php <code>OutputPage::AddJsConfigVars</code>]. Pay attention however that '''PHP parser code are not necessarily run each time a page is visited''' (eg. if using memcached). If the parser must transfer data to JS context, one solution is to generate inline javascript in <code><script></code> tag.
* [http://www.mediawiki.org/wiki/Manual:Tag_extensions Tag extensions on mediawiki.org]


===== The code =====
==== Run with jQuery support or in RL context ====
To run our inline script with jQuery support, use the ResourceLoader queue <code>RLQ</code> [https://www.mediawiki.org/wiki/Topic:T0bq15ycney6xs25], [https://www.mediawiki.org/wiki/Topic:Tdplyqpyhfoirplu]:
<source lang=javascript>
RLQ.push(function () {
console.log('This runs with jQuery support', $);
});
// or
(window.RLQ=window.RLQ||[]).push(function(){
$(function() { console.log("test") });
});
</source>
Note that this is only useful for inlined scripts. Script loaded with the ResourceLoader may always assume that jQuery is available (since MW 1.17).


==== Add an external script ====
{{hiddenSourceFile||RawFile-v0.3.patch|<source lang="php" class="RawFile.php">
More solutions on [https://stackoverflow.com/questions/29902768/how-to-add-custom-global-javascript-to-mediawiki Stack Overflow]. For external script, call <code>addHeadItem</code>:
<?php
<source lang=php>
# Add onBeforePageDisplay function to BeforePageDisplay Hook
$wgHooks['BeforePageDisplay'][] ='onBeforePageDisplay';


function onBeforePageDisplay( OutputPage &$out, Skin &$skin )
if (defined('MEDIAWIKI')) {
{
$script = '<script type="text/javascript" src="https://example.com/javascript.js"></script>';
$out->addHeadItem("itemName", $script);
return true;
};
</source>
Be aware that the script will be loaded in the default context, '''which is not the same as the ResourceLoader context that contains all loaded RL modules'''. So this script will not have access to RL libraries. To get access, add a callback to the ResourceLoader queue (see previous section).


==== Extension template ====
//Avoid unstubbing $wgParser on setHook() too early on modern (1.12+) MW versions, as per r35980
The [https://www.mediawiki.org/wiki/Manual:Developing_extensions Manual:Developing_extensions] page gives us the structure that all extensions must follow.
if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
$wgHooks['ParserFirstCallInit'][] = 'efRawFile_Setup';
} else { // Otherwise do things the old fashioned way
$wgExtensionFunctions[] = 'efRawFile_Setup';
}
$wgHooks['LanguageGetMagic'][] = 'efRawFile_Magic';
$wgHooks['RawPageViewBeforeOutput'][] = 'fnRawFile_Strip';


Several templates are available:
function efRawFile_Setup() {
* [https://github.com/JonasGroeger/cookiecutter-mediawiki-extension cookiecutter-mediawiki-extension].
global $wgParser;
* [https://www.mediawiki.org/wiki/Extension:BoilerPlate Extension:BoilerPlate]
$wgParser->setFunctionHook( 'file', 'efRawFile_Render' );
* [http://tools.wmflabs.org/mwstew/ MWStew].
$wgParser->setFunctionHook( 'filelink', 'efRawFile_Render' );
$wgParser->setFunctionHook( 'fileanchor', 'efRawFile_Empty' );
$wgParser->setHook( 'file', 'efRawFile_FileTagRender' );
return true;
}


;extension.json
function efRawFile_Magic( &$magicWords, $langCode ) {
:Since MW 1.25, all extension comes with a description file {{file|extension.json}}. See [https://www.mediawiki.org/wiki/Manual:Extension.json/Schema Extension.json schema] for the list of all possible entries.
$magicWords['file'] = array( 0, 'file' );
$magicWords['filelink'] = array( 0, 'filelink' );
$magicWords['fileanchor'] = array( 0, 'fileanchor' );
return true;
}


=== Troubleshooting an extension ===
function efRawFile_Render( &$parser, $filename = '', $titleText = '') {
;First reflexes
if( $titleText == '' )
* Test extension in Chrome and Firefox.
$title = $parser->mTitle;
* Open up the browser debug window (Ctrl-Shift-C) and check the Console for javascript errors, file not found. Check also the network tab.
else
* Try to load extension in an older version, and bisect the version where the extension fails.
$title = Title::newFromText( $titleText );
:* Look at the MediaWiki release note for breaking changes.
return $title->getFullURL( 'action=raw&anchor='.urlencode( $filename ) );
}


;Attention points
function efRawFile_Empty( &$parser, $filename = '') {
* MW + cache sucks. If changing PHP code, better edit a test page, add one character and save. This will flush the cache easily.
return '';
* If changing JS code, then Shift+F5 in browser should refresh it.
}


;Using foreign JS
function efRawFile_FileTagRender( $input, $args, &$parser ) {
* These are probably ''minified''. It helps greatly to replace them with pretty-printed version (e.g. https://www.prettifyjs.net/)
if( $args['title'] == '' )
* Insert <code>console.log(...)</code> statement to help debugging.
$title = $parser->mTitle;
else
$title = Title::newFromText( $args['title'] );
$link=$title->getFullURL( 'action=raw' );
if( $args['name'] != '' )
$link.='&name='.urlencode( $args['name'] );
if( $args['anchor'] != '' )
$link.='&anchor='.urlencode( $args['anchor'] );
if( $args['tag'] != '' )
$link.='&tag='.urlencode( $args['tag'] );
return $parser->recursiveTagParse( "[$link $input]" );
}


;Example: PgnJS extension, migration to mw1.35
function fnRawFile_Strip_Error($msg,$out,&$text) {
* Extension fails on MW 1.35
$text=$msg;
* Looking at MW 1.35 breaking changes, we see that <code>jquery.ui.*</code> have been removed. This is used in PgnJS {{file|extension.json}}.
if($out != '')
* Open up Firefox/Chrome debugging interface (Ctrl+Shift+C).
$text.="\nCandidate match: $out";
:* In Console, we see errors about <code>Error: Unknown module: jquery.ui.core</code>
return true;
:* Changing <code>"dependencies": [ "jquery.ui.core", "jquery.ui.widget" ]</code> to <code>"dependencies": [ "jquery.ui" ]</code> fixes the problem.
}
:* However we see we still get a deprecated warning.


;Example 2: PgnJS extension, migration to latest PgnViewerJS
function fnRawFile_Strip(&$rawPage, &$text) {
* We first create a static file {{file|example.html}} just to make sure that the apache server is configured correctly (no perm issue)
$filename=$_GET['name'];
:* This will gives the value of the path to use internally (PgnViewerJS expect this path in a variable <code>__globalCustomDomain</code>.
$anchor=$_GET['anchor'];

$tag=$_GET['tag'];
== How-To ==
// Either anchor or name must be specified
=== Add an extension stylesheet in HTML head element ===
if( $filename=='' )
The goal is to add a stylesheet <code><link></code> tag in the HTML <code><head></code> element, either ALWAYS or CONDITIONALLY, and/or STATIC link or DYNAMIC link (from page content).
$filename=$anchor;
<source lang=html4strict>
if ( $filename=='' )
<head>
return true;
...
// Uncomment the following line to avoid output buffering and gzipping:
<link rel="stylesheet" href="..." />
// wfResetOutputBuffers();
...
header("Content-disposition: attachment;filename={$filename}");
</head>
header("Content-type: application/octetstream");
</source>
header("Content-Transfer-Encoding: binary");

header("Expires: 0");
;Criteria
header("Pragma: no-cache");
* Must work with recent MW version, and use stable API.
header("Cache-Control: no-store");
* Must be page-caching friendly.
$maskedtext=preg_replace('!<nowiki>.*?</nowiki>!se',
* If link is added conditionally, avoid parsing twice the page content. Can we use some context information?
'preg_replace("/\\\\\\\\\\\'|./","X","$0")',

$text);
;Relevant hooks
if (($anchor!='') && preg_match_all('/({{#fileanchor: *'.$anchor.' *}})|(<[^>]+ class *= *"([^"]*\w)?'.$anchor.'(\w[^"]*)?"[^>]*>)/i', $maskedtext, $matches, PREG_OFFSET_CAPTURE))
* https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageBeforeHTML
$offsets=$matches[0];
* https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay
else if (preg_match_all('/{{#file: *'.$anchor.' *}}/i', $maskedtext, $matches, PREG_OFFSET_CAPTURE))
* https://www.mediawiki.org/wiki/Manual:Hooks/ParserFirstCallInit
$offsets=array($matches[0][0]);

else if (preg_match_all('/<file( [^>]*)? name *= *"'.$filename.'"[^>]*>/i', $maskedtext, $matches, PREG_OFFSET_CAPTURE))
;Relevant example extensions
$offsets=array($matches[0][0]);
* https://www.mediawiki.org/wiki/Category:HTML_head_extensions
else {
: list of extensions designed to modify information in the HTML <code><head></code> element
// We didn't find our anchor
* https://www.mediawiki.org/wiki/Extension:CSS
return fnRawFile_Strip_Error("ERROR - RawFile: anchor not found (anchor=$anchor, name=$filename, tag=$tag)","",$text);
: For MW 1.16.x and above. Use hook <code>RawPageViewBeforeOutput</code> to sanitize CSS, and <code>ParserFirstCallInit</code> to add a head item with <code>$parser->getOutput()->addHeadItem( $headItem );</code>.
}
* https://www.mediawiki.org/wiki/Extension:NewPageCSS
unset($maskedtext);
: For MW 1.16+. Use a <code>ParserFirstCallInit</code> hook, then add a <code><style></code> element using <code>$wgParser->mOutput->addHeadItem</code> when it encounters a <code><css></code> tag. Looks an excellent candidate for our stuff!
$textorig=$text;
* [https://www.mediawiki.org/wiki/Extension:AddScriptCss Extension:AddScriptCss]
$text='';
: Inserts <script> (i.e. Javascript) or <link> (i.e. CSS) code at the bottom of the page's head or within the page's body. Securely inserts arbitrary code to the page's head using <addtohead>.
foreach ($offsets as $offset) {
: For MW 1.10, 1.11. Likely too complex for our use. Insert a ''metatag'' as an HTML comment, which is then parsed again (via <code>preg_match_all</code>) in <code>OutputPageBeforeHTML</code> hook.
$out = substr($textorig, $offset[1]);
* [http://www.mediawiki.org/wiki/Extension:Cite Extension:Cite]
// If no tag specified, we take the first one
: Found simply by ... looking for {{file|.css}} files in MW {{file|extensions/}} directory!
if ($tag == '')
: Uses hooks <code>ParserFirstCallInit</code> (to register parser hooks for Cite tags like <code>&lt;ref></code>) and <code>BeforePageDisplay</code> (to add modules, including the call to <code>addModuleStyles</code>). '''But...''' checking the page source it turns out that Cite css file is *always* loaded by the dynamic resource loader, even when the tag is not used on the page. Is that a problem?
{

// With a regex assertion, we can easily ignore 'br' and 'file' tags
;Troubleshooting
if (!preg_match('/<((?!br\b|file\b)\w+\b)/', $out, $matches))
* <code>$parser->getOutput()->addHeadItem( "..." )</code> not working on mobile device.
return fnRawFile_Strip_Error ("ERROR - RawFile: Can't find opening tag after anchor '$offset[0]' (anchor=$anchor, name=$filename, tag=$tag)",$out,$text);
:It works on desktop, on my tablet, but not on my smartphone. Why?
$tag=$matches[1];
:The fix is to load the module with <code>[https://doc.wikimedia.org/mediawiki-core/master/php/classOutputPage.html addModuleStyles()]($modules)</code>, as done for instance in [http://www.mediawiki.org/wiki/Extension:Cite Extension:Cite]

;Questions
* On Wikimedia, there is a link at the bottom to toggle between mobile / desktop view. Handy to test a site in mobile mode. How can we get it installed? By upgrading to the latest MW? or installing Mobile extension

;The Solution
<source lang=bash>
if (defined('MEDIAWIKI')) {
$wgHooks['ParserFirstCallInit'][] = 'MWFenTT::onParserFirstCallInit';

$wgResourceModules['ext.FenTT'] = array(
'localBasePath' => __DIR__,
'remoteExtPath' => 'FenTT',
'styles' => 'FenTT.css',
'position' => 'top',
);

class MWFenTT {
private static $css_module_added = false;

static function onParserFirstCallInit( Parser $parser ) {
// Register parser handler for tag <fentt>
$parser->setHook( 'fentt', 'MWFenTT::renderFentt' )
}

static function renderFentt( $input, array $args, Parser $parser, PPFrame $frame ) {
if( ! self::$css_module_added ) {
// Tell ResourceLoader that we need our css module
$parser->getOutput()->addModuleStyles( 'ext.FenTT' );
self::$css_module_added = true;
}
return FenTT::renderFentt($input,$args);
}
}
// Find the first tag matching $tag, and return enclosed text
if (!preg_match('/<'.$tag.'( [^>]*)?>\n?(.*?)<\/'.$tag.'>/s', $out, $matches))
return fnRawFile_Strip_Error ("ERROR - RawFile: no closing '$tag' found after anchor '$offset[0]' (anchor=$anchor, name=$filename, tag=$tag)",$out,$text);
$text .= $matches[2];
}
}
return true;
}
}
</source>


== Extensions ==
$wgExtensionCredits['parserhook'][] = array('name' => 'RawFile',
* [[MediaWiki GeSHi]]
'version' => '0.4',
* [[MediaWiki RawFile]]
'author' => 'Philippe Teuwen, Michael Peeters',
'url' => 'http://www.mediawiki.org/wiki/Extension:RawFile',
// 'url' => 'http://wiki.yobi.be/wiki/Mediawiki_RawFile',
'description' => 'Downloads a RAW copy of <nowiki><tag>data</tag></nowiki> in a file<br>'.
'Useful e.g. to download a script or a patch<br>'.
'It also allows what is called [http://en.wikipedia.org/wiki/Literate_programming Literate Programming]');
}


== MediaWiki for Mobile ==
?>
;References:
* [https://www.mediawiki.org/wiki/Category:Mobile Category:Mobile]
* [https://www.mediawiki.org/wiki/Manual:Mobiles,_tablets_and_responsive_design Manual:Mobiles, tablets and responsive design]
* [https://www.mediawiki.org/wiki/Making_MediaWiki_Mobile_Friendly Making MediaWiki Mobile Friendly]

;CSS
* To apply CSS to a mobile skin, edit [[MediaWiki:Mobile.css]], the counterpart of [[MediaWiki:Common.css]].

=== Extensions for Mobile ===
* [https://www.mediawiki.org/wiki/Extension:MobileFrontend Extension:MobileFrontend]
: See also [https://www.mediawiki.org/wiki/ResourceLoader/Writing_a_MobileFrontend_friendly_ResourceLoader_module Writing a MobileFrontend friendly ResourceLoader module]

== Administration ==
=== Delete a page permanently ===
This procedure allows for permanently deleting a page from the wiki database, including the whole history. After this, there will be no trace left of the content of that page, except for a trace in the delete log indicating the date when the page was deleted and the reason (if any given).

* First, as admin user, go to the page to delete.
* In the menu, select 'Delete', select and type in a reason, then click "Delete page".
:From now on, the page is deleted, but history is still in the database. Deletion can be reverted by going to the delete log page ([[Special:Log/delete]])
* On the wiki server, run the maintenance script named <code>deleteArchivedRevisions.php</code>. This will permanently delete the page history from the wiki db.

<source lang=bash>
cd /var/lib/mediawiki/maintenance
php ./deleteArchivedRevisions.php --delete
</source>
</source>

}}
=== Upload lots of file at once ===
Use local command <code>importImages.php</code> [http://www.mediawiki.org/wiki/Manual:ImportImages.php].
php maintenance/importImages.php --comment "Rubik's cube position, better perspective" /opt/www/daemenj/web/kiwi.noekeon.org/miki/rb png
Or to force a specific user:
sudo -u www-data php maintenance/importImages.php --comment "Rubik OLL cases, from http://www.cubewhiz.com/oll.php" tmp/

Latest revision as of 10:30, 21 April 2022

Install

Install on Debian

MediaWiki is available as a regular package. This is the recommendation way to keep security patches up-to-date:

sudo apt install mediawiki

Install a 2nd wiki on Debian

On debian, the mediawiki installed with the package is installed in /var/lib/mediawiki. This folder contains many symlinks to the package files in /usr/share/mediawiki directories.

We can create a second mediawiki instance, but it needs some copy and clean up. Let's assume we want to create a second wiki instance at /var/lib/mediawiki-bis.

  • We basically copy everything in /var/lib/mediawiki, preserving existing symlinks.
  • We clean up folder Template:Cache.
  • We clean up folder Template:Config.
  • We clean up folder Template:Images.
  • We clean up folder Template:Upload.
  • We delete LocalSettings.php.
  • We start installation again.
  • Install LocalSettings.php in /etc/mediawiki and symlink to it
mkdir /var/lib/mediawiki-bis
cd /var/lib/mediawiki-bis
cp -rp /var/lib/mediawiki/* .
rm -rf cache/*
rm -rf config/*
rm -rf images/*
rm -rf upload/*
cp /var/lib/mediawiki/images/README images/
rm LocalSettings.php
# ... Run install via browser, and copy LocalSettings to /etc/mediawiki/LocalSettings-bis.php
ln -sf /etc/mediawiki/LocalSettings-bis.php LocalSettings.php
Troubleshoot
  • If during install, script detects that a mediawiki instance is already running, just temporarily rename file /etc/mediawiki/LocalSettings.php.

Hints and Tips

Purge wiki page cache

When changing templates, purge the browser & mediawiki cache. To purge the cache of a single page, add &action=purge to the URL (see [1] for more)

Increase default font size

The easiest way is to add the following to wiki common stylesheet (MediaWiki:Common.css):

/***** Increase default text size ****/
#content {font-size: 1.2em}
body.page-Main_Page #content {font-size: inherit}

The second line overrides effect of first line so that the new font size does not apply to the Main Page.

There are in fact several ways to increase the font size. Using Opera's DragonFly debug environment (Ctrl-Shift-I), it is easy to see how the font size of a normal wiki text is computed (css is filtered for property font-size):

Computed Style
    font-size: 15.36px;

Inherited from div
#bodyContent {
    font-size: 0.8em
}

Inherited from div
#content {
    font-size: larger
}

Inherited from body
body {
    font-size: 1.0em
}

Inherited from html
html {
    font-size: 1.0em
}

Note that em refers to the size of the current font, after application of all inherited styles. In the case above it means that the size of a standard wiki text is not 0.8em as given by div#bodyContent, but well 16px * 1.0 * 1.0 * 1.2 * 0.8 = 15.36px.

One can edit any CSS property above to change the default size of the wiki text. We choose to edit #content so that it only affects the wiki text part (including first header).

Make collapsible element

See https://www.mediawiki.org/wiki/Manual:Collapsible_elements.

Examples:

  • Some intro text (expand for details)

A very long text
A very long text
A very long text

<!-- overflow:auto; to fix collapsed display, because the toggle link has float:right; -->
<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;">
* Some intro text ('''expand''' for details)
<div class="mw-collapsible-content">
A very long text<br/>
A very long text<br/>
A very long text<br/>
</div></div>

Keyboard shortcuts

  • Reference page in wikipedia
  • Page explaining how to change keyboard shortcut using user custom stylesheet.
  • Most frequently-used HTML access keys (default access-key shortcut is <Alt+Shift> for Firefox and <shift+Esc> for Opera):
Action Key Firefox
accesskey-edit e <Alt+Shift+e>
accesskey-mainpage z <Alt+Shift+z>
accesskey-preview p <Alt+Shift+p>
accesskey-save s <Alt+Shift+s>
accesskey-search f <Alt+Shift+f>

Access Restriction

See these pages for implementing access restriction in MediaWiki:

  • A page that implement per-page access restriction [2].
  • Another way to hide pages [3].
  • Yet another extension [4].
  • Security problem with access restriction extension:
  • Some information on how to create custom namespaces [7].

Miscellaneous

Page Special:Version
produces a complete list of all extensions installed on the wiki.

Troubleshooting

Fix templates that always produce {{{1}}}

Update
No longer an issue on recent MW apparently (at least >=1.27).

Templates in Mediawiki will fail if the parameters contains an equal sign. Consider for instance the template nb:

<div class="noborder">
{{{1}}}</div>

Let's enclose a <source> tag:

{{nb|<source lang=bash>echo Hello</source>}}
echo Hello

The fix is simply to prepend 1= to the parameter value:

{{nb|1=<source lang=bash>echo Hello</source>}}
echo Hello

Tag attributes not expanded in templates

To have tag attributes expanded in wiki templates (in particular when these attributes contain template parameters), use the special construction {{#tag:tagname|content|attr1=val1|attr2=val2}}. See also #tag magic word and bugzilla 61341 for more information.

This is used in template Template:Rawfiledownloadexample:

You can download file "{{{name}}}" below, just click this link: {{#tag:file|{{{name}}}|name={{{name}}}|tag=pre}}.
{{#tag:pre|{{{content}}}}}

The example

{{Rawfiledownloadexample|name=myfile.txt|content=Once upon a time
There was a Tag
Tag was clickable
And clicked it was}}

expands into to the following with action ?action=raw&templates=expand:

You can download file "myfile.sh" below, just click this link: <file|name="myfile.sh" tag="pre">myfile.sh</file>.
<pre>Once upon a time
There was a Tag
Tag was clickable
And clicked it was</pre>

Can't upload file

Error message:

Could not create directory mwstore://local-backend/local-public/ when Uploading.

The problem is due to wrong ownership / permission in mediawiki folder [8]:

sudo chown -R www-data /var/www/mediawiki

MediaWiki for developers

References
Tips
  • In 99% of cases, extensions just need to use the method recursiveTagParse of the parser instead of Parser::parse (apparently this function is not re-entrant).

Debugging

To see PHP errors, add to LocalSettings.php (or can also edit php.ini or .htaccess Mediawiki - How to debug):

error_reporting( -1 );
ini_set( 'display_errors', 1 );

Globals

Some global variables defined by Mediawiki. Note that to use these variables, we must first declare them as global:

global $wgExtensionAssetsPath;
Name Default Description
$IP MW_INSTALL_PATH env var IP stands for Install Path. The variable holds the local file path to the base installation of your wiki.
$wgScriptPath /wiki The base URL path (in relation to DOCUMENT ROOT).
$wgExtensionAssetsPath {$wgScriptPath}/extensions URL to extensions directory. Used to provide a base URL for extension assets like extension-specific images and scripts. Note the difference between
  • $IP/extensions (points to the extensions directory on the server filesystem) and
  • $wgScriptPath/extensions (points to the URL of the extensions directory).

Modules

ResourceLoader

References
Quick walkthrough, registering modules, etc.
Add a CSS style module
For instance, from Extension::Cite
$wgHooks['BeforePageDisplay'][] = 'wfCiteBeforePageDisplay';
$wgResourceModules['ext.rtlcite'] = array(
	'localBasePath' => __DIR__ . '/modules',
	'remoteExtPath' => 'Cite/modules'
	'styles' => 'ext.rtlcite.css',
	'position' => 'top',
);

function wfCiteBeforePageDisplay( $out, &$sk ) {
	$out->addModuleStyles( 'ext.rtlcite' );
	return true;
}
In the following example we add the module only if a tag is present
$wgHooks['ParserFirstCallInit'][] = 'onParserSetup';
$wgResourceModules['ext.fentt'] = array(
    // ...
);
static function onParserSetup( Parser $parser ) {
    $parser->setHook( 'fentt', 'renderFenTT' );
}

$module_added = false;
function renderFenTT( $input, array $args, Parser $parser, PPFrame $frame ) {
    global $module_added;
    if( ! $module_added ) {
        $parser->getOutput()->addModuleStyles('ext.fentt');
        self::$module_added = true;
    }
    // ...
}
Troubleshoot
  • Module is listed in the <head> element, but corresponding CSS/JS does not appear in downloaded content
Try to register the module (add to $wgResourceModules) at global level (i.e. not in the hook handle function that calls $addModuleStyles).

Hooks

Javascript

Modules

JavaScript files are, like CSS files, also evaluated in the order they are defined in the scripts array (file extension.json). [9]

If a module must export a global object, do:

// foo.js
var Foo = {
    sayHello: function ( $element ) {
        $element.append( '<p>Hello Module!</p>' );
    }
};
window.Foo = Foo;

If a module must wait that the document be completely loaded before executing, do:

// init.js
$( function () {
    // This code must not be executed before the document is loaded. 
    Foo.sayHello( $( '#hello' ) );
});

Export javascript libraries

Some tips.

  • Javascript libraries must be loaded with the ResourceLoader.
  • JS libraries are loaded asynchronously. Moreover the global context is not the default global context, but the one of the ResourceLoader. If a library must export symbol to global context, they must attach it to the window object:
window.myjslib = myjslib;
In extension.json, we have:
    "ResourceModules": {
        "scripts": [ "myjslib.js", "myjslib.export.js" ]
    }
assuming that myjslib.js export to module.exports, we fix that in library myjslib.export.js:
// Let's export i18next correctly
window.myjslib = window.myjslib || module.exports;    // Don't export twice
$.myjslib = $.myjslib || module.exports;              // Alternatively we can attach to jQuery context
myjslib = $.myjslib;                                  // Export to default context
We must do this immediately after loading the library, because another library could overwrite module.exports.

ResourceLoader Core Modules

See ResourceLoader Core Modules.

These contains

  • The mediawiki module
  • The OOjs module
  • The jQuery module and plugins
jQuery plugins are available as ResourceLoader module that can be added as a module dependency in extension.json (for instance module jquery.ui.button).

To make sure that a module is available, either add it as dependency, or use the code [10]:

mw.loader.using( ['mediawiki.util','mediawiki.Title'] ).then( function () {
    /* This callback is invoked as soon as the modules are available. */
} );

There is also an error callback:

mw.loader.using([ 'mediawiki.util', 'jquery.placeholder', 'jquery.spinner' ], function(){
    console.warn( 'Ready callback was executed.', arguments );
}, function(){
    console.warn( 'Error callback was executed.', arguments );
});

Passing information from PHP to Javascript

See https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader#Passing_information_from_PHP_to_Javascript.

  • Store data in HTML.
  • Or use OutputPage::AddJsConfigVars. Pay attention however that PHP parser code are not necessarily run each time a page is visited (eg. if using memcached). If the parser must transfer data to JS context, one solution is to generate inline javascript in <script> tag.

Run with jQuery support or in RL context

To run our inline script with jQuery support, use the ResourceLoader queue RLQ [11], [12]:

RLQ.push(function () {
    console.log('This runs with jQuery support', $);
});
// or
(window.RLQ=window.RLQ||[]).push(function(){
    $(function() { console.log("test") });
});

Note that this is only useful for inlined scripts. Script loaded with the ResourceLoader may always assume that jQuery is available (since MW 1.17).

Add an external script

More solutions on Stack Overflow. For external script, call addHeadItem:

# Add onBeforePageDisplay function to BeforePageDisplay Hook
$wgHooks['BeforePageDisplay'][] ='onBeforePageDisplay';

function onBeforePageDisplay( OutputPage &$out, Skin &$skin )
{
    $script = '<script type="text/javascript" src="https://example.com/javascript.js"></script>';
    $out->addHeadItem("itemName", $script);
    return true;
};

Be aware that the script will be loaded in the default context, which is not the same as the ResourceLoader context that contains all loaded RL modules. So this script will not have access to RL libraries. To get access, add a callback to the ResourceLoader queue (see previous section).

Extension template

The Manual:Developing_extensions page gives us the structure that all extensions must follow.

Several templates are available:

extension.json
Since MW 1.25, all extension comes with a description file extension.json. See Extension.json schema for the list of all possible entries.

Troubleshooting an extension

First reflexes
  • Test extension in Chrome and Firefox.
  • Open up the browser debug window (Ctrl-Shift-C) and check the Console for javascript errors, file not found. Check also the network tab.
  • Try to load extension in an older version, and bisect the version where the extension fails.
  • Look at the MediaWiki release note for breaking changes.
Attention points
  • MW + cache sucks. If changing PHP code, better edit a test page, add one character and save. This will flush the cache easily.
  • If changing JS code, then Shift+F5 in browser should refresh it.
Using foreign JS
  • These are probably minified. It helps greatly to replace them with pretty-printed version (e.g. https://www.prettifyjs.net/)
  • Insert console.log(...) statement to help debugging.
Example
PgnJS extension, migration to mw1.35
  • Extension fails on MW 1.35
  • Looking at MW 1.35 breaking changes, we see that jquery.ui.* have been removed. This is used in PgnJS extension.json.
  • Open up Firefox/Chrome debugging interface (Ctrl+Shift+C).
  • In Console, we see errors about Error: Unknown module: jquery.ui.core
  • Changing "dependencies": [ "jquery.ui.core", "jquery.ui.widget" ] to "dependencies": [ "jquery.ui" ] fixes the problem.
  • However we see we still get a deprecated warning.
Example 2
PgnJS extension, migration to latest PgnViewerJS
  • We first create a static file example.html just to make sure that the apache server is configured correctly (no perm issue)
  • This will gives the value of the path to use internally (PgnViewerJS expect this path in a variable __globalCustomDomain.

How-To

Add an extension stylesheet in HTML head element

The goal is to add a stylesheet <link> tag in the HTML <head> element, either ALWAYS or CONDITIONALLY, and/or STATIC link or DYNAMIC link (from page content).

<head>
  ...
  <link rel="stylesheet" href="..." />
  ...
</head>
Criteria
  • Must work with recent MW version, and use stable API.
  • Must be page-caching friendly.
  • If link is added conditionally, avoid parsing twice the page content. Can we use some context information?
Relevant hooks
Relevant example extensions
list of extensions designed to modify information in the HTML <head> element
For MW 1.16.x and above. Use hook RawPageViewBeforeOutput to sanitize CSS, and ParserFirstCallInit to add a head item with $parser->getOutput()->addHeadItem( $headItem );.
For MW 1.16+. Use a ParserFirstCallInit hook, then add a <style> element using $wgParser->mOutput->addHeadItem when it encounters a <css> tag. Looks an excellent candidate for our stuff!
Inserts <script> (i.e. Javascript) or <link> (i.e. CSS) code at the bottom of the page's head or within the page's body. Securely inserts arbitrary code to the page's head using <addtohead>.
For MW 1.10, 1.11. Likely too complex for our use. Insert a metatag as an HTML comment, which is then parsed again (via preg_match_all) in OutputPageBeforeHTML hook.
Found simply by ... looking for .css files in MW extensions/ directory!
Uses hooks ParserFirstCallInit (to register parser hooks for Cite tags like <ref>) and BeforePageDisplay (to add modules, including the call to addModuleStyles). But... checking the page source it turns out that Cite css file is *always* loaded by the dynamic resource loader, even when the tag is not used on the page. Is that a problem?
Troubleshooting
  • $parser->getOutput()->addHeadItem( "..." ) not working on mobile device.
It works on desktop, on my tablet, but not on my smartphone. Why?
The fix is to load the module with addModuleStyles()($modules), as done for instance in Extension:Cite
Questions
  • On Wikimedia, there is a link at the bottom to toggle between mobile / desktop view. Handy to test a site in mobile mode. How can we get it installed? By upgrading to the latest MW? or installing Mobile extension
The Solution
if (defined('MEDIAWIKI')) {
    $wgHooks['ParserFirstCallInit'][] = 'MWFenTT::onParserFirstCallInit';

    $wgResourceModules['ext.FenTT'] = array(
	    'localBasePath' => __DIR__,
	    'remoteExtPath' => 'FenTT',
	    'styles'        => 'FenTT.css',
	    'position'      => 'top',
    );

    class MWFenTT {
        private static $css_module_added = false;

        static function onParserFirstCallInit( Parser $parser ) {
            // Register parser handler for tag <fentt>
            $parser->setHook( 'fentt', 'MWFenTT::renderFentt' )
        }

        static function renderFentt( $input, array $args, Parser $parser, PPFrame $frame ) {
            if( ! self::$css_module_added ) {
                // Tell ResourceLoader that we need our css module
                $parser->getOutput()->addModuleStyles( 'ext.FenTT' );
                self::$css_module_added = true;
            }
            return FenTT::renderFentt($input,$args);
        }
    }
}

Extensions

MediaWiki for Mobile

References
CSS

Extensions for Mobile

See also Writing a MobileFrontend friendly ResourceLoader module

Administration

Delete a page permanently

This procedure allows for permanently deleting a page from the wiki database, including the whole history. After this, there will be no trace left of the content of that page, except for a trace in the delete log indicating the date when the page was deleted and the reason (if any given).

  • First, as admin user, go to the page to delete.
  • In the menu, select 'Delete', select and type in a reason, then click "Delete page".
From now on, the page is deleted, but history is still in the database. Deletion can be reverted by going to the delete log page (Special:Log/delete)
  • On the wiki server, run the maintenance script named deleteArchivedRevisions.php. This will permanently delete the page history from the wiki db.
cd /var/lib/mediawiki/maintenance
php ./deleteArchivedRevisions.php --delete

Upload lots of file at once

Use local command importImages.php [13].

php maintenance/importImages.php --comment "Rubik's cube position, better perspective" /opt/www/daemenj/web/kiwi.noekeon.org/miki/rb png

Or to force a specific user:

sudo -u www-data php maintenance/importImages.php --comment "Rubik OLL cases, from http://www.cubewhiz.com/oll.php" tmp/