r114242 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r114241‎ | r114242 | r114243 >
Date:09:57, 20 March 2012
Author:daniel
Status:deferred (Comments)
Tags:
Comment:
auto-summary, auto-delete-reason
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/WikiPage.php (modified) (history)
  • /branches/Wikidata/phase3/includes/api/ApiDelete.php (modified) (history)

Diff [purge]

Index: branches/Wikidata/phase3/includes/Article.php
@@ -1894,7 +1894,9 @@
18951895 * @return mixed
18961896 */
18971897 public function generateReason( &$hasHistory ) {
1898 - return $this->mPage->getAutoDeleteReason( $hasHistory );
 1898+ $title = $this->mPage->getTitle();
 1899+ $handler = ContentHandler::getForTitle( $title );
 1900+ return $handler->getAutoDeleteReason( $title, $hasHistory );
18991901 }
19001902
19011903 // ****** B/C functions for static methods ( __callStatic is PHP>=5.3 ) ****** //
@@ -1932,6 +1934,7 @@
19331935 * @param $newtext
19341936 * @param $flags
19351937 * @return string
 1938+ * @deprecated since 1.20, use ContentHandler::getAutosummary() instead
19361939 */
19371940 public static function getAutosummary( $oldtext, $newtext, $flags ) {
19381941 return WikiPage::getAutosummary( $oldtext, $newtext, $flags );
Index: branches/Wikidata/phase3/includes/Content.php
@@ -16,22 +16,30 @@
1717 return $this->mModelName;
1818 }
1919
20 - public abstract function getSearchText( );
 20+ public abstract function getTextForSearchIndex( );
2121
2222 public abstract function getWikitextForTransclusion( );
2323
 24+ public abstract function getTextForSummary( $maxlength = 250 );
 25+
2426 /**
2527 * Returns native represenation of the data. Interpretation depends on the data model used,
2628 * as given by getDataModel().
2729 *
 30+ * @return mixed the native representation of the content. Could be a string, a nested array
 31+ * structure, an object, a binary blob... anything, really.
2832 */
29 - public abstract function getNativeData( );
 33+ public abstract function getNativeData( ); #FIXME: review all calls carefully, caller must be aware of content model!
3034
3135 /**
3236 * returns the content's nominal size in bogo-bytes.
3337 */
3438 public abstract function getSize( ); #XXX: do we really need/want this here? we could just use the byte syse of the serialized form...
3539
 40+ public function isEmpty() {
 41+ return $this->getSize() == 0;
 42+ }
 43+
3644 /**
3745 * Returns true if this content is countable as a "real" wiki page, provided
3846 * that it's also in a countable location (e.g. a current revision in the main namespace).
@@ -43,12 +51,16 @@
4452
4553 public abstract function getParserOutput( Title $title = null, $revId = null, ParserOptions $options = NULL );
4654
47 - public function getRedirectChain() {
 55+ public function getRedirectChain() { #TODO: document!
4856 return null;
4957 }
5058
 59+ public function getRedirectTarget() {
 60+ return null;
 61+ }
 62+
5163 public function isRedirect() {
52 - return false;
 64+ return $this->getRedirectTarget() != null;
5365 }
5466
5567 /**
@@ -64,7 +76,7 @@
6577 }
6678
6779 /**
68 - * Replaces a section of the content.
 80+ * Replaces a section of the content and returns a Content object with the section replaced.
6981 *
7082 * @param $section empty/null/false or a section number (0, 1, 2, T1, T2...), or "new"
7183 * @param $with Content: new content of the section
@@ -85,6 +97,7 @@
8698
8799 # TODO: EditPage::getPreloadedText( $preload ) // $wgParser->getPreloadText
88100 # TODO: tie into EditPage, make it use Content-objects throughout, make edit form aware of content model and format
 101+ # TODO: tie into WikiPage, make it use Content-objects throughout, especially in doEdit(), doDelete(), etc
89102 # TODO: make model-aware diff view!
90103 # TODO: handle ImagePage and CategoryPage
91104
@@ -106,6 +119,18 @@
107120 $this->mText = $text;
108121 }
109122
 123+ public function getTextForSummary( $maxlength = 250 ) {
 124+ global $wgContLang;
 125+
 126+ $text = $this->getNativeData();
 127+
 128+ $truncatedtext = $wgContLang->truncate(
 129+ preg_replace( "/[\n\r]/", ' ', $text ),
 130+ max( 0, $maxlength ) );
 131+
 132+ return $truncatedtext;
 133+ }
 134+
110135 /**
111136 * returns the content's nominal size in bogo-bytes.
112137 */
@@ -149,7 +174,7 @@
150175 *
151176 * @return String the raw text
152177 */
153 - public function getSearchText( ) { #FIXME: use!
 178+ public function getTextForSearchIndex( ) { #FIXME: use!
154179 return $this->getNativeData();
155180 }
156181
@@ -286,9 +311,9 @@
287312 return Title::newFromRedirectArray( $text );
288313 }
289314
290 - public function isRedirect() {
 315+ public function getRedirectTarget() {
291316 $text = $this->getNativeData();
292 - return Title::newFromRedirect( $text ) !== null;
 317+ return Title::newFromRedirect( $text );
293318 }
294319
295320 /**
@@ -326,6 +351,16 @@
327352 }
328353 }
329354
 355+ public function getTextForSummary( $maxlength = 250 ) {
 356+ $truncatedtext = parent::getTextForSummary( $maxlength );
 357+
 358+ #clean up unfinished links
 359+ #XXX: make this optional? wasn't there in autosummary, but required for deletion summary.
 360+ $truncatedtext = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $truncatedtext );
 361+
 362+ return $truncatedtext;
 363+ }
 364+
330365 }
331366
332367 class MessageContent extends TextContent {
Index: branches/Wikidata/phase3/includes/ContentHandler.php
@@ -104,6 +104,12 @@
105105 return ContentHandler::getForModelName( $modelName );
106106 }
107107
 108+ /**
 109+ * @static
 110+ * @param $modelName String the name of the content model for which to get a handler. Use CONTENT_MODEL_XXX constants.
 111+ * @return ContentHandler
 112+ * @throws MWException
 113+ */
108114 public static function getForModelName( $modelName ) {
109115 global $wgContentHandlers;
110116
@@ -143,8 +149,20 @@
144150 return $this->mSupportedFormats[0];
145151 }
146152
 153+ /**
 154+ * @abstract
 155+ * @param Content $content
 156+ * @param null $format
 157+ * @return String
 158+ */
147159 public abstract function serialize( Content $content, $format = null );
148160
 161+ /**
 162+ * @abstract
 163+ * @param $blob String
 164+ * @param null $format
 165+ * @return Content
 166+ */
149167 public abstract function unserialize( $blob, $format = null );
150168
151169 public abstract function emptyContent();
@@ -216,6 +234,153 @@
217235 return false;
218236 }
219237
 238+ /**
 239+ * Return an applicable autosummary if one exists for the given edit.
 240+ *
 241+ * @param $oldContent Content: the previous text of the page.
 242+ * @param $newContent Content: The submitted text of the page.
 243+ * @param $flags Int bitmask: a bitmask of flags submitted for the edit.
 244+ *
 245+ * @return string An appropriate autosummary, or an empty string.
 246+ */
 247+ public function getAutosummary( Content $oldContent, Content $newContent, $flags ) {
 248+ global $wgContLang;
 249+
 250+ # Decide what kind of autosummary is needed.
 251+
 252+ # Redirect autosummaries
 253+ $ot = $oldContent->getRedirectTarget();
 254+ $rt = $newContent->getRedirectTarget();
 255+
 256+ if ( is_object( $rt ) && ( !is_object( $ot ) || !$rt->equals( $ot ) || $ot->getFragment() != $rt->getFragment() ) ) {
 257+
 258+ $truncatedtext = $newContent->getTextForSummary(
 259+ 250
 260+ - strlen( wfMsgForContent( 'autoredircomment' ) )
 261+ - strlen( $rt->getFullText() ) );
 262+
 263+ return wfMsgForContent( 'autoredircomment', $rt->getFullText(), $truncatedtext );
 264+ }
 265+
 266+ # New page autosummaries
 267+ if ( $flags & EDIT_NEW && $newContent->getSize() > 0 ) {
 268+ # If they're making a new article, give its text, truncated, in the summary.
 269+
 270+ $truncatedtext = $newContent->getTextForSummary(
 271+ 200 - strlen( wfMsgForContent( 'autosumm-new' ) ) );
 272+
 273+ return wfMsgForContent( 'autosumm-new', $truncatedtext );
 274+ }
 275+
 276+ # Blanking autosummaries
 277+ if ( $oldContent->getSize() > 0 && $newContent->getSize() == 0 ) {
 278+ return wfMsgForContent( 'autosumm-blank' );
 279+ } elseif ( $oldContent->getSize() > 10 * $newContent->getSize() && $newContent->getSize() < 500 ) {
 280+ # Removing more than 90% of the article
 281+
 282+ $truncatedtext = $newContent->getTextForSummary(
 283+ 200 - strlen( wfMsgForContent( 'autosumm-replace' ) ) );
 284+
 285+ return wfMsgForContent( 'autosumm-replace', $truncatedtext );
 286+ }
 287+
 288+ # If we reach this point, there's no applicable autosummary for our case, so our
 289+ # autosummary is empty.
 290+ return '';
 291+ }
 292+
 293+ /**
 294+ * Auto-generates a deletion reason
 295+ *
 296+ * @param $title Title: the page's title
 297+ * @param &$hasHistory Boolean: whether the page has a history
 298+ * @return mixed String containing deletion reason or empty string, or boolean false
 299+ * if no revision occurred
 300+ */
 301+ public function getAutoDeleteReason( Title $title, &$hasHistory ) {
 302+ global $wgContLang;
 303+
 304+ $dbw = wfGetDB( DB_MASTER );
 305+
 306+ // Get the last revision
 307+ $rev = Revision::newFromTitle( $title );
 308+
 309+ if ( is_null( $rev ) ) {
 310+ return false;
 311+ }
 312+
 313+ // Get the article's contents
 314+ $content = $rev->getContent();
 315+ $blank = false;
 316+
 317+ // If the page is blank, use the text from the previous revision,
 318+ // which can only be blank if there's a move/import/protect dummy revision involved
 319+ if ( $content->getSize() == 0 ) {
 320+ $prev = $rev->getPrevious();
 321+
 322+ if ( $prev ) {
 323+ $content = $rev->getContent();
 324+ $blank = true;
 325+ }
 326+ }
 327+
 328+ // Find out if there was only one contributor
 329+ // Only scan the last 20 revisions
 330+ $res = $dbw->select( 'revision', 'rev_user_text',
 331+ array( 'rev_page' => $title->getArticleID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ),
 332+ __METHOD__,
 333+ array( 'LIMIT' => 20 )
 334+ );
 335+
 336+ if ( $res === false ) {
 337+ // This page has no revisions, which is very weird
 338+ return false;
 339+ }
 340+
 341+ $hasHistory = ( $res->numRows() > 1 );
 342+ $row = $dbw->fetchObject( $res );
 343+
 344+ if ( $row ) { // $row is false if the only contributor is hidden
 345+ $onlyAuthor = $row->rev_user_text;
 346+ // Try to find a second contributor
 347+ foreach ( $res as $row ) {
 348+ if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
 349+ $onlyAuthor = false;
 350+ break;
 351+ }
 352+ }
 353+ } else {
 354+ $onlyAuthor = false;
 355+ }
 356+
 357+ // Generate the summary with a '$1' placeholder
 358+ if ( $blank ) {
 359+ // The current revision is blank and the one before is also
 360+ // blank. It's just not our lucky day
 361+ $reason = wfMsgForContent( 'exbeforeblank', '$1' );
 362+ } else {
 363+ if ( $onlyAuthor ) {
 364+ $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
 365+ } else {
 366+ $reason = wfMsgForContent( 'excontent', '$1' );
 367+ }
 368+ }
 369+
 370+ if ( $reason == '-' ) {
 371+ // Allow these UI messages to be blanked out cleanly
 372+ return '';
 373+ }
 374+
 375+ // Max content length = max comment length - length of the comment (excl. $1)
 376+ $text = $content->getTextForSummary( 255 - ( strlen( $reason ) - 2 ) );
 377+
 378+ // Now replace the '$1' placeholder
 379+ $reason = str_replace( '$1', $text, $reason );
 380+
 381+ return $reason;
 382+ }
 383+
 384+
220385 #TODO: cover patch/undo just like merge3.
221386
222387 #TODO: how to handle extra message for JS/CSS previews??
@@ -280,6 +445,7 @@
281446 return new WikitextContent("");
282447 }
283448
 449+
284450 }
285451
286452 class JavaScriptContentHandler extends TextContentHandler {
Index: branches/Wikidata/phase3/includes/api/ApiDelete.php
@@ -123,7 +123,7 @@
124124 // Need to pass a throwaway variable because generateReason expects
125125 // a reference
126126 $hasHistory = false;
127 - $reason = $page->getAutoDeleteReason( $hasHistory );
 127+ $reason = $page->getAutoDeleteReason( $hasHistory ); #FIXME: use ContentHandler::getAutoDeleteReason()
128128 if ( $reason === false ) {
129129 return array( array( 'cannotdelete', $title->getPrefixedText() ) );
130130 }
Index: branches/Wikidata/phase3/includes/WikiPage.php
@@ -1271,7 +1271,7 @@
12721272
12731273 # Provide autosummaries if one is not provided and autosummaries are enabled.
12741274 if ( $wgUseAutomaticEditSummaries && $flags & EDIT_AUTOSUMMARY && $summary == '' ) {
1275 - $summary = self::getAutosummary( $oldtext, $text, $flags ); #FIXME: auto-summary from ContentHandler
 1275+ $summary = self::getAutosummary( $oldtext, $text, $flags ); #FIXME: ContentHandler::getAutosummary()
12761276 }
12771277
12781278 $editInfo = $this->prepareTextForEdit( $text, null, $user );
@@ -2385,53 +2385,16 @@
23862386 * @param $newtext String: The submitted text of the page.
23872387 * @param $flags Int bitmask: a bitmask of flags submitted for the edit.
23882388 * @return string An appropriate autosummary, or an empty string.
 2389+ * @deprecated since 1.20, use ContentHandler::getAutosummary() instead
23892390 */
23902391 public static function getAutosummary( $oldtext, $newtext, $flags ) {
2391 - global $wgContLang;
 2392+ # NOTE: stub for backwards-compatibility. assumes the given text is wikitext. will break horribly if it isn't.
23922393
2393 - # Decide what kind of autosummary is needed.
 2394+ $handler = ContentHandler::getForModelName( CONTENT_MODEL_WIKITEXT );
 2395+ $oldContent = $handler->unserialize( $oldtext );
 2396+ $newContent = $handler->unserialize( $newtext );
23942397
2395 - # Redirect autosummaries
2396 - $ot = Title::newFromRedirect( $oldtext );
2397 - $rt = Title::newFromRedirect( $newtext );
2398 -
2399 - if ( is_object( $rt ) && ( !is_object( $ot ) || !$rt->equals( $ot ) || $ot->getFragment() != $rt->getFragment() ) ) {
2400 - $truncatedtext = $wgContLang->truncate(
2401 - str_replace( "\n", ' ', $newtext ),
2402 - max( 0, 250
2403 - - strlen( wfMsgForContent( 'autoredircomment' ) )
2404 - - strlen( $rt->getFullText() )
2405 - ) );
2406 - return wfMsgForContent( 'autoredircomment', $rt->getFullText(), $truncatedtext );
2407 - }
2408 -
2409 - # New page autosummaries
2410 - if ( $flags & EDIT_NEW && strlen( $newtext ) ) {
2411 - # If they're making a new article, give its text, truncated, in the summary.
2412 -
2413 - $truncatedtext = $wgContLang->truncate(
2414 - str_replace( "\n", ' ', $newtext ),
2415 - max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new' ) ) ) );
2416 -
2417 - return wfMsgForContent( 'autosumm-new', $truncatedtext );
2418 - }
2419 -
2420 - # Blanking autosummaries
2421 - if ( $oldtext != '' && $newtext == '' ) {
2422 - return wfMsgForContent( 'autosumm-blank' );
2423 - } elseif ( strlen( $oldtext ) > 10 * strlen( $newtext ) && strlen( $newtext ) < 500 ) {
2424 - # Removing more than 90% of the article
2425 -
2426 - $truncatedtext = $wgContLang->truncate(
2427 - $newtext,
2428 - max( 0, 200 - strlen( wfMsgForContent( 'autosumm-replace' ) ) ) );
2429 -
2430 - return wfMsgForContent( 'autosumm-replace', $truncatedtext );
2431 - }
2432 -
2433 - # If we reach this point, there's no applicable autosummary for our case, so our
2434 - # autosummary is empty.
2435 - return '';
 2398+ return $handler->getAutosummary( $oldContent, $newContent, $flags );
24362399 }
24372400
24382401 /**
@@ -2440,92 +2403,13 @@
24412404 * @param &$hasHistory Boolean: whether the page has a history
24422405 * @return mixed String containing deletion reason or empty string, or boolean false
24432406 * if no revision occurred
 2407+ * @deprecated since 1.20, use ContentHandler::getAutoDeleteReason() instead
24442408 */
24452409 public function getAutoDeleteReason( &$hasHistory ) {
2446 - global $wgContLang;
 2410+ #NOTE: stub for backwards-compatibility.
24472411
2448 - $dbw = wfGetDB( DB_MASTER );
2449 - // Get the last revision
2450 - $rev = Revision::newFromTitle( $this->getTitle() );
2451 -
2452 - if ( is_null( $rev ) ) {
2453 - return false;
2454 - }
2455 -
2456 - // Get the article's contents
2457 - $contents = $rev->getText();
2458 - $blank = false;
2459 -
2460 - // If the page is blank, use the text from the previous revision,
2461 - // which can only be blank if there's a move/import/protect dummy revision involved
2462 - if ( $contents == '' ) {
2463 - $prev = $rev->getPrevious();
2464 -
2465 - if ( $prev ) {
2466 - $contents = $prev->getText();
2467 - $blank = true;
2468 - }
2469 - }
2470 -
2471 - // Find out if there was only one contributor
2472 - // Only scan the last 20 revisions
2473 - $res = $dbw->select( 'revision', 'rev_user_text',
2474 - array( 'rev_page' => $this->getID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ),
2475 - __METHOD__,
2476 - array( 'LIMIT' => 20 )
2477 - );
2478 -
2479 - if ( $res === false ) {
2480 - // This page has no revisions, which is very weird
2481 - return false;
2482 - }
2483 -
2484 - $hasHistory = ( $res->numRows() > 1 );
2485 - $row = $dbw->fetchObject( $res );
2486 -
2487 - if ( $row ) { // $row is false if the only contributor is hidden
2488 - $onlyAuthor = $row->rev_user_text;
2489 - // Try to find a second contributor
2490 - foreach ( $res as $row ) {
2491 - if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
2492 - $onlyAuthor = false;
2493 - break;
2494 - }
2495 - }
2496 - } else {
2497 - $onlyAuthor = false;
2498 - }
2499 -
2500 - // Generate the summary with a '$1' placeholder
2501 - if ( $blank ) {
2502 - // The current revision is blank and the one before is also
2503 - // blank. It's just not our lucky day
2504 - $reason = wfMsgForContent( 'exbeforeblank', '$1' );
2505 - } else {
2506 - if ( $onlyAuthor ) {
2507 - $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
2508 - } else {
2509 - $reason = wfMsgForContent( 'excontent', '$1' );
2510 - }
2511 - }
2512 -
2513 - if ( $reason == '-' ) {
2514 - // Allow these UI messages to be blanked out cleanly
2515 - return '';
2516 - }
2517 -
2518 - // Replace newlines with spaces to prevent uglyness
2519 - $contents = preg_replace( "/[\n\r]/", ' ', $contents );
2520 - // Calculate the maximum amount of chars to get
2521 - // Max content length = max comment length - length of the comment (excl. $1)
2522 - $maxLength = 255 - ( strlen( $reason ) - 2 );
2523 - $contents = $wgContLang->truncate( $contents, $maxLength );
2524 - // Remove possible unfinished links
2525 - $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
2526 - // Now replace the '$1' placeholder
2527 - $reason = str_replace( '$1', $contents, $reason );
2528 -
2529 - return $reason;
 2412+ $handler = ContentHandler::getForTitle( $this->getTitle() );
 2413+ $handler->getAutoDeleteReason( $this->getTitle(), $hasHistory );
25302414 }
25312415
25322416 /**

Comments

#Comment by Platonides (talk | contribs)   17:43, 4 April 2012

Spaces instead of tabs

Status & tagging log