48 private $saveParseLogger;
51 private $loadBalancer;
54 private $roleRegistry;
57 private $contentRenderer;
74 $this->loadBalancer = $loadBalancer;
75 $this->roleRegistry = $roleRegistry;
76 $this->contentRenderer = $contentRenderer;
77 $this->dbDomain = $dbDomain;
78 $this->saveParseLogger =
new NullLogger();
81 public function setLogger( LoggerInterface $saveParseLogger ) {
82 $this->saveParseLogger = $saveParseLogger;
119 if ( $rev->
getWikiId() !== $this->dbDomain ) {
120 throw new InvalidArgumentException(
'Mismatching wiki ID ' . $rev->
getWikiId() );
123 $audience = $hints[
'audience']
133 $options = $forPerformer ?
134 ParserOptions::newFromUser( $forPerformer->getUser() ) :
135 ParserOptions::newFromAnon();
138 if ( isset( $hints[
'causeAction'] ) ) {
139 $options->setRenderReason( $hints[
'causeAction'] );
142 $usePrimary = $hints[
'use-master'] ??
false;
144 $dbIndex = $usePrimary
148 $options->setSpeculativeRevIdCallback(
function () use ( $dbIndex ) {
149 return $this->getSpeculativeRevId( $dbIndex );
151 $options->setSpeculativePageIdCallback(
function () use ( $dbIndex ) {
152 return $this->getSpeculativePageId( $dbIndex );
162 $previousOutput = $hints[
'previous-output'] ??
null;
166 $this->contentRenderer,
167 function (
RenderedRevision $rrev, array $hints ) use ( $options, $previousOutput ) {
168 $h = [
'previous-output' => $previousOutput ] + $hints;
169 return $this->combineSlotOutput( $rrev, $options, $h );
177 if ( isset( $hints[
'known-revision-output'] ) ) {
178 $renderedRevision->setRevisionParserOutput( $hints[
'known-revision-output'] );
181 return $renderedRevision;
184 private function getSpeculativeRevId( $dbIndex ) {
187 $flags = ILoadBalancer::CONN_TRX_AUTOCOMMIT;
189 $db = $this->loadBalancer->getConnection( $dbIndex, [], $this->dbDomain, $flags );
191 return 1 + (int)$db->newSelectQueryBuilder()
192 ->select(
'MAX(rev_id)' )
194 ->caller( __METHOD__ )->fetchField();
197 private function getSpeculativePageId( $dbIndex ) {
200 $flags = ILoadBalancer::CONN_TRX_AUTOCOMMIT;
202 $db = $this->loadBalancer->getConnection( $dbIndex, [], $this->dbDomain, $flags );
204 return 1 + (int)$db->newSelectQueryBuilder()
205 ->select(
'MAX(page_id)' )
207 ->caller( __METHOD__ )->fetchField();
224 private function combineSlotOutput( RenderedRevision $rrev, ParserOptions $options, array $hints = [] ) {
225 $revision = $rrev->getRevision();
226 $slots = $revision->getSlots()->getSlots();
228 $withHtml = $hints[
'generate-html'] ??
true;
229 $previousOutputs = $this->splitSlotOutput( $rrev, $options, $hints[
'previous-output'] ??
null );
234 if ( array_keys( $slots ) === [
SlotRecord::MAIN ] || $options->getUseParsoid() ) {
244 $combinedOutput =
new ParserOutput(
null );
247 $options = $rrev->getOptions();
248 $options->registerWatcher( [ $combinedOutput,
'recordOption' ] );
250 foreach ( $slots as $role => $slot ) {
251 $h = [
'previous-output' => $previousOutputs[$role] ] + $hints;
252 $out = $rrev->getSlotParserOutput( $role, $h );
253 $slotOutput[$role] = $out;
256 $combinedOutput->mergeInternalMetaDataFrom( $out );
257 $combinedOutput->mergeTrackingMetaDataFrom( $out );
264 foreach ( $slotOutput as $role => $out ) {
265 $roleHandler = $this->roleRegistry->getRoleHandler( $role );
268 $layout = $roleHandler->getOutputLayoutHints();
269 $display = $layout[
'display'] ??
'section';
271 if ( $display ===
'none' ) {
281 $html .= Html::rawElement(
'h1', [
'class' =>
'mw-slot-header' ], $headText );
286 $html .= $out->getRawText();
287 $combinedOutput->mergeHtmlMetaDataFrom( $out );
290 $combinedOutput->setRawText( $html );
293 $options->registerWatcher(
null );
294 return $combinedOutput;
314 private function splitSlotOutput( RenderedRevision $rrev, ParserOptions $options, ?ParserOutput $previousOutput ) {
316 $revision = $rrev->getRevision();
317 $revslots = $revision->getSlots();
318 if ( $previousOutput ===
null ) {
319 return array_fill_keys( $revslots->getSlotRoles(),
null );
325 if ( $revslots->getSlotRoles() === [
SlotRecord::MAIN ] || $options->getUseParsoid() ) {
330 return array_fill_keys( $revslots->getSlotRoles(),
null );