Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Article often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Article, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 34 | class Article implements Page { |
||
| 35 | /** @var IContextSource The context this Article is executed in */ |
||
| 36 | protected $mContext; |
||
| 37 | |||
| 38 | /** @var WikiPage The WikiPage object of this instance */ |
||
| 39 | protected $mPage; |
||
| 40 | |||
| 41 | /** @var ParserOptions ParserOptions object for $wgUser articles */ |
||
| 42 | public $mParserOptions; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * @var string Text of the revision we are working on |
||
| 46 | * @todo BC cruft |
||
| 47 | */ |
||
| 48 | public $mContent; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var Content Content of the revision we are working on |
||
| 52 | * @since 1.21 |
||
| 53 | */ |
||
| 54 | public $mContentObject; |
||
| 55 | |||
| 56 | /** @var bool Is the content ($mContent) already loaded? */ |
||
| 57 | public $mContentLoaded = false; |
||
| 58 | |||
| 59 | /** @var int|null The oldid of the article that is to be shown, 0 for the current revision */ |
||
| 60 | public $mOldId; |
||
| 61 | |||
| 62 | /** @var Title Title from which we were redirected here */ |
||
| 63 | public $mRedirectedFrom = null; |
||
| 64 | |||
| 65 | /** @var string|bool URL to redirect to or false if none */ |
||
| 66 | public $mRedirectUrl = false; |
||
| 67 | |||
| 68 | /** @var int Revision ID of revision we are working on */ |
||
| 69 | public $mRevIdFetched = 0; |
||
| 70 | |||
| 71 | /** @var Revision Revision we are working on */ |
||
| 72 | public $mRevision = null; |
||
| 73 | |||
| 74 | /** @var ParserOutput */ |
||
| 75 | public $mParserOutput; |
||
| 76 | |||
| 77 | /** |
||
| 78 | * Constructor and clear the article |
||
| 79 | * @param Title $title Reference to a Title object. |
||
| 80 | * @param int $oldId Revision ID, null to fetch from request, zero for current |
||
| 81 | */ |
||
| 82 | public function __construct( Title $title, $oldId = null ) { |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @param Title $title |
||
| 89 | * @return WikiPage |
||
| 90 | */ |
||
| 91 | protected function newPage( Title $title ) { |
||
| 94 | |||
| 95 | /** |
||
| 96 | * Constructor from a page id |
||
| 97 | * @param int $id Article ID to load |
||
| 98 | * @return Article|null |
||
| 99 | */ |
||
| 100 | public static function newFromID( $id ) { |
||
| 101 | $t = Title::newFromID( $id ); |
||
| 102 | return $t == null ? null : new static( $t ); |
||
| 103 | } |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Create an Article object of the appropriate class for the given page. |
||
| 107 | * |
||
| 108 | * @param Title $title |
||
| 109 | * @param IContextSource $context |
||
| 110 | * @return Article |
||
| 111 | */ |
||
| 112 | public static function newFromTitle( $title, IContextSource $context ) { |
||
| 113 | if ( NS_MEDIA == $title->getNamespace() ) { |
||
| 114 | // FIXME: where should this go? |
||
| 115 | $title = Title::makeTitle( NS_FILE, $title->getDBkey() ); |
||
| 116 | } |
||
| 117 | |||
| 118 | $page = null; |
||
| 119 | Hooks::run( 'ArticleFromTitle', [ &$title, &$page, $context ] ); |
||
| 120 | if ( !$page ) { |
||
| 121 | switch ( $title->getNamespace() ) { |
||
| 122 | case NS_FILE: |
||
| 123 | $page = new ImagePage( $title ); |
||
| 124 | break; |
||
| 125 | case NS_CATEGORY: |
||
| 126 | $page = new CategoryPage( $title ); |
||
| 127 | break; |
||
| 128 | default: |
||
| 129 | $page = new Article( $title ); |
||
| 130 | } |
||
| 131 | } |
||
| 132 | $page->setContext( $context ); |
||
| 133 | |||
| 134 | return $page; |
||
| 135 | } |
||
| 136 | |||
| 137 | /** |
||
| 138 | * Create an Article object of the appropriate class for the given page. |
||
| 139 | * |
||
| 140 | * @param WikiPage $page |
||
| 141 | * @param IContextSource $context |
||
| 142 | * @return Article |
||
| 143 | */ |
||
| 144 | public static function newFromWikiPage( WikiPage $page, IContextSource $context ) { |
||
| 145 | $article = self::newFromTitle( $page->getTitle(), $context ); |
||
| 146 | $article->mPage = $page; // override to keep process cached vars |
||
| 147 | return $article; |
||
| 148 | } |
||
| 149 | |||
| 150 | /** |
||
| 151 | * Get the page this view was redirected from |
||
| 152 | * @return Title|null |
||
| 153 | * @since 1.28 |
||
| 154 | */ |
||
| 155 | public function getRedirectedFrom() { |
||
| 156 | return $this->mRedirectedFrom; |
||
| 157 | } |
||
| 158 | |||
| 159 | /** |
||
| 160 | * Tell the page view functions that this view was redirected |
||
| 161 | * from another page on the wiki. |
||
| 162 | * @param Title $from |
||
| 163 | */ |
||
| 164 | public function setRedirectedFrom( Title $from ) { |
||
| 165 | $this->mRedirectedFrom = $from; |
||
| 166 | } |
||
| 167 | |||
| 168 | /** |
||
| 169 | * Get the title object of the article |
||
| 170 | * |
||
| 171 | * @return Title Title object of this page |
||
| 172 | */ |
||
| 173 | public function getTitle() { |
||
| 174 | return $this->mPage->getTitle(); |
||
| 175 | } |
||
| 176 | |||
| 177 | /** |
||
| 178 | * Get the WikiPage object of this instance |
||
| 179 | * |
||
| 180 | * @since 1.19 |
||
| 181 | * @return WikiPage |
||
| 182 | */ |
||
| 183 | public function getPage() { |
||
| 184 | return $this->mPage; |
||
| 185 | } |
||
| 186 | |||
| 187 | /** |
||
| 188 | * Clear the object |
||
| 189 | */ |
||
| 190 | public function clear() { |
||
| 191 | $this->mContentLoaded = false; |
||
| 192 | |||
| 193 | $this->mRedirectedFrom = null; # Title object if set |
||
| 194 | $this->mRevIdFetched = 0; |
||
| 195 | $this->mRedirectUrl = false; |
||
| 196 | |||
| 197 | $this->mPage->clear(); |
||
| 198 | } |
||
| 199 | |||
| 200 | /** |
||
| 201 | * Note that getContent does not follow redirects anymore. |
||
| 202 | * If you need to fetch redirectable content easily, try |
||
| 203 | * the shortcut in WikiPage::getRedirectTarget() |
||
| 204 | * |
||
| 205 | * This function has side effects! Do not use this function if you |
||
| 206 | * only want the real revision text if any. |
||
| 207 | * |
||
| 208 | * @deprecated since 1.21; use WikiPage::getContent() instead |
||
| 209 | * |
||
| 210 | * @return string Return the text of this revision |
||
| 211 | */ |
||
| 212 | public function getContent() { |
||
| 213 | ContentHandler::deprecated( __METHOD__, '1.21' ); |
||
| 214 | $content = $this->getContentObject(); |
||
| 215 | return ContentHandler::getContentText( $content ); |
||
| 216 | } |
||
| 217 | |||
| 218 | /** |
||
| 219 | * Returns a Content object representing the pages effective display content, |
||
| 220 | * not necessarily the revision's content! |
||
| 221 | * |
||
| 222 | * Note that getContent does not follow redirects anymore. |
||
| 223 | * If you need to fetch redirectable content easily, try |
||
| 224 | * the shortcut in WikiPage::getRedirectTarget() |
||
| 225 | * |
||
| 226 | * This function has side effects! Do not use this function if you |
||
| 227 | * only want the real revision text if any. |
||
| 228 | * |
||
| 229 | * @return Content Return the content of this revision |
||
| 230 | * |
||
| 231 | * @since 1.21 |
||
| 232 | */ |
||
| 233 | protected function getContentObject() { |
||
| 234 | |||
| 235 | if ( $this->mPage->getId() === 0 ) { |
||
| 236 | # If this is a MediaWiki:x message, then load the messages |
||
| 237 | # and return the message value for x. |
||
| 238 | if ( $this->getTitle()->getNamespace() == NS_MEDIAWIKI ) { |
||
| 239 | $text = $this->getTitle()->getDefaultMessageText(); |
||
| 240 | if ( $text === false ) { |
||
| 241 | $text = ''; |
||
| 242 | } |
||
| 243 | |||
| 244 | $content = ContentHandler::makeContent( $text, $this->getTitle() ); |
||
| 245 | } else { |
||
| 246 | $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon'; |
||
| 247 | $content = new MessageContent( $message, null, 'parsemag' ); |
||
| 248 | } |
||
| 249 | } else { |
||
| 250 | $this->fetchContentObject(); |
||
| 251 | $content = $this->mContentObject; |
||
| 252 | } |
||
| 253 | |||
| 254 | return $content; |
||
| 255 | } |
||
| 256 | |||
| 257 | /** |
||
| 258 | * @return int The oldid of the article that is to be shown, 0 for the current revision |
||
| 259 | */ |
||
| 260 | public function getOldID() { |
||
| 261 | if ( is_null( $this->mOldId ) ) { |
||
| 262 | $this->mOldId = $this->getOldIDFromRequest(); |
||
| 263 | } |
||
| 264 | |||
| 265 | return $this->mOldId; |
||
| 266 | } |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Sets $this->mRedirectUrl to a correct URL if the query parameters are incorrect |
||
| 270 | * |
||
| 271 | * @return int The old id for the request |
||
| 272 | */ |
||
| 273 | public function getOldIDFromRequest() { |
||
| 274 | $this->mRedirectUrl = false; |
||
| 275 | |||
| 276 | $request = $this->getContext()->getRequest(); |
||
| 277 | $oldid = $request->getIntOrNull( 'oldid' ); |
||
| 278 | |||
| 279 | if ( $oldid === null ) { |
||
| 280 | return 0; |
||
| 281 | } |
||
| 282 | |||
| 283 | if ( $oldid !== 0 ) { |
||
| 284 | # Load the given revision and check whether the page is another one. |
||
| 285 | # In that case, update this instance to reflect the change. |
||
| 286 | if ( $oldid === $this->mPage->getLatest() ) { |
||
| 287 | $this->mRevision = $this->mPage->getRevision(); |
||
| 288 | } else { |
||
| 289 | $this->mRevision = Revision::newFromId( $oldid ); |
||
| 290 | if ( $this->mRevision !== null ) { |
||
| 291 | // Revision title doesn't match the page title given? |
||
| 292 | if ( $this->mPage->getId() != $this->mRevision->getPage() ) { |
||
| 293 | $function = [ get_class( $this->mPage ), 'newFromID' ]; |
||
| 294 | $this->mPage = call_user_func( $function, $this->mRevision->getPage() ); |
||
| 295 | } |
||
| 296 | } |
||
| 297 | } |
||
| 298 | } |
||
| 299 | |||
| 300 | if ( $request->getVal( 'direction' ) == 'next' ) { |
||
| 301 | $nextid = $this->getTitle()->getNextRevisionID( $oldid ); |
||
| 302 | if ( $nextid ) { |
||
|
|
|||
| 303 | $oldid = $nextid; |
||
| 304 | $this->mRevision = null; |
||
| 305 | } else { |
||
| 306 | $this->mRedirectUrl = $this->getTitle()->getFullURL( 'redirect=no' ); |
||
| 307 | } |
||
| 308 | } elseif ( $request->getVal( 'direction' ) == 'prev' ) { |
||
| 309 | $previd = $this->getTitle()->getPreviousRevisionID( $oldid ); |
||
| 310 | if ( $previd ) { |
||
| 311 | $oldid = $previd; |
||
| 312 | $this->mRevision = null; |
||
| 313 | } |
||
| 314 | } |
||
| 315 | |||
| 316 | return $oldid; |
||
| 317 | } |
||
| 318 | |||
| 319 | /** |
||
| 320 | * Get text of an article from database |
||
| 321 | * Does *NOT* follow redirects. |
||
| 322 | * |
||
| 323 | * @protected |
||
| 324 | * @note This is really internal functionality that should really NOT be |
||
| 325 | * used by other functions. For accessing article content, use the WikiPage |
||
| 326 | * class, especially WikiBase::getContent(). However, a lot of legacy code |
||
| 327 | * uses this method to retrieve page text from the database, so the function |
||
| 328 | * has to remain public for now. |
||
| 329 | * |
||
| 330 | * @return string|bool String containing article contents, or false if null |
||
| 331 | * @deprecated since 1.21, use WikiPage::getContent() instead |
||
| 332 | */ |
||
| 333 | function fetchContent() { |
||
| 334 | // BC cruft! |
||
| 335 | |||
| 336 | wfDeprecated( __METHOD__, '1.21' ); |
||
| 337 | |||
| 338 | if ( $this->mContentLoaded && $this->mContent ) { |
||
| 339 | return $this->mContent; |
||
| 340 | } |
||
| 341 | |||
| 342 | $content = $this->fetchContentObject(); |
||
| 343 | |||
| 344 | if ( !$content ) { |
||
| 345 | return false; |
||
| 346 | } |
||
| 347 | |||
| 348 | // @todo Get rid of mContent everywhere! |
||
| 349 | $this->mContent = ContentHandler::getContentText( $content ); |
||
| 350 | ContentHandler::runLegacyHooks( 'ArticleAfterFetchContent', [ &$this, &$this->mContent ] ); |
||
| 351 | |||
| 352 | return $this->mContent; |
||
| 353 | } |
||
| 354 | |||
| 355 | /** |
||
| 356 | * Get text content object |
||
| 357 | * Does *NOT* follow redirects. |
||
| 358 | * @todo When is this null? |
||
| 359 | * |
||
| 360 | * @note Code that wants to retrieve page content from the database should |
||
| 361 | * use WikiPage::getContent(). |
||
| 362 | * |
||
| 363 | * @return Content|null|bool |
||
| 364 | * |
||
| 365 | * @since 1.21 |
||
| 366 | */ |
||
| 367 | protected function fetchContentObject() { |
||
| 368 | if ( $this->mContentLoaded ) { |
||
| 369 | return $this->mContentObject; |
||
| 370 | } |
||
| 371 | |||
| 372 | $this->mContentLoaded = true; |
||
| 373 | $this->mContent = null; |
||
| 374 | |||
| 375 | $oldid = $this->getOldID(); |
||
| 376 | |||
| 377 | # Pre-fill content with error message so that if something |
||
| 378 | # fails we'll have something telling us what we intended. |
||
| 379 | // XXX: this isn't page content but a UI message. horrible. |
||
| 380 | $this->mContentObject = new MessageContent( 'missing-revision', [ $oldid ] ); |
||
| 381 | |||
| 382 | if ( $oldid ) { |
||
| 383 | # $this->mRevision might already be fetched by getOldIDFromRequest() |
||
| 384 | if ( !$this->mRevision ) { |
||
| 385 | $this->mRevision = Revision::newFromId( $oldid ); |
||
| 386 | if ( !$this->mRevision ) { |
||
| 387 | wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" ); |
||
| 388 | return false; |
||
| 389 | } |
||
| 390 | } |
||
| 391 | } else { |
||
| 392 | $oldid = $this->mPage->getLatest(); |
||
| 393 | if ( !$oldid ) { |
||
| 394 | wfDebug( __METHOD__ . " failed to find page data for title " . |
||
| 395 | $this->getTitle()->getPrefixedText() . "\n" ); |
||
| 396 | return false; |
||
| 397 | } |
||
| 398 | |||
| 399 | # Update error message with correct oldid |
||
| 400 | $this->mContentObject = new MessageContent( 'missing-revision', [ $oldid ] ); |
||
| 401 | |||
| 402 | $this->mRevision = $this->mPage->getRevision(); |
||
| 403 | |||
| 404 | if ( !$this->mRevision ) { |
||
| 405 | wfDebug( __METHOD__ . " failed to retrieve current page, rev_id $oldid\n" ); |
||
| 406 | return false; |
||
| 407 | } |
||
| 408 | } |
||
| 409 | |||
| 410 | // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks. |
||
| 411 | // We should instead work with the Revision object when we need it... |
||
| 412 | // Loads if user is allowed |
||
| 413 | $content = $this->mRevision->getContent( |
||
| 414 | Revision::FOR_THIS_USER, |
||
| 415 | $this->getContext()->getUser() |
||
| 416 | ); |
||
| 417 | |||
| 418 | if ( !$content ) { |
||
| 419 | wfDebug( __METHOD__ . " failed to retrieve content of revision " . |
||
| 420 | $this->mRevision->getId() . "\n" ); |
||
| 421 | return false; |
||
| 422 | } |
||
| 423 | |||
| 424 | $this->mContentObject = $content; |
||
| 425 | $this->mRevIdFetched = $this->mRevision->getId(); |
||
| 426 | |||
| 427 | Hooks::run( 'ArticleAfterFetchContentObject', [ &$this, &$this->mContentObject ] ); |
||
| 428 | |||
| 429 | return $this->mContentObject; |
||
| 430 | } |
||
| 431 | |||
| 432 | /** |
||
| 433 | * Returns true if the currently-referenced revision is the current edit |
||
| 434 | * to this page (and it exists). |
||
| 435 | * @return bool |
||
| 436 | */ |
||
| 437 | public function isCurrent() { |
||
| 438 | # If no oldid, this is the current version. |
||
| 439 | if ( $this->getOldID() == 0 ) { |
||
| 440 | return true; |
||
| 441 | } |
||
| 442 | |||
| 443 | return $this->mPage->exists() && $this->mRevision && $this->mRevision->isCurrent(); |
||
| 444 | } |
||
| 445 | |||
| 446 | /** |
||
| 447 | * Get the fetched Revision object depending on request parameters or null |
||
| 448 | * on failure. |
||
| 449 | * |
||
| 450 | * @since 1.19 |
||
| 451 | * @return Revision|null |
||
| 452 | */ |
||
| 453 | public function getRevisionFetched() { |
||
| 454 | $this->fetchContentObject(); |
||
| 455 | |||
| 456 | return $this->mRevision; |
||
| 457 | } |
||
| 458 | |||
| 459 | /** |
||
| 460 | * Use this to fetch the rev ID used on page views |
||
| 461 | * |
||
| 462 | * @return int Revision ID of last article revision |
||
| 463 | */ |
||
| 464 | public function getRevIdFetched() { |
||
| 465 | if ( $this->mRevIdFetched ) { |
||
| 466 | return $this->mRevIdFetched; |
||
| 467 | } else { |
||
| 468 | return $this->mPage->getLatest(); |
||
| 469 | } |
||
| 470 | } |
||
| 471 | |||
| 472 | /** |
||
| 473 | * This is the default action of the index.php entry point: just view the |
||
| 474 | * page of the given title. |
||
| 475 | */ |
||
| 476 | public function view() { |
||
| 477 | global $wgUseFileCache, $wgDebugToolbar; |
||
| 478 | |||
| 479 | # Get variables from query string |
||
| 480 | # As side effect this will load the revision and update the title |
||
| 481 | # in a revision ID is passed in the request, so this should remain |
||
| 482 | # the first call of this method even if $oldid is used way below. |
||
| 483 | $oldid = $this->getOldID(); |
||
| 484 | |||
| 485 | $user = $this->getContext()->getUser(); |
||
| 486 | # Another whitelist check in case getOldID() is altering the title |
||
| 487 | $permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $user ); |
||
| 488 | if ( count( $permErrors ) ) { |
||
| 489 | wfDebug( __METHOD__ . ": denied on secondary read check\n" ); |
||
| 490 | throw new PermissionsError( 'read', $permErrors ); |
||
| 491 | } |
||
| 492 | |||
| 493 | $outputPage = $this->getContext()->getOutput(); |
||
| 494 | # getOldID() may as well want us to redirect somewhere else |
||
| 495 | if ( $this->mRedirectUrl ) { |
||
| 496 | $outputPage->redirect( $this->mRedirectUrl ); |
||
| 497 | wfDebug( __METHOD__ . ": redirecting due to oldid\n" ); |
||
| 498 | |||
| 499 | return; |
||
| 500 | } |
||
| 501 | |||
| 502 | # If we got diff in the query, we want to see a diff page instead of the article. |
||
| 503 | if ( $this->getContext()->getRequest()->getCheck( 'diff' ) ) { |
||
| 504 | wfDebug( __METHOD__ . ": showing diff page\n" ); |
||
| 505 | $this->showDiffPage(); |
||
| 506 | |||
| 507 | return; |
||
| 508 | } |
||
| 509 | |||
| 510 | # Set page title (may be overridden by DISPLAYTITLE) |
||
| 511 | $outputPage->setPageTitle( $this->getTitle()->getPrefixedText() ); |
||
| 512 | |||
| 513 | $outputPage->setArticleFlag( true ); |
||
| 514 | # Allow frames by default |
||
| 515 | $outputPage->allowClickjacking(); |
||
| 516 | |||
| 517 | $parserCache = ParserCache::singleton(); |
||
| 518 | |||
| 519 | $parserOptions = $this->getParserOptions(); |
||
| 520 | # Render printable version, use printable version cache |
||
| 521 | if ( $outputPage->isPrintable() ) { |
||
| 522 | $parserOptions->setIsPrintable( true ); |
||
| 523 | $parserOptions->setEditSection( false ); |
||
| 524 | } elseif ( !$this->isCurrent() || !$this->getTitle()->quickUserCan( 'edit', $user ) ) { |
||
| 525 | $parserOptions->setEditSection( false ); |
||
| 526 | } |
||
| 527 | |||
| 528 | # Try client and file cache |
||
| 529 | if ( !$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched() ) { |
||
| 530 | # Try to stream the output from file cache |
||
| 531 | if ( $wgUseFileCache && $this->tryFileCache() ) { |
||
| 532 | wfDebug( __METHOD__ . ": done file cache\n" ); |
||
| 533 | # tell wgOut that output is taken care of |
||
| 534 | $outputPage->disable(); |
||
| 535 | $this->mPage->doViewUpdates( $user, $oldid ); |
||
| 536 | |||
| 537 | return; |
||
| 538 | } |
||
| 539 | } |
||
| 540 | |||
| 541 | # Should the parser cache be used? |
||
| 542 | $useParserCache = $this->mPage->shouldCheckParserCache( $parserOptions, $oldid ); |
||
| 543 | wfDebug( 'Article::view using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" ); |
||
| 544 | if ( $user->getStubThreshold() ) { |
||
| 545 | $this->getContext()->getStats()->increment( 'pcache_miss_stub' ); |
||
| 546 | } |
||
| 547 | |||
| 548 | $this->showRedirectedFromHeader(); |
||
| 549 | $this->showNamespaceHeader(); |
||
| 550 | |||
| 551 | # Iterate through the possible ways of constructing the output text. |
||
| 552 | # Keep going until $outputDone is set, or we run out of things to do. |
||
| 553 | $pass = 0; |
||
| 554 | $outputDone = false; |
||
| 555 | $this->mParserOutput = false; |
||
| 556 | |||
| 557 | while ( !$outputDone && ++$pass ) { |
||
| 558 | switch ( $pass ) { |
||
| 559 | case 1: |
||
| 560 | Hooks::run( 'ArticleViewHeader', [ &$this, &$outputDone, &$useParserCache ] ); |
||
| 561 | break; |
||
| 562 | case 2: |
||
| 563 | # Early abort if the page doesn't exist |
||
| 564 | if ( !$this->mPage->exists() ) { |
||
| 565 | wfDebug( __METHOD__ . ": showing missing article\n" ); |
||
| 566 | $this->showMissingArticle(); |
||
| 567 | $this->mPage->doViewUpdates( $user ); |
||
| 568 | return; |
||
| 569 | } |
||
| 570 | |||
| 571 | # Try the parser cache |
||
| 572 | if ( $useParserCache ) { |
||
| 573 | $this->mParserOutput = $parserCache->get( $this->mPage, $parserOptions ); |
||
| 574 | |||
| 575 | if ( $this->mParserOutput !== false ) { |
||
| 576 | if ( $oldid ) { |
||
| 577 | wfDebug( __METHOD__ . ": showing parser cache contents for current rev permalink\n" ); |
||
| 578 | $this->setOldSubtitle( $oldid ); |
||
| 579 | } else { |
||
| 580 | wfDebug( __METHOD__ . ": showing parser cache contents\n" ); |
||
| 581 | } |
||
| 582 | $outputPage->addParserOutput( $this->mParserOutput ); |
||
| 583 | # Ensure that UI elements requiring revision ID have |
||
| 584 | # the correct version information. |
||
| 585 | $outputPage->setRevisionId( $this->mPage->getLatest() ); |
||
| 586 | # Preload timestamp to avoid a DB hit |
||
| 587 | $cachedTimestamp = $this->mParserOutput->getTimestamp(); |
||
| 588 | if ( $cachedTimestamp !== null ) { |
||
| 589 | $outputPage->setRevisionTimestamp( $cachedTimestamp ); |
||
| 590 | $this->mPage->setTimestamp( $cachedTimestamp ); |
||
| 591 | } |
||
| 592 | $outputDone = true; |
||
| 593 | } |
||
| 594 | } |
||
| 595 | break; |
||
| 596 | case 3: |
||
| 597 | # This will set $this->mRevision if needed |
||
| 598 | $this->fetchContentObject(); |
||
| 599 | |||
| 600 | # Are we looking at an old revision |
||
| 601 | if ( $oldid && $this->mRevision ) { |
||
| 602 | $this->setOldSubtitle( $oldid ); |
||
| 603 | |||
| 604 | if ( !$this->showDeletedRevisionHeader() ) { |
||
| 605 | wfDebug( __METHOD__ . ": cannot view deleted revision\n" ); |
||
| 606 | return; |
||
| 607 | } |
||
| 608 | } |
||
| 609 | |||
| 610 | # Ensure that UI elements requiring revision ID have |
||
| 611 | # the correct version information. |
||
| 612 | $outputPage->setRevisionId( $this->getRevIdFetched() ); |
||
| 613 | # Preload timestamp to avoid a DB hit |
||
| 614 | $outputPage->setRevisionTimestamp( $this->mPage->getTimestamp() ); |
||
| 615 | |||
| 616 | # Pages containing custom CSS or JavaScript get special treatment |
||
| 617 | if ( $this->getTitle()->isCssOrJsPage() || $this->getTitle()->isCssJsSubpage() ) { |
||
| 618 | wfDebug( __METHOD__ . ": showing CSS/JS source\n" ); |
||
| 619 | $this->showCssOrJsPage(); |
||
| 620 | $outputDone = true; |
||
| 621 | } elseif ( !Hooks::run( 'ArticleContentViewCustom', |
||
| 622 | [ $this->fetchContentObject(), $this->getTitle(), $outputPage ] ) ) { |
||
| 623 | |||
| 624 | # Allow extensions do their own custom view for certain pages |
||
| 625 | $outputDone = true; |
||
| 626 | } elseif ( !ContentHandler::runLegacyHooks( |
||
| 627 | 'ArticleViewCustom', |
||
| 628 | [ $this->fetchContentObject(), $this->getTitle(), $outputPage ], |
||
| 629 | '1.21' |
||
| 630 | ) ) { |
||
| 631 | # Allow extensions do their own custom view for certain pages |
||
| 632 | $outputDone = true; |
||
| 633 | } |
||
| 634 | break; |
||
| 635 | case 4: |
||
| 636 | # Run the parse, protected by a pool counter |
||
| 637 | wfDebug( __METHOD__ . ": doing uncached parse\n" ); |
||
| 638 | |||
| 639 | $content = $this->getContentObject(); |
||
| 640 | $poolArticleView = new PoolWorkArticleView( $this->getPage(), $parserOptions, |
||
| 641 | $this->getRevIdFetched(), $useParserCache, $content ); |
||
| 642 | |||
| 643 | if ( !$poolArticleView->execute() ) { |
||
| 644 | $error = $poolArticleView->getError(); |
||
| 645 | if ( $error ) { |
||
| 646 | $outputPage->clearHTML(); // for release() errors |
||
| 647 | $outputPage->enableClientCache( false ); |
||
| 648 | $outputPage->setRobotPolicy( 'noindex,nofollow' ); |
||
| 649 | |||
| 650 | $errortext = $error->getWikiText( false, 'view-pool-error' ); |
||
| 651 | $outputPage->addWikiText( '<div class="errorbox">' . $errortext . '</div>' ); |
||
| 652 | } |
||
| 653 | # Connection or timeout error |
||
| 654 | return; |
||
| 655 | } |
||
| 656 | |||
| 657 | $this->mParserOutput = $poolArticleView->getParserOutput(); |
||
| 658 | $outputPage->addParserOutput( $this->mParserOutput ); |
||
| 659 | if ( $content->getRedirectTarget() ) { |
||
| 660 | $outputPage->addSubtitle( "<span id=\"redirectsub\">" . |
||
| 661 | $this->getContext()->msg( 'redirectpagesub' )->parse() . "</span>" ); |
||
| 662 | } |
||
| 663 | |||
| 664 | # Don't cache a dirty ParserOutput object |
||
| 665 | if ( $poolArticleView->getIsDirty() ) { |
||
| 666 | $outputPage->setCdnMaxage( 0 ); |
||
| 667 | $outputPage->addHTML( "<!-- parser cache is expired, " . |
||
| 668 | "sending anyway due to pool overload-->\n" ); |
||
| 669 | } |
||
| 670 | |||
| 671 | $outputDone = true; |
||
| 672 | break; |
||
| 673 | # Should be unreachable, but just in case... |
||
| 674 | default: |
||
| 675 | break 2; |
||
| 676 | } |
||
| 677 | } |
||
| 678 | |||
| 679 | # Get the ParserOutput actually *displayed* here. |
||
| 680 | # Note that $this->mParserOutput is the *current*/oldid version output. |
||
| 681 | $pOutput = ( $outputDone instanceof ParserOutput ) |
||
| 682 | ? $outputDone // object fetched by hook |
||
| 683 | : $this->mParserOutput; |
||
| 684 | |||
| 685 | # Adjust title for main page & pages with displaytitle |
||
| 686 | if ( $pOutput ) { |
||
| 687 | $this->adjustDisplayTitle( $pOutput ); |
||
| 688 | } |
||
| 689 | |||
| 690 | # For the main page, overwrite the <title> element with the con- |
||
| 691 | # tents of 'pagetitle-view-mainpage' instead of the default (if |
||
| 692 | # that's not empty). |
||
| 693 | # This message always exists because it is in the i18n files |
||
| 694 | if ( $this->getTitle()->isMainPage() ) { |
||
| 695 | $msg = wfMessage( 'pagetitle-view-mainpage' )->inContentLanguage(); |
||
| 696 | if ( !$msg->isDisabled() ) { |
||
| 697 | $outputPage->setHTMLTitle( $msg->title( $this->getTitle() )->text() ); |
||
| 698 | } |
||
| 699 | } |
||
| 700 | |||
| 701 | # Check for any __NOINDEX__ tags on the page using $pOutput |
||
| 702 | $policy = $this->getRobotPolicy( 'view', $pOutput ); |
||
| 703 | $outputPage->setIndexPolicy( $policy['index'] ); |
||
| 704 | $outputPage->setFollowPolicy( $policy['follow'] ); |
||
| 705 | |||
| 706 | $this->showViewFooter(); |
||
| 707 | $this->mPage->doViewUpdates( $user, $oldid ); |
||
| 708 | |||
| 709 | $outputPage->addModules( 'mediawiki.action.view.postEdit' ); |
||
| 710 | |||
| 711 | } |
||
| 712 | |||
| 713 | /** |
||
| 714 | * Adjust title for pages with displaytitle, -{T|}- or language conversion |
||
| 715 | * @param ParserOutput $pOutput |
||
| 716 | */ |
||
| 717 | public function adjustDisplayTitle( ParserOutput $pOutput ) { |
||
| 724 | |||
| 725 | /** |
||
| 726 | * Show a diff page according to current request variables. For use within |
||
| 727 | * Article::view() only, other callers should use the DifferenceEngine class. |
||
| 728 | * |
||
| 729 | */ |
||
| 730 | protected function showDiffPage() { |
||
| 772 | |||
| 773 | /** |
||
| 774 | * Show a page view for a page formatted as CSS or JavaScript. To be called by |
||
| 775 | * Article::view() only. |
||
| 776 | * |
||
| 777 | * This exists mostly to serve the deprecated ShowRawCssJs hook (used to customize these views). |
||
| 778 | * It has been replaced by the ContentGetParserOutput hook, which lets you do the same but with |
||
| 779 | * more flexibility. |
||
| 780 | * |
||
| 781 | * @param bool $showCacheHint Whether to show a message telling the user |
||
| 782 | * to clear the browser cache (default: true). |
||
| 783 | */ |
||
| 784 | protected function showCssOrJsPage( $showCacheHint = true ) { |
||
| 812 | |||
| 813 | /** |
||
| 814 | * Get the robot policy to be used for the current view |
||
| 815 | * @param string $action The action= GET parameter |
||
| 816 | * @param ParserOutput|null $pOutput |
||
| 817 | * @return array The policy that should be set |
||
| 818 | * @todo actions other than 'view' |
||
| 819 | */ |
||
| 820 | public function getRobotPolicy( $action, $pOutput = null ) { |
||
| 892 | |||
| 893 | /** |
||
| 894 | * Converts a String robot policy into an associative array, to allow |
||
| 895 | * merging of several policies using array_merge(). |
||
| 896 | * @param array|string $policy Returns empty array on null/false/'', transparent |
||
| 897 | * to already-converted arrays, converts string. |
||
| 898 | * @return array 'index' => \<indexpolicy\>, 'follow' => \<followpolicy\> |
||
| 899 | */ |
||
| 900 | public static function formatRobotPolicy( $policy ) { |
||
| 921 | |||
| 922 | /** |
||
| 923 | * If this request is a redirect view, send "redirected from" subtitle to |
||
| 924 | * the output. Returns true if the header was needed, false if this is not |
||
| 925 | * a redirect view. Handles both local and remote redirects. |
||
| 926 | * |
||
| 927 | * @return bool |
||
| 928 | */ |
||
| 929 | public function showRedirectedFromHeader() { |
||
| 998 | |||
| 999 | /** |
||
| 1000 | * Show a header specific to the namespace currently being viewed, like |
||
| 1001 | * [[MediaWiki:Talkpagetext]]. For Article::view(). |
||
| 1002 | */ |
||
| 1003 | public function showNamespaceHeader() { |
||
| 1013 | |||
| 1014 | /** |
||
| 1015 | * Show the footer section of an ordinary page view |
||
| 1016 | */ |
||
| 1017 | public function showViewFooter() { |
||
| 1030 | |||
| 1031 | /** |
||
| 1032 | * If patrol is possible, output a patrol UI box. This is called from the |
||
| 1033 | * footer section of ordinary page views. If patrol is not possible or not |
||
| 1034 | * desired, does nothing. |
||
| 1035 | * Side effect: When the patrol link is build, this method will call |
||
| 1036 | * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax. |
||
| 1037 | * |
||
| 1038 | * @return bool |
||
| 1039 | */ |
||
| 1040 | public function showPatrolFooter() { |
||
| 1203 | |||
| 1204 | /** |
||
| 1205 | * Purge the cache used to check if it is worth showing the patrol footer |
||
| 1206 | * For example, it is done during re-uploads when file patrol is used. |
||
| 1207 | * @param int $articleID ID of the article to purge |
||
| 1208 | * @since 1.27 |
||
| 1209 | */ |
||
| 1210 | public static function purgePatrolFooterCache( $articleID ) { |
||
| 1214 | |||
| 1215 | /** |
||
| 1216 | * Show the error text for a missing article. For articles in the MediaWiki |
||
| 1217 | * namespace, show the default message text. To be called from Article::view(). |
||
| 1218 | */ |
||
| 1219 | public function showMissingArticle() { |
||
| 1334 | |||
| 1335 | /** |
||
| 1336 | * If the revision requested for view is deleted, check permissions. |
||
| 1337 | * Send either an error message or a warning header to the output. |
||
| 1338 | * |
||
| 1339 | * @return bool True if the view is allowed, false if not. |
||
| 1340 | */ |
||
| 1341 | public function showDeletedRevisionHeader() { |
||
| 1375 | |||
| 1376 | /** |
||
| 1377 | * Generate the navigation links when browsing through an article revisions |
||
| 1378 | * It shows the information as: |
||
| 1379 | * Revision as of \<date\>; view current revision |
||
| 1380 | * \<- Previous version | Next Version -\> |
||
| 1381 | * |
||
| 1382 | * @param int $oldid Revision ID of this article revision |
||
| 1383 | */ |
||
| 1384 | public function setOldSubtitle( $oldid = 0 ) { |
||
| 1507 | |||
| 1508 | /** |
||
| 1509 | * Return the HTML for the top of a redirect page |
||
| 1510 | * |
||
| 1511 | * Chances are you should just be using the ParserOutput from |
||
| 1512 | * WikitextContent::getParserOutput instead of calling this for redirects. |
||
| 1513 | * |
||
| 1514 | * @param Title|array $target Destination(s) to redirect |
||
| 1515 | * @param bool $appendSubtitle [optional] |
||
| 1516 | * @param bool $forceKnown Should the image be shown as a bluelink regardless of existence? |
||
| 1517 | * @return string Containing HTML with redirect link |
||
| 1518 | */ |
||
| 1519 | public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) { |
||
| 1528 | |||
| 1529 | /** |
||
| 1530 | * Return the HTML for the top of a redirect page |
||
| 1531 | * |
||
| 1532 | * Chances are you should just be using the ParserOutput from |
||
| 1533 | * WikitextContent::getParserOutput instead of calling this for redirects. |
||
| 1534 | * |
||
| 1535 | * @since 1.23 |
||
| 1536 | * @param Language $lang |
||
| 1537 | * @param Title|array $target Destination(s) to redirect |
||
| 1538 | * @param bool $forceKnown Should the image be shown as a bluelink regardless of existence? |
||
| 1539 | * @return string Containing HTML with redirect link |
||
| 1540 | */ |
||
| 1541 | public static function getRedirectHeaderHtml( Language $lang, $target, $forceKnown = false ) { |
||
| 1567 | |||
| 1568 | /** |
||
| 1569 | * Adds help link with an icon via page indicators. |
||
| 1570 | * Link target can be overridden by a local message containing a wikilink: |
||
| 1571 | * the message key is: 'namespace-' + namespace number + '-helppage'. |
||
| 1572 | * @param string $to Target MediaWiki.org page title or encoded URL. |
||
| 1573 | * @param bool $overrideBaseUrl Whether $url is a full URL, to avoid MW.o. |
||
| 1574 | * @since 1.25 |
||
| 1575 | */ |
||
| 1576 | View Code Duplication | public function addHelpLink( $to, $overrideBaseUrl = false ) { |
|
| 1589 | |||
| 1590 | /** |
||
| 1591 | * Handle action=render |
||
| 1592 | */ |
||
| 1593 | public function render() { |
||
| 1594 | $this->getContext()->getRequest()->response()->header( 'X-Robots-Tag: noindex' ); |
||
| 1595 | $this->getContext()->getOutput()->setArticleBodyOnly( true ); |
||
| 1596 | $this->getContext()->getOutput()->enableSectionEditLinks( false ); |
||
| 1597 | $this->view(); |
||
| 1598 | } |
||
| 1599 | |||
| 1600 | /** |
||
| 1601 | * action=protect handler |
||
| 1602 | */ |
||
| 1603 | public function protect() { |
||
| 1607 | |||
| 1608 | /** |
||
| 1609 | * action=unprotect handler (alias) |
||
| 1610 | */ |
||
| 1611 | public function unprotect() { |
||
| 1614 | |||
| 1615 | /** |
||
| 1616 | * UI entry point for page deletion |
||
| 1617 | */ |
||
| 1618 | public function delete() { |
||
| 1740 | |||
| 1741 | /** |
||
| 1742 | * Output deletion confirmation dialog |
||
| 1743 | * @todo FIXME: Move to another file? |
||
| 1744 | * @param string $reason Prefilled reason |
||
| 1745 | */ |
||
| 1746 | public function confirmDelete( $reason ) { |
||
| 1850 | |||
| 1851 | /** |
||
| 1852 | * Perform a deletion and output success or failure messages |
||
| 1853 | * @param string $reason |
||
| 1854 | * @param bool $suppress |
||
| 1855 | */ |
||
| 1856 | public function doDelete( $reason, $suppress = false ) { |
||
| 1899 | |||
| 1900 | /* Caching functions */ |
||
| 1901 | |||
| 1902 | /** |
||
| 1903 | * checkLastModified returns true if it has taken care of all |
||
| 1904 | * output to the client that is necessary for this request. |
||
| 1905 | * (that is, it has sent a cached version of the page) |
||
| 1906 | * |
||
| 1907 | * @return bool True if cached version send, false otherwise |
||
| 1908 | */ |
||
| 1909 | protected function tryFileCache() { |
||
| 1934 | |||
| 1935 | /** |
||
| 1936 | * Check if the page can be cached |
||
| 1937 | * @param integer $mode One of the HTMLFileCache::MODE_* constants (since 1.28) |
||
| 1938 | * @return bool |
||
| 1939 | */ |
||
| 1940 | public function isFileCacheable( $mode = HTMLFileCache::MODE_NORMAL ) { |
||
| 1941 | $cacheable = false; |
||
| 1942 | |||
| 1943 | if ( HTMLFileCache::useFileCache( $this->getContext(), $mode ) ) { |
||
| 1944 | $cacheable = $this->mPage->getId() |
||
| 1945 | && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect(); |
||
| 1946 | // Extension may have reason to disable file caching on some pages. |
||
| 1947 | if ( $cacheable ) { |
||
| 1948 | $cacheable = Hooks::run( 'IsFileCacheable', [ &$this ] ); |
||
| 1949 | } |
||
| 1950 | } |
||
| 1951 | |||
| 1952 | return $cacheable; |
||
| 1953 | } |
||
| 1954 | |||
| 1955 | /**#@-*/ |
||
| 1956 | |||
| 1957 | /** |
||
| 1958 | * Lightweight method to get the parser output for a page, checking the parser cache |
||
| 1959 | * and so on. Doesn't consider most of the stuff that WikiPage::view is forced to |
||
| 1960 | * consider, so it's not appropriate to use there. |
||
| 1961 | * |
||
| 1962 | * @since 1.16 (r52326) for LiquidThreads |
||
| 1963 | * |
||
| 1964 | * @param int|null $oldid Revision ID or null |
||
| 1965 | * @param User $user The relevant user |
||
| 1966 | * @return ParserOutput|bool ParserOutput or false if the given revision ID is not found |
||
| 1967 | */ |
||
| 1968 | public function getParserOutput( $oldid = null, User $user = null ) { |
||
| 1969 | // XXX: bypasses mParserOptions and thus setParserOptions() |
||
| 1970 | |||
| 1971 | if ( $user === null ) { |
||
| 1972 | $parserOptions = $this->getParserOptions(); |
||
| 1973 | } else { |
||
| 1974 | $parserOptions = $this->mPage->makeParserOptions( $user ); |
||
| 1975 | } |
||
| 1976 | |||
| 1977 | return $this->mPage->getParserOutput( $parserOptions, $oldid ); |
||
| 1978 | } |
||
| 1979 | |||
| 1980 | /** |
||
| 1981 | * Override the ParserOptions used to render the primary article wikitext. |
||
| 1982 | * |
||
| 1983 | * @param ParserOptions $options |
||
| 1984 | * @throws MWException If the parser options where already initialized. |
||
| 1985 | */ |
||
| 1986 | public function setParserOptions( ParserOptions $options ) { |
||
| 1987 | if ( $this->mParserOptions ) { |
||
| 1988 | throw new MWException( "can't change parser options after they have already been set" ); |
||
| 1989 | } |
||
| 1990 | |||
| 1991 | // clone, so if $options is modified later, it doesn't confuse the parser cache. |
||
| 1992 | $this->mParserOptions = clone $options; |
||
| 1993 | } |
||
| 1994 | |||
| 1995 | /** |
||
| 1996 | * Get parser options suitable for rendering the primary article wikitext |
||
| 1997 | * @return ParserOptions |
||
| 1998 | */ |
||
| 1999 | public function getParserOptions() { |
||
| 2000 | if ( !$this->mParserOptions ) { |
||
| 2001 | $this->mParserOptions = $this->mPage->makeParserOptions( $this->getContext() ); |
||
| 2002 | } |
||
| 2003 | // Clone to allow modifications of the return value without affecting cache |
||
| 2004 | return clone $this->mParserOptions; |
||
| 2005 | } |
||
| 2006 | |||
| 2007 | /** |
||
| 2008 | * Sets the context this Article is executed in |
||
| 2009 | * |
||
| 2010 | * @param IContextSource $context |
||
| 2011 | * @since 1.18 |
||
| 2012 | */ |
||
| 2013 | public function setContext( $context ) { |
||
| 2014 | $this->mContext = $context; |
||
| 2015 | } |
||
| 2016 | |||
| 2017 | /** |
||
| 2018 | * Gets the context this Article is executed in |
||
| 2019 | * |
||
| 2020 | * @return IContextSource |
||
| 2021 | * @since 1.18 |
||
| 2022 | */ |
||
| 2023 | View Code Duplication | public function getContext() { |
|
| 2024 | if ( $this->mContext instanceof IContextSource ) { |
||
| 2025 | return $this->mContext; |
||
| 2026 | } else { |
||
| 2027 | wfDebug( __METHOD__ . " called and \$mContext is null. " . |
||
| 2028 | "Return RequestContext::getMain(); for sanity\n" ); |
||
| 2029 | return RequestContext::getMain(); |
||
| 2030 | } |
||
| 2031 | } |
||
| 2032 | |||
| 2033 | /** |
||
| 2034 | * Use PHP's magic __get handler to handle accessing of |
||
| 2035 | * raw WikiPage fields for backwards compatibility. |
||
| 2036 | * |
||
| 2037 | * @param string $fname Field name |
||
| 2038 | * @return mixed |
||
| 2039 | */ |
||
| 2040 | public function __get( $fname ) { |
||
| 2041 | if ( property_exists( $this->mPage, $fname ) ) { |
||
| 2042 | # wfWarn( "Access to raw $fname field " . __CLASS__ ); |
||
| 2043 | return $this->mPage->$fname; |
||
| 2044 | } |
||
| 2045 | trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE ); |
||
| 2046 | } |
||
| 2047 | |||
| 2048 | /** |
||
| 2049 | * Use PHP's magic __set handler to handle setting of |
||
| 2050 | * raw WikiPage fields for backwards compatibility. |
||
| 2051 | * |
||
| 2052 | * @param string $fname Field name |
||
| 2053 | * @param mixed $fvalue New value |
||
| 2054 | */ |
||
| 2055 | public function __set( $fname, $fvalue ) { |
||
| 2056 | if ( property_exists( $this->mPage, $fname ) ) { |
||
| 2057 | # wfWarn( "Access to raw $fname field of " . __CLASS__ ); |
||
| 2058 | $this->mPage->$fname = $fvalue; |
||
| 2059 | // Note: extensions may want to toss on new fields |
||
| 2060 | } elseif ( !in_array( $fname, [ 'mContext', 'mPage' ] ) ) { |
||
| 2061 | $this->mPage->$fname = $fvalue; |
||
| 2062 | } else { |
||
| 2063 | trigger_error( 'Inaccessible property via __set(): ' . $fname, E_USER_NOTICE ); |
||
| 2064 | } |
||
| 2065 | } |
||
| 2066 | |||
| 2067 | /** |
||
| 2068 | * Call to WikiPage function for backwards compatibility. |
||
| 2069 | * @see WikiPage::checkFlags |
||
| 2070 | */ |
||
| 2071 | public function checkFlags( $flags ) { |
||
| 2072 | return $this->mPage->checkFlags( $flags ); |
||
| 2073 | } |
||
| 2074 | |||
| 2075 | /** |
||
| 2076 | * Call to WikiPage function for backwards compatibility. |
||
| 2077 | * @see WikiPage::checkTouched |
||
| 2078 | */ |
||
| 2079 | public function checkTouched() { |
||
| 2080 | return $this->mPage->checkTouched(); |
||
| 2081 | } |
||
| 2082 | |||
| 2083 | /** |
||
| 2084 | * Call to WikiPage function for backwards compatibility. |
||
| 2085 | * @see WikiPage::clearPreparedEdit |
||
| 2086 | */ |
||
| 2087 | public function clearPreparedEdit() { |
||
| 2088 | $this->mPage->clearPreparedEdit(); |
||
| 2089 | } |
||
| 2090 | |||
| 2091 | /** |
||
| 2092 | * Call to WikiPage function for backwards compatibility. |
||
| 2093 | * @see WikiPage::doDeleteArticleReal |
||
| 2094 | */ |
||
| 2095 | public function doDeleteArticleReal( |
||
| 2096 | $reason, $suppress = false, $u1 = null, $u2 = null, &$error = '', User $user = null, |
||
| 2097 | $tags = [] |
||
| 2098 | ) { |
||
| 2099 | return $this->mPage->doDeleteArticleReal( |
||
| 2100 | $reason, $suppress, $u1, $u2, $error, $user, $tags |
||
| 2101 | ); |
||
| 2102 | } |
||
| 2103 | |||
| 2104 | /** |
||
| 2105 | * Call to WikiPage function for backwards compatibility. |
||
| 2106 | * @see WikiPage::doDeleteUpdates |
||
| 2107 | */ |
||
| 2108 | public function doDeleteUpdates( $id, Content $content = null ) { |
||
| 2109 | return $this->mPage->doDeleteUpdates( $id, $content ); |
||
| 2110 | } |
||
| 2111 | |||
| 2112 | /** |
||
| 2113 | * Call to WikiPage function for backwards compatibility. |
||
| 2114 | * @see WikiPage::doEdit |
||
| 2115 | * |
||
| 2116 | * @deprecated since 1.21: use doEditContent() instead. |
||
| 2117 | */ |
||
| 2118 | public function doEdit( $text, $summary, $flags = 0, $baseRevId = false, $user = null ) { |
||
| 2119 | wfDeprecated( __METHOD__, '1.21' ); |
||
| 2120 | return $this->mPage->doEdit( $text, $summary, $flags, $baseRevId, $user ); |
||
| 2121 | } |
||
| 2122 | |||
| 2123 | /** |
||
| 2124 | * Call to WikiPage function for backwards compatibility. |
||
| 2125 | * @see WikiPage::doEditContent |
||
| 2126 | */ |
||
| 2127 | public function doEditContent( Content $content, $summary, $flags = 0, $baseRevId = false, |
||
| 2128 | User $user = null, $serialFormat = null |
||
| 2129 | ) { |
||
| 2130 | return $this->mPage->doEditContent( $content, $summary, $flags, $baseRevId, |
||
| 2131 | $user, $serialFormat |
||
| 2132 | ); |
||
| 2133 | } |
||
| 2134 | |||
| 2135 | /** |
||
| 2136 | * Call to WikiPage function for backwards compatibility. |
||
| 2137 | * @see WikiPage::doEditUpdates |
||
| 2138 | */ |
||
| 2139 | public function doEditUpdates( Revision $revision, User $user, array $options = [] ) { |
||
| 2140 | return $this->mPage->doEditUpdates( $revision, $user, $options ); |
||
| 2141 | } |
||
| 2142 | |||
| 2143 | /** |
||
| 2144 | * Call to WikiPage function for backwards compatibility. |
||
| 2145 | * @see WikiPage::doPurge |
||
| 2146 | */ |
||
| 2147 | public function doPurge( $flags = WikiPage::PURGE_ALL ) { |
||
| 2148 | return $this->mPage->doPurge( $flags ); |
||
| 2149 | } |
||
| 2150 | |||
| 2151 | /** |
||
| 2152 | * Call to WikiPage function for backwards compatibility. |
||
| 2153 | * @see WikiPage::getLastPurgeTimestamp |
||
| 2154 | */ |
||
| 2155 | public function getLastPurgeTimestamp() { |
||
| 2156 | return $this->mPage->getLastPurgeTimestamp(); |
||
| 2157 | } |
||
| 2158 | |||
| 2159 | /** |
||
| 2160 | * Call to WikiPage function for backwards compatibility. |
||
| 2161 | * @see WikiPage::doViewUpdates |
||
| 2162 | */ |
||
| 2163 | public function doViewUpdates( User $user, $oldid = 0 ) { |
||
| 2166 | |||
| 2167 | /** |
||
| 2168 | * Call to WikiPage function for backwards compatibility. |
||
| 2169 | * @see WikiPage::exists |
||
| 2170 | */ |
||
| 2171 | public function exists() { |
||
| 2174 | |||
| 2175 | /** |
||
| 2176 | * Call to WikiPage function for backwards compatibility. |
||
| 2177 | * @see WikiPage::followRedirect |
||
| 2178 | */ |
||
| 2179 | public function followRedirect() { |
||
| 2182 | |||
| 2183 | /** |
||
| 2184 | * Call to WikiPage function for backwards compatibility. |
||
| 2185 | * @see ContentHandler::getActionOverrides |
||
| 2186 | */ |
||
| 2187 | public function getActionOverrides() { |
||
| 2190 | |||
| 2191 | /** |
||
| 2192 | * Call to WikiPage function for backwards compatibility. |
||
| 2193 | * @see WikiPage::getAutoDeleteReason |
||
| 2194 | */ |
||
| 2195 | public function getAutoDeleteReason( &$hasHistory ) { |
||
| 2198 | |||
| 2199 | /** |
||
| 2200 | * Call to WikiPage function for backwards compatibility. |
||
| 2201 | * @see WikiPage::getCategories |
||
| 2202 | */ |
||
| 2203 | public function getCategories() { |
||
| 2206 | |||
| 2207 | /** |
||
| 2208 | * Call to WikiPage function for backwards compatibility. |
||
| 2209 | * @see WikiPage::getComment |
||
| 2210 | */ |
||
| 2211 | public function getComment( $audience = Revision::FOR_PUBLIC, User $user = null ) { |
||
| 2214 | |||
| 2215 | /** |
||
| 2216 | * Call to WikiPage function for backwards compatibility. |
||
| 2217 | * @see WikiPage::getContentHandler |
||
| 2218 | */ |
||
| 2219 | public function getContentHandler() { |
||
| 2222 | |||
| 2223 | /** |
||
| 2224 | * Call to WikiPage function for backwards compatibility. |
||
| 2225 | * @see WikiPage::getContentModel |
||
| 2226 | */ |
||
| 2227 | public function getContentModel() { |
||
| 2230 | |||
| 2231 | /** |
||
| 2232 | * Call to WikiPage function for backwards compatibility. |
||
| 2233 | * @see WikiPage::getContributors |
||
| 2234 | */ |
||
| 2235 | public function getContributors() { |
||
| 2238 | |||
| 2239 | /** |
||
| 2240 | * Call to WikiPage function for backwards compatibility. |
||
| 2241 | * @see WikiPage::getCreator |
||
| 2242 | */ |
||
| 2243 | public function getCreator( $audience = Revision::FOR_PUBLIC, User $user = null ) { |
||
| 2246 | |||
| 2247 | /** |
||
| 2248 | * Call to WikiPage function for backwards compatibility. |
||
| 2249 | * @see WikiPage::getDeletionUpdates |
||
| 2250 | */ |
||
| 2251 | public function getDeletionUpdates( Content $content = null ) { |
||
| 2254 | |||
| 2255 | /** |
||
| 2256 | * Call to WikiPage function for backwards compatibility. |
||
| 2257 | * @see WikiPage::getHiddenCategories |
||
| 2258 | */ |
||
| 2259 | public function getHiddenCategories() { |
||
| 2262 | |||
| 2263 | /** |
||
| 2264 | * Call to WikiPage function for backwards compatibility. |
||
| 2265 | * @see WikiPage::getId |
||
| 2266 | */ |
||
| 2267 | public function getId() { |
||
| 2270 | |||
| 2271 | /** |
||
| 2272 | * Call to WikiPage function for backwards compatibility. |
||
| 2273 | * @see WikiPage::getLatest |
||
| 2274 | */ |
||
| 2275 | public function getLatest() { |
||
| 2278 | |||
| 2279 | /** |
||
| 2280 | * Call to WikiPage function for backwards compatibility. |
||
| 2281 | * @see WikiPage::getLinksTimestamp |
||
| 2282 | */ |
||
| 2283 | public function getLinksTimestamp() { |
||
| 2286 | |||
| 2287 | /** |
||
| 2288 | * Call to WikiPage function for backwards compatibility. |
||
| 2289 | * @see WikiPage::getMinorEdit |
||
| 2290 | */ |
||
| 2291 | public function getMinorEdit() { |
||
| 2294 | |||
| 2295 | /** |
||
| 2296 | * Call to WikiPage function for backwards compatibility. |
||
| 2297 | * @see WikiPage::getOldestRevision |
||
| 2298 | */ |
||
| 2299 | public function getOldestRevision() { |
||
| 2302 | |||
| 2303 | /** |
||
| 2304 | * Call to WikiPage function for backwards compatibility. |
||
| 2305 | * @see WikiPage::getRedirectTarget |
||
| 2306 | */ |
||
| 2307 | public function getRedirectTarget() { |
||
| 2310 | |||
| 2311 | /** |
||
| 2312 | * Call to WikiPage function for backwards compatibility. |
||
| 2313 | * @see WikiPage::getRedirectURL |
||
| 2314 | */ |
||
| 2315 | public function getRedirectURL( $rt ) { |
||
| 2318 | |||
| 2319 | /** |
||
| 2320 | * Call to WikiPage function for backwards compatibility. |
||
| 2321 | * @see WikiPage::getRevision |
||
| 2322 | */ |
||
| 2323 | public function getRevision() { |
||
| 2326 | |||
| 2327 | /** |
||
| 2328 | * Call to WikiPage function for backwards compatibility. |
||
| 2329 | * @see WikiPage::getText |
||
| 2330 | * @deprecated since 1.21 use WikiPage::getContent() instead |
||
| 2331 | */ |
||
| 2332 | public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { |
||
| 2333 | wfDeprecated( __METHOD__, '1.21' ); |
||
| 2334 | return $this->mPage->getText( $audience, $user ); |
||
| 2335 | } |
||
| 2336 | |||
| 2337 | /** |
||
| 2338 | * Call to WikiPage function for backwards compatibility. |
||
| 2339 | * @see WikiPage::getTimestamp |
||
| 2340 | */ |
||
| 2341 | public function getTimestamp() { |
||
| 2342 | return $this->mPage->getTimestamp(); |
||
| 2343 | } |
||
| 2344 | |||
| 2345 | /** |
||
| 2346 | * Call to WikiPage function for backwards compatibility. |
||
| 2347 | * @see WikiPage::getTouched |
||
| 2348 | */ |
||
| 2349 | public function getTouched() { |
||
| 2350 | return $this->mPage->getTouched(); |
||
| 2351 | } |
||
| 2352 | |||
| 2353 | /** |
||
| 2354 | * Call to WikiPage function for backwards compatibility. |
||
| 2355 | * @see WikiPage::getUndoContent |
||
| 2356 | */ |
||
| 2357 | public function getUndoContent( Revision $undo, Revision $undoafter = null ) { |
||
| 2358 | return $this->mPage->getUndoContent( $undo, $undoafter ); |
||
| 2359 | } |
||
| 2360 | |||
| 2361 | /** |
||
| 2362 | * Call to WikiPage function for backwards compatibility. |
||
| 2363 | * @see WikiPage::getUser |
||
| 2364 | */ |
||
| 2365 | public function getUser( $audience = Revision::FOR_PUBLIC, User $user = null ) { |
||
| 2366 | return $this->mPage->getUser( $audience, $user ); |
||
| 2368 | |||
| 2369 | /** |
||
| 2370 | * Call to WikiPage function for backwards compatibility. |
||
| 2371 | * @see WikiPage::getUserText |
||
| 2372 | */ |
||
| 2373 | public function getUserText( $audience = Revision::FOR_PUBLIC, User $user = null ) { |
||
| 2376 | |||
| 2377 | /** |
||
| 2378 | * Call to WikiPage function for backwards compatibility. |
||
| 2379 | * @see WikiPage::hasViewableContent |
||
| 2380 | */ |
||
| 2381 | public function hasViewableContent() { |
||
| 2384 | |||
| 2385 | /** |
||
| 2386 | * Call to WikiPage function for backwards compatibility. |
||
| 2387 | * @see WikiPage::insertOn |
||
| 2388 | */ |
||
| 2389 | public function insertOn( $dbw, $pageId = null ) { |
||
| 2392 | |||
| 2393 | /** |
||
| 2394 | * Call to WikiPage function for backwards compatibility. |
||
| 2395 | * @see WikiPage::insertProtectNullRevision |
||
| 2396 | */ |
||
| 2397 | public function insertProtectNullRevision( $revCommentMsg, array $limit, |
||
| 2404 | |||
| 2405 | /** |
||
| 2406 | * Call to WikiPage function for backwards compatibility. |
||
| 2407 | * @see WikiPage::insertRedirect |
||
| 2408 | */ |
||
| 2409 | public function insertRedirect() { |
||
| 2412 | |||
| 2413 | /** |
||
| 2414 | * Call to WikiPage function for backwards compatibility. |
||
| 2415 | * @see WikiPage::insertRedirectEntry |
||
| 2416 | */ |
||
| 2417 | public function insertRedirectEntry( Title $rt, $oldLatest = null ) { |
||
| 2420 | |||
| 2421 | /** |
||
| 2422 | * Call to WikiPage function for backwards compatibility. |
||
| 2423 | * @see WikiPage::isCountable |
||
| 2424 | */ |
||
| 2425 | public function isCountable( $editInfo = false ) { |
||
| 2428 | |||
| 2429 | /** |
||
| 2430 | * Call to WikiPage function for backwards compatibility. |
||
| 2431 | * @see WikiPage::isRedirect |
||
| 2432 | */ |
||
| 2433 | public function isRedirect() { |
||
| 2436 | |||
| 2437 | /** |
||
| 2438 | * Call to WikiPage function for backwards compatibility. |
||
| 2439 | * @see WikiPage::loadFromRow |
||
| 2440 | */ |
||
| 2441 | public function loadFromRow( $data, $from ) { |
||
| 2444 | |||
| 2445 | /** |
||
| 2446 | * Call to WikiPage function for backwards compatibility. |
||
| 2447 | * @see WikiPage::loadPageData |
||
| 2448 | */ |
||
| 2449 | public function loadPageData( $from = 'fromdb' ) { |
||
| 2452 | |||
| 2453 | /** |
||
| 2454 | * Call to WikiPage function for backwards compatibility. |
||
| 2455 | * @see WikiPage::lockAndGetLatest |
||
| 2456 | */ |
||
| 2457 | public function lockAndGetLatest() { |
||
| 2460 | |||
| 2461 | /** |
||
| 2462 | * Call to WikiPage function for backwards compatibility. |
||
| 2463 | * @see WikiPage::makeParserOptions |
||
| 2464 | */ |
||
| 2465 | public function makeParserOptions( $context ) { |
||
| 2468 | |||
| 2469 | /** |
||
| 2470 | * Call to WikiPage function for backwards compatibility. |
||
| 2471 | * @see WikiPage::pageDataFromId |
||
| 2472 | */ |
||
| 2473 | public function pageDataFromId( $dbr, $id, $options = [] ) { |
||
| 2476 | |||
| 2477 | /** |
||
| 2478 | * Call to WikiPage function for backwards compatibility. |
||
| 2479 | * @see WikiPage::pageDataFromTitle |
||
| 2480 | */ |
||
| 2481 | public function pageDataFromTitle( $dbr, $title, $options = [] ) { |
||
| 2484 | |||
| 2485 | /** |
||
| 2486 | * Call to WikiPage function for backwards compatibility. |
||
| 2487 | * @see WikiPage::prepareContentForEdit |
||
| 2488 | */ |
||
| 2489 | public function prepareContentForEdit( |
||
| 2498 | |||
| 2499 | /** |
||
| 2500 | * Call to WikiPage function for backwards compatibility. |
||
| 2501 | * @deprecated since 1.21, use prepareContentForEdit |
||
| 2502 | * @see WikiPage::prepareTextForEdit |
||
| 2503 | */ |
||
| 2504 | public function prepareTextForEdit( $text, $revid = null, User $user = null ) { |
||
| 2507 | |||
| 2508 | /** |
||
| 2509 | * Call to WikiPage function for backwards compatibility. |
||
| 2510 | * @see WikiPage::protectDescription |
||
| 2511 | */ |
||
| 2512 | public function protectDescription( array $limit, array $expiry ) { |
||
| 2515 | |||
| 2516 | /** |
||
| 2517 | * Call to WikiPage function for backwards compatibility. |
||
| 2518 | * @see WikiPage::protectDescriptionLog |
||
| 2519 | */ |
||
| 2520 | public function protectDescriptionLog( array $limit, array $expiry ) { |
||
| 2523 | |||
| 2524 | /** |
||
| 2525 | * Call to WikiPage function for backwards compatibility. |
||
| 2526 | * @see WikiPage::replaceSectionAtRev |
||
| 2527 | */ |
||
| 2528 | public function replaceSectionAtRev( $sectionId, Content $sectionContent, |
||
| 2535 | |||
| 2536 | /** |
||
| 2537 | * Call to WikiPage function for backwards compatibility. |
||
| 2538 | * @see WikiPage::replaceSectionContent |
||
| 2539 | */ |
||
| 2540 | public function replaceSectionContent( |
||
| 2547 | |||
| 2548 | /** |
||
| 2549 | * Call to WikiPage function for backwards compatibility. |
||
| 2550 | * @see WikiPage::setTimestamp |
||
| 2551 | */ |
||
| 2552 | public function setTimestamp( $ts ) { |
||
| 2555 | |||
| 2556 | /** |
||
| 2557 | * Call to WikiPage function for backwards compatibility. |
||
| 2558 | * @see WikiPage::shouldCheckParserCache |
||
| 2559 | */ |
||
| 2560 | public function shouldCheckParserCache( ParserOptions $parserOptions, $oldId ) { |
||
| 2563 | |||
| 2564 | /** |
||
| 2565 | * Call to WikiPage function for backwards compatibility. |
||
| 2566 | * @see WikiPage::supportsSections |
||
| 2567 | */ |
||
| 2568 | public function supportsSections() { |
||
| 2571 | |||
| 2572 | /** |
||
| 2573 | * Call to WikiPage function for backwards compatibility. |
||
| 2574 | * @see WikiPage::triggerOpportunisticLinksUpdate |
||
| 2575 | */ |
||
| 2576 | public function triggerOpportunisticLinksUpdate( ParserOutput $parserOutput ) { |
||
| 2579 | |||
| 2580 | /** |
||
| 2581 | * Call to WikiPage function for backwards compatibility. |
||
| 2582 | * @see WikiPage::updateCategoryCounts |
||
| 2583 | */ |
||
| 2584 | public function updateCategoryCounts( array $added, array $deleted, $id = 0 ) { |
||
| 2587 | |||
| 2588 | /** |
||
| 2589 | * Call to WikiPage function for backwards compatibility. |
||
| 2590 | * @see WikiPage::updateIfNewerOn |
||
| 2591 | */ |
||
| 2592 | public function updateIfNewerOn( $dbw, $revision ) { |
||
| 2595 | |||
| 2596 | /** |
||
| 2597 | * Call to WikiPage function for backwards compatibility. |
||
| 2598 | * @see WikiPage::updateRedirectOn |
||
| 2599 | */ |
||
| 2600 | public function updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null ) { |
||
| 2603 | |||
| 2604 | /** |
||
| 2605 | * Call to WikiPage function for backwards compatibility. |
||
| 2606 | * @see WikiPage::updateRevisionOn |
||
| 2607 | */ |
||
| 2608 | public function updateRevisionOn( $dbw, $revision, $lastRevision = null, |
||
| 2615 | |||
| 2616 | /** |
||
| 2617 | * @param array $limit |
||
| 2618 | * @param array $expiry |
||
| 2619 | * @param bool $cascade |
||
| 2620 | * @param string $reason |
||
| 2621 | * @param User $user |
||
| 2622 | * @return Status |
||
| 2623 | */ |
||
| 2624 | public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, |
||
| 2629 | |||
| 2630 | /** |
||
| 2631 | * @param array $limit |
||
| 2632 | * @param string $reason |
||
| 2633 | * @param int $cascade |
||
| 2634 | * @param array $expiry |
||
| 2635 | * @return bool |
||
| 2636 | */ |
||
| 2637 | public function updateRestrictions( $limit = [], $reason = '', |
||
| 2648 | |||
| 2649 | /** |
||
| 2650 | * @param string $reason |
||
| 2651 | * @param bool $suppress |
||
| 2652 | * @param int $u1 Unused |
||
| 2653 | * @param bool $u2 Unused |
||
| 2654 | * @param string $error |
||
| 2655 | * @return bool |
||
| 2656 | */ |
||
| 2657 | public function doDeleteArticle( |
||
| 2662 | |||
| 2663 | /** |
||
| 2664 | * @param string $fromP |
||
| 2665 | * @param string $summary |
||
| 2666 | * @param string $token |
||
| 2667 | * @param bool $bot |
||
| 2668 | * @param array $resultDetails |
||
| 2669 | * @param User|null $user |
||
| 2670 | * @return array |
||
| 2671 | */ |
||
| 2672 | public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user = null ) { |
||
| 2676 | |||
| 2677 | /** |
||
| 2678 | * @param string $fromP |
||
| 2679 | * @param string $summary |
||
| 2680 | * @param bool $bot |
||
| 2681 | * @param array $resultDetails |
||
| 2682 | * @param User|null $guser |
||
| 2683 | * @return array |
||
| 2684 | */ |
||
| 2685 | public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser = null ) { |
||
| 2689 | |||
| 2690 | /** |
||
| 2691 | * @param bool $hasHistory |
||
| 2692 | * @return mixed |
||
| 2693 | */ |
||
| 2694 | public function generateReason( &$hasHistory ) { |
||
| 2699 | |||
| 2700 | /** |
||
| 2701 | * @return array |
||
| 2702 | * |
||
| 2703 | * @deprecated since 1.24, use WikiPage::selectFields() instead |
||
| 2704 | */ |
||
| 2705 | public static function selectFields() { |
||
| 2709 | |||
| 2710 | /** |
||
| 2711 | * @param Title $title |
||
| 2712 | * |
||
| 2713 | * @deprecated since 1.24, use WikiPage::onArticleCreate() instead |
||
| 2714 | */ |
||
| 2715 | public static function onArticleCreate( $title ) { |
||
| 2719 | |||
| 2720 | /** |
||
| 2721 | * @param Title $title |
||
| 2722 | * |
||
| 2723 | * @deprecated since 1.24, use WikiPage::onArticleDelete() instead |
||
| 2724 | */ |
||
| 2725 | public static function onArticleDelete( $title ) { |
||
| 2729 | |||
| 2730 | /** |
||
| 2731 | * @param Title $title |
||
| 2732 | * |
||
| 2733 | * @deprecated since 1.24, use WikiPage::onArticleEdit() instead |
||
| 2734 | */ |
||
| 2735 | public static function onArticleEdit( $title ) { |
||
| 2739 | |||
| 2740 | /** |
||
| 2741 | * @param string $oldtext |
||
| 2742 | * @param string $newtext |
||
| 2743 | * @param int $flags |
||
| 2744 | * @return string |
||
| 2745 | * @deprecated since 1.21, use ContentHandler::getAutosummary() instead |
||
| 2746 | */ |
||
| 2747 | public static function getAutosummary( $oldtext, $newtext, $flags ) { |
||
| 2750 | // ****** |
||
| 2751 | } |
||
| 2752 |
In PHP, under loose comparison (like
==, or!=, orswitchconditions), values of different types might be equal.For
integervalues, zero is a special case, in particular the following results might be unexpected: