I try to write a parser-function extension for mediawiki and even with a very simple skeleton adapted from their docs, I get a class not found error, if the extension is loaded. I compared my skeleton code with the popular "ParserFunctions" extension, for me it looks identically...
"extensions/MyExtension/extension.json":
{
"name": "MyExtension",
"author": "me",
"version": "0.1.0",
"descriptionmsg": "myextension-desc",
"license-name": "proprietary",
"type": "parserhook",
"requires": {
"MediaWiki": ">= 1.31.0"
},
"config": {
"MyExtensionUrls": {
"value": [],
"description": "Set api URLs (associative array)"
}
},
"ConfigRegistry": {
"myextension": "GlobalVarConfig::newInstance"
},
"MessagesDirs": {
"MyExtension": [
"i18n"
]
},
"AutoloadNamespaces": {
"MediaWiki\\Extension\\MyExtension\\": "src/"
},
"ExtensionMessagesFiles": {
"MyExtensionMagic": "MyExtension.i18n.php"
},
"Hooks": {
"ParserFirstCallInit": "MyExtension::onParserFirstCallInit"
},
"manifest_version": 2
}
"extensions/MyExtension/src/MyExtension.php":
<?php
namespace MediaWiki\Extension\MyExtension;
use Parser;
use MWException;
use MediaWiki\MediaWikiServices;
class MyExtension {
private static array $urls;
public static function onParserFirstCallInit(Parser $parser): void {
// get config
$config = MediaWikiServices::getInstance()->getConfigFactory()->makeConfig('myextension');
// get api urls
$urls = $config->get('MyExtensionUrls');
// check api urls
if(\sizeof($urls) === 0) {
throw new MWException("Configuration error, no api URL set.\n
Please set at least one \"keyName\" => \"http://url.to/api\" pair in LocalSettings.php \$wgMyExtensionUrls array.");
} else {
// set urls
self::$urls = $urls;
// Create a function hook associating the "example" magic word with renderExample()
$parser->setFunctionHook('example', [ self::class, 'renderExample' ]);
}
}
public static function renderExample(Parser &$parser, ...$args): string {
// return
return '--Example--';
}
}
"extensions/MyExtension/MyExtension.i18n.php":
<?php
$magicWords = [];
// English
$magicWords['en'] = [
'example' => [ 0, 'example' ],
];
// German
$magicWords['de'] = [
'example' => [ 0, 'beispiel' ],
];
Using wfLoadExtension('MyExtension'); in LocalSettings.php leads to the following stack trace:
MediaWiki internal error.
Original exception: [2e8e18a2084d81b05f93bf0f] /index.php/Hauptseite Error: Class 'MyExtension' not found
Backtrace:
from /var/www/html/includes/HookContainer/HookContainer.php(338)
#0 /var/www/html/includes/HookContainer/HookContainer.php(137): MediaWiki\HookContainer\HookContainer->callLegacyHook(string, array, array, array)
#1 /var/www/html/includes/HookContainer/HookRunner.php(2872): MediaWiki\HookContainer\HookContainer->run(string, array)
#2 /var/www/html/includes/parser/Parser.php(533): MediaWiki\HookContainer\HookRunner->onParserFirstCallInit(Parser)
#3 /var/www/html/includes/parser/ParserFactory.php(196): Parser->__construct(MediaWiki\Config\ServiceOptions, MagicWordFactory, Language, ParserFactory, string, MediaWiki\SpecialPage\SpecialPageFactory, MediaWiki\Linker\LinkRendererFactory, NamespaceInfo, MediaWiki\Logger\LegacyLogger, MediaWiki\BadFileLookup, MediaWiki\Languages\LanguageConverterFactory, MediaWiki\HookContainer\HookContainer, MediaWiki\Tidy\RemexDriver, WANObjectCache, MediaWiki\User\UserOptionsManager, MediaWiki\User\UserFactory, MediaWikiTitleCodec, MediaWiki\Http\HttpRequestFactory, TrackingCategories)
#4 /var/www/html/includes/ServiceWiring.php(1211): ParserFactory->create()
#5 /var/www/html/vendor/wikimedia/services/src/ServiceContainer.php(447): Wikimedia\Services\ServiceContainer::{closure}(MediaWiki\MediaWikiServices)
#6 /var/www/html/vendor/wikimedia/services/src/ServiceContainer.php(416): Wikimedia\Services\ServiceContainer->createService(string)
#7 /var/www/html/includes/MediaWikiServices.php(294): Wikimedia\Services\ServiceContainer->getService(string)
#8 /var/www/html/includes/MediaWikiServices.php(1366): MediaWiki\MediaWikiServices->getService(string)
#9 /var/www/html/includes/cache/MessageCache.php(1270): MediaWiki\MediaWikiServices->getParser()
#10 /var/www/html/includes/cache/MessageCache.php(1249): MessageCache->getParser()
#11 /var/www/html/includes/language/Message.php(1474): MessageCache->transform(string, boolean, Language, Title)
#12 /var/www/html/includes/language/Message.php(1007): Message->transformText(string)
#13 /var/www/html/includes/language/Message.php(1071): Message->format(string)
#14 /var/www/html/includes/OutputPage.php(1041): Message->text()
#15 /var/www/html/includes/OutputPage.php(1090): OutputPage->setHTMLTitle(Message)
#16 /var/www/html/includes/page/Article.php(464): OutputPage->setPageTitle(string)
#17 /var/www/html/includes/actions/ViewAction.php(80): Article->view()
#18 /var/www/html/includes/MediaWiki.php(543): ViewAction->show()
#19 /var/www/html/includes/MediaWiki.php(321): MediaWiki->performAction(Article, Title)
#20 /var/www/html/includes/MediaWiki.php(912): MediaWiki->performRequest()
#21 /var/www/html/includes/MediaWiki.php(563): MediaWiki->main()
#22 /var/www/html/index.php(53): MediaWiki->run()
#23 /var/www/html/index.php(46): wfIndexMain()
#24 {main}
My test environment is the "official" docker container where I used the extensions directory as local volume.
Can anyone point me in the right direction, what my mistake might be?
UPDATE
I made a test using the AutoloadClasses setting in extension.json
{
"AutoloadClasses": {
"MyExtension": "src/MyExtension.php"
},
}
and removing the namespacing of the extension
<?php
use MediaWiki\MediaWikiServices;
class MyExtension {
...
and it (nearly) works like it should (but that "nearly" has nothing to do with the namespace problem here)...
So my code has definitively a problem with the namespacing, but I'd like to use it... if anyone sees my mistake, please post an answere...