Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
37.74% |
40 / 106 |
CRAP | |
72.73% |
1051 / 1445 |
WikiPage | |
0.00% |
0 / 1 |
|
37.74% |
40 / 106 |
3924.10 | |
72.73% |
1051 / 1445 |
__construct | |
100.00% |
1 / 1 |
2 | |
100.00% |
6 / 6 |
|||
__clone | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
factory | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
newFromID | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
newFromRow | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
convertSelectType | |
0.00% |
0 / 1 |
4.03 | |
87.50% |
7 / 8 |
|||
getRevisionStore | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getRevisionRenderer | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getSlotRoleRegistry | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getContentHandlerFactory | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getParserCache | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getDBLoadBalancer | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getActionOverrides | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getContentHandler | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getTitle | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
clear | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
clearCacheFields | |
100.00% |
1 / 1 |
1 | |
100.00% |
9 / 9 |
|||
clearPreparedEdit | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getQueryInfo | |
0.00% |
0 / 1 |
2.03 | |
80.00% |
4 / 5 |
|||
pageData | |
100.00% |
1 / 1 |
1 | |
100.00% |
12 / 12 |
|||
pageDataFromTitle | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
pageDataFromId | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
loadPageData | |
0.00% |
0 / 1 |
9.73 | |
79.17% |
19 / 24 |
|||
wasLoadedFrom | |
0.00% |
0 / 1 |
3.04 | |
83.33% |
5 / 6 |
|||
loadFromRow | |
0.00% |
0 / 1 |
5.02 | |
91.30% |
21 / 23 |
|||
getId | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
exists | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
hasViewableContent | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
isRedirect | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
getContentModel | |
0.00% |
0 / 1 |
3.16 | |
73.68% |
14 / 19 |
|||
checkTouched | |
0.00% |
0 / 1 |
3.33 | |
66.67% |
2 / 3 |
|||
getTouched | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
getLinksTimestamp | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
getLatest | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
getOldestRevision | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
loadLastEdit | |
0.00% |
0 / 1 |
7.06 | |
89.47% |
17 / 19 |
|||
setLastEdit | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
getRevision | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
getRevisionRecord | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
getContent | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
getTimestamp | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
setTimestamp | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getUser | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
|||
getCreator | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
getUserText | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
|||
getComment | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
|||
getMinorEdit | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
isCountable | |
100.00% |
1 / 1 |
7 | |
100.00% |
15 / 15 |
|||
getRedirectTarget | |
0.00% |
0 / 1 |
7.06 | |
89.47% |
17 / 19 |
|||
insertRedirect | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 11 |
|||
insertRedirectEntry | |
100.00% |
1 / 1 |
3 | |
100.00% |
22 / 22 |
|||
followRedirect | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getRedirectURL | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 12 |
|||
getContributors | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 22 |
|||
shouldCheckParserCache | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 3 |
|||
getParserOutput | |
100.00% |
1 / 1 |
5 | |
100.00% |
9 / 9 |
|||
doViewUpdates | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
doPurge | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
insertOn | |
100.00% |
1 / 1 |
4 | |
100.00% |
21 / 21 |
|||
updateRevisionOn | |
0.00% |
0 / 1 |
9 | |
95.00% |
38 / 40 |
|||
updateRedirectOn | |
0.00% |
0 / 1 |
5.12 | |
83.33% |
10 / 12 |
|||
updateIfNewerOn | |
0.00% |
0 / 1 |
3.01 | |
90.91% |
20 / 22 |
|||
hasDifferencesOutsideMainSlot | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 10 |
|||
getUndoContent | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
supportsSections | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
replaceSectionContent | |
0.00% |
0 / 1 |
27.67 | |
25.00% |
3 / 12 |
|||
replaceSectionAtRev | |
0.00% |
0 / 1 |
9.88 | |
61.11% |
11 / 18 |
|||
checkFlags | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 5 |
|||
newDerivedDataUpdater | |
100.00% |
1 / 1 |
1 | |
100.00% |
25 / 25 |
|||
getDerivedDataUpdater | |
100.00% |
1 / 1 |
9 | |
100.00% |
14 / 14 |
|||
newPageUpdater | |
100.00% |
1 / 1 |
1 | |
100.00% |
19 / 19 |
|||
doEditContent | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
doUserEditContent | |
0.00% |
0 / 1 |
17 | |
97.50% |
39 / 40 |
|||
makeParserOptions | |
0.00% |
0 / 1 |
2.06 | |
75.00% |
3 / 4 |
|||
prepareContentForEdit | |
0.00% |
0 / 1 |
8.32 | |
70.00% |
14 / 20 |
|||
doEditUpdates | |
0.00% |
0 / 1 |
4.37 | |
71.43% |
10 / 14 |
|||
updateParserCache | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 10 |
|||
doSecondaryDataUpdates | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 11 |
|||
doUpdateRestrictions | |
0.00% |
0 / 1 |
38.87 | |
91.56% |
141 / 154 |
|||
insertNullProtectionRevision | |
0.00% |
0 / 1 |
6.14 | |
84.38% |
27 / 32 |
|||
formatExpiry | |
100.00% |
1 / 1 |
2 | |
100.00% |
10 / 10 |
|||
protectDescription | |
100.00% |
1 / 1 |
3 | |
100.00% |
12 / 12 |
|||
protectDescriptionLog | |
100.00% |
1 / 1 |
2 | |
100.00% |
6 / 6 |
|||
isBatchedDelete | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
doDeleteArticleReal | |
0.00% |
0 / 1 |
3.33 | |
66.67% |
6 / 9 |
|||
doDeleteArticleBatched | |
0.00% |
0 / 1 |
17.88 | |
65.56% |
59 / 90 |
|||
archiveRevisions | |
0.00% |
0 / 1 |
9 | |
96.61% |
57 / 59 |
|||
lockAndGetLatest | |
100.00% |
1 / 1 |
1 | |
100.00% |
8 / 8 |
|||
doDeleteUpdates | |
0.00% |
0 / 1 |
10.27 | |
75.00% |
21 / 28 |
|||
doRollback | |
0.00% |
0 / 1 |
5.39 | |
75.00% |
9 / 12 |
|||
commitRollback | |
0.00% |
0 / 1 |
54.92 | |
74.67% |
112 / 150 |
|||
onArticleCreate | |
0.00% |
0 / 1 |
2.00 | |
92.86% |
13 / 14 |
|||
onArticleDelete | |
0.00% |
0 / 1 |
6.81 | |
58.33% |
14 / 24 |
|||
onArticleEdit | |
0.00% |
0 / 1 |
6.03 | |
90.91% |
20 / 22 |
|||
purgeInterwikiCheckKey | |
0.00% |
0 / 1 |
3.54 | |
27.27% |
3 / 11 |
|||
getCategories | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 9 |
|||
getHiddenCategories | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 14 |
|||
getAutoDeleteReason | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
updateCategoryCounts | |
0.00% |
0 / 1 |
12.37 | |
86.27% |
44 / 51 |
|||
triggerOpportunisticLinksUpdate | |
0.00% |
0 / 1 |
72 | |
0.00% |
0 / 20 |
|||
getDeletionUpdates | |
0.00% |
0 / 1 |
6.56 | |
75.00% |
21 / 28 |
|||
isLocal | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getWikiDisplayName | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getSourceURL | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getMutableCacheKeys | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
__wakeup | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
<?php | |
/** | |
* Base representation for a MediaWiki page. | |
* | |
* 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 | |
*/ | |
use MediaWiki\Config\ServiceOptions; | |
use MediaWiki\Content\ContentHandlerFactory; | |
use MediaWiki\Content\IContentHandlerFactory; | |
use MediaWiki\Debug\DeprecatablePropertyArray; | |
use MediaWiki\Edit\PreparedEdit; | |
use MediaWiki\HookContainer\ProtectedHookAccessorTrait; | |
use MediaWiki\Logger\LoggerFactory; | |
use MediaWiki\MediaWikiServices; | |
use MediaWiki\Page\ParserOutputAccess; | |
use MediaWiki\Revision\RevisionRecord; | |
use MediaWiki\Revision\RevisionRenderer; | |
use MediaWiki\Revision\RevisionStore; | |
use MediaWiki\Revision\SlotRecord; | |
use MediaWiki\Revision\SlotRoleRegistry; | |
use MediaWiki\Storage\DerivedPageDataUpdater; | |
use MediaWiki\Storage\EditResult; | |
use MediaWiki\Storage\EditResultCache; | |
use MediaWiki\Storage\PageUpdater; | |
use MediaWiki\Storage\RevisionSlotsUpdate; | |
use Wikimedia\Assert\Assert; | |
use Wikimedia\IPUtils; | |
use Wikimedia\NonSerializable\NonSerializableTrait; | |
use Wikimedia\Rdbms\FakeResultWrapper; | |
use Wikimedia\Rdbms\IDatabase; | |
use Wikimedia\Rdbms\LoadBalancer; | |
/** | |
* Class representing a MediaWiki article and history. | |
* | |
* 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 { | |
use NonSerializableTrait; | |
use ProtectedHookAccessorTrait; | |
// Constants for $mDataLoadedFrom and related | |
/** | |
* @var Title | |
* @todo make protected | |
* @note for access by subclasses only | |
*/ | |
public $mTitle = null; | |
/** | |
* @var bool | |
* @todo make protected | |
* @note for access by subclasses only | |
*/ | |
public $mDataLoaded = false; | |
/** | |
* @var bool | |
* @todo make protected | |
* @note for access by subclasses only | |
*/ | |
public $mIsRedirect = false; | |
/** | |
* @var int|false False means "not loaded" | |
* @todo make protected | |
* @note for access by subclasses only | |
*/ | |
public $mLatest = false; | |
/** | |
* @var PreparedEdit|false Map of cache fields (text, parser output, ect) for a proposed/new edit | |
* @todo make protected | |
* @note for access by subclasses only | |
*/ | |
public $mPreparedEdit = false; | |
/** | |
* @var int | |
*/ | |
protected $mId = null; | |
/** | |
* @var int One of the READ_* constants | |
*/ | |
protected $mDataLoadedFrom = self::READ_NONE; | |
/** | |
* @var Title | |
*/ | |
protected $mRedirectTarget = null; | |
/** | |
* @var RevisionRecord | |
*/ | |
private $mLastRevision = null; | |
/** | |
* @var string Timestamp of the current revision or empty string if not loaded | |
*/ | |
protected $mTimestamp = ''; | |
/** | |
* @var string | |
*/ | |
protected $mTouched = '19700101000000'; | |
/** | |
* @var string | |
*/ | |
protected $mLinksUpdated = '19700101000000'; | |
/** | |
* @var DerivedPageDataUpdater|null | |
*/ | |
private $derivedDataUpdater = null; | |
/** | |
* @param Title $title | |
*/ | |
public function __construct( Title $title ) { | |
if ( !$title->canExist() ) { | |
// TODO: In order to allow WikiPage to implement ProperPageIdentity, | |
// throw here to prevent construction of a WikiPage that doesn't | |
// represent a proper page. | |
wfDeprecatedMsg( | |
"WikiPage constructed on a Title that cannot exist as a page: $title", | |
'1.36' | |
); | |
} | |
$this->mTitle = $title; | |
} | |
/** | |
* Makes sure that the mTitle object is cloned | |
* to the newly cloned WikiPage. | |
*/ | |
public function __clone() { | |
$this->mTitle = clone $this->mTitle; | |
} | |
/** | |
* Create a WikiPage object of the appropriate class for the given title. | |
* | |
* @param Title $title | |
* | |
* @throws MWException | |
* @return WikiPage|WikiCategoryPage|WikiFilePage | |
* @deprecated since 1.36, use WikiPageFactory::newFromTitle instead | |
*/ | |
public static function factory( Title $title ) { | |
return MediaWikiServices::getInstance()->getWikiPageFactory()->newFromTitle( $title ); | |
} | |
/** | |
* Constructor from a page id | |
* | |
* @param int $id Article ID to load | |
* @param string|int $from One of the following values: | |
* - "fromdb" or WikiPage::READ_NORMAL to select from a replica DB | |
* - "fromdbmaster" or WikiPage::READ_LATEST to select from the master database | |
* | |
* @return WikiPage|null | |
* @deprecated since 1.36, use WikiPageFactory::newFromID instead | |
*/ | |
public static function newFromID( $id, $from = 'fromdb' ) { | |
return MediaWikiServices::getInstance()->getWikiPageFactory()->newFromID( $id, $from ); | |
} | |
/** | |
* Constructor from a database row | |
* | |
* @since 1.20 | |
* @param stdClass $row Database row containing at least fields returned by getQueryInfo(). | |
* @param string|int $from Source of $data: | |
* - "fromdb" or WikiPage::READ_NORMAL: from a replica DB | |
* - "fromdbmaster" or WikiPage::READ_LATEST: from the master DB | |
* - "forupdate" or WikiPage::READ_LOCKING: from the master DB using SELECT FOR UPDATE | |
* @return WikiPage | |
* @deprecated since 1.36, use WikiPageFactory::newFromRow instead | |
*/ | |
public static function newFromRow( $row, $from = 'fromdb' ) { | |
return MediaWikiServices::getInstance()->getWikiPageFactory()->newFromRow( $row, $from ); | |
} | |
/** | |
* Convert 'fromdb', 'fromdbmaster' and 'forupdate' to READ_* constants. | |
* | |
* @param stdClass|string|int $type | |
* @return mixed | |
*/ | |
public static function convertSelectType( $type ) { | |
switch ( $type ) { | |
case 'fromdb': | |
return self::READ_NORMAL; | |
case 'fromdbmaster': | |
return self::READ_LATEST; | |
case 'forupdate': | |
return self::READ_LOCKING; | |
default: | |
// It may already be an integer or whatever else | |
return $type; | |
} | |
} | |
/** | |
* @return RevisionStore | |
*/ | |
private function getRevisionStore() { | |
return MediaWikiServices::getInstance()->getRevisionStore(); | |
} | |
/** | |
* @return RevisionRenderer | |
*/ | |
private function getRevisionRenderer() { | |
return MediaWikiServices::getInstance()->getRevisionRenderer(); | |
} | |
/** | |
* @return SlotRoleRegistry | |
*/ | |
private function getSlotRoleRegistry() { | |
return MediaWikiServices::getInstance()->getSlotRoleRegistry(); | |
} | |
/** | |
* @return ContentHandlerFactory | |
*/ | |
private function getContentHandlerFactory(): IContentHandlerFactory { | |
return MediaWikiServices::getInstance()->getContentHandlerFactory(); | |
} | |
/** | |
* @return ParserCache | |
*/ | |
private function getParserCache() { | |
return MediaWikiServices::getInstance()->getParserCache(); | |
} | |
/** | |
* @return LoadBalancer | |
*/ | |
private function getDBLoadBalancer() { | |
return MediaWikiServices::getInstance()->getDBLoadBalancer(); | |
} | |
/** | |
* @todo Move this UI stuff somewhere else | |
* | |
* @see ContentHandler::getActionOverrides | |
* @return array | |
*/ | |
public function getActionOverrides() { | |
return $this->getContentHandler()->getActionOverrides(); | |
} | |
/** | |
* Returns the ContentHandler instance to be used to deal with the content of this WikiPage. | |
* | |
* Shorthand for ContentHandler::getForModelID( $this->getContentModel() ); | |
* | |
* @return ContentHandler | |
* | |
* @since 1.21 | |
*/ | |
public function getContentHandler() { | |
return $this->getContentHandlerFactory() | |
->getContentHandler( $this->getContentModel() ); | |
} | |
/** | |
* Get the title object of the article | |
* @return Title Title object of this page | |
*/ | |
public function getTitle() { | |
return $this->mTitle; | |
} | |
/** | |
* Clear the object | |
* @return void | |
*/ | |
public function clear() { | |
$this->mDataLoaded = false; | |
$this->mDataLoadedFrom = self::READ_NONE; | |
$this->clearCacheFields(); | |
} | |
/** | |
* Clear the object cache fields | |
* @return void | |
*/ | |
protected function clearCacheFields() { | |
$this->mId = null; | |
$this->mRedirectTarget = null; // Title object if set | |
$this->mLastRevision = null; // Latest revision | |
$this->mTouched = '19700101000000'; | |
$this->mLinksUpdated = '19700101000000'; | |
$this->mTimestamp = ''; | |
$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 | |
// content types, the output should not change during the lifetime of this cache. | |
// Clearing it can cause extra parses on edit for no reason. | |
} | |
/** | |
* Clear the mPreparedEdit cache field, as may be needed by mutable content types | |
* @return void | |
* @since 1.23 | |
*/ | |
public function clearPreparedEdit() { | |
$this->mPreparedEdit = false; | |
} | |
/** | |
* Return the tables, fields, and join conditions to be selected to create | |
* a new page object. | |
* @since 1.31 | |
* @return array With three keys: | |
* - tables: (string[]) to include in the `$table` to `IDatabase->select()` | |
* - fields: (string[]) to include in the `$vars` to `IDatabase->select()` | |
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()` | |
*/ | |
public static function getQueryInfo() { | |
global $wgPageLanguageUseDB; | |
$ret = [ | |
'tables' => [ 'page' ], | |
'fields' => [ | |
'page_id', | |
'page_namespace', | |
'page_title', | |
'page_restrictions', | |
'page_is_redirect', | |
'page_is_new', | |
'page_random', | |
'page_touched', | |
'page_links_updated', | |
'page_latest', | |
'page_len', | |
'page_content_model', | |
], | |
'joins' => [], | |
]; | |
if ( $wgPageLanguageUseDB ) { | |
$ret['fields'][] = 'page_lang'; | |
} | |
return $ret; | |
} | |
/** | |
* Fetch a page record with the given conditions | |
* @param IDatabase $dbr | |
* @param array $conditions | |
* @param array $options | |
* @return stdClass|false Database result resource, or false on failure | |
*/ | |
protected function pageData( $dbr, $conditions, $options = [] ) { | |
$pageQuery = self::getQueryInfo(); | |
$this->getHookRunner()->onArticlePageDataBefore( | |
$this, $pageQuery['fields'], $pageQuery['tables'], $pageQuery['joins'] ); | |
$row = $dbr->selectRow( | |
$pageQuery['tables'], | |
$pageQuery['fields'], | |
$conditions, | |
__METHOD__, | |
$options, | |
$pageQuery['joins'] | |
); | |
$this->getHookRunner()->onArticlePageDataAfter( $this, $row ); | |
return $row; | |
} | |
/** | |
* Fetch a page record matching the Title object's namespace and title | |
* using a sanitized title string | |
* | |
* @param IDatabase $dbr | |
* @param Title $title | |
* @param array $options | |
* @return stdClass|false Database result resource, or false on failure | |
*/ | |
public function pageDataFromTitle( $dbr, $title, $options = [] ) { | |
return $this->pageData( $dbr, [ | |
'page_namespace' => $title->getNamespace(), | |
'page_title' => $title->getDBkey() ], $options ); | |
} | |
/** | |
* Fetch a page record matching the requested ID | |
* | |
* @param IDatabase $dbr | |
* @param int $id | |
* @param array $options | |
* @return stdClass|false Database result resource, or false on failure | |
*/ | |
public function pageDataFromId( $dbr, $id, $options = [] ) { | |
return $this->pageData( $dbr, [ 'page_id' => $id ], $options ); | |
} | |
/** | |
* Load the object from a given source by title | |
* | |
* @param stdClass|string|int $from One of the following: | |
* - A DB query result object. | |
* - "fromdb" or WikiPage::READ_NORMAL to get from a replica DB. | |
* - "fromdbmaster" or WikiPage::READ_LATEST to get from the master DB. | |
* - "forupdate" or WikiPage::READ_LOCKING to get from the master DB | |
* using SELECT FOR UPDATE. | |
* | |
* @return void | |
*/ | |
public function loadPageData( $from = 'fromdb' ) { | |
if ( !$this->mTitle->canExist() ) { | |
// NOTE: If and when WikiPage implements PageIdentity but not yet ProperPageIdentity, | |
// throw here to prevent usage of a WikiPage that doesn't | |
// represent a proper page. | |
// NOTE: The constructor will already have triggered a warning, but seeing how | |
// bad instances of WikiPage are used will be helpful. | |
wfDeprecatedMsg( | |
"Accessing WikiPage that cannot exist as a page: {$this->mTitle}. ", | |
'1.36' | |
); | |
} | |
$from = self::convertSelectType( $from ); | |
if ( is_int( $from ) && $from <= $this->mDataLoadedFrom ) { | |
// We already have the data from the correct location, no need to load it twice. | |
return; | |
} | |
if ( is_int( $from ) ) { | |
list( $index, $opts ) = DBAccessObjectUtils::getDBOptions( $from ); | |
$loadBalancer = $this->getDBLoadBalancer(); | |
$db = $loadBalancer->getConnection( $index ); | |
$data = $this->pageDataFromTitle( $db, $this->mTitle, $opts ); | |
if ( !$data | |
&& $index == DB_REPLICA | |
&& $loadBalancer->getServerCount() > 1 | |
&& $loadBalancer-> |