diff options
author | Petr Pchelko <ppchelko@wikimedia.org> | 2021-05-04 13:45:30 -0700 |
---|---|---|
committer | Petr Pchelko <ppchelko@wikimedia.org> | 2021-05-05 18:54:58 -0700 |
commit | 4ca16e8d08205a7cfaa46713316fd6c85c7f8001 (patch) | |
tree | d78c881894123ed86cbcc8b672c68e33b41a97b4 /includes | |
parent | f413a6210bb873df54b6005d2ed7db2293e0f01a (diff) | |
download | mediawikicore-4ca16e8d08205a7cfaa46713316fd6c85c7f8001.tar.gz mediawikicore-4ca16e8d08205a7cfaa46713316fd6c85c7f8001.zip |
Eliminate use of Title object in REST infrastructure
Change-Id: I585f0f23cac5f6dc2a4879f69f7b83828fda3dd3
Diffstat (limited to 'includes')
19 files changed, 407 insertions, 273 deletions
diff --git a/includes/Rest/Entity/SearchResultPageIdentity.php b/includes/Rest/Entity/SearchResultPageIdentity.php index 5673ea376993..65436c0b9044 100644 --- a/includes/Rest/Entity/SearchResultPageIdentity.php +++ b/includes/Rest/Entity/SearchResultPageIdentity.php @@ -1,6 +1,8 @@ <?php namespace MediaWiki\Rest\Entity; +use MediaWiki\Page\PageIdentity; + /** * Lightweight interface representing a page identity * @@ -11,8 +13,8 @@ namespace MediaWiki\Rest\Entity; interface SearchResultPageIdentity { /** * The numerical page ID. - * At the moment it is equivalent to Title::getArticleID() - * @see Title::getArticleID() + * At the moment it is equivalent to PageIdentity::getId() + * @see PageIdentity::getId() * * @return int */ @@ -20,8 +22,8 @@ interface SearchResultPageIdentity { /** * Returns the page's namespace number. - * At the moment it is equivalent to Title::getNamespace() - * @see Title::getNamespace() + * At the moment it is equivalent to PageIdentity::getNamespace() + * @see PageIdentity::getNamespace() * * @return int */ @@ -29,8 +31,8 @@ interface SearchResultPageIdentity { /** * Get the page title in DB key form. - * At the moment it is equivalent to Title::getDBkey() - * @see Title::getDBkey() + * At the moment it is equivalent to PageIdentity::getDBkey() + * @see PageIdentity::getDBkey() * * @return string */ diff --git a/includes/Rest/Handler/LanguageLinksHandler.php b/includes/Rest/Handler/LanguageLinksHandler.php index 7fe7ed73782f..3bdb8f25d9a1 100644 --- a/includes/Rest/Handler/LanguageLinksHandler.php +++ b/includes/Rest/Handler/LanguageLinksHandler.php @@ -4,10 +4,11 @@ namespace MediaWiki\Rest\Handler; use MalformedTitleException; use MediaWiki\Languages\LanguageNameUtils; +use MediaWiki\Page\ExistingPageRecord; +use MediaWiki\Page\PageLookup; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; -use Title; use TitleFormatter; use TitleParser; use Wikimedia\Message\MessageValue; @@ -36,37 +37,45 @@ class LanguageLinksHandler extends SimpleHandler { /** @var TitleParser */ private $titleParser; + /** @var PageLookup */ + private $pageLookup; + /** - * @var Title|bool|null + * @var ExistingPageRecord|false|null */ - private $title = null; + private $page = false; /** * @param ILoadBalancer $loadBalancer * @param LanguageNameUtils $languageNameUtils * @param TitleFormatter $titleFormatter * @param TitleParser $titleParser + * @param PageLookup $pageLookup */ public function __construct( ILoadBalancer $loadBalancer, LanguageNameUtils $languageNameUtils, TitleFormatter $titleFormatter, - TitleParser $titleParser + TitleParser $titleParser, + PageLookup $pageLookup ) { $this->loadBalancer = $loadBalancer; $this->languageNameUtils = $languageNameUtils; $this->titleFormatter = $titleFormatter; $this->titleParser = $titleParser; + $this->pageLookup = $pageLookup; } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - private function getTitle() { - if ( $this->title === null ) { - $this->title = Title::newFromText( $this->getValidatedParams()['title'] ) ?? false; + private function getPage(): ?ExistingPageRecord { + if ( $this->page === false ) { + $this->page = $this->pageLookup->getExistingPageByText( + $this->getValidatedParams()['title'] + ); } - return $this->title; + return $this->page; } /** @@ -75,8 +84,8 @@ class LanguageLinksHandler extends SimpleHandler { * @throws LocalizedHttpException */ public function run( $title ) { - $titleObj = $this->getTitle(); - if ( !$titleObj || !$titleObj->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { throw new LocalizedHttpException( new MessageValue( 'rest-nonexistent-title', [ new ScalarParam( ParamType::PLAINTEXT, $title ) ] @@ -84,7 +93,7 @@ class LanguageLinksHandler extends SimpleHandler { 404 ); } - if ( !$this->getAuthority()->authorizeRead( 'read', $titleObj ) ) { + if ( !$this->getAuthority()->authorizeRead( 'read', $page ) ) { throw new LocalizedHttpException( new MessageValue( 'rest-permission-denied-title', [ new ScalarParam( ParamType::PLAINTEXT, $title ) ] ), @@ -93,7 +102,7 @@ class LanguageLinksHandler extends SimpleHandler { } return $this->getResponseFactory() - ->createJson( $this->fetchLinks( $titleObj->getArticleID() ) ); + ->createJson( $this->fetchLinks( $page->getId() ) ); } private function fetchLinks( $pageId ) { @@ -138,37 +147,34 @@ class LanguageLinksHandler extends SimpleHandler { /** * @return string|null - * @throws LocalizedHttpException */ protected function getETag(): ?string { - $title = $this->getTitle(); - if ( !$title || !$title->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { return null; } // XXX: use hash of the rendered HTML? - return '"' . $title->getLatestRevID() . '@' . wfTimestamp( TS_MW, $title->getTouched() ) . '"'; + return '"' . $page->getLatest() . '@' . wfTimestamp( TS_MW, $page->getTouched() ) . '"'; } /** * @return string|null - * @throws LocalizedHttpException */ protected function getLastModified(): ?string { - $title = $this->getTitle(); - if ( !$title || !$title->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { return null; } - return $title->getTouched(); + return $page->getTouched(); } /** * @return bool */ protected function hasRepresentation() { - $title = $this->getTitle(); - return $title ? $title->exists() : false; + return (bool)$this->getPage(); } } diff --git a/includes/Rest/Handler/MediaFileHandler.php b/includes/Rest/Handler/MediaFileHandler.php index e0357621353f..23047af1f3ff 100644 --- a/includes/Rest/Handler/MediaFileHandler.php +++ b/includes/Rest/Handler/MediaFileHandler.php @@ -4,11 +4,12 @@ namespace MediaWiki\Rest\Handler; use File; use MediaFileTrait; +use MediaWiki\Page\ExistingPageRecord; +use MediaWiki\Page\PageLookup; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; use RepoGroup; -use Title; use User; use Wikimedia\Message\MessageValue; use Wikimedia\ParamValidator\ParamValidator; @@ -22,46 +23,53 @@ class MediaFileHandler extends SimpleHandler { /** @var RepoGroup */ private $repoGroup; + /** @var PageLookup */ + private $pageLookup; + /** - * @var Title|bool|null + * @var ExistingPageRecord|false|null */ - private $title = null; + private $page = false; /** - * @var File|bool|null + * @var File|false|null */ - private $file = null; + private $file = false; /** * @param RepoGroup $repoGroup + * @param PageLookup $pageLookup */ public function __construct( - RepoGroup $repoGroup + RepoGroup $repoGroup, + PageLookup $pageLookup ) { $this->repoGroup = $repoGroup; + $this->pageLookup = $pageLookup; } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - private function getTitle() { - if ( $this->title === null ) { - $this->title = - Title::newFromText( $this->getValidatedParams()['title'], NS_FILE ) ?? false; + private function getPage(): ?ExistingPageRecord { + if ( $this->page === false ) { + $this->page = $this->pageLookup->getExistingPageByText( + $this->getValidatedParams()['title'], NS_FILE + ); } - return $this->title; + return $this->page; } /** - * @return File|bool File or false if unable to retrieve file + * @return File|null */ - private function getFile() { - if ( $this->file === null ) { - $title = $this->getTitle(); + private function getFile(): ?File { + if ( $this->file === false ) { + $page = $this->getPage(); // TODO: make RepoGroup::findFile take Authority $user = User::newFromIdentity( $this->getAuthority()->getUser() ); $this->file = - $this->repoGroup->findFile( $title, [ 'private' => $user ] ) ?? false; + $this->repoGroup->findFile( $page, [ 'private' => $user ] ) ?: null; } return $this->file; } @@ -72,32 +80,26 @@ class MediaFileHandler extends SimpleHandler { * @throws LocalizedHttpException */ public function run( $title ) { - $titleObj = $this->getTitle(); - $fileObj = $this->getFile(); + $page = $this->getPage(); - if ( !$titleObj || !$titleObj->exists() ) { + if ( !$page ) { throw new LocalizedHttpException( - MessageValue::new( 'rest-nonexistent-title' )->plaintextParams( - $titleObj->getPrefixedDBkey() - ), + MessageValue::new( 'rest-nonexistent-title' )->plaintextParams( $title ), 404 ); } - if ( !$this->getAuthority()->authorizeRead( 'read', $titleObj ) ) { + if ( !$this->getAuthority()->authorizeRead( 'read', $page ) ) { throw new LocalizedHttpException( - MessageValue::new( 'rest-permission-denied-title' )->plaintextParams( - $titleObj->getPrefixedDBkey() - ), + MessageValue::new( 'rest-permission-denied-title' )->plaintextParams( $title ), 403 ); } + $fileObj = $this->getFile(); if ( !$fileObj || !$fileObj->exists() ) { throw new LocalizedHttpException( - MessageValue::new( 'rest-cannot-load-file' )->plaintextParams( - $titleObj->getPrefixedDBkey() - ), + MessageValue::new( 'rest-cannot-load-file' )->plaintextParams( $title ), 404 ); } diff --git a/includes/Rest/Handler/MediaLinksHandler.php b/includes/Rest/Handler/MediaLinksHandler.php index 0c0c41afe101..919140476adb 100644 --- a/includes/Rest/Handler/MediaLinksHandler.php +++ b/includes/Rest/Handler/MediaLinksHandler.php @@ -3,11 +3,12 @@ namespace MediaWiki\Rest\Handler; use MediaFileTrait; +use MediaWiki\Page\ExistingPageRecord; +use MediaWiki\Page\PageLookup; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; use RepoGroup; -use Title; use User; use Wikimedia\Message\MessageValue; use Wikimedia\ParamValidator\ParamValidator; @@ -28,31 +29,39 @@ class MediaLinksHandler extends SimpleHandler { /** @var RepoGroup */ private $repoGroup; + /** @var PageLookup */ + private $pageLookup; + /** - * @var Title|bool|null + * @var ExistingPageRecord|false|null */ - private $title = null; + private $page = false; /** * @param ILoadBalancer $loadBalancer * @param RepoGroup $repoGroup + * @param PageLookup $pageLookup */ public function __construct( ILoadBalancer $loadBalancer, - RepoGroup $repoGroup + RepoGroup $repoGroup, + PageLookup $pageLookup ) { $this->loadBalancer = $loadBalancer; $this->repoGroup = $repoGroup; + $this->pageLookup = $pageLookup; } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - private function getTitle() { - if ( $this->title === null ) { - $this->title = Title::newFromText( $this->getValidatedParams()['title'] ) ?? false; + private function getPage(): ?ExistingPageRecord { + if ( $this->page === false ) { + $this->page = $this->pageLookup->getExistingPageByText( + $this->getValidatedParams()['title'] + ); } - return $this->title; + return $this->page; } /** @@ -61,15 +70,15 @@ class MediaLinksHandler extends SimpleHandler { * @throws LocalizedHttpException */ public function run( $title ) { - $titleObj = Title::newFromText( $title ); - if ( !$titleObj || !$titleObj->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { throw new LocalizedHttpException( MessageValue::new( 'rest-nonexistent-title' )->plaintextParams( $title ), 404 ); } - if ( !$this->getAuthority()->authorizeRead( 'read', $titleObj ) ) { + if ( !$this->getAuthority()->authorizeRead( 'read', $page ) ) { throw new LocalizedHttpException( MessageValue::new( 'rest-permission-denied-title' )->plaintextParams( $title ), 403 @@ -77,7 +86,7 @@ class MediaLinksHandler extends SimpleHandler { } // @todo: add continuation if too many links are found - $results = $this->getDbResults( $titleObj->getArticleID() ); + $results = $this->getDbResults( $page->getId() ); if ( count( $results ) > self::MAX_NUM_LINKS ) { throw new LocalizedHttpException( MessageValue::new( 'rest-media-too-many-links' ) @@ -166,13 +175,13 @@ class MediaLinksHandler extends SimpleHandler { * @throws LocalizedHttpException */ protected function getETag(): ?string { - $title = $this->getTitle(); - if ( !$title || !$title->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { return null; } // XXX: use hash of the rendered HTML? - return '"' . $title->getLatestRevID() . '@' . wfTimestamp( TS_MW, $title->getTouched() ) . '"'; + return '"' . $page->getLatest() . '@' . wfTimestamp( TS_MW, $page->getTouched() ) . '"'; } /** @@ -180,19 +189,18 @@ class MediaLinksHandler extends SimpleHandler { * @throws LocalizedHttpException */ protected function getLastModified(): ?string { - $title = $this->getTitle(); - if ( !$title || !$title->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { return null; } - return $title->getTouched(); + return $page->getTouched(); } /** * @return bool */ protected function hasRepresentation() { - $title = $this->getTitle(); - return $title ? $title->exists() : false; + return (bool)$this->getPage(); } } diff --git a/includes/Rest/Handler/PageContentHelper.php b/includes/Rest/Handler/PageContentHelper.php index 6d105b088657..5813409e8b88 100644 --- a/includes/Rest/Handler/PageContentHelper.php +++ b/includes/Rest/Handler/PageContentHelper.php @@ -3,6 +3,8 @@ namespace MediaWiki\Rest\Handler; use Config; +use MediaWiki\Page\ExistingPageRecord; +use MediaWiki\Page\PageLookup; use MediaWiki\Permissions\Authority; use MediaWiki\Rest\Handler; use MediaWiki\Rest\LocalizedHttpException; @@ -13,14 +15,12 @@ use MediaWiki\Revision\RevisionRecord; use MediaWiki\Revision\SlotRecord; use MediaWiki\Revision\SuppressedDataException; use TextContent; -use Title; -use TitleFactory; use TitleFormatter; use Wikimedia\Message\MessageValue; use Wikimedia\ParamValidator\ParamValidator; /** - * @since 1.36 + * @internal for use by core REST infrastructure */ class PageContentHelper { private const MAX_AGE_200 = 5; @@ -34,8 +34,8 @@ class PageContentHelper { /** @var TitleFormatter */ protected $titleFormatter; - /** @var TitleFactory */ - protected $titleFactory; + /** @var PageLookup */ + protected $pageLookup; /** @var Authority|null */ protected $authority = null; @@ -43,28 +43,28 @@ class PageContentHelper { /** @var string[] */ protected $parameters = null; - /** @var RevisionRecord|bool|null */ - protected $targetRevision = null; + /** @var RevisionRecord|false|null */ + protected $targetRevision = false; - /** @var Title|bool|null */ - protected $titleObject = null; + /** @var ExistingPageRecord|false|null */ + protected $pageRecord = false; /** * @param Config $config * @param RevisionLookup $revisionLookup * @param TitleFormatter $titleFormatter - * @param TitleFactory $titleFactory + * @param PageLookup $pageLookup */ public function __construct( Config $config, RevisionLookup $revisionLookup, TitleFormatter $titleFormatter, - TitleFactory $titleFactory + PageLookup $pageLookup ) { $this->config = $config; $this->revisionLookup = $revisionLookup; $this->titleFormatter = $titleFormatter; - $this->titleFactory = $titleFactory; + $this->pageLookup = $pageLookup; } /** @@ -77,36 +77,38 @@ class PageContentHelper { } /** - * @return string|null Title text or null if unable to retrieve title + * @return string|null title text or null if unable to retrieve title */ public function getTitleText(): ?string { return $this->parameters['title'] ?? null; } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - public function getTitle() { - if ( $this->titleObject === null ) { + public function getPage(): ?ExistingPageRecord { + if ( $this->pageRecord === false ) { $titleText = $this->getTitleText(); - $this->titleObject = - $this->titleFactory->newFromText( $titleText ) ?? false; + if ( !$titleText ) { + return null; + } + $this->pageRecord = $this->pageLookup->getExistingPageByText( $titleText ); } - return $this->titleObject; + return $this->pageRecord; } /** * Returns the target revision. No permission checks are applied. * - * @return RevisionRecord|bool latest revision or false if unable to retrieve revision + * @return RevisionRecord|null latest revision or null if unable to retrieve revision */ - public function getTargetRevision() { - if ( $this->targetRevision === null ) { - $title = $this->getTitle(); - if ( $title && $title->getArticleID() ) { - $this->targetRevision = $this->revisionLookup->getRevisionByTitle( $title ); + public function getTargetRevision(): ?RevisionRecord { + if ( $this->targetRevision === false ) { + $page = $this->getPage(); + if ( $page ) { + $this->targetRevision = $this->revisionLookup->getRevisionByTitle( $page ); } else { - $this->targetRevision = false; + $this->targetRevision = null; } } return $this->targetRevision; @@ -160,9 +162,8 @@ class PageContentHelper { * @return bool */ public function isAccessible(): bool { - $title = $this->getTitle(); - return $title && $title->getArticleID() - && $this->authority->probablyCan( 'read', $title ); + $page = $this->getPage(); + return $page && $this->authority->probablyCan( 'read', $page ); } /** @@ -203,25 +204,26 @@ class PageContentHelper { * @return bool */ public function hasContent(): bool { - $title = $this->getTitle(); - return $title && $title->getArticleID(); + return (bool)$this->getPage(); } /** * @return array */ public function constructMetadata(): array { - $titleObject = $this->getTitle(); + $page = $this->getPage(); $revision = $this->getTargetRevision(); return [ - 'id' => $titleObject->getArticleID(), - 'key' => $this->titleFormatter->getPrefixedDBkey( $titleObject ), - 'title' => $this->titleFormatter->getPrefixedText( $titleObject ), + 'id' => $page->getId(), + 'key' => $this->titleFormatter->getPrefixedDBkey( $page ), + 'title' => $this->titleFormatter->getPrefixedText( $page ), 'latest' => [ 'id' => $revision->getId(), 'timestamp' => wfTimestampOrNull( TS_ISO_8601, $revision->getTimestamp() ) ], - 'content_model' => $titleObject->getContentModel(), + 'content_model' => $this->getTargetRevision() + ->getSlot( SlotRecord::MAIN, RevisionRecord::RAW ) + ->getModel(), 'license' => [ 'url' => $this->config->get( 'RightsUrl' ), 'title' => $this->config->get( 'RightsText' ) @@ -272,7 +274,7 @@ class PageContentHelper { ); } - if ( !$this->authority->authorizeRead( 'read', $this->getTitle() ) ) { + if ( !$this->authority->authorizeRead( 'read', $this->getPage() ) ) { throw new LocalizedHttpException( MessageValue::new( 'rest-permission-denied-title' )->plaintextParams( $titleText ), 403 diff --git a/includes/Rest/Handler/PageHTMLHandler.php b/includes/Rest/Handler/PageHTMLHandler.php index d9ba49572216..552f7ae9486e 100644 --- a/includes/Rest/Handler/PageHTMLHandler.php +++ b/includes/Rest/Handler/PageHTMLHandler.php @@ -4,14 +4,13 @@ namespace MediaWiki\Rest\Handler; use Config; use LogicException; -use MediaWiki\Page\WikiPageFactory; +use MediaWiki\Page\PageLookup; use MediaWiki\Parser\ParserCacheFactory; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; use MediaWiki\Rest\StringStream; use MediaWiki\Revision\RevisionLookup; -use TitleFactory; use TitleFormatter; use Wikimedia\Assert\Assert; use Wikimedia\UUID\GlobalIdGenerator; @@ -35,21 +34,19 @@ class PageHTMLHandler extends SimpleHandler { Config $config, RevisionLookup $revisionLookup, TitleFormatter $titleFormatter, - TitleFactory $titleFactory, ParserCacheFactory $parserCacheFactory, - WikiPageFactory $wikiPageFactory, - GlobalIdGenerator $globalIdGenerator + GlobalIdGenerator $globalIdGenerator, + PageLookup $pageLookup ) { $this->contentHelper = new PageContentHelper( $config, $revisionLookup, $titleFormatter, - $titleFactory + $pageLookup ); $this->htmlHelper = new ParsoidHTMLHelper( $parserCacheFactory->getParserCache( 'parsoid' ), $parserCacheFactory->getRevisionOutputCache( 'parsoid' ), - $wikiPageFactory, $globalIdGenerator ); } @@ -57,9 +54,9 @@ class PageHTMLHandler extends SimpleHandler { protected function postValidationSetup() { $this->contentHelper->init( $this->getAuthority(), $this->getValidatedParams() ); - $title = $this->contentHelper->getTitle(); - if ( $title ) { - $this->htmlHelper->init( $title ); + $page = $this->contentHelper->getPage(); + if ( $page ) { + $this->htmlHelper->init( $page ); } } @@ -70,11 +67,11 @@ class PageHTMLHandler extends SimpleHandler { public function run(): Response { $this->contentHelper->checkAccess(); - $titleObj = $this->contentHelper->getTitle(); + $page = $this->contentHelper->getPage(); - // The call to $this->contentHelper->getTitle() should not return null if + // The call to $this->contentHelper->getPage() should not return null if // $this->contentHelper->checkAccess() did not throw. - Assert::invariant( $titleObj !== null, 'Title should be known' ); + Assert::invariant( $page !== null, 'Page should be known' ); $outputMode = $this->getOutputMode(); switch ( $outputMode ) { diff --git a/includes/Rest/Handler/PageHistoryCountHandler.php b/includes/Rest/Handler/PageHistoryCountHandler.php index 4eebaee77577..d243214c1d22 100644 --- a/includes/Rest/Handler/PageHistoryCountHandler.php +++ b/includes/Rest/Handler/PageHistoryCountHandler.php @@ -3,6 +3,8 @@ namespace MediaWiki\Rest\Handler; use ChangeTags; +use MediaWiki\Page\ExistingPageRecord; +use MediaWiki\Page\PageLookup; use MediaWiki\Permissions\PermissionManager; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; @@ -12,7 +14,6 @@ use MediaWiki\Revision\RevisionStore; use MediaWiki\Storage\NameTableAccessException; use MediaWiki\Storage\NameTableStore; use MediaWiki\Storage\NameTableStoreFactory; -use Title; use WANObjectCache; use Wikimedia\Message\MessageValue; use Wikimedia\Message\ParamType; @@ -54,17 +55,20 @@ class PageHistoryCountHandler extends SimpleHandler { /** @var ILoadBalancer */ private $loadBalancer; + /** @var PageLookup */ + private $pageLookup; + /** @var WANObjectCache */ private $cache; - /** @var RevisionRecord|bool */ - private $revision; + /** @var RevisionRecord|false|null */ + private $revision = false; /** @var array */ private $lastModifiedTimes; - /** @var Title */ - private $titleObject; + /** @var ExistingPageRecord|false|null */ + private $page = false; /** * @param RevisionStore $revisionStore @@ -72,19 +76,22 @@ class PageHistoryCountHandler extends SimpleHandler { * @param PermissionManager $permissionManager * @param ILoadBalancer $loadBalancer * @param WANObjectCache $cache + * @param PageLookup $pageLookup */ public function __construct( RevisionStore $revisionStore, NameTableStoreFactory $nameTableStoreFactory, PermissionManager $permissionManager, ILoadBalancer $loadBalancer, - WANObjectCache $cache + WANObjectCache $cache, + PageLookup $pageLookup ) { $this->revisionStore = $revisionStore; $this->changeTagDefStore = $nameTableStoreFactory->getChangeTagDef(); $this->permissionManager = $permissionManager; $this->loadBalancer = $loadBalancer; $this->cache = $cache; + $this->pageLookup = $pageLookup; } private function normalizeType( $type ) { @@ -121,7 +128,7 @@ class PageHistoryCountHandler extends SimpleHandler { } /** - * @param Title $title the title of the page to load history for + * @param string $title the title of the page to load history for * @param string $type the validated count type * @return Response * @throws LocalizedHttpException @@ -129,8 +136,8 @@ class PageHistoryCountHandler extends SimpleHandler { public function run( $title, $type ) { $normalizedType = $this->normalizeType( $type ); $this->validateParameterCombination( $normalizedType ); - $titleObj = $this->getTitle(); - if ( !$titleObj || !$titleObj->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { throw new LocalizedHttpException( new MessageValue( 'rest-nonexistent-title', [ new ScalarParam( ParamType::PLAINTEXT, $title ) ] @@ -139,7 +146,7 @@ class PageHistoryCountHandler extends SimpleHandler { ); } - if ( !$this->getAuthority()->authorizeRead( 'read', $titleObj ) ) { + if ( !$this->getAuthority()->authorizeRead( 'read', $page ) ) { throw new LocalizedHttpException( new MessageValue( 'rest-permission-denied-title', [ new ScalarParam( ParamType::PLAINTEXT, $title ) ] @@ -173,7 +180,7 @@ class PageHistoryCountHandler extends SimpleHandler { * @throws LocalizedHttpException */ private function getCount( $type ) { - $pageId = $this->getTitle()->getArticleID(); + $pageId = $this->getPage()->getId(); switch ( $type ) { case 'anonymous': return $this->getCachedCount( $type, @@ -261,28 +268,30 @@ class PageHistoryCountHandler extends SimpleHandler { } /** - * @return RevisionRecord|bool current revision or false if unable to retrieve revision + * @return RevisionRecord|null current revision or false if unable to retrieve revision */ - private function getCurrentRevision() { - if ( $this->revision === null ) { - $title = $this->getTitle(); - if ( $title && $title->getArticleID() ) { - $this->revision = $this->revisionStore->getKnownCurrentRevision( $title ); + private function getCurrentRevision(): ?RevisionRecord { + if ( $this->revision === false ) { + $page = $this->getPage(); + if ( $page ) { + $this->revision = $this->revisionStore->getKnownCurrentRevision( $page ) ?: null; } else { - $this->revision = false; + $this->revision = null; } } return $this->revision; } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - private function getTitle() { - if ( $this->titleObject === null ) { - $this->titleObject = Title::newFromText( $this->getValidatedParams()['title'] ); + private function getPage(): ?ExistingPageRecord { + if ( $this->page === false ) { + $this->page = $this->pageLookup->getExistingPageByText( + $this->getValidatedParams()['title'] + ); } - return $this->titleObject; + return $this->page; } /** @@ -296,6 +305,7 @@ class PageHistoryCountHandler extends SimpleHandler { if ( $lastModifiedTimes ) { return max( array_values( $lastModifiedTimes ) ); } + return null; } /** @@ -357,8 +367,7 @@ class PageHistoryCountHandler extends SimpleHandler { private function getCachedCount( $type, callable $fetchCount ) { - $titleObj = $this->getTitle(); - $pageId = $titleObj->getArticleID(); + $pageId = $this->getPage()->getId(); return $this->cache->getWithSetCallback( $this->cache->makeKey( 'rest', 'pagehistorycount', $pageId, $type ), WANObjectCache::TTL_WEEK, diff --git a/includes/Rest/Handler/PageHistoryHandler.php b/includes/Rest/Handler/PageHistoryHandler.php index 57f03e5cb9eb..7dffc4f96474 100644 --- a/includes/Rest/Handler/PageHistoryHandler.php +++ b/includes/Rest/Handler/PageHistoryHandler.php @@ -4,6 +4,8 @@ namespace MediaWiki\Rest\Handler; use ChangeTags; use IDBAccessObject; +use MediaWiki\Page\ExistingPageRecord; +use MediaWiki\Page\PageLookup; use MediaWiki\Permissions\PermissionManager; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; @@ -13,7 +15,7 @@ use MediaWiki\Revision\RevisionStore; use MediaWiki\Storage\NameTableAccessException; use MediaWiki\Storage\NameTableStore; use MediaWiki\Storage\NameTableStoreFactory; -use Title; +use TitleFormatter; use Wikimedia\Message\MessageValue; use Wikimedia\Message\ParamType; use Wikimedia\Message\ScalarParam; @@ -40,10 +42,16 @@ class PageHistoryHandler extends SimpleHandler { /** @var ILoadBalancer */ private $loadBalancer; + /** @var PageLookup */ + private $pageLookup; + + /** @var TitleFormatter */ + private $titleFormatter; + /** - * @var Title|bool|null + * @var ExistingPageRecord|false|null */ - private $title = null; + private $page = false; /** * RevisionStore $revisionStore @@ -52,27 +60,35 @@ class PageHistoryHandler extends SimpleHandler { * @param NameTableStoreFactory $nameTableStoreFactory * @param PermissionManager $permissionManager * @param ILoadBalancer $loadBalancer + * @param PageLookup $pageLookup + * @param TitleFormatter $titleFormatter */ public function __construct( RevisionStore $revisionStore, NameTableStoreFactory $nameTableStoreFactory, PermissionManager $permissionManager, - ILoadBalancer $loadBalancer + ILoadBalancer $loadBalancer, + PageLookup $pageLookup, + TitleFormatter $titleFormatter ) { $this->revisionStore = $revisionStore; $this->changeTagDefStore = $nameTableStoreFactory->getChangeTagDef(); $this->permissionManager = $permissionManager; $this->loadBalancer = $loadBalancer; + $this->pageLookup = $pageLookup; + $this->titleFormatter = $titleFormatter; } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - private function getTitle() { - if ( $this->title === null ) { - $this->title = Title::newFromText( $this->getValidatedParams()['title'] ) ?? false; + private function getPage(): ?ExistingPageRecord { + if ( $this->page === false ) { + $this->page = $this->pageLookup->getExistingPageByText( + $this->getValidatedParams()['title'] + ); } - return $this->title; + return $this->page; } /** @@ -109,8 +125,8 @@ class PageHistoryHandler extends SimpleHandler { } } - $titleObj = Title::newFromText( $title ); - if ( !$titleObj || !$titleObj->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { throw new LocalizedHttpException( new MessageValue( 'rest-nonexistent-title', [ new ScalarParam( ParamType::PLAINTEXT, $title ) ] @@ -118,7 +134,7 @@ class PageHistoryHandler extends SimpleHandler { 404 ); } - if ( !$this->getAuthority()->authorizeRead( 'read', $titleObj ) ) { + if ( !$this->getAuthority()->authorizeRead( 'read', $page ) ) { throw new LocalizedHttpException( new MessageValue( 'rest-permission-denied-title', [ new ScalarParam( ParamType::PLAINTEXT, $title ) ] ), @@ -130,7 +146,7 @@ class PageHistoryHandler extends SimpleHandler { if ( $relativeRevId ) { // Confirm the relative revision exists for this page. If so, get its timestamp. $rev = $this->revisionStore->getRevisionByPageId( - $titleObj->getArticleID(), + $page->getId(), $relativeRevId ); if ( !$rev ) { @@ -154,24 +170,24 @@ class PageHistoryHandler extends SimpleHandler { $ts = 0; } - $res = $this->getDbResults( $titleObj, $params, $relativeRevId, $ts, $tagIds ); - $response = $this->processDbResults( $res, $titleObj, $params ); + $res = $this->getDbResults( $page, $params, $relativeRevId, $ts, $tagIds ); + $response = $this->processDbResults( $res, $page, $params ); return $this->getResponseFactory()->createJson( $response ); } /** - * @param Title $titleObj title object identifying the page to load history for + * @param ExistingPageRecord $page object identifying the page to load history for * @param array $params request parameters * @param int $relativeRevId relative revision id for paging, or zero if none * @param int $ts timestamp for paging, or zero if none * @param array $tagIds validated tags ids, or empty array if not needed for this query * @return IResultWrapper|bool the results, or false if no query was executed */ - private function getDbResults( Title $titleObj, array $params, $relativeRevId, $ts, $tagIds ) { + private function getDbResults( ExistingPageRecord $page, array $params, $relativeRevId, $ts, $tagIds ) { $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA ); $revQuery = $this->revisionStore->getQueryInfo(); $cond = [ - 'rev_page' => $titleObj->getArticleID() + 'rev_page' => $page->getId() ]; if ( $params['filter'] ) { @@ -274,11 +290,11 @@ class PageHistoryHandler extends SimpleHandler { /** * @param IResultWrapper|bool $res database results, or false if no query was executed - * @param Title $titleObj title object identifying the page to load history for + * @param ExistingPageRecord $page object identifying the page to load history for * @param array $params request parameters * @return array response data */ - private function processDbResults( $res, $titleObj, $params ) { + private function processDbResults( $res, $page, $params ) { $revisions = []; if ( $res ) { @@ -287,7 +303,7 @@ class PageHistoryHandler extends SimpleHandler { $rev = $this->revisionStore->newRevisionFromRow( $row, IDBAccessObject::READ_NORMAL, - $titleObj + $page ); if ( !$revisions ) { $firstRevId = $row->rev_id; @@ -383,7 +399,7 @@ class PageHistoryHandler extends SimpleHandler { $queryParts['filter'] = $params['filter']; } - $pathParams = [ 'title' => $titleObj->getPrefixedDBkey() ]; + $pathParams = [ 'title' => $this->titleFormatter->getPrefixedDBkey( $page ) ]; $response['latest'] = $this->getRouteUrl( $pathParams, $queryParts ); @@ -434,12 +450,12 @@ class PageHistoryHandler extends SimpleHandler { * @return string|null */ protected function getETag(): ?string { - $title = $this->getTitle(); - if ( !$title || !$title->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { return null; } - return '"' . $title->getLatestRevID() . '"'; + return '"' . $page->getLatest() . '"'; } /** @@ -448,12 +464,12 @@ class PageHistoryHandler extends SimpleHandler { * @return string|null */ protected function getLastModified(): ?string { - $title = $this->getTitle(); - if ( !$title || !$title->getArticleID() ) { + $page = $this->getPage(); + if ( !$page ) { return null; } - $rev = $this->revisionStore->getKnownCurrentRevision( $title ); + $rev = $this->revisionStore->getKnownCurrentRevision( $page ); return $rev->getTimestamp(); } @@ -461,7 +477,6 @@ class PageHistoryHandler extends SimpleHandler { * @return bool */ protected function hasRepresentation() { - $title = $this->getTitle(); - return $title ? $title->exists() : false; + return (bool)$this->getPage(); } } diff --git a/includes/Rest/Handler/PageSourceHandler.php b/includes/Rest/Handler/PageSourceHandler.php index 15e028d5570b..c626a2cf4607 100644 --- a/includes/Rest/Handler/PageSourceHandler.php +++ b/includes/Rest/Handler/PageSourceHandler.php @@ -4,12 +4,12 @@ namespace MediaWiki\Rest\Handler; use Config; use LogicException; +use MediaWiki\Page\PageLookup; +use MediaWiki\Page\PageReference; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; use MediaWiki\Revision\RevisionLookup; -use Title; -use TitleFactory; use TitleFormatter; use Wikimedia\Assert\Assert; @@ -20,6 +20,9 @@ use Wikimedia\Assert\Assert; */ class PageSourceHandler extends SimpleHandler { + /** @var TitleFormatter */ + private $titleFormatter; + /** @var PageContentHelper */ private $contentHelper; @@ -27,13 +30,14 @@ class PageSourceHandler extends SimpleHandler { Config $config, RevisionLookup $revisionLookup, TitleFormatter $titleFormatter, - TitleFactory $titleFactory + PageLookup $pageLookup ) { + $this->titleFormatter = $titleFormatter; $this->contentHelper = new PageContentHelper( $config, $revisionLookup, $titleFormatter, - $titleFactory + $pageLookup ); } @@ -42,13 +46,13 @@ class PageSourceHandler extends SimpleHandler { } /** - * @param Title $title + * @param PageReference $page * @return string */ - private function constructHtmlUrl( Title $title ): string { + private function constructHtmlUrl( PageReference $page ): string { return $this->getRouter()->getRouteUrl( '/v1/page/{title}/html', - [ 'title' => $title->getPrefixedText() ] + [ 'title' => $this->titleFormatter->getPrefixedText( $page ) ] ); } @@ -59,17 +63,17 @@ class PageSourceHandler extends SimpleHandler { public function run(): Response { $this->contentHelper->checkAccess(); - $titleObj = $this->contentHelper->getTitle(); + $page = $this->contentHelper->getPage(); - // The call to $this->contentHelper->getTitle() should not return null if + // The call to $this->contentHelper->getPage() should not return null if // $this->contentHelper->checkAccess() did not throw. - Assert::invariant( $titleObj !== null, 'Title should be known' ); + Assert::invariant( $page !== null, 'Page should be known' ); $outputMode = $this->getOutputMode(); switch ( $outputMode ) { case 'bare': $body = $this->contentHelper->constructMetadata(); - $body['html_url'] = $this->constructHtmlUrl( $titleObj ); + $body['html_url'] = $this->constructHtmlUrl( $page ); break; case 'source': $content = $this->contentHelper->getContent(); diff --git a/includes/Rest/Handler/ParsoidHTMLHelper.php b/includes/Rest/Handler/ParsoidHTMLHelper.php index 3a880d48f264..4e271281959d 100644 --- a/includes/Rest/Handler/ParsoidHTMLHelper.php +++ b/includes/Rest/Handler/ParsoidHTMLHelper.php @@ -22,14 +22,14 @@ namespace MediaWiki\Rest\Handler; use MediaWiki\MediaWikiServices; -use MediaWiki\Page\WikiPageFactory; +use MediaWiki\Page\PageRecord; use MediaWiki\Parser\RevisionOutputCache; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Revision\RevisionRecord; use ParserCache; use ParserOptions; use ParserOutput; -use Title; +use TitleValue; use Wikimedia\Message\MessageValue; use Wikimedia\Parsoid\Config\PageConfig; use Wikimedia\Parsoid\Core\ClientError; @@ -55,14 +55,11 @@ class ParsoidHTMLHelper { /** @var RevisionOutputCache */ private $revisionOutputCache; - /** @var WikiPageFactory */ - private $wikiPageFactory; - /** @var GlobalIdGenerator */ private $globalIdGenerator; - /** @var Title|null */ - private $title = null; + /** @var PageRecord|null */ + private $page = null; /** @var Parsoid|null */ private $parsoid = null; @@ -73,27 +70,24 @@ class ParsoidHTMLHelper { /** * @param ParserCache $parserCache * @param RevisionOutputCache $revisionOutputCache - * @param WikiPageFactory $wikiPageFactory * @param GlobalIdGenerator $globalIdGenerator */ public function __construct( ParserCache $parserCache, RevisionOutputCache $revisionOutputCache, - WikiPageFactory $wikiPageFactory, GlobalIdGenerator $globalIdGenerator ) { $this->parserCache = $parserCache; - $this->wikiPageFactory = $wikiPageFactory; $this->globalIdGenerator = $globalIdGenerator; $this->revisionOutputCache = $revisionOutputCache; } /** - * @param Title $title + * @param PageRecord $page * @param RevisionRecord|null $revision */ - public function init( Title $title, ?RevisionRecord $revision = null ) { - $this->title = $title; + public function init( PageRecord $page, ?RevisionRecord $revision = null ) { + $this->page = $page; $this->revision = $revision; } @@ -178,9 +172,14 @@ class ParsoidHTMLHelper { // can't report the used options. // Already checked that title/revision exist and accessible. // TODO: make ParsoidPageConfigFactory take a RevisionRecord + // TODO: make ParsoidPageConfigFactory take PageReference as well return MediaWikiServices::getInstance() ->get( 'ParsoidPageConfigFactory' ) - ->create( $this->title, null, $this->revision ? $this->revision->getId() : null ); + ->create( + TitleValue::newFromPage( $this->page ), + null, + $this->revision ? $this->revision->getId() : null + ); } /** @@ -188,16 +187,15 @@ class ParsoidHTMLHelper { * @throws LocalizedHttpException */ public function getHtml(): ParserOutput { - $wikiPage = $this->wikiPageFactory->newFromLinkTarget( $this->title ); $parserOptions = ParserOptions::newCanonical( 'canonical' ); - $revId = $this->revision ? $this->revision->getId() : $wikiPage->getLatest(); - $isOld = $revId !== $wikiPage->getLatest(); + $revId = $this->revision ? $this->revision->getId() : $this->page->getLatest(); + $isOld = $revId !== $this->page->getLatest(); if ( $isOld ) { $parserOutput = $this->revisionOutputCache->get( $this->revision, $parserOptions ); } else { - $parserOutput = $this->parserCache->get( $wikiPage, $parserOptions ); + $parserOutput = $this->parserCache->get( $this->page, $parserOptions ); } if ( $parserOutput ) { return $parserOutput; @@ -218,7 +216,7 @@ class ParsoidHTMLHelper { if ( $isOld ) { $this->revisionOutputCache->save( $fakeParserOutput, $this->revision, $parserOptions, $now ); } else { - $this->parserCache->save( $fakeParserOutput, $wikiPage, $parserOptions, $now ); + $this->parserCache->save( $fakeParserOutput, $this->page, $parserOptions, $now ); } return $fakeParserOutput; diff --git a/includes/Rest/Handler/RevisionContentHelper.php b/includes/Rest/Handler/RevisionContentHelper.php index 1cf186bb2b3b..0165b21c0e0e 100644 --- a/includes/Rest/Handler/RevisionContentHelper.php +++ b/includes/Rest/Handler/RevisionContentHelper.php @@ -2,17 +2,17 @@ namespace MediaWiki\Rest\Handler; +use MediaWiki\Page\ExistingPageRecord; use MediaWiki\Rest\Handler; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\ResponseInterface; use MediaWiki\Revision\RevisionRecord; use MediaWiki\Revision\SlotRecord; -use Title; use Wikimedia\Message\MessageValue; use Wikimedia\ParamValidator\ParamValidator; /** - * @since 1.36 + * @internal for use by core REST infrastructure */ class RevisionContentHelper extends PageContentHelper { @@ -24,7 +24,7 @@ class RevisionContentHelper extends PageContentHelper { } /** - * @return string|null Title text or null if unable to retrieve title + * @return string|null title text or null if unable to retrieve title */ public function getTitleText(): ?string { $revision = $this->getTargetRevision(); @@ -34,25 +34,23 @@ class RevisionContentHelper extends PageContentHelper { } /** - * @return Title|bool Title or false if unable to retrieve title + * @return ExistingPageRecord|null */ - public function getTitle() { + public function getPage(): ?ExistingPageRecord { $revision = $this->getTargetRevision(); - return $revision - ? $this->titleFactory->castFromLinkTarget( $revision->getPageAsLinkTarget() ) - : false; + return $revision ? $this->pageLookup->getPageByReference( $revision->getPage() ) : null; } /** - * @return RevisionRecord|bool latest revision or false if unable to retrieve revision + * @return RevisionRecord|null latest revision or null if unable to retrieve revision */ - public function getTargetRevision() { - if ( $this->targetRevision === null ) { + public function getTargetRevision(): ?RevisionRecord { + if ( $this->targetRevision === false ) { $revId = $this->getRevisionId(); if ( $revId ) { - $this->targetRevision = $this->revisionLookup->getRevisionById( $revId ) ?: false; + $this->targetRevision = $this->revisionLookup->getRevisionById( $revId ); } else { - $this->targetRevision = false; + $this->targetRevision = null; } } return $this->targetRevision; @@ -101,7 +99,7 @@ class RevisionContentHelper extends PageContentHelper { * @return array */ public function constructMetadata(): array { - $titleObject = $this->getTitle(); + $page = $this->getPage(); $revision = $this->getTargetRevision(); $mainSlot = $revision->getSlot( SlotRecord::MAIN, RevisionRecord::RAW ); @@ -113,9 +111,9 @@ class RevisionContentHelper extends PageContentHelper { 'timestamp' => wfTimestampOrNull( TS_ISO_8601, $revision->getTimestamp() ), 'content_model' => $mainSlot->getModel(), 'page' => [ - 'id' => $titleObject->getArticleID(), - 'key' => $this->titleFormatter->getPrefixedDBkey( $titleObject ), - 'title' => $this->titleFormatter->getPrefixedText( $titleObject ), + 'id' => $page->getId(), + 'key' => $this->titleFormatter->getPrefixedDBkey( $page ), + 'title' => $this->titleFormatter->getPrefixedText( $page ), ], 'license' => [ 'url' => $this->config->get( 'RightsUrl' ), @@ -173,7 +171,7 @@ class RevisionContentHelper extends PageContentHelper { ); } - if ( !$this->authority->authorizeRead( 'read', $this->getTitle() ) ) { + if ( !$this->authority->authorizeRead( 'read', $this->getPage() ) ) { throw new LocalizedHttpException( MessageValue::new( 'rest-permission-denied-revision' )->plaintextParams( $revId ), 403 diff --git a/includes/Rest/Handler/RevisionHTMLHandler.php b/includes/Rest/Handler/RevisionHTMLHandler.php index e368d049e28a..f7aa5330c8f1 100644 --- a/includes/Rest/Handler/RevisionHTMLHandler.php +++ b/includes/Rest/Handler/RevisionHTMLHandler.php @@ -4,14 +4,13 @@ namespace MediaWiki\Rest\Handler; use Config; use LogicException; -use MediaWiki\Page\WikiPageFactory; +use MediaWiki\Page\PageLookup; use MediaWiki\Parser\ParserCacheFactory; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; use MediaWiki\Rest\StringStream; use MediaWiki\Revision\RevisionLookup; -use TitleFactory; use TitleFormatter; use Wikimedia\Assert\Assert; use Wikimedia\UUID\GlobalIdGenerator; @@ -36,21 +35,19 @@ class RevisionHTMLHandler extends SimpleHandler { Config $config, RevisionLookup $revisionLookup, TitleFormatter $titleFormatter, - TitleFactory $titleFactory, ParserCacheFactory $parserCacheFactory, - WikiPageFactory $wikiPageFactory, - GlobalIdGenerator $globalIdGenerator + GlobalIdGenerator $globalIdGenerator, + PageLookup $pageLookup ) { $this->contentHelper = new RevisionContentHelper( $config, $revisionLookup, $titleFormatter, - $titleFactory + $pageLookup ); $this->htmlHelper = new ParsoidHTMLHelper( $parserCacheFactory->getParserCache( 'parsoid' ), $parserCacheFactory->getRevisionOutputCache( 'parsoid' ), - $wikiPageFactory, $globalIdGenerator ); } @@ -58,11 +55,11 @@ class RevisionHTMLHandler extends SimpleHandler { protected function postValidationSetup() { $this->contentHelper->init( $this->getAuthority(), $this->getValidatedParams() ); - $title = $this->contentHelper->getTitle(); + $page = $this->contentHelper->getPage(); $revision = $this->contentHelper->getTargetRevision(); - if ( $title && $revision ) { - $this->htmlHelper->init( $title, $revision ); + if ( $page && $revision ) { + $this->htmlHelper->init( $page, $revision ); } } @@ -73,12 +70,12 @@ class RevisionHTMLHandler extends SimpleHandler { public function run(): Response { $this->contentHelper->checkAccess(); - $titleObj = $this->contentHelper->getTitle(); + $page = $this->contentHelper->getPage(); $revisionRecord = $this->contentHelper->getTargetRevision(); - // The call to $this->contentHelper->getTitle() should not return null if + // The call to $this->contentHelper->getPage() should not return null if // $this->contentHelper->checkAccess() did not throw. - Assert::invariant( $titleObj !== null, 'Title should be known' ); + Assert::invariant( $page !== null, 'Page should be known' ); // The call to $this->contentHelper->getTargetRevision() should not return null if // $this->contentHelper->checkAccess() did not throw. diff --git a/includes/Rest/Handler/RevisionSourceHandler.php b/includes/Rest/Handler/RevisionSourceHandler.php index 3071cd0928b1..77040475c752 100644 --- a/includes/Rest/Handler/RevisionSourceHandler.php +++ b/includes/Rest/Handler/RevisionSourceHandler.php @@ -4,12 +4,12 @@ namespace MediaWiki\Rest\Handler; use Config; use LogicException; +use MediaWiki\Page\PageLookup; use MediaWiki\Rest\LocalizedHttpException; use MediaWiki\Rest\Response; use MediaWiki\Rest\SimpleHandler; use MediaWiki\Revision\RevisionLookup; use MediaWiki\Revision\RevisionRecord; -use TitleFactory; use TitleFormatter; /** @@ -26,19 +26,19 @@ class RevisionSourceHandler extends SimpleHandler { * @param Config $config * @param RevisionLookup $revisionLookup * @param TitleFormatter $titleFormatter - * @param TitleFactory $titleFactory + * @param PageLookup $pageLookup */ public function __construct( Config $config, RevisionLookup $revisionLookup, TitleFormatter $titleFormatter, - TitleFactory $titleFactory + PageLookup $pageLookup ) { $this->contentHelper = new RevisionContentHelper( $config, $revisionLookup, $titleFormatter, - $titleFactory + $pageLookup ); } diff --git a/includes/Rest/coreDevelopmentRoutes.json b/includes/Rest/coreDevelopmentRoutes.json index 385c0b606158..1984e14e2598 100644 --- a/includes/Rest/coreDevelopmentRoutes.json +++ b/includes/Rest/coreDevelopmentRoutes.json @@ -42,7 +42,7 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory" + "PageStore" ], "format": "source" }, @@ -53,10 +53,9 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory", "ParserCacheFactory", - "WikiPageFactory", - "GlobalIdGenerator" + "GlobalIdGenerator", + "PageStore" ], "format": "html" }, @@ -67,10 +66,9 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory", "ParserCacheFactory", - "WikiPageFactory", - "GlobalIdGenerator" + "GlobalIdGenerator", + "PageStore" ], "format": "with_html" } diff --git a/includes/Rest/coreRoutes.json b/includes/Rest/coreRoutes.json index 321812622fea..28285d02df3c 100644 --- a/includes/Rest/coreRoutes.json +++ b/includes/Rest/coreRoutes.json @@ -6,7 +6,9 @@ "RevisionStore", "NameTableStoreFactory", "PermissionManager", - "DBLoadBalancer" + "DBLoadBalancer", + "PageStore", + "TitleFormatter" ] }, { @@ -17,7 +19,8 @@ "NameTableStoreFactory", "PermissionManager", "DBLoadBalancer", - "MainWANObjectCache" + "MainWANObjectCache", + "PageStore" ] }, { @@ -35,7 +38,7 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory" + "PageStore" ], "format": "bare" }, @@ -66,7 +69,8 @@ "DBLoadBalancer", "LanguageNameUtils", "TitleFormatter", - "TitleParser" + "TitleParser", + "PageStore" ] }, { @@ -76,7 +80,7 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory" + "PageStore" ], "format": "source" }, @@ -87,7 +91,7 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory" + "PageStore" ], "format": "bare" }, @@ -98,10 +102,9 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory", "ParserCacheFactory", - "WikiPageFactory", - "GlobalIdGenerator" + "GlobalIdGenerator", + "PageStore" ], "format": "html" }, @@ -112,10 +115,9 @@ "MainConfig", "RevisionLookup", "TitleFormatter", - "TitleFactory", "ParserCacheFactory", - "WikiPageFactory", - "GlobalIdGenerator" + "GlobalIdGenerator", + "PageStore" ], "format": "with_html" }, @@ -124,14 +126,16 @@ "class": "MediaWiki\\Rest\\Handler\\MediaLinksHandler", "services": [ "DBLoadBalancer", - "RepoGroup" + "RepoGroup", + "PageStore" ] }, { "path": "/v1/file/{title}", "class": "MediaWiki\\Rest\\Handler\\MediaFileHandler", "services": [ - "RepoGroup" + "RepoGroup", + "PageStore" ] }, { diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 8884949067cb..4f58f0b9bc15 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -985,7 +985,8 @@ return [ return new PageStoreFactory( $options, $services->getDBLoadBalancerFactory(), - $services->getNamespaceInfo() + $services->getNamespaceInfo(), + $services->getTitleParser() ); }, diff --git a/includes/page/PageLookup.php b/includes/page/PageLookup.php index 683047a0b9c5..0caa27a3c664 100644 --- a/includes/page/PageLookup.php +++ b/includes/page/PageLookup.php @@ -62,6 +62,40 @@ interface PageLookup extends IDBAccessObject { ): ?ExistingPageRecord; /** + * Returns a PageIdentity for a given user provided page name text. + * + * @since 1.37 + * + * @param string $text + * @param int $defaultNamespace Namespace to assume per default (usually NS_MAIN) + * @param int $queryFlags + * + * @return ProperPageIdentity|null + */ + public function getPageByText( + string $text, + int $defaultNamespace = NS_MAIN, + int $queryFlags = self::READ_NORMAL + ): ?ProperPageIdentity; + + /** + * Returns an existing PageRecord for a given user provided page name text. + * + * @since 1.37 + * + * @param string $text + * @param int $defaultNamespace Namespace to assume per default (usually NS_MAIN) + * @param int $queryFlags + * + * @return ExistingPageRecord|null + */ + public function getExistingPageByText( + string $text, + int $defaultNamespace = NS_MAIN, + int $queryFlags = self::READ_NORMAL + ): ?ExistingPageRecord; + + /** * Returns the PageRecord of the given page. * May return $page if that already is a PageRecord. * diff --git a/includes/page/PageStore.php b/includes/page/PageStore.php index d8627a981eef..7674870526f8 100644 --- a/includes/page/PageStore.php +++ b/includes/page/PageStore.php @@ -5,11 +5,13 @@ namespace MediaWiki\Page; use DBAccessObjectUtils; use EmptyIterator; use Iterator; +use MalformedTitleException; use MediaWiki\Config\ServiceOptions; use MediaWiki\DAO\WikiAwareEntity; use MediaWiki\Linker\LinkTarget; use NamespaceInfo; use stdClass; +use TitleParser; use Wikimedia\Assert\Assert; use Wikimedia\Rdbms\IDatabase; use Wikimedia\Rdbms\ILoadBalancer; @@ -31,6 +33,9 @@ class PageStore implements PageLookup { /** @var NamespaceInfo */ private $namespaceInfo; + /** @var TitleParser */ + private $titleParser; + /** @var string|false */ private $wikiId; @@ -45,12 +50,14 @@ class PageStore implements PageLookup { * @param ServiceOptions $options * @param ILoadBalancer $dbLoadBalancer * @param NamespaceInfo $namespaceInfo + * @param TitleParser $titleParser * @param false|string $wikiId */ public function __construct( ServiceOptions $options, ILoadBalancer $dbLoadBalancer, NamespaceInfo $namespaceInfo, + TitleParser $titleParser, $wikiId = WikiAwareEntity::LOCAL ) { $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); @@ -58,6 +65,7 @@ class PageStore implements PageLookup { $this->options = $options; $this->dbLoadBalancer = $dbLoadBalancer; $this->namespaceInfo = $namespaceInfo; + $this->titleParser = $titleParser; $this->wikiId = $wikiId; } @@ -117,6 +125,49 @@ class PageStore implements PageLookup { } /** + * @since 1.37 + * + * @param string $text + * @param int $defaultNamespace Namespace to assume per default (usually NS_MAIN) + * @param int $queryFlags + * + * @return ProperPageIdentity|null + */ + public function getPageByText( + string $text, + int $defaultNamespace = NS_MAIN, + int $queryFlags = self::READ_NORMAL + ): ?ProperPageIdentity { + try { + $title = $this->titleParser->parseTitle( $text, $defaultNamespace ); + return $this->getPageForLink( $title, $queryFlags ); + } catch ( MalformedTitleException $e ) { + return null; + } + } + + /** + * @since 1.37 + * + * @param string $text + * @param int $defaultNamespace Namespace to assume per default (usually NS_MAIN) + * @param int $queryFlags + * + * @return ExistingPageRecord|null + */ + public function getExistingPageByText( + string $text, + int $defaultNamespace = NS_MAIN, + int $queryFlags = self::READ_NORMAL + ): ?ExistingPageRecord { + $pageIdentity = $this->getPageByText( $text, $defaultNamespace, $queryFlags ); + if ( !$pageIdentity ) { + return null; + } + return $this->getPageByReference( $pageIdentity, $queryFlags ); + } + + /** * @param int $pageId * @param int $queryFlags * diff --git a/includes/page/PageStoreFactory.php b/includes/page/PageStoreFactory.php index 6bff4d472a09..c93dfa6d0d61 100644 --- a/includes/page/PageStoreFactory.php +++ b/includes/page/PageStoreFactory.php @@ -5,6 +5,7 @@ namespace MediaWiki\Page; use MediaWiki\Config\ServiceOptions; use MediaWiki\DAO\WikiAwareEntity; use NamespaceInfo; +use TitleParser; use Wikimedia\Rdbms\ILBFactory; /** @@ -26,21 +27,27 @@ class PageStoreFactory { /** @var NamespaceInfo */ private $namespaceInfo; + /** @var TitleParser */ + private $titleParser; + /** * @param ServiceOptions $options * @param ILBFactory $dbLoadBalancerFactory * @param NamespaceInfo $namespaceInfo + * @param TitleParser $titleParser */ public function __construct( ServiceOptions $options, ILBFactory $dbLoadBalancerFactory, - NamespaceInfo $namespaceInfo + NamespaceInfo $namespaceInfo, + TitleParser $titleParser ) { $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); $this->options = $options; $this->dbLoadBalancerFactory = $dbLoadBalancerFactory; $this->namespaceInfo = $namespaceInfo; + $this->titleParser = $titleParser; } /** @@ -53,6 +60,7 @@ class PageStoreFactory { $this->options, $this->dbLoadBalancerFactory->getMainLB( $wikiId ), $this->namespaceInfo, + $this->titleParser, $wikiId ); } |