r114425 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r114424‎ | r114425 | r114426 >
Date:17:43, 22 March 2012
Author:daniel
Status:deferred
Tags:
Comment:
reworking EditPage to use the content object - work in horrible progress
Modified paths:
  • /branches/Wikidata/phase3/includes/Content.php (modified) (history)
  • /branches/Wikidata/phase3/includes/ContentHandler.php (modified) (history)
  • /branches/Wikidata/phase3/includes/EditPage.php (modified) (history)
  • /branches/Wikidata/phase3/includes/WikiPage.php (modified) (history)
  • /branches/Wikidata/phase3/includes/diff/DifferenceEngine.php (modified) (history)

Diff [purge]

Index: branches/Wikidata/phase3/includes/diff/DifferenceEngine.php
@@ -926,7 +926,7 @@
927927 /**
928928 * Use specified text instead of loading from the database
929929 */
930 - function setText( $oldText, $newText ) {
 930+ function setText( $oldText, $newText ) { #FIXME: deprecate, use Content objects instead!
931931 $this->mOldtext = $oldText;
932932 $this->mNewtext = $newText;
933933 $this->mTextLoaded = 2;
Index: branches/Wikidata/phase3/includes/Content.php
@@ -24,10 +24,25 @@
2525 return $this->getContentHandler()->serialize( $this, $format );
2626 }
2727
 28+ /**
 29+ * @return String a string representing the content in a way useful for building a full text search index.
 30+ * If no useful representation exists, this method returns an empty string.
 31+ */
2832 public abstract function getTextForSearchIndex( );
2933
30 - public abstract function getWikitextForTransclusion( );
 34+ /**
 35+ * @return String the wikitext to include when another page includes this content, or false if the content is not
 36+ * includable in a wikitext page.
 37+ */
 38+ #TODO: allow native handling, bypassing wikitext representation, like for includable special pages.
 39+ public abstract function getWikitextForTransclusion( ); #FIXME: use in parser, etc!
3140
 41+ /**
 42+ * Returns a textual representation of the content suitable for use in edit summaries and log messages.
 43+ *
 44+ * @param int $maxlength maximum length of the summary text
 45+ * @return String the summary text
 46+ */
3247 public abstract function getTextForSummary( $maxlength = 250 );
3348
3449 /**
@@ -67,16 +82,50 @@
6883 */
6984 public abstract function isCountable( $hasLinks = null ) ;
7085
 86+ /**
 87+ * @param null|Title $title
 88+ * @param null $revId
 89+ * @param null|ParserOptions $options
 90+ * @return ParserOutput
 91+ */
7192 public abstract function getParserOutput( Title $title = null, $revId = null, ParserOptions $options = NULL );
7293
73 - public function getRedirectChain() { #TODO: document!
 94+ /**
 95+ * Construct the redirect destination from this content and return an
 96+ * array of Titles, or null if this content doesn't represent a redirect.
 97+ * The last element in the array is the final destination after all redirects
 98+ * have been resolved (up to $wgMaxRedirects times).
 99+ *
 100+ * @return Array of Titles, with the destination last
 101+ */
 102+ public function getRedirectChain() {
74103 return null;
75104 }
76105
 106+ /**
 107+ * Construct the redirect destination from this content and return an
 108+ * array of Titles, or null if this content doesn't represent a redirect.
 109+ * This will only return the immediate redirect target, useful for
 110+ * the redirect table and other checks that don't need full recursion.
 111+ *
 112+ * @return Title: The corresponding Title
 113+ */
77114 public function getRedirectTarget() {
78115 return null;
79116 }
80117
 118+ /**
 119+ * Construct the redirect destination from this content and return the
 120+ * Title, or null if this content doesn't represent a redirect.
 121+ * This will recurse down $wgMaxRedirects times or until a non-redirect target is hit
 122+ * in order to provide (hopefully) the Title of the final destination instead of another redirect.
 123+ *
 124+ * @return Title
 125+ */
 126+ public function getUltimateRedirectTarget() {
 127+ return null;
 128+ }
 129+
81130 public function isRedirect() {
82131 return $this->getRedirectTarget() != null;
83132 }
@@ -117,6 +166,17 @@
118167 return $this;
119168 }
120169
 170+ /**
 171+ * Returns a Content object with preload transformations applied (or this object if no transformations apply).
 172+ *
 173+ * @param Title $title
 174+ * @param null|ParserOptions $popts
 175+ * @return Content
 176+ */
 177+ public function preloadTransform( Title $title, ParserOptions $popts = null ) {
 178+ return $this;
 179+ }
 180+
121181 #TODO: implement specialized ParserOutput for Wikidata model
122182 #TODO: provide "combined" ParserOutput for Multipart... somehow.
123183
@@ -124,7 +184,6 @@
125185
126186 # TODO: EditPage::getPreloadedText( $preload ) // $wgParser->getPreloadText
127187 # TODO: tie into EditPage, make it use Content-objects throughout, make edit form aware of content model and format
128 - # TODO: tie into WikiPage, make it use Content-objects throughout, especially in doEditUpdates(), doDelete(), updateRevisionOn(), etc
129188 # TODO: make model-aware diff view!
130189 # TODO: handle ImagePage and CategoryPage
131190
@@ -340,12 +399,32 @@
341400 public function preSaveTransform( Title $title, User $user, ParserOptions $popts = null ) {
342401 global $wgParser;
343402
 403+ if ( $popts == null ) $popts = $this->getDefaultParserOptions();
 404+
344405 $text = $this->getNativeData();
345406 $pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
346407
347408 return new WikitextContent( $pst );
348409 }
349410
 411+ /**
 412+ * Returns a Content object with preload transformations applied (or this object if no transformations apply).
 413+ *
 414+ * @param Title $title
 415+ * @param null|ParserOptions $popts
 416+ * @return Content
 417+ */
 418+ public function preloadTransform( Title $title, ParserOptions $popts = null ) {
 419+ global $wgParser;
 420+
 421+ if ( $popts == null ) $popts = $this->getDefaultParserOptions();
 422+
 423+ $text = $this->getNativeData();
 424+ $plt = $wgParser->getPreloadText( $text, $title, $popts );
 425+
 426+ return new WikitextContent( $plt );
 427+ }
 428+
350429 public function getRedirectChain() {
351430 $text = $this->getNativeData();
352431 return Title::newFromRedirectArray( $text );
@@ -356,6 +435,11 @@
357436 return Title::newFromRedirect( $text );
358437 }
359438
 439+ public function getUltimateRedirectTarget() {
 440+ $text = $this->getNativeData();
 441+ return Title::newFromRedirectRecurse( $text );
 442+ }
 443+
360444 /**
361445 * Returns true if this content is not a redirect, and this content's text is countable according to
362446 * the criteria defiend by $wgArticleCountMethod.
@@ -405,7 +489,7 @@
406490
407491 class MessageContent extends TextContent {
408492 public function __construct( $msg_key, $params = null, $options = null ) {
409 - parent::__construct(null, CONTENT_MODEL_WIKITEXT);
 493+ parent::__construct(null, CONTENT_MODEL_WIKITEXT); #XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
410494
411495 $this->mMessageKey = $msg_key;
412496
Index: branches/Wikidata/phase3/includes/ContentHandler.php
@@ -213,7 +213,7 @@
214214 }
215215 **/
216216
217 - public function getDiffEngine( Article $article ) {
 217+ public function getDiffEngine( Article $article ) { #FIXME: change interface of diff engine? or accept content objects here=?
218218 $de = new DifferenceEngine( $article->getContext() );
219219 return $de;
220220 }
Index: branches/Wikidata/phase3/includes/EditPage.php
@@ -192,6 +192,7 @@
193193 var $textbox1 = '', $textbox2 = '', $summary = '', $nosummary = false;
194194 var $edittime = '', $section = '', $sectiontitle = '', $starttime = '';
195195 var $oldid = 0, $editintro = '', $scrolltop = null, $bot = true;
 196+ var $content_model = null, $content_format = null;
196197
197198 # Placeholders for text injection by hooks (must be HTML)
198199 # extensions should take care to _append_ to the present value
@@ -203,7 +204,7 @@
204205 public $editFormTextBottom = '';
205206 public $editFormTextAfterContent = '';
206207 public $previewTextAfterContent = '';
207 - public $mPreloadText = '';
 208+ public $mPreloadContent = null;
208209
209210 /* $didSave should be set to true whenever an article was succesfully altered. */
210211 public $didSave = false;
@@ -217,6 +218,11 @@
218219 public function __construct( Article $article ) {
219220 $this->mArticle = $article;
220221 $this->mTitle = $article->getTitle();
 222+
 223+ $this->content_model = $this->mTitle->getContentModelName();
 224+
 225+ $handler = ContentHandler::getForModelName( $this->content_model );
 226+ $this->content_format = $handler->getDefaultFormat(); #NOTE: should be overridden by format of actual revision
221227 }
222228
223229 /**
@@ -428,10 +434,10 @@
429435 return;
430436 }
431437
432 - $content = $this->getContent();
 438+ $content = $this->getContentObject();
433439
434440 # Use the normal message if there's nothing to display
435 - if ( $this->firsttime && $content === '' ) {
 441+ if ( $this->firsttime && $content->isEmpty() ) {
436442 $action = $this->mTitle->exists() ? 'edit' :
437443 ( $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage' );
438444 throw new PermissionsError( $action, $permErrors );
@@ -445,13 +451,18 @@
446452 # If the user made changes, preserve them when showing the markup
447453 # (This happens when a user is blocked during edit, for instance)
448454 if ( !$this->firsttime ) {
449 - $content = $this->textbox1;
 455+ $handler = ContentHandler::getForModelName( $this->content_model );
 456+
 457+ if ( empty( $this->textbox1 ) ) $content = $handler->emptyContent();
 458+ else $content = $handler->unserialize( $this->textbox1 );
 459+
450460 $wgOut->addWikiMsg( 'viewyourtext' );
451461 } else {
452462 $wgOut->addWikiMsg( 'viewsourcetext' );
453463 }
454464
455 - $this->showTextbox( $content, 'wpTextbox1', array( 'readonly' ) );
 465+ $text = $content->serialize( $this->content_format );
 466+ $this->showTextbox( $text, 'wpTextbox1', array( 'readonly' ) );
456467
457468 $wgOut->addHTML( Html::rawElement( 'div', array( 'class' => 'templatesUsed' ),
458469 Linker::formatTemplates( $this->getTemplates() ) ) );
@@ -563,9 +574,9 @@
564575 // from a conflict page with raw page text, not a custom form
565576 // modified by subclasses
566577 wfProfileIn( get_class($this)."::importContentFormData" );
567 - $textbox1 = $this->importContentFormData( $request );
 578+ $textbox1 = $this->importContentFormData( $request ); #FIXME: what should this return??
568579 if ( isset($textbox1) )
569 - $this->textbox1 = $textbox1;
 580+ $this->textbox1 = $textbox1; #XXX: unserialize to Content-object... when?
570581 wfProfileOut( get_class($this)."::importContentFormData" );
571582 }
572583
@@ -657,7 +668,7 @@
658669 } else {
659670 # Not a posted form? Start with nothing.
660671 wfDebug( __METHOD__ . ": Not a posted form.\n" );
661 - $this->textbox1 = '';
 672+ $this->textbox1 = ''; #FIXME: track content object
662673 $this->summary = '';
663674 $this->sectiontitle = '';
664675 $this->edittime = '';
@@ -686,10 +697,14 @@
687698 }
688699 }
689700
 701+ $this->oldid = $request->getInt( 'oldid' );
 702+
690703 $this->bot = $request->getBool( 'bot', true );
691704 $this->nosummary = $request->getBool( 'nosummary' );
692705
693 - $this->oldid = $request->getInt( 'oldid' );
 706+ $content_handler = ContentHandler::getForTitle( $this->mTitle );
 707+ $this->content_model = $request->getText( 'model', $content_handler->getModelName() ); #may be overridden by revision
 708+ $this->content_format = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision
694709
695710 $this->live = $request->getCheck( 'live' );
696711 $this->editintro = $request->getText( 'editintro',
@@ -722,7 +737,10 @@
723738 function initialiseForm() {
724739 global $wgUser;
725740 $this->edittime = $this->mArticle->getTimestamp();
726 - $this->textbox1 = $this->getContent( false );
 741+
 742+ $content = $this->getContentObject( false ); #TODO: track content object?!
 743+ $this->textbox1 = $content->serialize( $this->content_format );
 744+
727745 // activate checkboxes if user wants them to be always active
728746 # Sort out the "watch" checkbox
729747 if ( $wgUser->getOption( 'watchdefault' ) ) {
@@ -751,33 +769,52 @@
752770 * @param $def_text string
753771 * @return mixed string on success, $def_text for invalid sections
754772 * @private
 773+ * @deprecated since 1.20
755774 */
756 - function getContent( $def_text = '' ) {
757 - global $wgOut, $wgRequest, $wgParser;
 775+ function getContent( $def_text = false ) { #FIXME: deprecated, replace usage!
 776+ if ( $def_text !== null && $def_text !== false && $def_text !== '' ) {
 777+ $def_content = ContentHandler::makeContent( $def_text, $this->getTitle() );
 778+ } else {
 779+ $def_content = false;
 780+ }
758781
 782+ $content = $this->getContentObject( $def_content );
 783+
 784+ return $content->serialize( $this->content_format ); #XXX: really use serialized form? use ContentHandler::getContentText() instead?
 785+ }
 786+
 787+ private function getContentObject( $def_content = null ) { #FIXME: use this!
 788+ global $wgOut, $wgRequest;
 789+
759790 wfProfileIn( __METHOD__ );
760791
761 - $text = false;
 792+ $content = false;
762793
763794 // For message page not locally set, use the i18n message.
764795 // For other non-existent articles, use preload text if any.
765796 if ( !$this->mTitle->exists() || $this->section == 'new' ) {
766797 if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI && $this->section != 'new' ) {
767798 # If this is a system message, get the default text.
768 - $text = $this->mTitle->getDefaultMessageText();
 799+ $msg = $this->mTitle->getDefaultMessageText();
 800+
 801+ $content = new WikitextContent($msg); //XXX: really hardcode wikitext here?
769802 }
770 - if ( $text === false ) {
 803+ if ( $content === false ) {
771804 # If requested, preload some text.
772805 $preload = $wgRequest->getVal( 'preload',
773806 // Custom preload text for new sections
774807 $this->section === 'new' ? 'MediaWiki:addsection-preload' : '' );
775 - $text = $this->getPreloadedText( $preload );
 808+
 809+ $content = $this->getPreloadedContent( $preload );
776810 }
777811 // For existing pages, get text based on "undo" or section parameters.
778812 } else {
779813 if ( $this->section != '' ) {
780814 // Get section edit text (returns $def_text for invalid sections)
781 - $text = $wgParser->getSection( $this->getOriginalContent(), $this->section, $def_text );
 815+ $orig = $this->getOriginalContent();
 816+ $content = $orig ? $orig->getSection( $this->section ) : null;
 817+
 818+ if ( !$content ) $content = $def_content;
782819 } else {
783820 $undoafter = $wgRequest->getInt( 'undoafter' );
784821 $undo = $wgRequest->getInt( 'undo' );
@@ -793,15 +830,16 @@
794831
795832 # Sanity check, make sure it's the right page,
796833 # the revisions exist and they were not deleted.
797 - # Otherwise, $text will be left as-is.
 834+ # Otherwise, $content will be left as-is.
798835 if ( !is_null( $undorev ) && !is_null( $oldrev ) &&
799836 $undorev->getPage() == $oldrev->getPage() &&
800837 $undorev->getPage() == $this->mTitle->getArticleId() &&
801838 !$undorev->isDeleted( Revision::DELETED_TEXT ) &&
802839 !$oldrev->isDeleted( Revision::DELETED_TEXT ) ) {
803840
804 - $text = $this->mArticle->getUndoText( $undorev, $oldrev );
805 - if ( $text === false ) {
 841+ $content = $this->mArticle->getUndoContent( $undorev, $oldrev );
 842+
 843+ if ( $content === false ) {
806844 # Warn the user that something went wrong
807845 $undoMsg = 'failure';
808846 } else {
@@ -832,14 +870,14 @@
833871 wfMsgNoTrans( 'undo-' . $undoMsg ) . '</div>', true, /* interface */true );
834872 }
835873
836 - if ( $text === false ) {
837 - $text = $this->getOriginalContent();
 874+ if ( $content === false ) {
 875+ $content = $this->getOriginalContent();
838876 }
839877 }
840878 }
841879
842880 wfProfileOut( __METHOD__ );
843 - return $text;
 881+ return $content;
844882 }
845883
846884 /**
@@ -856,33 +894,45 @@
857895 * @since 1.19
858896 * @return string
859897 */
860 - private function getOriginalContent() {
 898+ private function getOriginalContent() { #FIXME: use Content! set content_model and content_format!
861899 if ( $this->section == 'new' ) {
862 - return $this->getCurrentText();
 900+ return $this->getCurrentContent();
863901 }
864902 $revision = $this->mArticle->getRevisionFetched();
865903 if ( $revision === null ) {
866 - return '';
 904+ if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModelName();
 905+ $handler = ContentHandler::getForModelName( $this->content_model );
 906+
 907+ return $handler->emptyContent();
867908 }
868909
869910 $content = $this->mArticle->getContentObject();
870 - return ContentHandler::getContentText( $content ); # this editor is for editing the raw text. so use the raw text.
 911+ return $content;
871912 }
872913
873914 /**
874 - * Get the actual text of the page. This is basically similar to
875 - * WikiPage::getRawText() except that when the page doesn't exist an empty
876 - * string is returned instead of false.
 915+ * Get the current content of the page. This is basically similar to
 916+ * WikiPage::getContent( Revision::RAW ) except that when the page doesn't exist an empty
 917+ * content object is returned instead of null.
877918 *
878 - * @since 1.19
 919+ * @since 1.20
879920 * @return string
880921 */
881 - private function getCurrentText() {
882 - $text = $this->mArticle->getRawText();
883 - if ( $text === false ) {
884 - return '';
 922+ private function getCurrentContent() {
 923+ $rev = $this->mArticle->getRevision();
 924+ $content = $rev->getContentObject( Revision::RAW );
 925+
 926+ if ( $content === false || $content === null ) {
 927+ if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModelName();
 928+ $handler = ContentHandler::getForModelName( $this->content_model );
 929+
 930+ return $handler->emptyContent();
885931 } else {
886 - return $text;
 932+ #FIXME: nasty side-effect!
 933+ $this->content_model = $rev->getContentModelName();
 934+ $this->content_format = $rev->getContentFormat();
 935+
 936+ return $content;
887937 }
888938 }
889939
@@ -890,33 +940,59 @@
891941 * Use this method before edit() to preload some text into the edit box
892942 *
893943 * @param $text string
 944+ * @deprecated since 1.20
894945 */
895 - public function setPreloadedText( $text ) {
896 - $this->mPreloadText = $text;
 946+ public function setPreloadedText( $text ) { #FIXME: deprecated, use setPreloadedContent()
 947+ wfDeprecated( __METHOD__, "1.20" );
 948+
 949+ $content = ContentHandler::makeContent( $text, $this->getTitle() );
 950+
 951+ $this->setPreloadedContent( $content );
897952 }
898953
 954+ /**
 955+ * Use this method before edit() to preload some content into the edit box
 956+ *
 957+ * @param $content Content
 958+ */
 959+ public function setPreloadedContent( Content $content ) { #FIXME: use this!
 960+ $this->mPreloadedContent = $content;
 961+ }
 962+
899963 /**
900964 * Get the contents to be preloaded into the box, either set by
901965 * an earlier setPreloadText() or by loading the given page.
902966 *
903967 * @param $preload String: representing the title to preload from.
904968 * @return String
 969+ * @deprecated since 1.20
905970 */
906 - protected function getPreloadedText( $preload ) { #FIXME: change to getPreloadedContent()
907 - global $wgUser, $wgParser;
 971+ protected function getPreloadedText( $preload ) { #FIXME: B/C only, replace usage!
 972+ wfDeprecated( __METHOD__, "1.20" );
908973
909 - if ( !empty( $this->mPreloadText ) ) {
910 - return $this->mPreloadText;
 974+ $content = $this->getPreloadedContent( $preload );
 975+ $text = $content->serialize( $this->content_format ); #XXX: really use serialized form? use ContentHandler::getContentText() instead?!
 976+
 977+ return $text;
 978+ }
 979+
 980+ protected function getPreloadedContent( $preload ) { #FIXME: use this!
 981+ global $wgUser;
 982+
 983+ if ( !empty( $this->mPreloadContent ) ) {
 984+ return $this->mPreloadContent;
911985 }
 986+
 987+ $handler = ContentHandler::getForTitle( $this->getTitle() );
912988
913989 if ( $preload === '' ) {
914 - return '';
 990+ return $handler->emptyContent();
915991 }
916992
917993 $title = Title::newFromText( $preload );
918994 # Check for existence to avoid getting MediaWiki:Noarticletext
919995 if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
920 - return '';
 996+ return $handler->emptyContent();
921997 }
922998
923999 $page = WikiPage::factory( $title );
@@ -924,13 +1000,15 @@
9251001 $title = $page->getRedirectTarget();
9261002 # Same as before
9271003 if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
928 - return '';
 1004+ return $handler->emptyContent();
9291005 }
9301006 $page = WikiPage::factory( $title );
9311007 }
9321008
9331009 $parserOptions = ParserOptions::newFromUser( $wgUser );
934 - return $wgParser->getPreloadText( $page->getRawText(), $title, $parserOptions ); #FIXME: create Content::getPreloadCopy
 1010+ $content = $page->getContent( Revision::RAW );
 1011+
 1012+ return $content->preloadTransform( $title, $parserOptions );
9351013 }
9361014
9371015 /**
@@ -1227,12 +1305,14 @@
12281306 }
12291307 }
12301308
1231 - $text = $this->textbox1;
 1309+ $content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format );
 1310+
12321311 $result['sectionanchor'] = '';
12331312 if ( $this->section == 'new' ) {
 1313+ .........FIXME...............
12341314 if ( $this->sectiontitle !== '' ) {
12351315 // Insert the section title above the content.
1236 - $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $text;
 1316+ $T_E_X_T = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $T_E_X_T;
12371317
12381318 // Jump to the new section
12391319 $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
@@ -1246,7 +1326,7 @@
12471327 }
12481328 } elseif ( $this->summary !== '' ) {
12491329 // Insert the section title above the content.
1250 - $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->summary ) . "\n\n" . $text;
 1330+ $T_E_X_T = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->summary ) . "\n\n" . $T_E_X_T;
12511331
12521332 // Jump to the new section
12531333 $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
@@ -1299,24 +1379,24 @@
13001380
13011381 if ( $this->isConflict ) {
13021382 wfDebug( __METHOD__ . ": conflict! getting section '$this->section' for time '$this->edittime' (article time '{$timestamp}')\n" );
1303 - $text = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle, $this->edittime ); #FIXME: use Content object throughout, make edit form aware of content model and serialization format
 1383+ $T_E_X_T = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle, $this->edittime ); #FIXME: use Content object throughout, make edit form aware of content model and serialization format
13041384 } else {
13051385 wfDebug( __METHOD__ . ": getting section '$this->section'\n" );
1306 - $text = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle ); #FIXME: use Content object throughout, make edit form aware of content model and serialization format
 1386+ $T_E_X_T = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle ); #FIXME: use Content object throughout, make edit form aware of content model and serialization format
13071387 }
1308 - if ( is_null( $text ) ) {
 1388+ if ( is_null( $T_E_X_T ) ) {
13091389 wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" );
13101390 $this->isConflict = true;
1311 - $text = $this->textbox1; // do not try to merge here! #FIXME: unserialize Content
 1391+ $T_E_X_T = $this->textbox1; // do not try to merge here! #FIXME: unserialize Content
13121392 } elseif ( $this->isConflict ) {
13131393 # Attempt merge
1314 - if ( $this->mergeChangesInto( $text ) ) { #FIXME: passe/receive Content object
 1394+ if ( $this->mergeChangesInto( $T_E_X_T ) ) { #FIXME: passe/receive Content object
13151395 // Successful merge! Maybe we should tell the user the good news?
13161396 $this->isConflict = false;
13171397 wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" );
13181398 } else {
13191399 $this->section = '';
1320 - $this->textbox1 = $text;
 1400+ $this->textbox1 = $T_E_X_T;
13211401 wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" );
13221402 }
13231403 }
@@ -1328,7 +1408,7 @@
13291409 }
13301410
13311411 // Run post-section-merge edit filter
1332 - if ( !wfRunHooks( 'EditFilterMerged', array( $this, $text, &$this->hookError, $this->summary ) ) ) {
 1412+ if ( !wfRunHooks( 'EditFilterMerged', array( $this, $T_E_X_T, &$this->hookError, $this->summary ) ) ) {
13331413 # Error messages etc. could be handled within the hook...
13341414 $status->fatal( 'hookaborted' );
13351415 $status->value = self::AS_HOOK_ERROR;
@@ -1344,8 +1424,8 @@
13451425
13461426 # Handle the user preference to force summaries here, but not for null edits
13471427 if ( $this->section != 'new' && !$this->allowBlankSummary
1348 - && $this->getOriginalContent() != $text
1349 - && !Title::newFromRedirect( $text ) ) # check if it's not a redirect
 1428+ && $this->getOriginalContent()... != $T_E_X_T
 1429+ && !Title::newFromRedirect( $T_E_X_T ) ) # check if it's not a redirect
13501430 {
13511431 if ( md5( $this->summary ) == $this->autoSumm ) {
13521432 $this->missingSummary = true;
@@ -1413,14 +1493,14 @@
14141494 // merged the section into full text. Clear the section field
14151495 // so that later submission of conflict forms won't try to
14161496 // replace that into a duplicated mess.
1417 - $this->textbox1 = $text;
 1497+ $this->textbox1 = $T_E_X_T;
14181498 $this->section = '';
14191499
14201500 $status->value = self::AS_SUCCESS_UPDATE;
14211501 }
14221502
14231503 // Check for length errors again now that the section is merged in
1424 - $this->kblength = (int)( strlen( $text ) / 1024 );
 1504+ $this->kblength = (int)( strlen( $T_E_X_T ) / 1024 );
14251505 if ( $this->kblength > $wgMaxArticleSize ) {
14261506 $this->tooBig = true;
14271507 $status->setResult( false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED );
@@ -1433,10 +1513,10 @@
14341514 ( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) |
14351515 ( $bot ? EDIT_FORCE_BOT : 0 );
14361516
1437 - $doEditStatus = $this->mArticle->doEdit( $text, $this->summary, $flags ); # FIXME: use WikiPage::doEditContent()
 1517+ $doEditStatus = $this->mArticle->doEdit( $T_E_X_T, $this->summary, $flags ); # FIXME: use WikiPage::doEditContent()
14381518
14391519 if ( $doEditStatus->isOK() ) {
1440 - $result['redirect'] = Title::newFromRedirect( $text ) !== null;
 1520+ $result['redirect'] = Title::newFromRedirect( $T_E_X_T ) !== null;
14411521 $this->commitWatch();
14421522 wfProfileOut( __METHOD__ );
14431523 return $status;
@@ -1524,11 +1604,11 @@
15251605 $currentContent = $currentRevision->getContent();
15261606
15271607 $handler = ContentHandler::getForModelName( $baseContent->getModelName() );
1528 - $editContent = $handler->unserialize( $editText ); #FIXME: supply serialization fomrat from edit form!
 1608+ $editContent = $handler->unserialize( $editText, $this->content_format ); #FIXME: supply serialization fomrat from edit form!
15291609
15301610 $result = $handler->merge3( $baseContent, $editContent, $currentContent );
15311611 if ( $result ) {
1532 - $editText = ContentHandler::getContentText($result); #FIXME: supply serialization fomrat from edit form!
 1612+ $editText = ContentHandler::getContentText($result, $this->content_format ); #FIXME: supply serialization fomrat from edit form!
15331613 wfProfileOut( __METHOD__ );
15341614 return true;
15351615 } else {
@@ -1822,8 +1902,10 @@
18231903 // resolved between page source edits and custom ui edits using the
18241904 // custom edit ui.
18251905 $this->textbox2 = $this->textbox1;
1826 - $this->textbox1 = $this->getCurrentText();
18271906
 1907+ $content = $this->getCurrentContent();
 1908+ $this->textbox1 = $content->serialize( $this->content_format );
 1909+
18281910 $this->showTextbox1();
18291911 } else {
18301912 $this->showContentForm();
@@ -1857,7 +1939,7 @@
18581940
18591941 $wgOut->addHTML( $this->editFormTextBottom . "\n</form>\n" );
18601942
1861 - if ( !$wgUser->getOption( 'previewontop' ) ) {
 1943+ if ( !$wgUser->getOption( 'previewontop' ) ) {
18621944 $this->displayPreviewArea( $previewOutput, false );
18631945 }
18641946
@@ -2230,10 +2312,10 @@
22312313 $this->showTextbox( $this->textbox2, 'wpTextbox2', array( 'tabindex' => 6, 'readonly' ) );
22322314 }
22332315
2234 - protected function showTextbox( $content, $name, $customAttribs = array() ) {
 2316+ protected function showTextbox( $text, $name, $customAttribs = array() ) {
22352317 global $wgOut, $wgUser;
22362318
2237 - $wikitext = $this->safeUnicodeOutput( $content );
 2319+ $wikitext = $this->safeUnicodeOutput( $text );
22382320 if ( strval($wikitext) !== '' ) {
22392321 // Ensure there's a newline at the end, otherwise adding lines
22402322 // is awkward.
@@ -2309,23 +2391,38 @@
23102392 * save and then make a comparison.
23112393 */
23122394 function showDiff() {
2313 - global $wgUser, $wgContLang, $wgParser, $wgOut;
 2395+ global $wgUser, $wgContLang, $wgOut;
23142396
2315 - $oldtext = $this->getOriginalContent();
2316 - $newtext = $this->mArticle->replaceSection(
2317 - $this->section, $this->textbox1, $this->summary, $this->edittime ); #FIXME: use Content::replaceSection
 2397+ $oldContent = $this->getOriginalContent();
23182398
 2399+ $textboxContent = ContentHandler::makeContent( $this->textbox1, $this->getTitle(),
 2400+ $this->content_model, $this->content_format );
 2401+
 2402+ $newContent = $this->mArticle->replaceSectionContent(
 2403+ $this->section, $textboxContent,
 2404+ $this->summary, $this->edittime );
 2405+
 2406+ # hanlde legacy text-based hook
 2407+ $newtext_orig = $newContent->serialize( $this->content_format );
 2408+ $newtext = $newtext_orig; #clone
23192409 wfRunHooks( 'EditPageGetDiffText', array( $this, &$newtext ) );
23202410
 2411+ if ( $newtext != $newtext_orig ) {
 2412+ #if the hook changed the text, create a new Content object accordingly.
 2413+ $newContent = ContentHandler::makeContent( $newtext, $this->getTitle(), $newContent->getModelName() );
 2414+ }
 2415+
 2416+ wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) ); #FIXME: document new hook
 2417+
23212418 $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
2322 - $newtext = $wgParser->preSaveTransform( $newtext, $this->mTitle, $wgUser, $popts );
 2419+ $newContent = $newContent->preSaveTransform( $this->mTitle, $wgUser, $popts );
23232420
2324 - if ( $oldtext !== false || $newtext != '' ) {
 2421+ if ( ( $oldContent && !$oldContent->isEmpty() ) || ( $newContent && !$newContent->isEmpty() ) ) {
23252422 $oldtitle = wfMsgExt( 'currentrev', array( 'parseinline' ) );
23262423 $newtitle = wfMsgExt( 'yourtext', array( 'parseinline' ) );
23272424
23282425 $de = new DifferenceEngine( $this->mArticle->getContext() );
2329 - $de->setText( $oldtext, $newtext );
 2426+ $de->setText( $oldContent, $newContent ); #FIXME: content-based diff!
23302427 $difftext = $de->getDiff( $oldtitle, $newtitle );
23312428 $de->showDiffStyle();
23322429 } else {
@@ -3043,10 +3140,12 @@
30443141 $wgOut->addHTML( '</div>' );
30453142
30463143 $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
3047 - $de = new DifferenceEngine( $this->mArticle->getContext() );
3048 - $de->setText( $this->getCurrentText(), $this->textbox2 );
3049 - $de->showDiff( wfMsg( "storedversion" ), wfMsgExt( 'yourtext', 'parseinline' ) );
 3144+ $de = new DifferenceEngine( $this->mArticle->getContext() ); #FIXME: get from content handler!
30503145
 3146+ $de->setText( $this->getCurrentText(), $this->textbox2 ); #FIXME: make Content based
 3147+
 3148+ $de->showDiff( wfMsg( "storedversion" ), wfMsgExt( 'yourtext', 'parseinline' ) );
 3149+
30513150 $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourtext" );
30523151 $this->showTextbox2();
30533152
Index: branches/Wikidata/phase3/includes/WikiPage.php
@@ -632,7 +632,8 @@
633633 */
634634 public function insertRedirect() {
635635 // recurse through to only get the final target
636 - $retval = Title::newFromRedirectRecurse( $this->getRawText() ); #FIXME: move this to Content object
 636+ $content = $this->getContent();
 637+ $retval = $content ? $content->getUltimateRedirectTarget() : null;
637638 if ( !$retval ) {
638639 return null;
639640 }
@@ -983,9 +984,9 @@
984985 public function updateRevisionOn( $dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null ) {
985986 wfProfileIn( __METHOD__ );
986987
987 - $text = $revision->getText();
988 - $len = strlen( $text );
989 - $rt = Title::newFromRedirectRecurse( $text );
 988+ $content = $revision->getContent();
 989+ $len = $content->getSize();
 990+ $rt = $content->getUltimateRedirectTarget();
990991
991992 $conditions = array( 'page_id' => $this->getId() );
992993
@@ -1129,45 +1130,53 @@
11301131 * @param $sectionTitle String: new section's subject, only if $section is 'new'
11311132 * @param $edittime String: revision timestamp or null to use the current revision
11321133 * @return Content new complete article content, or null if error
1133 - * @deprecated since 1.20: use Content::replaceSection () instead.
 1134+ * @deprected since 1.20, use replaceSectionContent() instead
11341135 */
1135 - public function replaceSection( $section, $text, $sectionTitle = '', $edittime = null ) { #FIXME: create a Content-based version (take and return Content object)
1136 - wfProfileIn( __METHOD__ );
 1136+ public function replaceSection( $section, $text, $sectionTitle = '', $edittime = null ) { #FIXME: use replaceSectionContent() instead!
 1137+ wfDeprecated( __METHOD__, '1.20' );
11371138
11381139 $sectionContent = ContentHandler::makeContent( $text, $this->getTitle() ); #XXX: could make section title, but that's not required.
11391140
1140 - if ( strval( $section ) == '' ) {
1141 - // Whole-page edit; let the whole text through
 1141+ $newContent = $this->replaceSectionContent( $section, $sectionContent, $sectionTitle, $edittime );
 1142+
 1143+ return ContentHandler::getContentText( $newContent ); #XXX: unclear what will happen for non-wikitext!
 1144+ }
 1145+
 1146+ public function replaceSectionContent( $section, $sectionContent, $sectionTitle = '', $edittime = null ) {
 1147+ wfProfileIn( __METHOD__ );
 1148+
 1149+ if ( strval( $section ) == '' ) {
 1150+ // Whole-page edit; let the whole text through
11421151 $newContent = $sectionContent;
1143 - } else {
1144 - // Bug 30711: always use current version when adding a new section
1145 - if ( is_null( $edittime ) || $section == 'new' ) {
1146 - $oldContent = $this->getContent();
1147 - if ( ! $oldContent ) {
1148 - wfDebug( __METHOD__ . ": no page text\n" );
1149 - wfProfileOut( __METHOD__ );
1150 - return null;
1151 - }
1152 - } else {
1153 - $dbw = wfGetDB( DB_MASTER );
1154 - $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
 1152+ } else {
 1153+ // Bug 30711: always use current version when adding a new section
 1154+ if ( is_null( $edittime ) || $section == 'new' ) {
 1155+ $oldContent = $this->getContent();
 1156+ if ( ! $oldContent ) {
 1157+ wfDebug( __METHOD__ . ": no page text\n" );
 1158+ wfProfileOut( __METHOD__ );
 1159+ return null;
 1160+ }
 1161+ } else {
 1162+ $dbw = wfGetDB( DB_MASTER );
 1163+ $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
11551164
1156 - if ( !$rev ) {
1157 - wfDebug( "WikiPage::replaceSection asked for bogus section (page: " .
1158 - $this->getId() . "; section: $section; edittime: $edittime)\n" );
1159 - wfProfileOut( __METHOD__ );
1160 - return null;
1161 - }
 1165+ if ( !$rev ) {
 1166+ wfDebug( "WikiPage::replaceSection asked for bogus section (page: " .
 1167+ $this->getId() . "; section: $section; edittime: $edittime)\n" );
 1168+ wfProfileOut( __METHOD__ );
 1169+ return null;
 1170+ }
11621171
11631172 $oldContent = $rev->getContent();
1164 - }
 1173+ }
11651174
11661175 $newContent = $oldContent->replaceSection( $section, $sectionContent, $sectionTitle );
1167 - }
 1176+ }
11681177
1169 - wfProfileOut( __METHOD__ );
1170 - return ContentHandler::getContentText( $newContent ); #XXX: unclear what will happen for non-wikitext!
1171 - }
 1178+ wfProfileOut( __METHOD__ );
 1179+ return $newContent;
 1180+ }
11721181
11731182 /**
11741183 * Check flags and add EDIT_NEW or EDIT_UPDATE to them as needed.
@@ -1653,13 +1662,13 @@
16541663 wfProfileIn( __METHOD__ );
16551664
16561665 $options += array( 'changed' => true, 'created' => false, 'oldcountable' => null );
1657 - $text = $revision->getText();
 1666+ $content = $revision->getContent();
16581667
16591668 # Parse the text
16601669 # Be careful not to double-PST: $text is usually already PST-ed once
16611670 if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
16621671 wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
1663 - $editInfo = $this->prepareTextForEdit( $text, $revision->getId(), $user );
 1672+ $editInfo = $this->prepareContentForEdit( $content, $revision->getId(), $user );
16641673 } else {
16651674 wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" );
16661675 $editInfo = $this->mPreparedEdit;
@@ -1717,7 +1726,7 @@
17181727 }
17191728
17201729 DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, $good, $total ) );
1721 - DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $text ) );
 1730+ DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $content->getTextForSearchIndex() ) );
17221731
17231732 # If this is another user's talk page, update newtalk.
17241733 # Don't do this if $options['changed'] = false (null-edits) nor if
@@ -1743,7 +1752,10 @@
17441753 }
17451754
17461755 if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
1747 - MessageCache::singleton()->replace( $shortTitle, $text );
 1756+ $msgtext = ContentHandler::getContentText( $content ); #XXX: could skip pseudo-messages like js/css here, based on content model.
 1757+ if ( $msgtext === false || $msgtext === null ) $msgtext = '';
 1758+
 1759+ MessageCache::singleton()->replace( $shortTitle, $msgtext );
17481760 }
17491761
17501762 if( $options['created'] ) {
@@ -2371,7 +2383,7 @@
23722384 }
23732385
23742386 # Actually store the edit
2375 - $status = $this->doEdit( $target->getText(), $summary, $flags, $target->getId(), $guser );
 2387+ $status = $this->doEditContent( $target->getContent(), $summary, $flags, $target->getId(), $guser );
23762388 if ( !empty( $status->value['revision'] ) ) {
23772389 $revId = $status->value['revision']->getId();
23782390 } else {

Status & tagging log