r113044 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113043‎ | r113044 | r113045 >
Date:15:53, 5 March 2012
Author:daniel
Status:deferred
Tags:
Comment:
adapted WikiPage and Article (work in progress)
Modified paths:
  • /branches/Wikidata/phase3/includes/Article.php (modified) (history)
  • /branches/Wikidata/phase3/includes/Content.php (modified) (history)
  • /branches/Wikidata/phase3/includes/ContentHandler.php (modified) (history)
  • /branches/Wikidata/phase3/includes/Revision.php (modified) (history)
  • /branches/Wikidata/phase3/includes/WikiPage.php (modified) (history)
  • /branches/Wikidata/phase3/includes/specials/SpecialUndelete.php (modified) (history)

Diff [purge]

Index: branches/Wikidata/phase3/includes/Article.php
@@ -38,6 +38,7 @@
3939 public $mParserOptions;
4040
4141 var $mContent; // !< #FIXME: use Content object!
 42+ var $mContentObject; // !<
4243 var $mContentLoaded = false; // !<
4344 var $mOldId; // !<
4445
@@ -189,8 +190,25 @@
190191 * only want the real revision text if any.
191192 *
192193 * @return Return the text of this revision
 194+ * @deprecated in 1.20; use getContentObject() instead
193195 */
194 - public function getContent() {
 196+ public function getContent() { #FIXME: deprecated! replace usage! use content object!
 197+ wfDeprecated( __METHOD__, '1.20' );
 198+ $content = $this->getContentObject();
 199+ return ContentHandler::getContentText( $content );
 200+ }
 201+
 202+ /**
 203+ * Note that getContent/loadContent do not follow redirects anymore.
 204+ * If you need to fetch redirectable content easily, try
 205+ * the shortcut in WikiPage::getRedirectTarget()
 206+ *
 207+ * This function has side effects! Do not use this function if you
 208+ * only want the real revision text if any.
 209+ *
 210+ * @return Return the content of this revision
 211+ */
 212+ public function getContentObject() {
195213 global $wgUser;
196214
197215 wfProfileIn( __METHOD__ );
@@ -208,12 +226,12 @@
209227 }
210228 wfProfileOut( __METHOD__ );
211229
212 - return $text;
 230+ return new WikitextContent( $text, $this->getTitle() );
213231 } else {
214 - $this->fetchContent();
 232+ $this->fetchContentObject();
215233 wfProfileOut( __METHOD__ );
216234
217 - return $this->mContent;
 235+ return $this->mContentObject;
218236 }
219237 }
220238
@@ -292,61 +310,89 @@
293311 * Does *NOT* follow redirects.
294312 *
295313 * @return mixed string containing article contents, or false if null
 314+ * @deprecated in 1.20, use getContentObject() instead
296315 */
297 - function fetchContent() {
298 - if ( $this->mContentLoaded ) {
 316+ function fetchContent() { #BC cruft! #FIXME: deprecated, replace usage
 317+ wfDeprecated( __METHOD__, '1.20' );
 318+
 319+ if ( $this->mContentLoaded && $this->mContent ) {
299320 return $this->mContent;
300321 }
301322
302323 wfProfileIn( __METHOD__ );
303324
304 - $this->mContentLoaded = true;
 325+ $content = $this->fetchContentObject();
305326
306 - $oldid = $this->getOldID();
 327+ $this->mContent = ContentHandler::getContentText( $content );
 328+ wfRunHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) ); #BC cruft!
307329
308 - # Pre-fill content with error message so that if something
309 - # fails we'll have something telling us what we intended.
310 - $t = $this->getTitle()->getPrefixedText();
311 - $d = $oldid ? wfMsgExt( 'missingarticle-rev', array( 'escape' ), $oldid ) : '';
312 - $this->mContent = wfMsgNoTrans( 'missing-article', $t, $d ) ;
 330+ wfProfileOut( __METHOD__ );
313331
314 - if ( $oldid ) {
315 - # $this->mRevision might already be fetched by getOldIDFromRequest()
316 - if ( !$this->mRevision ) {
317 - $this->mRevision = Revision::newFromId( $oldid );
318 - if ( !$this->mRevision ) {
319 - wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" );
320 - wfProfileOut( __METHOD__ );
321 - return false;
322 - }
323 - }
324 - } else {
325 - if ( !$this->mPage->getLatest() ) {
326 - wfDebug( __METHOD__ . " failed to find page data for title " . $this->getTitle()->getPrefixedText() . "\n" );
327 - wfProfileOut( __METHOD__ );
328 - return false;
329 - }
 332+ return $this->mContent;
 333+ }
330334
331 - $this->mRevision = $this->mPage->getRevision();
332 - if ( !$this->mRevision ) {
333 - wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n" );
334 - wfProfileOut( __METHOD__ );
335 - return false;
336 - }
337 - }
338335
339 - // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks.
340 - // We should instead work with the Revision object when we need it...
341 - $this->mContent = $this->mRevision->getText( Revision::FOR_THIS_USER ); // Loads if user is allowed
342 - $this->mRevIdFetched = $this->mRevision->getId();
 336+ /**
 337+ * Get text content object
 338+ * Does *NOT* follow redirects.
 339+ *
 340+ * @return Content object containing article contents, or null
 341+ */
 342+ function fetchContentObject() {
 343+ if ( $this->mContentLoaded ) {
 344+ return $this->mContentObject;
 345+ }
343346
344 - wfRunHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) );
 347+ wfProfileIn( __METHOD__ );
345348
346 - wfProfileOut( __METHOD__ );
 349+ $this->mContentLoaded = true;
 350+ $this->mContent = null;
347351
348 - return $this->mContent;
349 - }
 352+ $oldid = $this->getOldID();
350353
 354+ # Pre-fill content with error message so that if something
 355+ # fails we'll have something telling us what we intended.
 356+ $t = $this->getTitle()->getPrefixedText();
 357+ $d = $oldid ? wfMsgExt( 'missingarticle-rev', array( 'escape' ), $oldid ) : '';
 358+ $this->mContentObject = new MessageContent( 'missing-article', array($t, $d), array() ) ;
 359+
 360+ if ( $oldid ) {
 361+ # $this->mRevision might already be fetched by getOldIDFromRequest()
 362+ if ( !$this->mRevision ) {
 363+ $this->mRevision = Revision::newFromId( $oldid );
 364+ if ( !$this->mRevision ) {
 365+ wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" );
 366+ wfProfileOut( __METHOD__ );
 367+ return false;
 368+ }
 369+ }
 370+ } else {
 371+ if ( !$this->mPage->getLatest() ) {
 372+ wfDebug( __METHOD__ . " failed to find page data for title " . $this->getTitle()->getPrefixedText() . "\n" );
 373+ wfProfileOut( __METHOD__ );
 374+ return false;
 375+ }
 376+
 377+ $this->mRevision = $this->mPage->getRevision();
 378+ if ( !$this->mRevision ) {
 379+ wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n" );
 380+ wfProfileOut( __METHOD__ );
 381+ return false;
 382+ }
 383+ }
 384+
 385+ // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks.
 386+ // We should instead work with the Revision object when we need it...
 387+ $this->mContentObject = $this->mRevision->getContent( Revision::FOR_THIS_USER ); // Loads if user is allowed
 388+ $this->mRevIdFetched = $this->mRevision->getId();
 389+
 390+ wfRunHooks( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) ); #FIXME: register new hook
 391+
 392+ wfProfileOut( __METHOD__ );
 393+
 394+ return $this->mContentObject;
 395+ }
 396+
351397 /**
352398 * No-op
353399 * @deprecated since 1.18
Index: branches/Wikidata/phase3/includes/Content.php
@@ -68,6 +68,8 @@
6969 $html = $this->getHtml( $options );
7070 $po = new ParserOutput( $html );
7171
 72+ if ( $this->mTitle ) $po->setTitleText( $this->mTitle->getText() );
 73+
7274 #TODO: cache settings, etc?
7375
7476 return $po;
@@ -84,8 +86,6 @@
8587
8688
8789 public function getRawData( ) {
88 - global $wgParser, $wgUser;
89 -
9090 $text = $this->mText;
9191 return $text;
9292 }
@@ -128,7 +128,36 @@
129129
130130 }
131131
 132+class MessageContent extends TextContent {
 133+ public function __construct( $msg_key, $params = null, $options = null ) {
 134+ parent::__construct(null, null, null, CONTENT_MODEL_WIKITEXT);
132135
 136+ $this->mMessageKey = $msg_key;
 137+
 138+ $this->mParameters = $params;
 139+
 140+ if ( !$options ) $options = array();
 141+ $this->mOptions = $options;
 142+
 143+ $this->mHtmlOptions = null;
 144+ }
 145+
 146+
 147+ public function getHtml( ParserOptions $options ) {
 148+ $opt = array_merge( $this->mOptions, array('parse') );
 149+ return wfMsgExt( $this->mMessageKey, $this->mParameters, $opt );
 150+ }
 151+
 152+
 153+ public function getRawData( ) {
 154+ $opt = array_diff( $this->mOptions, array('parse', 'parseinline') );
 155+
 156+ return wfMsgExt( $this->mMessageKey, $this->mParameters, $opt );
 157+ }
 158+
 159+}
 160+
 161+
133162 class JavaScriptContent extends TextContent {
134163 public function __construct( $text, Title $title, $revId = null ) {
135164 parent::__construct($text, $title, $revId, CONTENT_MODEL_JAVASCRIPT);
@@ -160,6 +189,9 @@
161190 }
162191 }
163192
 193+#FIXME: special type for redirects?!
 194+#FIXME: special type for message-based pseudo-content? with raw html?
 195+
164196 #TODO: MultipartMultipart < WikipageContent (Main + Links + X)
165197 #TODO: LinksContent < LanguageLinksContent, CategoriesContent
166198 #EXAMPLE: CoordinatesContent
Index: branches/Wikidata/phase3/includes/ContentHandler.php
@@ -13,6 +13,18 @@
1414 */
1515 abstract class ContentHandler {
1616
 17+ public static function getContentText( Content $content ) {
 18+ if ( !$content ) return '';
 19+
 20+ if ( $content instanceof TextContent ) {
 21+ #XXX: or check by model name?
 22+ #XXX: or define $content->allowRawData()?
 23+ return $content->getRawData();
 24+ }
 25+
 26+ return null;
 27+ }
 28+
1729 public static function getDefaultModelFor( Title $title ) {
1830 global $wgNamespaceContentModels;
1931
Index: branches/Wikidata/phase3/includes/Revision.php
@@ -21,7 +21,9 @@
2222 protected $mTitle;
2323 protected $mCurrent;
2424 protected $mContentModelName;
25 - protected $mContentType;
 25+ protected $mContentFormat;
 26+ protected $mContent;
 27+ protected $mContentHandler;
2628
2729 const DELETED_TEXT = 1;
2830 const DELETED_COMMENT = 2;
@@ -128,7 +130,7 @@
129131 'len' => $row->ar_len,
130132 'sha1' => isset( $row->ar_sha1 ) ? $row->ar_sha1 : null,
131133 'content_model' => isset( $row->ar_content_model ) ? $row->ar_content_model : null,
132 - 'content_type' => isset( $row->ar_content_type ) ? $row->ar_content_type : null,
 134+ 'content_format' => isset( $row->ar_content_format ) ? $row->ar_content_format : null,
133135 );
134136 if ( isset( $row->ar_text ) && !$row->ar_text_id ) {
135137 // Pre-1.5 ar_text row
@@ -339,7 +341,9 @@
340342 'rev_deleted',
341343 'rev_len',
342344 'rev_parent_id',
343 - 'rev_sha1'
 345+ 'rev_sha1',
 346+ 'rev_content_format',
 347+ 'rev_content_model'
344348 );
345349 }
346350
@@ -422,10 +426,10 @@
423427 $this->mContentModelName = strval( $row->rev_content_model );
424428 }
425429
426 - if( !isset( $row->rev_content_type ) || is_null( $row->rev_content_type ) ) {
427 - $this->mContentType = null; # determine on demand if needed
 430+ if( !isset( $row->rev_content_format ) || is_null( $row->rev_content_format ) ) {
 431+ $this->mContentFormat = null; # determine on demand if needed
428432 } else {
429 - $this->mContentType = strval( $row->rev_content_type );
 433+ $this->mContentFormat = strval( $row->rev_content_format );
430434 }
431435
432436 // Lazy extraction...
@@ -449,6 +453,19 @@
450454 // Build a new revision to be saved...
451455 global $wgUser; // ugh
452456
 457+
 458+ # if we have a content object, use it to set the model and type
 459+ if ( !empty( $row['content'] ) ) {
 460+ if ( !empty( $row['text_id'] ) ) { #FIXME: when is that set? test with external store setup! check out insertOn()
 461+ throw new MWException( "Text already stored in external store (id {$row['text_id']}), can't serialize content object" );
 462+ }
 463+
 464+ $row['content_model'] = $row['content']->getModelName();
 465+ # note: mContentFormat is initializes later accordingly
 466+ # note: content is serialized later in this method!
 467+ # also set text to null?
 468+ }
 469+
453470 $this->mId = isset( $row['id'] ) ? intval( $row['id'] ) : null;
454471 $this->mPage = isset( $row['page'] ) ? intval( $row['page'] ) : null;
455472 $this->mTextId = isset( $row['text_id'] ) ? intval( $row['text_id'] ) : null;
@@ -462,12 +479,12 @@
463480 $this->mSha1 = isset( $row['sha1'] ) ? strval( $row['sha1'] ) : null;
464481
465482 $this->mContentModelName = isset( $row['content_model'] ) ? strval( $row['content_model'] ) : null;
466 - $this->mContentType = isset( $row['content_type'] ) ? strval( $row['content_type'] ) : null;
 483+ $this->mContentFormat = isset( $row['content_format'] ) ? strval( $row['content_format'] ) : null;
467484
468 - if( !isset( $row->rev_content_type ) || is_null( $row->rev_content_type ) ) {
469 - $this->mContentType = null; # determine on demand if needed
 485+ if( !isset( $row->rev_content_format ) || is_null( $row->rev_content_format ) ) {
 486+ $this->mContentFormat = null; # determine on demand if needed
470487 } else {
471 - $this->mContentType = $row->rev_content_type;
 488+ $this->mContentFormat = $row->rev_content_format;
472489 }
473490
474491 // Enforce spacing trimming on supplied text
@@ -487,11 +504,20 @@
488505 }
489506
490507 $this->getContentModelName(); # force lazy init
491 - $this->getContentType(); # force lazy init
 508+ $this->getContentFormat(); # force lazy init
 509+
 510+ # if we have a content object, serialize it, overriding mText
 511+ if ( !empty( $row['content'] ) ) {
 512+ $handler = $this->getContentHandler();
 513+ $this->mText = $handler->serialize( $row['content'], $this->getContentFormat() );
 514+ }
492515 } else {
493516 throw new MWException( 'Revision constructor passed invalid row format.' );
494517 }
495518 $this->mUnpatrolled = null;
 519+
 520+ #FIXME: add patch for ar_content_format, ar_content_model, rev_content_format, rev_content_model to installer
 521+ #FIXME: add support for ar_content_format, ar_content_model, rev_content_format, rev_content_model to API
496522 }
497523
498524 /**
@@ -755,19 +781,9 @@
756782 */
757783 public function getText( $audience = self::FOR_PUBLIC, User $user = null ) { #FIXME: deprecated, replace usage!
758784 wfDeprecated( __METHOD__, '1.20' );
 785+
759786 $content = $this->getContent();
760 -
761 - if ( $content == null ) {
762 - return ""; # not allowed
763 - }
764 -
765 - if ( $content instanceof TextContent ) {
766 - #FIXME: or check by model name? or define $content->allowRawData()?
767 - return $content->getRawData();
768 - }
769 -
770 - #TODO: log this failure!
771 - return null;
 787+ return ContentHandler::getContentText( $content ); # returns the raw content text, if applicable
772788 }
773789
774790 /**
@@ -818,14 +834,14 @@
819835 // Revision is immutable. Load on demand:
820836
821837 $handler = $this->getContentHandler();
822 - $type = $this->getContentType();
 838+ $format = $this->getContentFormat();
823839
824840 if( is_null( $this->mText ) ) {
825841 // Load text on demand:
826842 $this->mText = $this->loadText();
827843 }
828844
829 - $this->mContent = $handler->unserialize( $this->mText, $type );
 845+ $this->mContent = $handler->unserialize( $this->mText, $format );
830846 }
831847
832848 return $this->mContent;
@@ -840,19 +856,22 @@
841857 return $this->mContentModelName;
842858 }
843859
844 - public function getContentType() {
845 - if ( !$this->mContentType ) {
 860+ public function getContentFormat() {
 861+ if ( !$this->mContentFormat ) {
846862 $handler = $this->getContentHandler();
847 - $this->mContentType = $handler->getDefaultFormat();
 863+ $this->mContentFormat = $handler->getDefaultFormat();
848864 }
849865
850 - return $this->mContentType;
 866+ return $this->mContentFormat;
851867 }
852868
853869 public function getContentHandler() {
854870 if ( !$this->mContentHandler ) {
855871 $m = $this->getModelName();
856872 $this->mContentHandler = ContentHandler::getForModelName( $m );
 873+
 874+ #XXX: do we need to verify that mContentHandler supports mContentFormat?
 875+ # otherwise, a fixed content format may cause problems on insert.
857876 }
858877
859878 return $this->mContentHandler;
@@ -1098,7 +1117,7 @@
10991118 ? Revision::base36Sha1( $this->mText )
11001119 : $this->mSha1,
11011120 'rev_content_model' => $this->getContentModelName(),
1102 - 'rev_content_type' => $this->getContentType(),
 1121+ 'rev_content_format' => $this->getContentFormat(),
11031122 ), __METHOD__
11041123 );
11051124
@@ -1199,7 +1218,7 @@
12001219 $current = $dbw->selectRow(
12011220 array( 'page', 'revision' ),
12021221 array( 'page_latest', 'rev_text_id', 'rev_len', 'rev_sha1',
1203 - 'rev_content_model', 'rev_content_type' ),
 1222+ 'rev_content_model', 'rev_content_format' ),
12041223 array(
12051224 'page_id' => $pageId,
12061225 'page_latest=rev_id',
@@ -1216,7 +1235,7 @@
12171236 'len' => $current->rev_len,
12181237 'sha1' => $current->rev_sha1,
12191238 'content_model' => $current->rev_content_model,
1220 - 'content_type' => $current->rev_content_type
 1239+ 'content_format' => $current->rev_content_format
12211240 ) );
12221241 } else {
12231242 $revision = null;
Index: branches/Wikidata/phase3/includes/WikiPage.php
@@ -161,6 +161,7 @@
162162 'page_touched',
163163 'page_latest',
164164 'page_len',
 165+ 'page_content_model',
165166 );
166167 }
167168
@@ -383,6 +384,23 @@
384385 return null;
385386 }
386387
 388+ /**
 389+ * Get the content of the current revision. No side-effects...
 390+ *
 391+ * @param $audience Integer: one of:
 392+ * Revision::FOR_PUBLIC to be displayed to all users
 393+ * Revision::FOR_THIS_USER to be displayed to $wgUser
 394+ * Revision::RAW get the text regardless of permissions
 395+ * @return String|null The content of the current revision
 396+ */
 397+ public function getContent( $audience = Revision::FOR_PUBLIC ) {
 398+ $this->loadLastEdit();
 399+ if ( $this->mLastRevision ) {
 400+ return $this->mLastRevision->getContent( $audience );
 401+ }
 402+ return false;
 403+ }
 404+
387405 /**
388406 * Get the text of the current revision. No side-effects...
389407 *
@@ -391,8 +409,10 @@
392410 * Revision::FOR_THIS_USER to be displayed to $wgUser
393411 * Revision::RAW get the text regardless of permissions
394412 * @return String|false The text of the current revision
 413+ * @deprecated as of 1.20, getContent() should be used instead.
395414 */
396 - public function getText( $audience = Revision::FOR_PUBLIC ) {
 415+ public function getText( $audience = Revision::FOR_PUBLIC ) { #FIXME: deprecated, replace usage!
 416+ wfDeprecated( __METHOD__, '1.20' );
397417 $this->loadLastEdit();
398418 if ( $this->mLastRevision ) {
399419 return $this->mLastRevision->getText( $audience );
@@ -405,12 +425,8 @@
406426 *
407427 * @return String|false The text of the current revision
408428 */
409 - public function getRawText() {
410 - $this->loadLastEdit();
411 - if ( $this->mLastRevision ) {
412 - return $this->mLastRevision->getRawText();
413 - }
414 - return false;
 429+ public function getRawText() { #FIXME: deprecated, replace usage!
 430+ return $this->getText( Revision::RAW );
415431 }
416432
417433 /**
@@ -1293,7 +1309,7 @@
12941310 'page' => $this->getId(),
12951311 'comment' => $summary,
12961312 'minor_edit' => $isminor,
1297 - 'text' => $text,
 1313+ 'text' => $text, #FIXME: set content instead, leavfe serialization to revision?!
12981314 'parent_id' => $oldid,
12991315 'user' => $user->getId(),
13001316 'user_text' => $user->getName(),
@@ -1963,7 +1979,9 @@
19641980 'ar_len' => 'rev_len',
19651981 'ar_page_id' => 'page_id',
19661982 'ar_deleted' => $bitfield,
1967 - 'ar_sha1' => 'rev_sha1'
 1983+ 'ar_sha1' => 'rev_content_model',
 1984+ 'ar_content_format' => 'rev_content_format',
 1985+ 'ar_content_format' => 'rev_sha1'
19681986 ), array(
19691987 'page_id' => $id,
19701988 'page_id = rev_page'
Index: branches/Wikidata/phase3/includes/specials/SpecialUndelete.php
@@ -116,7 +116,8 @@
117117 $res = $dbr->select( 'archive',
118118 array(
119119 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text',
120 - 'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id', 'ar_sha1'
 120+ 'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id', 'ar_sha1',
 121+ 'ar_content_format', 'ar_content_model'
121122 ),
122123 array( 'ar_namespace' => $this->title->getNamespace(),
123124 'ar_title' => $this->title->getDBkey() ),
@@ -189,6 +190,8 @@
190191 'ar_deleted',
191192 'ar_len',
192193 'ar_sha1',
 194+ 'ar_content_format',
 195+ 'ar_content_model',
193196 ),
194197 array( 'ar_namespace' => $this->title->getNamespace(),
195198 'ar_title' => $this->title->getDBkey(),
@@ -463,7 +466,9 @@
464467 'ar_deleted',
465468 'ar_page_id',
466469 'ar_len',
467 - 'ar_sha1' ),
 470+ 'ar_sha1',
 471+ 'ar_content_format',
 472+ 'ar_content_model' ),
468473 /* WHERE */ array(
469474 'ar_namespace' => $this->title->getNamespace(),
470475 'ar_title' => $this->title->getDBkey(),

Status & tagging log