SemanticMediaWiki / SemanticResultFormats

Provides additional visualizations (result formats) for Semantic MediaWiki
https://www.semantic-mediawiki.org/wiki/Extension:Semantic_Result_Formats
Other
45 stars 75 forks source link

Access to global `Parser` object can break in non-index.php-request contexts #802

Open osnard opened 7 months ago

osnard commented 7 months ago

Some result formats (e.g. "filtered") seem to rely on the global Parser object. Example: https://github.com/SemanticMediaWiki/SemanticResultFormats/blob/4.1.0/formats/filtered/src/Filtered.php#L102

This can lead to errors like

Error: Call to a member function getMaxIncludeSize() on null

Backtrace:

from includes/parser/Parser.php(2935)
#0 includes/parser/Parser.php(1609): Parser->replaceVariables()
#1 includes/parser/Parser.php(881): Parser->internalParse()
#2 extensions/SemanticResultFormats/formats/filtered/src/Filters/Filter.php(144): Parser->recursiveTagParse()
#3 extensions/SemanticResultFormats/formats/filtered/src/Filters/Filter.php(171): SRF\Filtered\Filter\Filter->addValueToJsConfig()
#4 extensions/SemanticResultFormats/formats/filtered/src/Filters/ValueFilter.php(38): SRF\Filtered\Filter\Filter->addValueListToJsConfig()
#5 extensions/SemanticResultFormats/formats/filtered/src/Filters/Filter.php(115): SRF\Filtered\Filter\ValueFilter->buildJsConfig()
#6 extensions/SemanticResultFormats/formats/filtered/src/Filtered.php(375): SRF\Filtered\Filter\Filter->getJsConfig()
#7 extensions/SemanticResultFormats/formats/filtered/src/Filtered.php(189): SRF\Filtered\Filtered->getFilterHtml()
#8 extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php(339): SRF\Filtered\Filtered->getResultText()
#9 extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php(304): SMW\Query\ResultPrinters\ResultPrinter->buildResult()
#10 extensions/SemanticMediaWiki/includes/query/SMW_QueryProcessor.php(348): SMW\Query\ResultPrinters\ResultPrinter->getResult()
#11 extensions/SemanticMediaWiki/src/ParserFunctions/AskParserFunction.php(370): SMWQueryProcessor::getResultFromQuery()
#12 extensions/SemanticMediaWiki/src/ParserFunctions/AskParserFunction.php(202): SMW\ParserFunctions\AskParserFunction->doFetchResultsFromFunctionParameters()
#13 extensions/SemanticMediaWiki/src/ParserFunctionFactory.php(402): SMW\ParserFunctions\AskParserFunction->parse()
#14 includes/parser/Parser.php(3437): SMW\ParserFunctionFactory->SMW\{closure}()
#15 includes/parser/Parser.php(3122): Parser->callParserFunction()
#16 includes/parser/PPFrame_Hash.php(275): Parser->braceSubstitution()
#17 includes/parser/Parser.php(2951): PPFrame_Hash->expand()
#18 includes/parser/Parser.php(1609): Parser->replaceVariables()
#19 includes/parser/Parser.php(723): Parser->internalParse()
...

when the code gets executed in a context different from the regular index.php-request.

Background: In newer MediaWiki versions there is a dedicated MediaWikiServices service (ParserFactory) to create new, independent Parser objects

Example for such code:

$page = $this->wikiPageFactory->newFromLinkTarget( $target );
$parserOptions = $page->makeParserOptions( 'canonical' );
$parser = $this->parserFactory->create();
$parserOutput = $parser->parse(
    $page->getContent()->getWikitextForTransclusion(),
    $page->getTitle(),
    $parserOptions,
    true,
    true,
    $page->getTitle()->getLatestRevID()
);

In this case the valid ParserOptions object passed to the Parser::parse method will not be set on the global Parser object. In the global object it may be null, depending on the context of this code (e.g. within a REST-API call).

One could probably consider this an edge case, but relying on global state objects should be avoided in general.

Usually this would be solved by passing the Parser object provided by MediaWiki to the handler implementation of the {{#ask:}} parser function (the callback registered by Parser::setFunctionHook) down to the result format. Unfortunately I didn't find a nice way to do that.

Any suggestions are welcome. If you can give me a hint about how to properly solve this, I can submit a patch.

simontaurus commented 1 month ago

I can confirm this issue for the case a page with

{{#ask: [[Category:SomeProcessCategory]]
|?HasSuccessor
|format=graph
|graphlink=yes
|rankdir=TB
}}

is edited with the VisualEditor

{
  "error": {
    "code": "internal_api_error_Error",
     "info":"[18e4c61e4d11b00628c7ec6f] Exception caught: Call to a member function getMaxIncludeSize() on null",
     "errorclass":"Error",
     "trace":"Error at ...."
   }
}
Error at /var/www/html/w/includes/parser/Parser.php(2935)
from /var/www/html/w/includes/parser/Parser.php(2935)
#0 /var/www/html/w/includes/parser/Parser.php(1609): Parser->replaceVariables()
#1 /var/www/html/w/includes/parser/Parser.php(881): Parser->internalParse()
#2 /var/www/html/w/extensions/SemanticResultFormats/src/Graph/GraphPrinter.php(173): Parser->recursiveTagParse()
#3 /var/www/html/w/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php(339): SRF\\Graph\\GraphPrinter->ge…ncludes/ApiVisualEditor.php(279): MediaWiki\\Extension\\VisualEditor\\ApiVisualEditor->requestRestbasePageHtml()
#34 /var/www/html/w/includes/api/ApiMain.php(1900): MediaWiki\\Extension\\VisualEditor\\ApiVisualEditor->execute()
#35 /var/www/html/w/includes/api/ApiMain.php(875): ApiMain->executeAction()
#36 /var/www/html/w/includes/api/ApiMain.php(846): ApiMain->executeActionWithErrorHandling()
#37 /var/www/html/w/api.php(90): ApiMain->execute()
#38 /var/www/html/w/api.php(45): wfApiMain()
#39 {main}

@kghbln, @JeroenDeDauw: Can you give us a hint where to inject a proper Parser object?