Index: branches/Wikidata/phase3/includes/diff/DifferenceEngine.php |
— | — | @@ -67,7 +67,7 @@ |
68 | 68 | * @param $refreshCache boolean If set, refreshes the diff cache |
69 | 69 | * @param $unhide boolean If set, allow viewing deleted revs |
70 | 70 | */ |
71 | | - function __construct( $context = null, $old = 0, $new = 0, $rcid = 0, |
| 71 | + function __construct( $context = null, $old = 0, $new = 0, $rcid = 0, # FIXME: use Contenthandler::getDifferenceEngine everywhere! |
72 | 72 | $refreshCache = false, $unhide = false ) |
73 | 73 | { |
74 | 74 | if ( $context instanceof IContextSource ) { |
— | — | @@ -925,14 +925,35 @@ |
926 | 926 | |
927 | 927 | /** |
928 | 928 | * Use specified text instead of loading from the database |
| 929 | + * @deprecated since 1.20 |
929 | 930 | */ |
930 | | - function setText( $oldText, $newText ) { #FIXME: deprecate, use Content objects instead! |
| 931 | + function setText( $oldText, $newText ) { |
| 932 | + wfDeprecated( __METHOD__, "1.20" ); |
| 933 | + $this->setText_internal( $oldText, $newText ); |
| 934 | + } |
| 935 | + |
| 936 | + /** |
| 937 | + * @private |
| 938 | + * Use specified text instead of loading from the database |
| 939 | + */ |
| 940 | + private function setText_internal( $oldText, $newText ) { |
931 | 941 | $this->mOldtext = $oldText; |
932 | 942 | $this->mNewtext = $newText; |
933 | 943 | $this->mTextLoaded = 2; |
934 | 944 | $this->mRevisionsLoaded = true; |
935 | 945 | } |
936 | 946 | |
| 947 | + /** |
| 948 | + * Use specified text instead of loading from the database |
| 949 | + * @since 1.20 |
| 950 | + */ |
| 951 | + function setContent( Content $oldContent, Content $newContent, $format = null ) { #FIXME: use this! |
| 952 | + $oldText = $oldContent->serialize( $format ); |
| 953 | + $newText = $newContent->serialize( $format ); |
| 954 | + |
| 955 | + return $this->setText_internal( $oldText, $newText ); |
| 956 | + } |
| 957 | + |
937 | 958 | /** |
938 | 959 | * Set the language in which the diff text is written |
939 | 960 | * (Defaults to page content language). |
Index: branches/Wikidata/phase3/includes/Content.php |
— | — | @@ -167,6 +167,17 @@ |
168 | 168 | } |
169 | 169 | |
170 | 170 | /** |
| 171 | + * Returns a new WikitextContent object with the given section heading prepended, if supported. |
| 172 | + * The default implementation just returns this Content object unmodified, ignoring the section header. |
| 173 | + * |
| 174 | + * @param $header String |
| 175 | + * @return Content |
| 176 | + */ |
| 177 | + public function addSectionHeader( $header ) { |
| 178 | + return $this; |
| 179 | + } |
| 180 | + |
| 181 | + /** |
171 | 182 | * Returns a Content object with preload transformations applied (or this object if no transformations apply). |
172 | 183 | * |
173 | 184 | * @param Title $title |
— | — | @@ -389,6 +400,18 @@ |
390 | 401 | } |
391 | 402 | |
392 | 403 | /** |
| 404 | + * Returns a new WikitextContent object with the given section heading prepended. |
| 405 | + * |
| 406 | + * @param $header String |
| 407 | + * @return Content |
| 408 | + */ |
| 409 | + public function addSectionHeader( $header ) { |
| 410 | + $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $this->getNativeData(); |
| 411 | + |
| 412 | + return new WikitextContent( $text ); |
| 413 | + } |
| 414 | + |
| 415 | + /** |
393 | 416 | * Returns a Content object with pre-save transformations applied (or this object if no transformations apply). |
394 | 417 | * |
395 | 418 | * @param Title $title |
Index: branches/Wikidata/phase3/includes/ContentHandler.php |
— | — | @@ -209,12 +209,19 @@ |
210 | 210 | } |
211 | 211 | |
212 | 212 | /** |
213 | | - public function updatePage( $title, $obj ) { |
214 | | - } |
215 | | - **/ |
216 | | - |
217 | | - public function getDiffEngine( Article $article ) { #FIXME: change interface of diff engine? or accept content objects here=? |
218 | | - $de = new DifferenceEngine( $article->getContext() ); |
| 213 | + * Factory |
| 214 | + * @param $context IContextSource context to use, anything else will be ignored |
| 215 | + * @param $old Integer old ID we want to show and diff with. |
| 216 | + * @param $new String either 'prev' or 'next'. |
| 217 | + * @param $rcid Integer ??? FIXME (default 0) |
| 218 | + * @param $refreshCache boolean If set, refreshes the diff cache |
| 219 | + * @param $unhide boolean If set, allow viewing deleted revs |
| 220 | + */ |
| 221 | + public function getDifferenceEngine( IContextSource $context, $old = 0, $new = 0, $rcid = 0, #FIMXE: use everywhere! |
| 222 | + $refreshCache = false, $unhide = false ) { |
| 223 | + |
| 224 | + $de = new DifferenceEngine( $context, $old, $new, $rcid, $refreshCache, $unhide ); |
| 225 | + |
219 | 226 | return $de; |
220 | 227 | } |
221 | 228 | |
Index: branches/Wikidata/phase3/includes/EditPage.php |
— | — | @@ -920,7 +920,7 @@ |
921 | 921 | */ |
922 | 922 | private function getCurrentContent() { |
923 | 923 | $rev = $this->mArticle->getRevision(); |
924 | | - $content = $rev->getContentObject( Revision::RAW ); |
| 924 | + $content = $rev->getContent( Revision::RAW ); |
925 | 925 | |
926 | 926 | if ( $content === false || $content === null ) { |
927 | 927 | if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModelName(); |
— | — | @@ -1309,10 +1309,9 @@ |
1310 | 1310 | |
1311 | 1311 | $result['sectionanchor'] = ''; |
1312 | 1312 | if ( $this->section == 'new' ) { |
1313 | | - .........FIXME............... |
1314 | 1313 | if ( $this->sectiontitle !== '' ) { |
1315 | 1314 | // Insert the section title above the content. |
1316 | | - $T_E_X_T = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $T_E_X_T; |
| 1315 | + $content = $content->addSectionHeader( $this->sectiontitle ); |
1317 | 1316 | |
1318 | 1317 | // Jump to the new section |
1319 | 1318 | $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle ); |
— | — | @@ -1326,7 +1325,7 @@ |
1327 | 1326 | } |
1328 | 1327 | } elseif ( $this->summary !== '' ) { |
1329 | 1328 | // Insert the section title above the content. |
1330 | | - $T_E_X_T = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->summary ) . "\n\n" . $T_E_X_T; |
| 1329 | + $content = $content->addSectionHeader( $this->sectiontitle ); |
1331 | 1330 | |
1332 | 1331 | // Jump to the new section |
1333 | 1332 | $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary ); |
— | — | @@ -1376,27 +1375,34 @@ |
1377 | 1376 | } else { |
1378 | 1377 | $sectionTitle = $this->summary; |
1379 | 1378 | } |
1380 | | - |
| 1379 | + |
| 1380 | + $textbox_content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format ); |
| 1381 | + $content = false; |
| 1382 | + |
1381 | 1383 | if ( $this->isConflict ) { |
1382 | 1384 | wfDebug( __METHOD__ . ": conflict! getting section '$this->section' for time '$this->edittime' (article time '{$timestamp}')\n" ); |
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 |
| 1385 | + |
| 1386 | + $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle, $this->edittime ); |
1384 | 1387 | } else { |
1385 | 1388 | wfDebug( __METHOD__ . ": getting section '$this->section'\n" ); |
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 |
| 1389 | + |
| 1390 | + $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle ); |
1387 | 1391 | } |
1388 | | - if ( is_null( $T_E_X_T ) ) { |
| 1392 | + |
| 1393 | + if ( is_null( $content ) ) { |
1389 | 1394 | wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" ); |
1390 | 1395 | $this->isConflict = true; |
1391 | | - $T_E_X_T = $this->textbox1; // do not try to merge here! #FIXME: unserialize Content |
| 1396 | + $content = $textbox_content; // do not try to merge here! |
1392 | 1397 | } elseif ( $this->isConflict ) { |
1393 | 1398 | # Attempt merge |
1394 | | - if ( $this->mergeChangesInto( $T_E_X_T ) ) { #FIXME: passe/receive Content object |
| 1399 | + if ( $this->mergeChangesIntoContent( $textbox_content ) ) { |
1395 | 1400 | // Successful merge! Maybe we should tell the user the good news? |
| 1401 | + $content = $textbox_content; |
1396 | 1402 | $this->isConflict = false; |
1397 | 1403 | wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" ); |
1398 | 1404 | } else { |
1399 | 1405 | $this->section = ''; |
1400 | | - $this->textbox1 = $T_E_X_T; |
| 1406 | + #$this->textbox1 = $text; #redundant, nothing to do here? |
1401 | 1407 | wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" ); |
1402 | 1408 | } |
1403 | 1409 | } |
— | — | @@ -1408,7 +1414,8 @@ |
1409 | 1415 | } |
1410 | 1416 | |
1411 | 1417 | // Run post-section-merge edit filter |
1412 | | - if ( !wfRunHooks( 'EditFilterMerged', array( $this, $T_E_X_T, &$this->hookError, $this->summary ) ) ) { |
| 1418 | + if ( !wfRunHooks( 'EditFilterMerged', array( $this, $content->serialize( $this->content_format ), &$this->hookError, $this->summary ) ) |
| 1419 | + || !wfRunHooks( 'EditFilterMergedContent', array( $this, $content, &$this->hookError, $this->summary ) ) ) { #FIXME: document new hook |
1413 | 1420 | # Error messages etc. could be handled within the hook... |
1414 | 1421 | $status->fatal( 'hookaborted' ); |
1415 | 1422 | $status->value = self::AS_HOOK_ERROR; |
— | — | @@ -1424,8 +1431,8 @@ |
1425 | 1432 | |
1426 | 1433 | # Handle the user preference to force summaries here, but not for null edits |
1427 | 1434 | if ( $this->section != 'new' && !$this->allowBlankSummary |
1428 | | - && $this->getOriginalContent()... != $T_E_X_T |
1429 | | - && !Title::newFromRedirect( $T_E_X_T ) ) # check if it's not a redirect |
| 1435 | + && !$content->equals( $this->getOriginalContent() ) |
| 1436 | + && !$content->isRedirect() ) # check if it's not a redirect |
1430 | 1437 | { |
1431 | 1438 | if ( md5( $this->summary ) == $this->autoSumm ) { |
1432 | 1439 | $this->missingSummary = true; |
— | — | @@ -1493,14 +1500,14 @@ |
1494 | 1501 | // merged the section into full text. Clear the section field |
1495 | 1502 | // so that later submission of conflict forms won't try to |
1496 | 1503 | // replace that into a duplicated mess. |
1497 | | - $this->textbox1 = $T_E_X_T; |
| 1504 | + $this->textbox1 = $content->serialize( $this->content_format ); |
1498 | 1505 | $this->section = ''; |
1499 | 1506 | |
1500 | 1507 | $status->value = self::AS_SUCCESS_UPDATE; |
1501 | 1508 | } |
1502 | 1509 | |
1503 | 1510 | // Check for length errors again now that the section is merged in |
1504 | | - $this->kblength = (int)( strlen( $T_E_X_T ) / 1024 ); |
| 1511 | + $this->kblength = (int)( strlen( $content->serialize( $this->content_format ) ) / 1024 ); |
1505 | 1512 | if ( $this->kblength > $wgMaxArticleSize ) { |
1506 | 1513 | $this->tooBig = true; |
1507 | 1514 | $status->setResult( false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED ); |
— | — | @@ -1513,10 +1520,10 @@ |
1514 | 1521 | ( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) | |
1515 | 1522 | ( $bot ? EDIT_FORCE_BOT : 0 ); |
1516 | 1523 | |
1517 | | - $doEditStatus = $this->mArticle->doEdit( $T_E_X_T, $this->summary, $flags ); # FIXME: use WikiPage::doEditContent() |
| 1524 | + $doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags ); |
1518 | 1525 | |
1519 | 1526 | if ( $doEditStatus->isOK() ) { |
1520 | | - $result['redirect'] = Title::newFromRedirect( $T_E_X_T ) !== null; |
| 1527 | + $result['redirect'] = $content->isRedirect(); |
1521 | 1528 | $this->commitWatch(); |
1522 | 1529 | wfProfileOut( __METHOD__ ); |
1523 | 1530 | return $status; |
— | — | @@ -1581,8 +1588,34 @@ |
1582 | 1589 | * @parma $editText string |
1583 | 1590 | * |
1584 | 1591 | * @return bool |
| 1592 | + * @deprecated since 1.20 |
1585 | 1593 | */ |
1586 | | - function mergeChangesInto( &$editText ){ |
| 1594 | + function mergeChangesInto( &$editText ){ |
| 1595 | + wfDebug( __METHOD__, "1.20" ); |
| 1596 | + |
| 1597 | + $handler = ContentHandler::getForModelName( $this->content_model ); |
| 1598 | + $editContent = $handler->unserialize( $editText, $this->content_format ); |
| 1599 | + |
| 1600 | + $ok = $this->mergeChangesIntoContent( $editContent ); |
| 1601 | + |
| 1602 | + if ( $ok ) { |
| 1603 | + $editText = $editContent->serialize( $this->content_format ); #XXX: really serialize?! |
| 1604 | + return true; |
| 1605 | + } else { |
| 1606 | + return false; |
| 1607 | + } |
| 1608 | + } |
| 1609 | + |
| 1610 | + /** |
| 1611 | + * @private |
| 1612 | + * @todo document |
| 1613 | + * |
| 1614 | + * @parma $editText string |
| 1615 | + * |
| 1616 | + * @return bool |
| 1617 | + * @since since 1.20 |
| 1618 | + */ |
| 1619 | + private function mergeChangesIntoContent( &$editContent ){ |
1587 | 1620 | wfProfileIn( __METHOD__ ); |
1588 | 1621 | |
1589 | 1622 | $db = wfGetDB( DB_MASTER ); |
— | — | @@ -1604,11 +1637,11 @@ |
1605 | 1638 | $currentContent = $currentRevision->getContent(); |
1606 | 1639 | |
1607 | 1640 | $handler = ContentHandler::getForModelName( $baseContent->getModelName() ); |
1608 | | - $editContent = $handler->unserialize( $editText, $this->content_format ); #FIXME: supply serialization fomrat from edit form! |
1609 | 1641 | |
1610 | 1642 | $result = $handler->merge3( $baseContent, $editContent, $currentContent ); |
| 1643 | + |
1611 | 1644 | if ( $result ) { |
1612 | | - $editText = ContentHandler::getContentText($result, $this->content_format ); #FIXME: supply serialization fomrat from edit form! |
| 1645 | + $editContent = $result; |
1613 | 1646 | wfProfileOut( __METHOD__ ); |
1614 | 1647 | return true; |
1615 | 1648 | } else { |
— | — | @@ -2421,8 +2454,9 @@ |
2422 | 2455 | $oldtitle = wfMsgExt( 'currentrev', array( 'parseinline' ) ); |
2423 | 2456 | $newtitle = wfMsgExt( 'yourtext', array( 'parseinline' ) ); |
2424 | 2457 | |
2425 | | - $de = new DifferenceEngine( $this->mArticle->getContext() ); |
2426 | | - $de->setText( $oldContent, $newContent ); #FIXME: content-based diff! |
| 2458 | + $de = $oldContent->getContentHandler()->getDifferenceEngine( $this->mArticle->getContext() ); |
| 2459 | + $de->setContent( $oldContent, $newContent ); |
| 2460 | + |
2427 | 2461 | $difftext = $de->getDiff( $oldtitle, $newtitle ); |
2428 | 2462 | $de->showDiffStyle(); |
2429 | 2463 | } else { |
— | — | @@ -2512,8 +2546,12 @@ |
2513 | 2547 | if ( wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) { |
2514 | 2548 | $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" ); |
2515 | 2549 | |
2516 | | - $de = new DifferenceEngine( $this->mArticle->getContext() ); |
2517 | | - $de->setText( $this->textbox2, $this->textbox1 ); |
| 2550 | + $content1 = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format ); |
| 2551 | + $content2 = ContentHandler::makeContent( $this->textbox2, $this->getTitle(), $this->content_model, $this->content_format ); |
| 2552 | + |
| 2553 | + $handler = ContentHandler::getForModelName( $this->content_model ); |
| 2554 | + $de = $handler->getDifferenceEngine( $this->mArticle->getContext() ); |
| 2555 | + $de->setContent( $content2, $content1 ); |
2518 | 2556 | $de->showDiff( wfMsgExt( 'yourtext', 'parseinline' ), wfMsg( 'storedversion' ) ); |
2519 | 2557 | |
2520 | 2558 | $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourtext" ); |
— | — | @@ -3140,10 +3178,13 @@ |
3141 | 3179 | $wgOut->addHTML( '</div>' ); |
3142 | 3180 | |
3143 | 3181 | $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" ); |
3144 | | - $de = new DifferenceEngine( $this->mArticle->getContext() ); #FIXME: get from content handler! |
3145 | 3182 | |
3146 | | - $de->setText( $this->getCurrentText(), $this->textbox2 ); #FIXME: make Content based |
| 3183 | + $handler = ContentHandler::getForTitle( $this->getTitle() ); |
| 3184 | + $de = $handler->getDifferenceEngine( $this->mArticle->getContext() ); |
3147 | 3185 | |
| 3186 | + $content2 = ContentHandler::makeContent( $this->textbox2, $this->getTitle(), $this->content_model, $this->content_format ); |
| 3187 | + $de->setContent( $this->getCurrentContent(), $content2 ); |
| 3188 | + |
3148 | 3189 | $de->showDiff( wfMsg( "storedversion" ), wfMsgExt( 'yourtext', 'parseinline' ) ); |
3149 | 3190 | |
3150 | 3191 | $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourtext" ); |
Index: branches/Wikidata/phase3/includes/WikiPage.php |
— | — | @@ -1142,7 +1142,7 @@ |
1143 | 1143 | return ContentHandler::getContentText( $newContent ); #XXX: unclear what will happen for non-wikitext! |
1144 | 1144 | } |
1145 | 1145 | |
1146 | | - public function replaceSectionContent( $section, $sectionContent, $sectionTitle = '', $edittime = null ) { |
| 1146 | + public function replaceSectionContent( $section, Content $sectionContent, $sectionTitle = '', $edittime = null ) { |
1147 | 1147 | wfProfileIn( __METHOD__ ); |
1148 | 1148 | |
1149 | 1149 | if ( strval( $section ) == '' ) { |