Implement ParsoidFetchTemplateData hook for Parsoid/PHP

* This hook supports functionality that Parsoid/JS used the MW API for.

  Parsoid's html2wt code requests templatedata for titles one
  at a time currently and so this hook also supports lookups one
  title at a time.

  This initial implementation is good enough for initial Parsoid/PHP
  deployment.

* As part of later performance optimization, we should figure out if
  we want to fetch templatedata for all templates in batch mode and
  work out the details (selser doesn't touch all templates, for one).

  The hook does accept an array of titles, but it looks them up
  serially in a simple for-loop.

  Separately, we need to resolve if this is better architected as
  a lookup service vs. a hook as it is now (see discussion on gerrit).

* Tested locally on my local wiki.

Bug: T238954
Change-Id: I01fb6a9f334ca37a703be497524180f87fb8bbf7
This commit is contained in:
Subramanya Sastry 2019-11-22 23:18:15 -06:00
parent 06adf70c0c
commit 956367fb90
2 changed files with 66 additions and 0 deletions

View file

@ -41,6 +41,9 @@
],
"EditPage::showEditForm:initial": [
"TemplateDataHooks::onEditPage"
],
"ParserFetchTemplateData": [
"TemplateDataHooks::onParserFetchTemplateData"
]
},
"MessagesDirs": {

View file

@ -159,4 +159,67 @@ class TemplateDataHooks {
return $ti->getHtml( $parser->getOptions()->getUserLangObj() );
}
/**
* Fetch templatedata for an array of titles.
*
* @todo Document this hook
*
* The following questions are yet to be resolved.
* (a) Should we extend functionality to looking up an array of titles instead of one?
* The signature allows for an array of titles to be passed in, but the
* current implementation is not optimized for the multple-title use case.
* (b) Should this be a lookup service instead of this faux hook?
* This will be resolved separately.
*
* @param array $tplTitles
* @param stdclass[] &$tplData
* @return bool
*/
public static function onParserFetchTemplateData( array $tplTitles, array &$tplData ): bool {
$tplData = [];
// This inefficient implementation is currently tuned for
// Parsoid's use case where it requests info for exactly one title.
// For a real batch use case, this code will need an overhaul.
foreach ( $tplTitles as $tplTitle ) {
$title = Title::newFromText( $tplTitle );
if ( !$title ) { // Invalid title
$tplData[$tplTitle] = null;
continue;
}
if ( $title->isRedirect() ) {
$title = ( new WikiPage( $title ) )->getRedirectTarget();
if ( !$title ) { // Invalid redirecting title
$tplData[$tplTitle] = null;
continue;
}
}
if ( !$title->exists() ) {
$tplData[$tplTitle] = (object)[ "missing" => true ];
continue;
}
$pageId = $title->getArticleID();
$props = PageProps::getInstance()->getProperties( $title, 'templatedata' );
if ( !isset( $props[$pageId] ) ) { // No templatedata
$tplData[$tplTitle] = (object)[ "notemplatedata" => true ];
continue;
}
$tdb = TemplateDataBlob::newFromDatabase( wfGetDB( DB_REPLICA ), $props[$pageId] );
$status = $tdb->getStatus();
if ( !$status->isOK() ) {
// Invalid data. Parsoid has no use for the error.
$tplData[$tplTitle] = (object)[ "notemplatedata" => true ];
continue;
}
$tplData[$tplTitle] = $tdb->getData();
}
return true;
}
}