Merge "Move ParsoidOutputAccess::supportsContentModel() into Parsoid SiteConfig"

This commit is contained in:
jenkins-bot 2024-05-22 16:46:31 +00:00 committed by Gerrit Code Review
commit 08ef39abfd
16 changed files with 106 additions and 69 deletions

View file

@ -7141,7 +7141,7 @@ config-schema:
revertedTagUpdate: RevertedTagUpdateJob
'null': NullJob
userEditCountInit: UserEditCountInitJob
parsoidCachePrewarm: { class: ParsoidCachePrewarmJob, services: [ParsoidOutputAccess, PageStore, RevisionLookup], needsPage: false }
parsoidCachePrewarm: { class: ParsoidCachePrewarmJob, services: [ParsoidOutputAccess, PageStore, RevisionLookup, ParsoidSiteConfig], needsPage: false }
renameUser: { class: MediaWiki\RenameUser\RenameUserJob, services: [MainConfig, DBLoadBalancerFactory] }
type: object
description: |-

View file

@ -11445,7 +11445,8 @@ class MainConfigSchema {
'services' => [
'ParsoidOutputAccess',
'PageStore',
'RevisionLookup'
'RevisionLookup',
'ParsoidSiteConfig',
],
// tell the JobFactory not to include the $page parameter in the constructor call
'needsPage' => false

View file

@ -118,6 +118,7 @@ use MediaWiki\Parser\MagicWordFactory;
use MediaWiki\Parser\Parser;
use MediaWiki\Parser\ParserCacheFactory;
use MediaWiki\Parser\Parsoid\Config\PageConfigFactory;
use MediaWiki\Parser\Parsoid\Config\SiteConfig;
use MediaWiki\Parser\Parsoid\HtmlTransformFactory;
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
use MediaWiki\Parser\Parsoid\ParsoidParserFactory;
@ -208,7 +209,6 @@ use Wikimedia\Message\IMessageFormatterFactory;
use Wikimedia\NonSerializable\NonSerializableTrait;
use Wikimedia\ObjectFactory\ObjectFactory;
use Wikimedia\Parsoid\Config\DataAccess;
use Wikimedia\Parsoid\Config\SiteConfig;
use Wikimedia\Rdbms\ChronologyProtector;
use Wikimedia\Rdbms\ConfiguredReadOnlyMode;
use Wikimedia\Rdbms\DatabaseFactory;

View file

@ -245,7 +245,6 @@ use Wikimedia\EventRelayer\EventRelayerGroup;
use Wikimedia\Message\IMessageFormatterFactory;
use Wikimedia\ObjectFactory\ObjectFactory;
use Wikimedia\Parsoid\Config\DataAccess;
use Wikimedia\Parsoid\Config\SiteConfig;
use Wikimedia\Parsoid\Parsoid;
use Wikimedia\Rdbms\ChronologyProtector;
use Wikimedia\Rdbms\ConfiguredReadOnlyMode;
@ -1654,7 +1653,7 @@ return [
);
},
'ParsoidSiteConfig' => static function ( MediaWikiServices $services ): SiteConfig {
'ParsoidSiteConfig' => static function ( MediaWikiServices $services ): MWSiteConfig {
$mainConfig = $services->getMainConfig();
$parsoidSettings = $mainConfig->get( MainConfigNames::ParsoidSettings );
return new MWSiteConfig(
@ -1672,6 +1671,7 @@ return [
$services->getLanguageConverterFactory(),
$services->getLanguageNameUtils(),
$services->getUrlUtils(),
$services->getContentHandlerFactory(),
ExtensionRegistry::getInstance()->getAttribute( 'ParsoidModules' ),
// These arguments are temporary and will be removed once
// better solutions are found.

View file

@ -2144,6 +2144,7 @@ return [
'ParsoidOutputAccess',
'PageStore',
'RevisionLookup',
'ParsoidSiteConfig',
],
'needsPage' => false,
],

View file

@ -21,6 +21,7 @@
use MediaWiki\Logger\LoggerFactory;
use MediaWiki\Page\PageLookup;
use MediaWiki\Page\PageRecord;
use MediaWiki\Parser\Parsoid\Config\SiteConfig as ParsoidSiteConfig;
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
use MediaWiki\Revision\RevisionLookup;
use MediaWiki\Revision\SlotRecord;
@ -36,18 +37,21 @@ class ParsoidCachePrewarmJob extends Job {
private ParsoidOutputAccess $parsoidOutputAccess;
private PageLookup $pageLookup;
private RevisionLookup $revisionLookup;
private ParsoidSiteConfig $parsoidSiteConfig;
/**
* @param array $params
* @param ParsoidOutputAccess $parsoidOutputAccess
* @param PageLookup $pageLookup
* @param RevisionLookup $revisionLookup
* @param ParsoidSiteConfig $parsoidSiteConfig
*/
public function __construct(
array $params,
ParsoidOutputAccess $parsoidOutputAccess,
PageLookup $pageLookup,
RevisionLookup $revisionLookup
RevisionLookup $revisionLookup,
ParsoidSiteConfig $parsoidSiteConfig
) {
parent::__construct( 'parsoidCachePrewarm', $params );
@ -56,6 +60,7 @@ class ParsoidCachePrewarmJob extends Job {
$this->parsoidOutputAccess = $parsoidOutputAccess;
$this->pageLookup = $pageLookup;
$this->revisionLookup = $revisionLookup;
$this->parsoidSiteConfig = $parsoidSiteConfig;
}
/**
@ -124,7 +129,7 @@ class ParsoidCachePrewarmJob extends Job {
$parserOpts->setRenderReason( $renderReason );
$mainSlot = $rev->getSlot( SlotRecord::MAIN );
if ( !$this->parsoidOutputAccess->supportsContentModel( $mainSlot->getModel() ) ) {
if ( !$this->parsoidSiteConfig->supportsContentModel( $mainSlot->getModel() ) ) {
$this->logger->debug( __METHOD__ . ': Parsoid does not support content model ' . $mainSlot->getModel() );
return;
}

View file

@ -28,6 +28,7 @@ use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
use MediaWiki\Config\Config;
use MediaWiki\Config\MutableConfig;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\Interwiki\InterwikiLookup;
use MediaWiki\Languages\LanguageConverterFactory;
use MediaWiki\Languages\LanguageFactory;
@ -43,6 +44,7 @@ use MediaWiki\Title\Title;
use MediaWiki\User\Options\UserOptionsLookup;
use MediaWiki\Utils\UrlUtils;
use MediaWiki\WikiMap\WikiMap;
use MWUnknownContentModelException;
use ParserFactory;
use PrefixingStatsdDataFactoryProxy;
use Psr\Log\LoggerInterface;
@ -113,6 +115,7 @@ class SiteConfig extends ISiteConfig {
private LanguageConverterFactory $languageConverterFactory;
private LanguageNameUtils $languageNameUtils;
private UrlUtils $urlUtils;
private IContentHandlerFactory $contentHandlerFactory;
private ?string $baseUri = null;
private ?string $relativeLinkPrefix = null;
private ?array $interwikiMap = null;
@ -135,6 +138,7 @@ class SiteConfig extends ISiteConfig {
* @param LanguageConverterFactory $languageConverterFactory
* @param LanguageNameUtils $languageNameUtils
* @param UrlUtils $urlUtils
* @param IContentHandlerFactory $contentHandlerFactory
* @param array $extensionParsoidModules
* @param ParserFactory $parserFactory
* @param Config $mwConfig
@ -155,6 +159,7 @@ class SiteConfig extends ISiteConfig {
LanguageConverterFactory $languageConverterFactory,
LanguageNameUtils $languageNameUtils,
UrlUtils $urlUtils,
IContentHandlerFactory $contentHandlerFactory,
array $extensionParsoidModules,
// $parserFactory is temporary and may be removed once a better solution is found.
ParserFactory $parserFactory, // T268776
@ -181,6 +186,7 @@ class SiteConfig extends ISiteConfig {
$this->languageConverterFactory = $languageConverterFactory;
$this->languageNameUtils = $languageNameUtils;
$this->urlUtils = $urlUtils;
$this->contentHandlerFactory = $contentHandlerFactory;
// Override parent default
if ( isset( $this->parsoidSettings['linting'] ) ) {
@ -763,4 +769,33 @@ class SiteConfig extends ISiteConfig {
public function getExternalLinkTarget() {
return $this->config->get( MainConfigNames::ExternalLinkTarget );
}
// MW-specific helper
/**
* Returns true iff Parsoid natively supports the given content model.
* @param string $model content model identifier
* @return bool
*/
public function supportsContentModel( string $model ): bool {
if ( $model === CONTENT_MODEL_WIKITEXT ) {
return true;
}
// Check if the content model serializes to wikitext.
// NOTE: We could use isSupportedFormat( CONTENT_FORMAT_WIKITEXT ) if PageContent::getContent()
// would specify the format when calling serialize().
try {
$handler = $this->contentHandlerFactory->getContentHandler( $model );
if ( $handler->getDefaultFormat() === CONTENT_FORMAT_WIKITEXT ) {
return true;
}
} catch ( MWUnknownContentModelException $ex ) {
// If the content model is not known, it can't be supported.
return false;
}
return $this->getContentModelHandler( $model ) !== null;
}
}

View file

@ -25,14 +25,13 @@ use MediaWiki\Page\PageLookup;
use MediaWiki\Page\PageRecord;
use MediaWiki\Page\ParserOutputAccess;
use MediaWiki\Parser\ParserOutput;
use MediaWiki\Parser\Parsoid\Config\SiteConfig;
use MediaWiki\Revision\RevisionAccessException;
use MediaWiki\Revision\RevisionLookup;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\Status\Status;
use MWUnknownContentModelException;
use ParserOptions;
use Wikimedia\Parsoid\Config\SiteConfig;
use Wikimedia\Parsoid\Core\ClientError;
use Wikimedia\Parsoid\Core\ResourceLimitExceededException;
@ -81,32 +80,6 @@ class ParsoidOutputAccess {
$this->contentHandlerFactory = $contentHandlerFactory;
}
/**
* @param string $model
*
* @return bool
*/
public function supportsContentModel( string $model ): bool {
if ( $model === CONTENT_MODEL_WIKITEXT ) {
return true;
}
// Check if the content model serializes to wikitext.
// NOTE: We could use isSupportedFormat( CONTENT_FORMAT_WIKITEXT ) if PageContent::getContent()
// would specify the format when calling serialize().
try {
$handler = $this->contentHandlerFactory->getContentHandler( $model );
if ( $handler->getDefaultFormat() === CONTENT_FORMAT_WIKITEXT ) {
return true;
}
} catch ( MWUnknownContentModelException $ex ) {
// If the content model is not known, it can't be supported.
return false;
}
return $this->siteConfig->getContentModelHandler( $model ) !== null;
}
/**
* @param PageIdentity $page
* @param ParserOptions $parserOpts
@ -272,7 +245,7 @@ class ParsoidOutputAccess {
private function adjustParserOptions( RevisionRecord $revision, ParserOptions $parserOpts ): void {
$mainSlot = $revision->getSlot( SlotRecord::MAIN );
$contentModel = $mainSlot->getModel();
if ( $this->supportsContentModel( $contentModel ) ) {
if ( $this->siteConfig->supportsContentModel( $contentModel ) ) {
// Since we know Parsoid supports this content model, explicitly
// call ParserOptions::setUseParsoid. This ensures that when
// we query the parser-cache, the right cache key is called.

View file

@ -2,6 +2,7 @@
use MediaWiki\Page\PageIdentity;
use MediaWiki\Page\PageLookup;
use MediaWiki\Page\ParserOutputAccess;
use MediaWiki\Parser\Parsoid\Config\SiteConfig as ParsoidSiteConfig;
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
use MediaWiki\Revision\RevisionLookup;
use MediaWiki\Revision\RevisionRecord;
@ -23,6 +24,7 @@ class PrewarmParsoidParserCache extends Maintenance {
private ParsoidOutputAccess $parsoidOutputAccess;
private PageLookup $pageLookup;
private RevisionLookup $revisionLookup;
private ParsoidSiteConfig $parsoidSiteConfig;
public function __construct() {
parent::__construct();
@ -57,6 +59,11 @@ class PrewarmParsoidParserCache extends Maintenance {
return $this->parsoidOutputAccess;
}
private function getParsoidSiteConfig(): ParsoidSiteConfig {
$this->parsoidSiteConfig = $this->getServiceContainer()->getParsoidSiteConfig();
return $this->parsoidSiteConfig;
}
private function getQueryBuilder(): SelectQueryBuilder {
$dbr = $this->getReplicaDB();
@ -149,7 +156,7 @@ class PrewarmParsoidParserCache extends Maintenance {
$mainSlot = $revision->getSlot( SlotRecord::MAIN );
// POA will write a dummy output to PC, but we don't want that here. Just skip!
if ( !$this->getParsoidOutputAccess()->supportsContentModel( $mainSlot->getModel() ) ) {
if ( !$this->getParsoidSiteConfig()->supportsContentModel( $mainSlot->getModel() ) ) {
$this->output(
'[Skipped] Content model "' .
$mainSlot->getModel() .

View file

@ -50,7 +50,8 @@ class JobFactoryTest extends MediaWikiIntegrationTestCase {
'services' => [
'ParsoidOutputAccess',
'PageStore',
'RevisionLookup'
'RevisionLookup',
'ParsoidSiteConfig',
],
'needsPage' => false
],

View file

@ -132,7 +132,8 @@ class JobTest extends MediaWikiIntegrationTestCase {
'services' => [
'ParsoidOutputAccess',
'PageStore',
'RevisionLookup'
'RevisionLookup',
'ParsoidSiteConfig',
],
'needsPage' => false
],

View file

@ -35,7 +35,8 @@ class ParsoidCachePrewarmJobTest extends MediaWikiIntegrationTestCase {
[ 'revId' => $rev1->getId(), 'pageId' => $page->getId() ],
$this->getServiceContainer()->getParsoidOutputAccess(),
$this->getServiceContainer()->getPageStore(),
$this->getServiceContainer()->getRevisionLookup()
$this->getServiceContainer()->getRevisionLookup(),
$this->getServiceContainer()->getParsoidSiteConfig()
);
// NOTE: calling ->run() will not run the job scheduled in the queue but will
@ -65,7 +66,8 @@ class ParsoidCachePrewarmJobTest extends MediaWikiIntegrationTestCase {
[ 'revId' => $rev2->getId(), 'pageId' => $page->getId(), 'causeAction' => 'just for testing' ],
$this->getServiceContainer()->getParsoidOutputAccess(),
$this->getServiceContainer()->getPageStore(),
$this->getServiceContainer()->getRevisionLookup()
$this->getServiceContainer()->getRevisionLookup(),
$this->getServiceContainer()->getParsoidSiteConfig()
);
$jobQueueGroup = $this->getServiceContainer()->getJobQueueGroup();

View file

@ -205,10 +205,8 @@ class ArticleTest extends \MediaWikiIntegrationTestCase {
$parsoidOutputAccess = $this->createNoOpMock(
ParsoidOutputAccess::class,
[ 'getParserOutput', 'supportsContentModel' ]
[ 'getParserOutput' ]
);
$parsoidOutputAccess->method( 'supportsContentModel' )
->willReturn( true );
$parsoidOutputAccess
->expects( $this->once() ) // This is the key assertion in this test case.
->method( 'getParserOutput' )

View file

@ -1,7 +1,6 @@
<?php
use MediaWiki\Content\JavaScriptContent;
use MediaWiki\Content\TextContentHandler;
use MediaWiki\Edit\ParsoidRenderID;
use MediaWiki\Page\ParserOutputAccess;
use MediaWiki\Parser\ParserOutputFlags;
@ -386,30 +385,6 @@ class ParsoidOutputAccessTest extends MediaWikiIntegrationTestCase {
$this->assertNotNull( ParsoidRenderID::newFromParserOutput( $output1 ) );
}
public static function provideSupportsContentModels() {
yield [ CONTENT_MODEL_WIKITEXT, true ];
yield [ CONTENT_MODEL_JSON, true ];
yield [ CONTENT_MODEL_JAVASCRIPT, false ];
yield [ 'with-text', true ];
yield [ 'xyzzy', false ];
}
/**
* @dataProvider provideSupportsContentModels
*/
public function testSupportsContentModel( $model, $expected ) {
$contentHandlers = $this->getConfVar( 'ContentHandlers' );
$this->overrideConfigValue( 'ContentHandlers', [
'with-text' => [ 'factory' => static function () {
return new TextContentHandler( 'with-text', [ CONTENT_FORMAT_WIKITEXT, 'plain/test' ] );
} ],
] + $contentHandlers );
$this->resetServicesWithMockedParsoid( 0 );
$access = $this->getParsoidOutputAccessWithCache();
$this->assertSame( $expected, $access->supportsContentModel( $model ) );
}
/**
* @covers \MediaWiki\Parser\Parsoid\ParsoidOutputAccess::getParserOutput
*/

View file

@ -0,0 +1,36 @@
<?php
namespace MediaWiki\Tests\Parser\Parsoid\Config;
use MediaWikiIntegrationTestCase;
use TextContentHandler;
/**
* @covers \MediaWiki\Parser\Parsoid\Config\SiteConfig
*/
class SiteConfigTest extends MediaWikiIntegrationTestCase {
public static function provideSupportsContentModels() {
yield [ CONTENT_MODEL_WIKITEXT, true ];
yield [ CONTENT_MODEL_JSON, true ];
yield [ CONTENT_MODEL_JAVASCRIPT, false ];
yield [ 'with-text', true ];
yield [ 'xyzzy', false ];
}
/**
* @dataProvider provideSupportsContentModels
*/
public function testSupportsContentModel( $model, $expected ) {
$contentHandlers = $this->getConfVar( 'ContentHandlers' );
$this->overrideConfigValue( 'ContentHandlers', [
'with-text' => [ 'factory' => static function () {
return new TextContentHandler( 'with-text', [ CONTENT_FORMAT_WIKITEXT, 'plain/test' ] );
} ],
] + $contentHandlers );
$this->resetServices();
$siteConfig = $this->getServiceContainer()->getParsoidSiteConfig();
$this->assertSame( $expected, $siteConfig->supportsContentModel( $model ) );
}
}

View file

@ -6,6 +6,7 @@ use ILanguageConverter;
use Language;
use MediaWiki\Config\HashConfig;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\Interwiki\InterwikiLookup;
use MediaWiki\Languages\LanguageConverterFactory;
use MediaWiki\Languages\LanguageFactory;
@ -107,6 +108,7 @@ class SiteConfigTest extends MediaWikiUnitTestCase {
$this->createMockOrOverride( LanguageConverterFactory::class, $serviceOverrides ),
$this->createMockOrOverride( LanguageNameUtils::class, $serviceOverrides ),
$this->createMockOrOverride( UrlUtils::class, $serviceOverrides ),
$this->createMockOrOverride( IContentHandlerFactory::class, $serviceOverrides ),
[],
$this->createMockOrOverride( ParserFactory::class, $serviceOverrides ),
new HashConfig( $configOverrides ),