Introduce PageRecord interface
PageRecord is intended as a lightweight alternative to WikiPage, similar to RevisionRecord. Bug: T272421 Bug: T272422 Depends-On: Ia34cc8fa795b6b27832982fc22fa237ee36339b4 Depends-On: I39a984c9f3132f755f7d8984b789d05ad080d7b4 Change-Id: Ib3c9b22e0c0b7c97e6c230f2fecf0663b4c68cc6
This commit is contained in:
parent
749b25892b
commit
f37ebf4478
8 changed files with 684 additions and 5 deletions
|
|
@ -27,8 +27,10 @@ use MediaWiki\Interwiki\InterwikiLookup;
|
|||
use MediaWiki\Linker\LinkTarget;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Page\ExistingPageRecord;
|
||||
use MediaWiki\Page\PageIdentity;
|
||||
use MediaWiki\Page\PageIdentityValue;
|
||||
use MediaWiki\Page\PageStoreRecord;
|
||||
use MediaWiki\Page\ProperPageIdentity;
|
||||
use Wikimedia\Assert\Assert;
|
||||
use Wikimedia\Assert\PreconditionException;
|
||||
|
|
@ -4682,4 +4684,44 @@ class Title implements LinkTarget, PageIdentity, IDBAccessObject {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page represented by this Title as a ProperPageRecord.
|
||||
* The PageRecord returned by this method is guaranteed to be immutable,
|
||||
* the page is guaranteed to exist.
|
||||
*
|
||||
* @note For now, this method queries the database on every call.
|
||||
* @since 1.36
|
||||
*
|
||||
* @param int $flags Either a bitfield of class READ_* constants or GAID_FOR_UPDATE
|
||||
*
|
||||
* @return ExistingPageRecord
|
||||
* @throws PreconditionException if the page does not exist, or is not a proper page,
|
||||
* that is, if it is a section link, interwiki link, link to a special page, or such.
|
||||
*/
|
||||
public function toPageRecord( $flags = 0 ): ExistingPageRecord {
|
||||
// TODO: Cache this? Construct is more efficiently?
|
||||
|
||||
$this->assertProperPage();
|
||||
|
||||
Assert::precondition(
|
||||
$this->exists(),
|
||||
'This Title instance does not represent an existing page: ' . $this
|
||||
);
|
||||
|
||||
return new PageStoreRecord(
|
||||
(object)[
|
||||
'page_id' => $this->getArticleID( $flags ),
|
||||
'page_namespace' => $this->getNamespace(),
|
||||
'page_title' => $this->getDBkey(),
|
||||
'page_wiki_id' => $this->getWikiId(),
|
||||
'page_latest' => $this->getLatestRevID( $flags ),
|
||||
'page_is_new' => $this->isNewPage(), // no flags?
|
||||
'page_is_redirect' => $this->isRedirect( $flags ),
|
||||
'page_touched' => $this->getTouched(), // no flags?
|
||||
'page_lang' => $this->getPageLanguage()->getCode(),
|
||||
],
|
||||
PageIdentity::LOCAL
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
23
includes/page/ExistingPageRecord.php
Normal file
23
includes/page/ExistingPageRecord.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
namespace MediaWiki\Page;
|
||||
|
||||
/**
|
||||
* Data record representing a page that currently exists as
|
||||
* an editable page on a wiki.
|
||||
*
|
||||
* @note This is intended to become an alias for PageRecord, once PageRecord is guaranteed
|
||||
* to be immutable and to represent existing pages.
|
||||
*
|
||||
* @stable to type
|
||||
*
|
||||
* @since 1.36
|
||||
*/
|
||||
interface ExistingPageRecord extends PageRecord, ProperPageIdentity {
|
||||
|
||||
/**
|
||||
* Always true.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(): bool;
|
||||
}
|
||||
70
includes/page/PageRecord.php
Normal file
70
includes/page/PageRecord.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
namespace MediaWiki\Page;
|
||||
|
||||
/**
|
||||
* Data record representing a page that is (or used to be, or could be)
|
||||
* an editable page on a wiki.
|
||||
*
|
||||
* @note For compatibility with the WikiPage class, PageIdentity instances may
|
||||
* represent non-existing pages. In the future, the contract of this interface is intended
|
||||
* to be changed to disallow this.
|
||||
*
|
||||
* @note For compatibility with the WikiPage class, PageIdentity instances may
|
||||
* be mutable, and return different values from methods such as getLatest() or isRedirect()
|
||||
* at different times. In the future, the contract of this interface is intended
|
||||
* to be changed to disallow this.
|
||||
*
|
||||
* @note Only WikiPage should implement PageRecord directly, other implementations should use
|
||||
* ExistingPageRecord instead. Once WikiPage is removed or guaranteed to be immutable and
|
||||
* existing, ExistingPageRecord will become an alias of PageRecord.
|
||||
*
|
||||
* @todo In the future, PageRecord should extend ProperPageIdentity. This will only
|
||||
* become possible when WikiPage can no longer represent non-proper pages.
|
||||
*
|
||||
* @stable to type
|
||||
*
|
||||
* @since 1.36
|
||||
*/
|
||||
interface PageRecord extends PageIdentity {
|
||||
|
||||
/**
|
||||
* False if the page has had more than one edit.
|
||||
*
|
||||
* @warning this is not guaranteed to always return true for old pages that have only one edit.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNew();
|
||||
|
||||
/**
|
||||
* True if the page is a redirect.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedirect();
|
||||
|
||||
/**
|
||||
* The ID of the page's latest revision.
|
||||
*
|
||||
* @param string|false $wikiId Must be provided when accessing the ID of the latest revision of
|
||||
* a non-local PageRecord, to prevent data corruption when using a PageRecord belonging
|
||||
* to one wiki in the context of another. Should be omitted if expecting the local wiki.
|
||||
*
|
||||
* @return int The revision ID of the page's latest revision, or 0 if the page does not exist.
|
||||
*/
|
||||
public function getLatest( $wikiId = self::LOCAL );
|
||||
|
||||
/**
|
||||
* Timestamp at which the page was last flagged for rerendering.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTouched();
|
||||
|
||||
/**
|
||||
* The page's language.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage();
|
||||
}
|
||||
122
includes/page/PageStoreRecord.php
Normal file
122
includes/page/PageStoreRecord.php
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Page;
|
||||
|
||||
use MWTimestamp;
|
||||
use stdClass;
|
||||
use Wikimedia\Assert\Assert;
|
||||
|
||||
/**
|
||||
* Immutable data record representing an editable page on a wiki.
|
||||
* Corresponds to a row in the page table.
|
||||
*
|
||||
* @since 1.36
|
||||
*/
|
||||
class PageStoreRecord extends PageIdentityValue implements ExistingPageRecord {
|
||||
|
||||
/**
|
||||
* Fields from the page table.
|
||||
*
|
||||
* @var stdClass
|
||||
*/
|
||||
private $row;
|
||||
|
||||
/**
|
||||
* The $row object must provide the following fields:
|
||||
* - page_id: the page ID
|
||||
* - page_namespace: the page's namespace
|
||||
* - page_title: the page's title in normalized DB key form.
|
||||
* - page_latest: the revision ID of the page's current revision
|
||||
* - page_is_new: whether the page is new and only has one edit
|
||||
* - page_is_redirect: whether the page is a redirect
|
||||
* - page_touched: the time at which the page was last re-parsed
|
||||
* - page_lang: the page's primary language (supply the content language if not known)
|
||||
*
|
||||
* @param stdClass $row A row from the page table
|
||||
* @param string|bool $wikiId The Id of the wiki this page belongs to,
|
||||
* or self::LOCAL for the local wiki.
|
||||
*/
|
||||
public function __construct( stdClass $row, $wikiId ) {
|
||||
Assert::parameter( isset( $row->page_id ), '$row->page_id', 'is required' );
|
||||
Assert::parameter( isset( $row->page_namespace ), '$row->page_namespace', 'is required' );
|
||||
Assert::parameter( isset( $row->page_title ), '$row->page_title', 'is required' );
|
||||
Assert::parameter( isset( $row->page_latest ), '$row->page_latest', 'is required' );
|
||||
Assert::parameter( isset( $row->page_is_new ), '$row->page_is_new', 'is required' );
|
||||
Assert::parameter( isset( $row->page_is_redirect ), '$row->page_is_redirect', 'is required' );
|
||||
Assert::parameter( isset( $row->page_touched ), '$row->page_touched', 'is required' );
|
||||
Assert::parameter( isset( $row->page_lang ), '$row->page_lang', 'is required' );
|
||||
|
||||
Assert::parameter( $row->page_id > 0, '$pageId', 'must be greater than zero (page must exist)' );
|
||||
|
||||
parent::__construct( $row->page_id, $row->page_namespace, $row->page_title, $wikiId );
|
||||
|
||||
$this->row = $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* False if the page has had more than one edit.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNew(): bool {
|
||||
return (bool)$this->row->page_is_new;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the page is a redirect.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedirect(): bool {
|
||||
return (bool)$this->row->page_is_redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the page'S latest revision.
|
||||
*
|
||||
* @param bool $wikiId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLatest( $wikiId = self::LOCAL ): int {
|
||||
$this->assertWiki( $wikiId );
|
||||
return (int)$this->row->page_latest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp at which the page was last rerendered.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTouched(): string {
|
||||
return MWTimestamp::convert( TS_MW, $this->row->page_touched );
|
||||
}
|
||||
|
||||
/**
|
||||
* Language in which the page is written.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage(): string {
|
||||
return (string)$this->row->page_lang;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -29,7 +29,10 @@ use MediaWiki\Edit\PreparedEdit;
|
|||
use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Page\ExistingPageRecord;
|
||||
use MediaWiki\Page\PageIdentity;
|
||||
use MediaWiki\Page\PageRecord;
|
||||
use MediaWiki\Page\PageStoreRecord;
|
||||
use MediaWiki\Page\ParserOutputAccess;
|
||||
use MediaWiki\Permissions\Authority;
|
||||
use MediaWiki\Permissions\PermissionStatus;
|
||||
|
|
@ -58,7 +61,7 @@ use Wikimedia\Rdbms\LoadBalancer;
|
|||
* Some fields are public only for backwards-compatibility. Use accessors.
|
||||
* In the past, this class was part of Article.php and everything was public.
|
||||
*/
|
||||
class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
||||
class WikiPage implements Page, IDBAccessObject, PageRecord {
|
||||
use NonSerializableTrait;
|
||||
use ProtectedHookAccessorTrait;
|
||||
use WikiAwareEntityTrait;
|
||||
|
|
@ -100,6 +103,16 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
*/
|
||||
protected $mRedirectTarget = null;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $mIsNew = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $mIsRedirect = false;
|
||||
|
||||
/**
|
||||
* @var int|false False means "not loaded"
|
||||
* @todo make protected
|
||||
|
|
@ -139,6 +152,11 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
*/
|
||||
protected $mTouched = '19700101000000';
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $mLanguage = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -340,8 +358,11 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
$this->mPageIsRedirectField = false;
|
||||
$this->mLastRevision = null; // Latest revision
|
||||
$this->mTouched = '19700101000000';
|
||||
$this->mLanguage = null;
|
||||
$this->mLinksUpdated = '19700101000000';
|
||||
$this->mTimestamp = '';
|
||||
$this->mIsNew = false;
|
||||
$this->mIsRedirect = false;
|
||||
$this->mLatest = false;
|
||||
// T59026: do not clear $this->derivedDataUpdater since getDerivedDataUpdater() already
|
||||
// checks the requested rev ID and content against the cached one. For most
|
||||
|
|
@ -561,12 +582,17 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
// Old-fashioned restrictions
|
||||
$this->mTitle->loadRestrictions( $data->page_restrictions );
|
||||
|
||||
$contLang = MediaWikiServices::getInstance()->getContentLanguage();
|
||||
|
||||
$this->mId = intval( $data->page_id );
|
||||
$this->mTouched = MWTimestamp::convert( TS_MW, $data->page_touched );
|
||||
$this->mLanguage = $data->page_lang ?? $contLang->getCode();
|
||||
$this->mLinksUpdated = $data->page_links_updated === null
|
||||
? null
|
||||
: MWTimestamp::convert( TS_MW, $data->page_links_updated );
|
||||
$this->mPageIsRedirectField = (bool)$data->page_is_redirect;
|
||||
$this->mIsNew = intval( $data->page_is_new ?? 0 );
|
||||
$this->mIsRedirect = intval( $data->page_is_redirect ?? 0 );
|
||||
$this->mLatest = intval( $data->page_latest );
|
||||
// T39225: $latest may no longer match the cached latest RevisionRecord object.
|
||||
// Double-check the ID of any cached latest RevisionRecord object for consistency.
|
||||
|
|
@ -650,7 +676,11 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
* @return bool
|
||||
*/
|
||||
public function isRedirect() {
|
||||
return $this->getRedirectTarget() !== null;
|
||||
if ( !$this->mDataLoaded ) {
|
||||
$this->loadPageData();
|
||||
}
|
||||
|
||||
return (bool)$this->mIsRedirect;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -669,6 +699,22 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
return $this->mPageIsRedirectField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the page is new (only has one revision).
|
||||
* May produce false negatives for some old pages.
|
||||
*
|
||||
* @since 1.36
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNew() {
|
||||
if ( !$this->mDataLoaded ) {
|
||||
$this->loadPageData();
|
||||
}
|
||||
|
||||
return (bool)$this->mIsNew;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page's content model id (see the CONTENT_MODEL_XXX constants).
|
||||
*
|
||||
|
|
@ -733,6 +779,17 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
return $this->mTouched;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string language code for the page
|
||||
*/
|
||||
public function getLanguage() {
|
||||
if ( !$this->mDataLoaded ) {
|
||||
$this->loadLastEdit();
|
||||
}
|
||||
|
||||
return $this->mLanguage ?: MediaWikiServices::getInstance()->getContentLanguage()->getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page_links_updated field
|
||||
* @return string|null Containing GMT timestamp
|
||||
|
|
@ -746,9 +803,12 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
|
||||
/**
|
||||
* Get the page_latest field
|
||||
* @param bool $wikiId
|
||||
* @return int The rev_id of current revision
|
||||
*/
|
||||
public function getLatest() {
|
||||
public function getLatest( $wikiId = self::LOCAL ) {
|
||||
$this->assertWiki( $wikiId );
|
||||
|
||||
if ( !$this->mDataLoaded ) {
|
||||
$this->loadPageData();
|
||||
}
|
||||
|
|
@ -1454,6 +1514,8 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
$content = $revision->getContent( SlotRecord::MAIN );
|
||||
$len = $content ? $content->getSize() : 0;
|
||||
$rt = $content ? $content->getUltimateRedirectTarget() : null;
|
||||
$isNew = ( $lastRevision === 0 ) ? 1 : 0;
|
||||
$isRedirect = $rt !== null ? 1 : 0;
|
||||
|
||||
$conditions = [ 'page_id' => $this->getId() ];
|
||||
|
||||
|
|
@ -1470,8 +1532,8 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
$row = [ /* SET */
|
||||
'page_latest' => $revId,
|
||||
'page_touched' => $dbw->timestamp( $revision->getTimestamp() ),
|
||||
'page_is_new' => ( $lastRevision === 0 ) ? 1 : 0,
|
||||
'page_is_redirect' => $rt !== null ? 1 : 0,
|
||||
'page_is_new' => $isNew,
|
||||
'page_is_redirect' => $isRedirect,
|
||||
'page_len' => $len,
|
||||
'page_content_model' => $model,
|
||||
];
|
||||
|
|
@ -1489,6 +1551,8 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
$this->mRedirectTarget = null;
|
||||
$this->mHasRedirectTarget = null;
|
||||
$this->mPageIsRedirectField = (bool)$rt;
|
||||
$this->mIsNew = (bool)$isNew;
|
||||
$this->mIsRedirect = (bool)$isRedirect;
|
||||
// Update the LinkCache.
|
||||
$linkCache = MediaWikiServices::getInstance()->getLinkCache();
|
||||
$linkCache->addGoodLinkObj(
|
||||
|
|
@ -4223,4 +4287,42 @@ class WikiPage implements Page, IDBAccessObject, PageIdentity {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page represented by this WikiPage as a PageStoreRecord.
|
||||
* The PageRecord returned by this method is guaranteed to be immutable.
|
||||
*
|
||||
* It is preferred to use this method rather than using the WikiPage as a PageIdentity directly.
|
||||
* @since 1.36
|
||||
*
|
||||
* @throws PreconditionException if the page does not exist.
|
||||
*
|
||||
* @return ExistingPageRecord
|
||||
*/
|
||||
public function toPageRecord(): ExistingPageRecord {
|
||||
// TODO: replace individual member fields with a PageRecord instance that is always present
|
||||
|
||||
if ( !$this->mDataLoaded ) {
|
||||
$this->loadPageData();
|
||||
}
|
||||
|
||||
Assert::precondition(
|
||||
$this->exists(),
|
||||
'This WikiPage instance does not represent an existing page: ' . $this->mTitle
|
||||
);
|
||||
|
||||
return new PageStoreRecord(
|
||||
(object)[
|
||||
'page_id' => $this->getId(),
|
||||
'page_namespace' => $this->mTitle->getNamespace(),
|
||||
'page_title' => $this->mTitle->getDBkey(),
|
||||
'page_latest' => $this->mLatest,
|
||||
'page_is_new' => $this->mIsNew,
|
||||
'page_is_redirect' => $this->mIsRedirect,
|
||||
'page_touched' => $this->mTouched,
|
||||
'page_lang' => $this->getLanguage()
|
||||
],
|
||||
PageIdentity::LOCAL
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -475,6 +475,41 @@ class TitleMethodsTest extends MediaWikiLangTestCase {
|
|||
$this->assertSame( $title->getWikiId(), $page->getWikiId() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideProperPage
|
||||
* @covers Title::toPageRecord
|
||||
*/
|
||||
public function testToPageRecord( $ns, $text ) {
|
||||
$title = Title::makeTitle( $ns, $text );
|
||||
$wikiPage = $this->getExistingTestPage( $title );
|
||||
|
||||
$record = $title->toPageRecord();
|
||||
|
||||
$this->assertNotSame( $title, $record );
|
||||
$this->assertNotSame( $title, $wikiPage );
|
||||
|
||||
$this->assertSame( $title->getId(), $record->getId() );
|
||||
$this->assertSame( $title->getNamespace(), $record->getNamespace() );
|
||||
$this->assertSame( $title->getDBkey(), $record->getDBkey() );
|
||||
$this->assertSame( $title->getWikiId(), $record->getWikiId() );
|
||||
|
||||
$this->assertSame( $title->getLatestRevID(), $record->getLatest() );
|
||||
$this->assertSame( MWTimestamp::convert( TS_MW, $title->getTouched() ), $record->getTouched() );
|
||||
$this->assertSame( $title->isNewPage(), $record->isNew() );
|
||||
$this->assertSame( $title->isRedirect(), $record->isRedirect() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideImproperPage
|
||||
* @covers Title::toPageRecord
|
||||
*/
|
||||
public function testToPageRecord_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
||||
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
||||
|
||||
$this->expectException( PreconditionException::class );
|
||||
$title->toPageRecord();
|
||||
}
|
||||
|
||||
public function provideImproperPage() {
|
||||
return [
|
||||
[ NS_MAIN, '' ],
|
||||
|
|
|
|||
|
|
@ -1931,12 +1931,14 @@ more stuff
|
|||
'page_id' => '44',
|
||||
'page_len' => '76',
|
||||
'page_is_redirect' => '1',
|
||||
'page_is_new' => '1',
|
||||
'page_latest' => '99',
|
||||
'page_namespace' => '3',
|
||||
'page_title' => 'JaJaTitle',
|
||||
'page_restrictions' => 'edit=autoconfirmed,sysop:move=sysop',
|
||||
'page_touched' => '20120101020202',
|
||||
'page_links_updated' => '20140101020202',
|
||||
'page_lang' => 'it',
|
||||
];
|
||||
foreach ( $overrides as $key => $value ) {
|
||||
$row[$key] = $value;
|
||||
|
|
@ -1952,6 +1954,8 @@ more stuff
|
|||
$test->assertSame( 76, $wikiPage->getTitle()->getLength() );
|
||||
$test->assertTrue( $wikiPage->getPageIsRedirectField() );
|
||||
$test->assertSame( 99, $wikiPage->getLatest() );
|
||||
$test->assertSame( true, $wikiPage->isNew() );
|
||||
$test->assertSame( 'it', $wikiPage->getLanguage() );
|
||||
$test->assertSame( 3, $wikiPage->getTitle()->getNamespace() );
|
||||
$test->assertSame( 'JaJaTitle', $wikiPage->getTitle()->getDBkey() );
|
||||
$test->assertSame(
|
||||
|
|
@ -1989,6 +1993,17 @@ more stuff
|
|||
);
|
||||
}
|
||||
];
|
||||
yield 'no language' => [
|
||||
$this->getRow( [
|
||||
'page_lang' => null,
|
||||
] ),
|
||||
function ( WikiPage $wikiPage, self $test ) {
|
||||
$test->assertSame(
|
||||
'en',
|
||||
$wikiPage->getLanguage()
|
||||
);
|
||||
}
|
||||
];
|
||||
yield 'not redirect' => [
|
||||
$this->getRow( [
|
||||
'page_is_redirect' => '0',
|
||||
|
|
@ -1997,6 +2012,14 @@ more stuff
|
|||
$test->assertFalse( $wikiPage->isRedirect() );
|
||||
}
|
||||
];
|
||||
yield 'not new' => [
|
||||
$this->getRow( [
|
||||
'page_is_new' => '0',
|
||||
] ),
|
||||
function ( WikiPage $wikiPage, self $test ) {
|
||||
$test->assertFalse( $wikiPage->isNew() );
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2699,4 +2722,48 @@ more stuff
|
|||
$this->assertTrue( $title->isRedirect() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers WikiPage::getTitle
|
||||
* @covers WikiPage::getId
|
||||
* @covers WikiPage::getNamespace
|
||||
* @covers WikiPage::getDBkey
|
||||
* @covers WikiPage::getWikiId
|
||||
* @covers WikiPage::canExist
|
||||
*/
|
||||
public function testGetTitle() {
|
||||
$page = $this->createPage( __METHOD__, 'whatever' );
|
||||
|
||||
$title = $page->getTitle();
|
||||
$this->assertSame( __METHOD__, $title->getText() );
|
||||
|
||||
$this->assertSame( $page->getId(), $title->getId() );
|
||||
$this->assertSame( $page->getNamespace(), $title->getNamespace() );
|
||||
$this->assertSame( $page->getDBkey(), $title->getDBkey() );
|
||||
$this->assertSame( $page->getWikiId(), $title->getWikiId() );
|
||||
$this->assertSame( $page->canExist(), $title->canExist() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers WikiPage::toPageRecord
|
||||
* @covers WikiPage::getLatest
|
||||
* @covers WikiPage::getTouched
|
||||
* @covers WikiPage::isNew
|
||||
* @covers WikiPage::isRedirect
|
||||
*/
|
||||
public function testToPageRecord() {
|
||||
$page = $this->createPage( __METHOD__, 'whatever' );
|
||||
$record = $page->toPageRecord();
|
||||
|
||||
$this->assertSame( $page->getId(), $record->getId() );
|
||||
$this->assertSame( $page->getNamespace(), $record->getNamespace() );
|
||||
$this->assertSame( $page->getDBkey(), $record->getDBkey() );
|
||||
$this->assertSame( $page->getWikiId(), $record->getWikiId() );
|
||||
$this->assertSame( $page->canExist(), $record->canExist() );
|
||||
|
||||
$this->assertSame( $page->getLatest(), $record->getLatest() );
|
||||
$this->assertSame( $page->getTouched(), $record->getTouched() );
|
||||
$this->assertSame( $page->isNew(), $record->isNew() );
|
||||
$this->assertSame( $page->isRedirect(), $record->isRedirect() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
218
tests/phpunit/unit/includes/page/PageStoreRecordTest.php
Normal file
218
tests/phpunit/unit/includes/page/PageStoreRecordTest.php
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
* @author Daniel Kinzler
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Tests\Unit\Page;
|
||||
|
||||
use MediaWiki\Page\PageIdentity;
|
||||
use MediaWiki\Page\PageIdentityValue;
|
||||
use MediaWiki\Page\PageRecord;
|
||||
use MediaWiki\Page\PageStoreRecord;
|
||||
use MediaWikiUnitTestCase;
|
||||
use RuntimeException;
|
||||
use Wikimedia\Assert\ParameterAssertionException;
|
||||
|
||||
/**
|
||||
* @covers \MediaWiki\Page\PageStoreRecord
|
||||
*
|
||||
* @group Title
|
||||
*/
|
||||
class PageStoreRecordTest extends MediaWikiUnitTestCase {
|
||||
|
||||
public function goodConstructorProvider() {
|
||||
return [
|
||||
[
|
||||
(object)[
|
||||
'page_id' => 7,
|
||||
'page_namespace' => NS_MAIN,
|
||||
'page_title' => 'Test',
|
||||
'page_touched' => '20200909001122',
|
||||
'page_latest' => 1717,
|
||||
'page_is_new' => true,
|
||||
'page_is_redirect' => true,
|
||||
'page_lang' => 'it',
|
||||
],
|
||||
PageIdentity::LOCAL
|
||||
],
|
||||
[
|
||||
(object)[
|
||||
'page_id' => 3,
|
||||
'page_namespace' => NS_USER,
|
||||
'page_title' => 'Test',
|
||||
'page_touched' => '20200909001122',
|
||||
'page_latest' => 1717,
|
||||
'page_is_new' => false,
|
||||
'page_is_redirect' => false,
|
||||
'page_lang' => 'und',
|
||||
],
|
||||
'h2g2'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider goodConstructorProvider
|
||||
*/
|
||||
public function testConstruction( $row, $wikiId ) {
|
||||
$pageRecord = new PageStoreRecord( $row, $wikiId );
|
||||
|
||||
$this->assertSame( $row->page_id, $pageRecord->getId( $wikiId ) );
|
||||
$this->assertSame( $row->page_id > 0, $pageRecord->exists() );
|
||||
$this->assertSame( $row->page_namespace, $pageRecord->getNamespace() );
|
||||
$this->assertSame( $row->page_title, $pageRecord->getDBkey() );
|
||||
|
||||
$this->assertTrue( $pageRecord->canExist() );
|
||||
|
||||
$this->assertSame( $wikiId, $pageRecord->getWikiId() );
|
||||
$this->assertSame( $row->page_touched, $pageRecord->getTouched() );
|
||||
$this->assertSame( $row->page_latest, $pageRecord->getLatest( $wikiId ) );
|
||||
$this->assertSame( $row->page_is_new, $pageRecord->isNew() );
|
||||
$this->assertSame( $row->page_is_redirect, $pageRecord->isRedirect() );
|
||||
$this->assertSame( $row->page_lang, $pageRecord->getLanguage() );
|
||||
}
|
||||
|
||||
public function badConstructorProvider() {
|
||||
$row = [
|
||||
'page_id' => 1,
|
||||
'page_namespace' => NS_MAIN,
|
||||
'page_title' => 'Test',
|
||||
'page_touched' => '20200909001122',
|
||||
'page_latest' => 1717,
|
||||
'page_is_new' => true,
|
||||
'page_is_redirect' => true,
|
||||
];
|
||||
return [
|
||||
'nonexisting page' => [ (object)( [ 'page_id' => 0 ] + $row ) ],
|
||||
'negative id' => [ (object)( [ 'page_id' => -1 ] + $row ) ],
|
||||
'special page' => [ (object)( [ 'page_namespace' => NS_SPECIAL ] + $row ) ],
|
||||
'empty title' => [ (object)( [ 'page_title' => '' ] + $row ) ],
|
||||
'section link' => [ (object)( [ 'page_title' => 'Foo#Bar' ] + $row ) ],
|
||||
'pipe in title' => [ (object)( [ 'page_title' => 'Foo|Bar' ] + $row ) ],
|
||||
'tab in title' => [ (object)( [ 'page_title' => "Foo\tBar" ] + $row ) ],
|
||||
|
||||
// missing data
|
||||
'missing touched' => [ (object)array_diff_key( $row, [ 'touched' => 'foo' ] ) ],
|
||||
'missing latest' => [ (object)array_diff_key( $row, [ 'latest' => 'foo' ] ) ],
|
||||
'missing is_new' => [ (object)array_diff_key( $row, [ 'is_new' => 'foo' ] ) ],
|
||||
'missing lang' => [ (object)array_diff_key( $row, [ 'lang' => 'foo' ] ) ],
|
||||
'missing is_redirect' => [ (object)array_diff_key( $row, [ 'is_redirect' => 'foo' ] ) ],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider badConstructorProvider
|
||||
*/
|
||||
public function testConstructionErrors( $row ) {
|
||||
$this->expectException( ParameterAssertionException::class );
|
||||
new PageStoreRecord( $row, PageStoreRecord::LOCAL );
|
||||
}
|
||||
|
||||
public function testGetLatestRequiresForeignWikiId() {
|
||||
$row = (object)[
|
||||
'page_id' => 7,
|
||||
'page_namespace' => NS_MAIN,
|
||||
'page_title' => 'Test',
|
||||
'page_touched' => '20200909001122',
|
||||
'page_latest' => 1717,
|
||||
'page_is_new' => true,
|
||||
'page_is_redirect' => true,
|
||||
'page_lang' => 'it',
|
||||
];
|
||||
$pageRecord = new PageStoreRecord( $row, 'acme' );
|
||||
|
||||
$this->expectException( RuntimeException::class );
|
||||
$pageRecord->getLatest( 'xyzzy' );
|
||||
}
|
||||
|
||||
public function provideToString() {
|
||||
$row = [
|
||||
'page_id' => 7,
|
||||
'page_namespace' => NS_MAIN,
|
||||
'page_title' => 'Test',
|
||||
'page_touched' => '20200909001122',
|
||||
'page_latest' => 1717,
|
||||
'page_is_new' => true,
|
||||
'page_is_redirect' => true,
|
||||
'page_lang' => 'it',
|
||||
];
|
||||
|
||||
yield [
|
||||
new PageStoreRecord( (object)$row, PageIdentity::LOCAL ),
|
||||
'#7 [0:Test]'
|
||||
];
|
||||
yield [
|
||||
new PageStoreRecord( (object)( [ 'page_namespace' => 200 ] + $row ), 'codewiki' ),
|
||||
'#7@codewiki [200:Test]'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideToString
|
||||
*/
|
||||
public function testToString( PageStoreRecord $value, $expected ) {
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$value->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function provideIsSamePageAs() {
|
||||
$row = [
|
||||
'page_id' => 7,
|
||||
'page_namespace' => NS_MAIN,
|
||||
'page_title' => 'Test',
|
||||
'page_touched' => '20200909001122',
|
||||
'page_latest' => 1717,
|
||||
'page_is_new' => true,
|
||||
'page_is_redirect' => true,
|
||||
'page_lang' => 'it',
|
||||
];
|
||||
|
||||
yield [
|
||||
new PageStoreRecord( (object)$row, PageRecord::LOCAL ),
|
||||
new PageStoreRecord( (object)$row, PageRecord::LOCAL ),
|
||||
true
|
||||
];
|
||||
yield [
|
||||
new PageStoreRecord( (object)$row, PageRecord::LOCAL ),
|
||||
new PageStoreRecord( (object)$row, 'acme' ),
|
||||
false
|
||||
];
|
||||
yield [
|
||||
new PageStoreRecord( (object)$row, 'acme' ),
|
||||
new PageStoreRecord( (object)$row, 'acme' ),
|
||||
true
|
||||
];
|
||||
yield [
|
||||
new PageStoreRecord( (object)$row, 'acme' ),
|
||||
new PageIdentityValue( 7, NS_MAIN, 'Test', 'acme' ),
|
||||
true
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideIsSamePageAs
|
||||
*/
|
||||
public function testIsSamePageAs( PageIdentity $a, PageIdentity $b, $expected ) {
|
||||
$this->assertSame( $expected, $a->isSamePageAs( $b ) );
|
||||
$this->assertSame( $expected, $b->isSamePageAs( $a ) );
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue