Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
osnard opened this issue Dec 4, 2023 · 1 comment

Comments

@osnard
Copy link
Contributor

osnard commented Dec 4, 2023

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
Copy link

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants