wiki.techinc.nl/includes/Rest/Handler/Helper/PageRestHelperFactory.php
Subramanya Sastry 5fc7e1974c For Internal REST API users, make revid handling lenient
* Parsoid REST API which considers both title and revid will soon
  be made internal. The core REST API only has endpoints where either
  the title OR the revid is provided and is not subject to this issue.

* This patch ignores page id mismatches and simply uses the revision
  page id where the mismatch is detected. This is only supported for
  ParsoidHandler which sets the lenient revision handling while fetching
  the HtmlOutputRendererHelper.

  For these API requests, the output is not cached.

* Local testing shows that this fixes the issue.

* Added new phpunit tests to ParsoidHandlerTest to verify expectations.
  Also verified that disabling this fix fails that test.

Bug: T349235
Change-Id: I2f4a4a644710ee1e3894e6dc6a066eb37846bdfd
2023-10-23 09:31:38 -05:00

157 lines
4.7 KiB
PHP

<?php
namespace MediaWiki\Rest\Handler\Helper;
use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\Edit\ParsoidOutputStash;
use MediaWiki\Languages\LanguageConverterFactory;
use MediaWiki\Languages\LanguageFactory;
use MediaWiki\Page\PageLookup;
use MediaWiki\Page\RedirectStore;
use MediaWiki\Parser\Parsoid\HtmlTransformFactory;
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
use MediaWiki\Rest\RequestInterface;
use MediaWiki\Rest\ResponseFactory;
use MediaWiki\Rest\Router;
use MediaWiki\Revision\RevisionLookup;
use MediaWiki\Title\TitleFormatter;
/**
* @since 1.40 Factory for helper objects designed for sharing logic between REST handlers that deal with page content.
*/
class PageRestHelperFactory {
/**
* @internal
*/
public const CONSTRUCTOR_OPTIONS = PageContentHelper::CONSTRUCTOR_OPTIONS;
private ServiceOptions $options;
private RevisionLookup $revisionLookup;
private TitleFormatter $titleFormatter;
private PageLookup $pageLookup;
private ParsoidOutputStash $parsoidOutputStash;
private StatsdDataFactoryInterface $stats;
private ParsoidOutputAccess $parsoidOutputAccess;
private HtmlTransformFactory $htmlTransformFactory;
private IContentHandlerFactory $contentHandlerFactory;
private LanguageFactory $languageFactory;
private RedirectStore $redirectStore;
private LanguageConverterFactory $languageConverterFactory;
/**
* @param ServiceOptions $options
* @param RevisionLookup $revisionLookup
* @param TitleFormatter $titleFormatter
* @param PageLookup $pageLookup
* @param ParsoidOutputStash $parsoidOutputStash
* @param StatsdDataFactoryInterface $statsDataFactory
* @param ParsoidOutputAccess $parsoidOutputAccess
* @param HtmlTransformFactory $htmlTransformFactory
* @param IContentHandlerFactory $contentHandlerFactory
* @param LanguageFactory $languageFactory
* @param RedirectStore $redirectStore
* @param LanguageConverterFactory $languageConverterFactory
*/
public function __construct(
ServiceOptions $options,
RevisionLookup $revisionLookup,
TitleFormatter $titleFormatter,
PageLookup $pageLookup,
ParsoidOutputStash $parsoidOutputStash,
StatsdDataFactoryInterface $statsDataFactory,
ParsoidOutputAccess $parsoidOutputAccess,
HtmlTransformFactory $htmlTransformFactory,
IContentHandlerFactory $contentHandlerFactory,
LanguageFactory $languageFactory,
RedirectStore $redirectStore,
LanguageConverterFactory $languageConverterFactory
) {
$this->options = $options;
$this->revisionLookup = $revisionLookup;
$this->titleFormatter = $titleFormatter;
$this->pageLookup = $pageLookup;
$this->parsoidOutputStash = $parsoidOutputStash;
$this->stats = $statsDataFactory;
$this->parsoidOutputAccess = $parsoidOutputAccess;
$this->htmlTransformFactory = $htmlTransformFactory;
$this->contentHandlerFactory = $contentHandlerFactory;
$this->languageFactory = $languageFactory;
$this->redirectStore = $redirectStore;
$this->languageConverterFactory = $languageConverterFactory;
}
public function newRevisionContentHelper(): RevisionContentHelper {
return new RevisionContentHelper(
$this->options,
$this->revisionLookup,
$this->titleFormatter,
$this->pageLookup
);
}
public function newPageContentHelper(): PageContentHelper {
return new PageContentHelper(
$this->options,
$this->revisionLookup,
$this->titleFormatter,
$this->pageLookup
);
}
/**
* Should we ignore page id mismatches between page and revision objects
* in HTML/pagebundle requests? Mismatches arise because of page moves.
* This is recommended only for handling calls to internal APIs.
*/
public function newHtmlOutputRendererHelper(
bool $lenientRevHandling = false
): HtmlOutputRendererHelper {
return new HtmlOutputRendererHelper(
$this->parsoidOutputStash,
$this->stats,
$this->parsoidOutputAccess,
$this->htmlTransformFactory,
$this->contentHandlerFactory,
$this->languageFactory,
$lenientRevHandling
);
}
public function newHtmlMessageOutputHelper(): HtmlMessageOutputHelper {
return new HtmlMessageOutputHelper();
}
public function newHtmlInputTransformHelper( $envOptions = [] ): HtmlInputTransformHelper {
return new HtmlInputTransformHelper(
$this->stats,
$this->htmlTransformFactory,
$this->parsoidOutputStash,
$this->parsoidOutputAccess,
$envOptions
);
}
/**
* @since 1.41
*/
public function newPageRedirectHelper(
ResponseFactory $responseFactory,
Router $router,
string $route,
RequestInterface $request
): PageRedirectHelper {
return new PageRedirectHelper(
$this->redirectStore,
$this->titleFormatter,
$responseFactory,
$router,
$route,
$request,
$this->languageConverterFactory
);
}
}