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();
84 public function setLogger( LoggerInterface $saveParseLogger ) {
85 $this->saveParseLogger = $saveParseLogger;
122 if ( $rev->
getWikiId() !== $this->dbDomain ) {
123 throw new InvalidArgumentException(
'Mismatching wiki ID ' . $rev->
getWikiId() );
126 $audience = $hints[
'audience']
136 $options = $forPerformer ?
137 ParserOptions::newFromUser( $forPerformer->getUser() ) :
138 ParserOptions::newFromAnon();
141 if ( isset( $hints[
'causeAction'] ) ) {
145 $usePrimary = $hints[
'use-master'] ??
false;
147 $dbIndex = $usePrimary
152 return $this->getSpeculativeRevId( $dbIndex );
155 return $this->getSpeculativePageId( $dbIndex );
165 $previousOutput = $hints[
'previous-output'] ??
null;
169 $this->contentRenderer,
170 function (
RenderedRevision $rrev, array $hints ) use ( $options, $previousOutput ) {
171 $h = [
'previous-output' => $previousOutput ] + $hints;
172 return $this->combineSlotOutput( $rrev, $options, $h );
180 if ( isset( $hints[
'known-revision-output'] ) ) {
181 $renderedRevision->setRevisionParserOutput( $hints[
'known-revision-output'] );
184 return $renderedRevision;
187 private function getSpeculativeRevId( $dbIndex ) {
190 $flags = ILoadBalancer::CONN_TRX_AUTOCOMMIT;
192 $db = $this->loadBalancer->getConnection( $dbIndex, [], $this->dbDomain, $flags );
194 return 1 + (int)$db->newSelectQueryBuilder()
195 ->select(
'MAX(rev_id)' )
197 ->caller( __METHOD__ )->fetchField();
200 private function getSpeculativePageId( $dbIndex ) {
203 $flags = ILoadBalancer::CONN_TRX_AUTOCOMMIT;
205 $db = $this->loadBalancer->getConnection( $dbIndex, [], $this->dbDomain, $flags );
207 return 1 + (int)$db->newSelectQueryBuilder()
208 ->select(
'MAX(page_id)' )
210 ->caller( __METHOD__ )->fetchField();
227 private function combineSlotOutput( RenderedRevision $rrev,
ParserOptions $options, array $hints = [] ) {
228 $revision = $rrev->getRevision();
229 $slots = $revision->getSlots()->getSlots();
231 $withHtml = $hints[
'generate-html'] ??
true;
232 $previousOutputs = $this->splitSlotOutput( $rrev, $options, $hints[
'previous-output'] ??
null );
247 $combinedOutput =
new ParserOutput(
null );
250 $options = $rrev->getOptions();
253 foreach ( $slots as $role => $slot ) {
254 $h = [
'previous-output' => $previousOutputs[$role] ] + $hints;
255 $out = $rrev->getSlotParserOutput( $role, $h );
256 $slotOutput[$role] = $out;
259 $combinedOutput->mergeInternalMetaDataFrom( $out );
260 $combinedOutput->mergeTrackingMetaDataFrom( $out );
267 foreach ( $slotOutput as $role => $out ) {
268 $roleHandler = $this->roleRegistry->getRoleHandler( $role );
271 $layout = $roleHandler->getOutputLayoutHints();
272 $display = $layout[
'display'] ??
'section';
274 if ( $display ===
'none' ) {
284 $html .= Html::rawElement(
'h1', [
'class' =>
'mw-slot-header' ], $headText );
289 $html .= $out->getRawText();
290 $combinedOutput->mergeHtmlMetaDataFrom( $out );
293 $combinedOutput->setRawText( $html );
297 return $combinedOutput;
317 private function splitSlotOutput( RenderedRevision $rrev,
ParserOptions $options, ?ParserOutput $previousOutput ) {
319 $revision = $rrev->getRevision();
320 $revslots = $revision->getSlots();
321 if ( $previousOutput ===
null ) {
322 return array_fill_keys( $revslots->getSlotRoles(),
null );
333 return array_fill_keys( $revslots->getSlotRoles(),
null );