r23590 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r23589‎ | r23590 | r23591 >
Date:10:22, 30 June 2007
Author:catrope
Status:old
Tags:
Comment:
* Putting delete reason generation in a separate function
(Article::generateReason())
* Adding action=delete functionality to the API
* Minor nitpickery
Modified paths:
  • /branches/apiedit/phase3/includes/Article.php (modified) (history)
  • /branches/apiedit/phase3/includes/AutoLoader.php (modified) (history)
  • /branches/apiedit/phase3/includes/Defines.php (modified) (history)
  • /branches/apiedit/phase3/includes/api/ApiDelete.php (added) (history)
  • /branches/apiedit/phase3/includes/api/ApiMain.php (modified) (history)
  • /branches/apiedit/phase3/includes/api/ApiQueryRevisions.php (modified) (history)

Diff [purge]

Index: branches/apiedit/phase3/includes/Defines.php
@@ -203,7 +203,7 @@
204204 define('ROLLBACK_BLOCKED', 2); // User has been blocked
205205 define('ROLLBACK_READONLY', 3); // Wiki is in read-only mode
206206 define('ROLLBACK_BADTOKEN', 4); // Invalid token specified
207 -define('ROLLBACK_BADARTICLE', 5); // $article is not a valid Article
 207+define('ROLLBACK_BADARTICLE', 5); // $this is not a valid Article
208208 define('ROLLBACK_ALREADYROLLED', 6); // Someone else already rolled this back. $info['usertext'] and $info['comment'] will be set
209209 define('ROLLBACK_ONLYAUTHOR', 7); // User is the only author of the page
210210 define('ROLLBACK_EDITFAILED', 8); // Article::doEdit() failed. This is a very weird error
Index: branches/apiedit/phase3/includes/Article.php
@@ -1801,6 +1801,65 @@
18021802 return implode( ':', $bits );
18031803 }
18041804
 1805+ /** Auto-generates a deletion reason */
 1806+ public function generateReason()
 1807+ {
 1808+ global $wgContLang;
 1809+ $dbw = wfGetDB(DB_MASTER);
 1810+ // Get the last revision
 1811+ $rev = Revision::newFromTitle($this->mTitle);
 1812+ if(is_null($rev))
 1813+ return false;
 1814+ // Get the article's contents
 1815+ $contents = $rev->getText();
 1816+ $blank = false;
 1817+ // If the page is blank, use the text from the previous revision (which can't be blank)
 1818+ if($contents == '')
 1819+ {
 1820+ $prev = $rev->getPrevious();
 1821+ if($prev)
 1822+ {
 1823+ $contents = $prev->getText();
 1824+ $blank = true;
 1825+ }
 1826+ }
 1827+ // Get the first 150 chars
 1828+ $contents = $wgContLang->truncate($contents, 150, '...');
 1829+ // Replace newlines with spaces to prevent uglyness
 1830+ $contents = preg_replace("/[\n\r]/", ' ', $contents);
 1831+
 1832+ // Find out if there was only one contributor
 1833+ // Only scan the last 20 revisions
 1834+ $limit = 20;
 1835+ $res = $dbw->select('revision', 'rev_user_text', array('rev_page' => $this->getID()), __METHOD__,
 1836+ array('LIMIT' => $limit));
 1837+ if($res === false)
 1838+ // This page has no revisions, which is very weird
 1839+ return false;
 1840+ $row = $dbw->fetchObject($res);
 1841+ $onlyAuthor = $row->rev_user_text;
 1842+ // Try to find a second contributor
 1843+ while(($row = $dbw->fetchObject($res)))
 1844+ if($row->rev_user_text != $onlyAuthor)
 1845+ {
 1846+ $onlyAuthor = false;
 1847+ break;
 1848+ }
 1849+ $dbw->freeResult($res);
 1850+
 1851+ // Summary generation time
 1852+ if($blank)
 1853+ $reason = wfMsgForContent('exbeforeblank');
 1854+ else
 1855+ {
 1856+ if($onlyAuthor)
 1857+ $reason = wfMsgForContent('excontentauthor', $contents, $onlyAuthor);
 1858+ else
 1859+ $reason = wfMsgForContent('excontent', $contents);
 1860+ }
 1861+ return $reason;
 1862+ }
 1863+
18051864 /*
18061865 * UI entry point for page deletion
18071866 */
@@ -1851,73 +1910,15 @@
18521911
18531912 # determine whether this page has earlier revisions
18541913 # and insert a warning if it does
1855 - $maxRevisions = 20;
1856 - $authors = $this->getLastNAuthors( $maxRevisions, $latest );
 1914+ $authors = $this->getLastNAuthors( 2, $latest );
18571915
18581916 if( count( $authors ) > 1 && !$confirm ) {
18591917 $skin=$wgUser->getSkin();
18601918 $wgOut->addHTML( '<strong>' . wfMsg( 'historywarning' ) . ' ' . $skin->historyLink() . '</strong>' );
18611919 }
18621920
1863 - # If a single user is responsible for all revisions, find out who they are
1864 - if ( count( $authors ) == $maxRevisions ) {
1865 - // Query bailed out, too many revisions to find out if they're all the same
1866 - $authorOfAll = false;
1867 - } else {
1868 - $authorOfAll = reset( $authors );
1869 - foreach ( $authors as $author ) {
1870 - if ( $authorOfAll != $author ) {
1871 - $authorOfAll = false;
1872 - break;
1873 - }
1874 - }
1875 - }
1876 - # Fetch article text
1877 - $rev = Revision::newFromTitle( $this->mTitle );
 1921+ $reason = $this->generateReason();
18781922
1879 - if( !is_null( $rev ) ) {
1880 - # if this is a mini-text, we can paste part of it into the deletion reason
1881 - $text = $rev->getText();
1882 -
1883 - #if this is empty, an earlier revision may contain "useful" text
1884 - $blanked = false;
1885 - if( $text == '' ) {
1886 - $prev = $rev->getPrevious();
1887 - if( $prev ) {
1888 - $text = $prev->getText();
1889 - $blanked = true;
1890 - }
1891 - }
1892 -
1893 - $length = strlen( $text );
1894 -
1895 - # this should not happen, since it is not possible to store an empty, new
1896 - # page. Let's insert a standard text in case it does, though
1897 - if( $length == 0 && $reason === '' ) {
1898 - $reason = wfMsgForContent( 'exblank' );
1899 - }
1900 -
1901 - if( $reason === '' ) {
1902 - # comment field=255, let's grep the first 150 to have some user
1903 - # space left
1904 - global $wgContLang;
1905 - $text = $wgContLang->truncate( $text, 150, '...' );
1906 -
1907 - # let's strip out newlines
1908 - $text = preg_replace( "/[\n\r]/", '', $text );
1909 -
1910 - if( !$blanked ) {
1911 - if( $authorOfAll === false ) {
1912 - $reason = wfMsgForContent( 'excontent', $text );
1913 - } else {
1914 - $reason = wfMsgForContent( 'excontentauthor', $text, $authorOfAll );
1915 - }
1916 - } else {
1917 - $reason = wfMsgForContent( 'exbeforeblank', $text );
1918 - }
1919 - }
1920 - }
1921 -
19221923 return $this->confirmDelete( '', $reason );
19231924 }
19241925
@@ -2091,6 +2092,7 @@
20922093 //
20932094 // In the future, we may keep revisions and mark them with
20942095 // the rev_deleted field, which is reserved for this purpose.
 2096+ $dbw->begin();
20952097 $dbw->insertSelect( 'archive', array( 'page', 'revision' ),
20962098 array(
20972099 'ar_namespace' => 'page_namespace',
@@ -2152,6 +2154,7 @@
21532155 # Clear the cached article id so the interface doesn't act like we exist
21542156 $this->mTitle->resetArticleID( 0 );
21552157 $this->mTitle->mArticleID = 0;
 2158+ $dbw->commit();
21562159 return true;
21572160 }
21582161
Index: branches/apiedit/phase3/includes/AutoLoader.php
@@ -288,6 +288,7 @@
289289
290290 # API
291291 'ApiBase' => 'includes/api/ApiBase.php',
 292+ 'ApiDelete' => 'includes/api/ApiDelete.php',
292293 'ApiFormatFeedWrapper' => 'includes/api/ApiFormatBase.php',
293294 'ApiFeedWatchlist' => 'includes/api/ApiFeedWatchlist.php',
294295 'ApiFormatBase' => 'includes/api/ApiFormatBase.php',
Index: branches/apiedit/phase3/includes/api/ApiDelete.php
@@ -0,0 +1,172 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Jun 21, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**#@+
 32+ * ApiDelete::delete() return values
 33+ */
 34+define('DELETE_SUCCESS', 0);
 35+define('DELETE_PERM', 1); // Permission denied
 36+define('DELETE_BLOCKED', 2); // You are blocked
 37+define('DELETE_READONLY', 3); // Wiki is in read-only mode
 38+define('DELETE_BADTOKEN', 4); // Invalid token
 39+define('DELETE_BADARTICLE', 5); // $this is not a valid Article
 40+
 41+
 42+
 43+/**
 44+ * @addtogroup API
 45+ */
 46+class ApiDelete extends ApiBase {
 47+
 48+ public function __construct($main, $action) {
 49+ parent :: __construct($main, $action);
 50+ }
 51+
 52+ /**
 53+ * We have our own delete() function, since Article.php's implementation is split in two phases
 54+ * Maybe Article.php can be changed some day to use this function instead.
 55+ * @param Article $article - Article object to work on
 56+ * @param string $token - Delete token (same as edit token)
 57+ * @param string $reason - Reason for the deletion. Autogenerated if NULL
 58+ * @return DELETE_SUCCESS on success, DELETE_* on failure
 59+ */
 60+
 61+ public static function delete(&$article, $token, &$reason = NULL)
 62+ {
 63+ global $wgUser;
 64+
 65+ // Check permissions first
 66+ if(!$wgUser->isAllowed('delete'))
 67+ return DELETE_PERM;
 68+ if($wgUser->isBlocked())
 69+ return DELETE_BLOCKED;
 70+ if(wfReadOnly())
 71+ return DELETE_READONLY;
 72+
 73+ // Check token
 74+ if(!$wgUser->matchEditToken($token))
 75+ return DELETE_BADTOKEN;
 76+
 77+ // Auto-generate a summary, if necessary
 78+ if(is_null($reason))
 79+ {
 80+ $reason = $article->generateReason();
 81+ if($reason === false)
 82+ return DELETE_BADARTICLE;
 83+ }
 84+
 85+ // Luckily, Article.php provides a reusable delete function that does the hard work for us
 86+ if($article->doDeleteArticle($reason))
 87+ return DELETE_SUCCESS;
 88+ return DELETE_BADARTICLE;
 89+ }
 90+
 91+ public function execute() {
 92+ global $wgUser;
 93+ $params = $this->extractRequestParams();
 94+
 95+ $titleObj = NULL;
 96+ if(!isset($params['title']))
 97+ $this->dieUsage('The title parameter must be set', 'notarget');
 98+ if(!isset($params['token']))
 99+ $this->dieUsage('The token parameter must be set', 'notoken');
 100+
 101+ // delete() also checks for these, but we wanna save some work
 102+ if(!$wgUser->isAllowed('delete'))
 103+ $this->dieUsage('You don\'t have permission to delete pages', 'permissiondenied');
 104+ if($wgUser->isBlocked())
 105+ $this->dieUsage('You have been blocked from editing', 'blocked');
 106+ if(wfReadOnly())
 107+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 108+
 109+ $titleObj = Title::newFromText($params['title']);
 110+ if(!$titleObj)
 111+ $this->dieUsage("bad title {$params['title']}", 'invalidtitle');
 112+
 113+ $articleObj = new Article($titleObj);
 114+ $reason = (isset($params['reason']) ? $params['reason'] : NULL);
 115+ $retval = self::delete(&$articleObj, $params['token'], &$reason);
 116+
 117+ switch($retval)
 118+ {
 119+ case DELETE_SUCCESS:
 120+ break; // We'll deal with that later
 121+ case DELETE_PERM: // If we get PERM, BLOCKED or READONLY that's weird, but it's possible
 122+ $this->dieUsage('You don\'t have permission to rollback', 'permissiondenied');
 123+ case DELETE_BLOCKED:
 124+ $this->dieUsage('You have been blocked from editing', 'blocked');
 125+ case DELETE_READONLY:
 126+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 127+ case DELETE_BADTOKEN:
 128+ $this->dieUsage('Invalid token', 'badtoken');
 129+ case ROLLBACK_BADARTICLE:
 130+ $this->dieUsage("The article ``{$params['title']}'' doesn't exist or has already been deleted", 'missingtitle');
 131+ default:
 132+ // delete() has apparently invented a new error, which is extremely weird
 133+ $this->dieDebug(__METHOD__, "delete() returned an unknown error ($retval)");
 134+ }
 135+ // $retval has to be DELETE_SUCCESS if we get here
 136+ $r = array('title' => $titleObj->getPrefixedText(), 'reason' => $reason);
 137+ $this->getResult()->addValue(null, 'delete', $r);
 138+ }
 139+
 140+ protected function getAllowedParams() {
 141+ return array (
 142+ 'title' => null,
 143+ 'token' => null,
 144+ 'reason' => null,
 145+ );
 146+ }
 147+
 148+ protected function getParamDescription() {
 149+ return array (
 150+ 'title' => 'Title of the page you want to delete.',
 151+ 'token' => 'A delete token previously retrieved through prop=info',
 152+ 'reason' => 'Reason for the deletion. If not set, an automatically generated reason will be used.'
 153+ );
 154+ }
 155+
 156+ protected function getDescription() {
 157+ return array(
 158+ 'Deletes a page. You need to be logged in as a sysop to use this function, see also action=login.'
 159+ );
 160+ }
 161+
 162+ protected function getExamples() {
 163+ return array (
 164+ 'api.php?action=delete&title=Main%20Page&token=123ABC',
 165+ 'api.php?action=delete&title=Main%20Page&token=123ABC&reason=Preparing%20for%20move'
 166+ );
 167+ }
 168+
 169+ public function getVersion() {
 170+ return __CLASS__ . ': $Id: ApiDelete.php 22289 2007-05-20 23:31:44Z yurik $';
 171+ }
 172+}
 173+?>
Property changes on: branches/apiedit/phase3/includes/api/ApiDelete.php
___________________________________________________________________
Added: svn:eol-style
1174 + native
Index: branches/apiedit/phase3/includes/api/ApiQueryRevisions.php
@@ -81,7 +81,7 @@
8282 // lastid automatically sets ids and timestamp
8383 // because it needs them internally
8484 $this->fld_lastid = isset ($prop['lastid']);
85 - $this->fld_ids = isset ($prop['ids']) || $this->fld_lastid);
 85+ $this->fld_ids = isset ($prop['ids']) || $this->fld_lastid;
8686 // $this->addFieldsIf('rev_text_id', $this->fld_ids); // should this be exposed?
8787 $this->fld_flags = $this->addFieldsIf('rev_minor_edit', isset ($prop['flags']));
8888 $this->fld_timestamp = $this->addFieldsIf('rev_timestamp', isset ($prop['timestamp']) || $this->fld_lastid);
Index: branches/apiedit/phase3/includes/api/ApiMain.php
@@ -55,6 +55,7 @@
5656 'login' => 'ApiLogin',
5757 'query' => 'ApiQuery',
5858 'rollback' => 'ApiRollback',
 59+ 'delete' => 'ApiDelete',
5960 'opensearch' => 'ApiOpenSearch',
6061 'feedwatchlist' => 'ApiFeedWatchlist',
6162 'help' => 'ApiHelp',

Status & tagging log