r16888 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r16887‎ | r16888 | r16889 >
Date:11:27, 9 October 2006
Author:jeluf
Status:old
Tags:
Comment:
Extension that allows the upload of multiple files in one step.
Modified paths:
  • /trunk/extensions/MultiUpload (added) (history)
  • /trunk/extensions/MultiUpload/README (added) (history)
  • /trunk/extensions/MultiUpload/SpecialMultipleUpload.php (added) (history)

Diff [purge]

Index: trunk/extensions/MultiUpload/SpecialMultipleUpload.php
@@ -0,0 +1,459 @@
 2+<?php
 3+if ( ! defined( 'MEDIAWIKI' ) )
 4+ die();
 5+
 6+/**#@+
 7+ * An extension that allows users to upload multiple photos at once.
 8+ *
 9+ * @package MediaWiki
 10+ * @subpackage Extensions
 11+ *
 12+ * @link http://www.wikihow.com/WikiHow:MultipleUpload-Extension Documentation
 13+ *
 14+ *
 15+ * @author Travis Derouin <travis@wikihow.com>
 16+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 17+ */
 18+
 19+// change this parameter to limit the # of files one can upload
 20+$wgMaxUploadFiles = 5;
 21+
 22+require_once("SpecialPage.php");
 23+
 24+
 25+SpecialPage::AddPage(new SpecialPage('MultipleUpload'));
 26+
 27+$wgExtensionFunctions[] = 'wfMultipleUpload';
 28+
 29+$wgExtensionCredits['parserhook'][] = array(
 30+ 'name' => 'MultipleUpload',
 31+ 'author' => 'Travis Derouin',
 32+ 'description' => 'Allows users to upload several files at once.',
 33+ 'url' => 'http://www.wikihow.com/WikiHow:MultipleUpload-Extension',
 34+);
 35+
 36+function wfMultipleUpload() {
 37+ global $wgMessageCache, $wgMaxUploadFiles;
 38+ $wgMaxUploadFiles = intval( $wgMaxUploadFiles );
 39+ $wgMessageCache->addMessages(
 40+ array(
 41+ 'ignoreallwarnings' => "Ignore <b>all warnings</b> and save the files anyway.",
 42+ 'multipleupload' => "Upload Files",
 43+ 'saveallfiles' => "Save all files",
 44+ 'addresswarnings' => "Please address any warnings before reuploading files.",
 45+ 'multiuploadtext' => "Upload multiple files here. <br/><br/>
 46+ Choose 'Browse' and select each file you wish to upload. You can upload from 1 to $wgMaxUploadFiles
 47+ files at a time. <br/><br/>
 48+ You can enter an optional <b>Destination filename</b> and provide a <b>Summary</b> describing your photo. <br/><br/>
 49+ <br/>
 50+ Inappropriate images will be deleted immediately, see the [[Project:Image Deletion Policy|Image Deletion Policy]]<br/><br/>
 51+ ",
 52+ )
 53+ );
 54+}
 55+
 56+
 57+/**
 58+ *
 59+ */
 60+require_once 'SpecialUpload.php';
 61+/**
 62+ * Entry point
 63+ */
 64+function wfSpecialMultipleUpload() {
 65+ global $wgRequest;
 66+ $form = new MultipleUploadForm( $wgRequest );
 67+ $form->execute();
 68+}
 69+
 70+/**
 71+ *
 72+ * @package MediaWiki
 73+ * @subpackage SpecialPage
 74+ */
 75+class MultipleUploadForm extends UploadForm {
 76+
 77+ // extra goodies
 78+ // access private
 79+ var $mUploadTempNameArray, $mUploadSizeArray, $mOnameArray, $mUploadError, $mDestFileArray;
 80+ var $mUploadDescriptionArray;
 81+ var $mShowUploadForm, $mHasWarning, $mFileIndex;
 82+ /**
 83+ * Constructor : initialise object
 84+ * Get data POSTed through the form and assign them to the object
 85+ * @param $request Data posted.
 86+ */
 87+ function MultipleUploadForm( &$request ) {
 88+ global $wgMaxUploadFiles;
 89+ // call the parent constructor
 90+ parent::UploadForm(&$request);
 91+
 92+ //initialize
 93+ $this->mUploadTempNameArray= $this->mUploadSizeArray= $this->mOnameArray= $this->mUploadError= $this->mDestFileArray = $this->mUploadDescriptionArray = array();
 94+ $this->mShowUploadForm = true;
 95+ $this->mFileIndex = 0;
 96+
 97+ for ($x = 0; $x < $wgMaxUploadFiles; $x++) $this->mDestFileArray[$x] = $request->getText( "wpDestFile_$x" );
 98+
 99+ if( !$request->wasPosted() ) {
 100+ # GET requests just give the main form; no data except wpDestfile.
 101+ return ;
 102+ }
 103+
 104+
 105+
 106+ for ($x = 0; $x < $wgMaxUploadFiles; $x++) {
 107+ $this->mDestFile[$x] = $request->getText( "wpDestFile_$x" );
 108+ $this->mUploadDescriptionArray[$x] = $request->getText( "wpUploadDescription_$x" );
 109+ }
 110+ $this->mSessionKey = $request->getInt( 'wpSessionKey' );
 111+
 112+
 113+ if( !empty( $this->mSessionKey ) ) {
 114+ for ($x = 0; $x < $wgMaxUploadFiles; $x++) {
 115+ //if (!isset($_SESSION["wsUploadData_$x"][$this->mSessionKey])) continue;
 116+ $data = $_SESSION["wsUploadData_$x"][$this->mSessionKey];
 117+ $this->mUploadTempNameArray[$x] = $data["mUploadTempName"];
 118+ $this->mUploadSizeArray[$x] = $data["mUploadSize"];
 119+ $this->mOnameArray[$x] = $data["mOname"];
 120+ }
 121+ } else {
 122+ /**
 123+ *Check for a newly uploaded file.
 124+ */
 125+ for ($x = 0; $x < $wgMaxUploadFiles; $x++) {
 126+ $this->mUploadTempNameArray[$x] = $request->getFileTempName( "wpUploadFile_$x" );
 127+ $this->mUploadSizeArray [$x] = $request->getFileSize( "wpUploadFile_$x" );
 128+ $this->mOnameArray[$x] = $request->getFileName( "wpUploadFile_$x" );
 129+ $this->mUploadErrorArray[$x] = $request->getUploadError( "wpUploadFile_$x" );
 130+ $this->mUploadDescriptionArray [$x] = $request->getVal("wpUploadDescription_$x");
 131+ }
 132+ }
 133+
 134+ }
 135+
 136+
 137+ /* -------------------------------------------------------------- */
 138+
 139+ /**
 140+ * Really do the upload
 141+ * Checks are made in SpecialUpload::execute()
 142+ * @access private
 143+ */
 144+ function processUpload() {
 145+ global $wgMaxUploadFiles, $wgOut;
 146+
 147+ $wgOut->addHTML("<table>");
 148+ $this->mShowUploadForm = false;
 149+ for ($x = 0; $x < $wgMaxUploadFiles; $x++) {
 150+ $this->mFileIndex = $x;
 151+ if (!isset ($this->mUploadTempNameArray[$x]) || $this->mUploadTempNameArray[$x] == null) continue;
 152+ $this->mUploadTempName = $this->mUploadTempNameArray[$x];
 153+ $this->mUploadSize = $this->mUploadSizeArray[$x];
 154+ $this->mOname = $this->mOnameArray [$x];
 155+ $this->mUploadError = $this->mUploadErrorArray [$x];
 156+ $this->mDestFile = $this->mDestFileArray [$x];
 157+ $this->mUploadDescription = $this->mUploadDescriptionArray [$x];
 158+ $wgOut->addHTML("<tr><td>");
 159+ parent::processUpload();
 160+ $wgOut->addHTML("</td></tr>");
 161+ }
 162+
 163+ $wgOut->addHTML("</table>");
 164+ $this->mShowUploadForm = false;
 165+ $wgOut->redirect(''); // clear the redirect, we want to show a nice page of images
 166+ $this->mShowUploadForm = true;
 167+ if ($this->mHasWarning) {
 168+ $this->showWarningOptions();
 169+ }
 170+ }
 171+
 172+
 173+ /* -------------------------------------------------------------- */
 174+
 175+ /**
 176+ * Show some text and linkage on successful upload.
 177+ * @access private
 178+ */
 179+ function showSuccess() {
 180+ global $wgUser, $wgOut, $wgContLang;
 181+
 182+ $sk = $wgUser->getSkin();
 183+ $ilink = $sk->makeMediaLink( $this->mUploadSaveName, Image::imageUrl( $this->mUploadSaveName ) );
 184+ $dname = $wgContLang->getNsText( NS_IMAGE ) . ':'.$this->mUploadSaveName;
 185+ $dlink = $sk->makeKnownLink( $dname, $dname );
 186+
 187+ $wgOut->addWikiText( "[[$dname|left|thumb]]" );
 188+ $text = wfMsgWikiHtml( 'fileuploaded', $ilink, $dlink );
 189+ $wgOut->addHTML( $text );
 190+ }
 191+
 192+ /**
 193+ * @param string $error as HTML
 194+ * @access private
 195+ */
 196+ function uploadError( $error ) {
 197+ global $wgOut;
 198+ $wgOut->addHTML( "<b>{$this->mUploadSaveName}</b>\n" );
 199+ $wgOut->addHTML( "<span class='error'>{$error}</span>\n" );
 200+ }
 201+
 202+ /**
 203+ * There's something wrong with this file, not enough to reject it
 204+ * totally but we require manual intervention to save it for real.
 205+ * Stash it away, then present a form asking to confirm or cancel.
 206+ *
 207+ * @param string $warning as HTML
 208+ * @access private
 209+ */
 210+ function uploadWarning( $warning ) {
 211+ global $wgOut;
 212+ global $wgUseCopyrightUpload;
 213+
 214+ if (!$this->mHasWarning) {
 215+ $titleObj = Title::makeTitle( NS_SPECIAL, 'MultipleUpload' );
 216+ $action = $titleObj->escapeLocalURL( 'action=submit' );
 217+ $wgOut->addHTML( "<h2>" . wfMsgHtml( 'uploadwarning' ) . "</h2>\n
 218+ <form id='uploadwarning' method='post' enctype='multipart/form-data' action='$action'>");
 219+ }
 220+ $this->mHasWarning = true;
 221+ $this->mSessionKey = $this->stashSession();
 222+ if( !$this->mSessionKey ) {
 223+ # Couldn't save file; an error has been displayed so let's go.
 224+ return;
 225+ }
 226+
 227+ $wgOut->addHTML( "<b>{$this->mUploadSaveName}</b>\n" );
 228+ $wgOut->addHTML( "<ul class='warning'>{$warning}</ul><br />\n" );
 229+ $wgOut->addHTML(" <input type='hidden' name='wpUploadDescription_{$this->mFileIndex}' value=\"" . htmlspecialchars( $this->mUploadDescription ) . "\" />");
 230+
 231+
 232+ }
 233+ function stashSession() {
 234+ $stash = $this->saveTempUploadedFile(
 235+ $this->mUploadSaveName, $this->mUploadTempName );
 236+
 237+ if( !$stash ) {
 238+ # Couldn't save the file.
 239+ return false;
 240+ }
 241+
 242+ if ($this->mSessionKey == null)
 243+ $key = mt_rand( 0, 0x7fffffff );
 244+ else
 245+ $key = $this->mSessionKey;
 246+ $_SESSION["wsUploadData_" . $this->mFileIndex][$key] = array(
 247+ 'mUploadTempName' => $stash,
 248+ 'mUploadSize' => $this->mUploadSize,
 249+ 'mOname' => $this->mOname );
 250+ return $key;
 251+ }
 252+
 253+ function showWarningOptions() {
 254+ global $wgOut;
 255+ $save = wfMsgHtml( 'saveallfiles' );
 256+ $reupload = wfMsgHtml( 'reupload' );
 257+ $iw = wfMsgWikiHtml( 'ignoreallwarnings' );
 258+ $reup = wfMsgWikiHtml( 'reuploaddesc' );
 259+ if ( $wgUseCopyrightUpload )
 260+ {
 261+ $copyright = "
 262+ <input type='hidden' name='wpUploadCopyStatus' value=\"" . htmlspecialchars( $this->mUploadCopyStatus ) . "\" />
 263+ <input type='hidden' name='wpUploadSource' value=\"" . htmlspecialchars( $this->mUploadSource ) . "\" />
 264+ ";
 265+ } else {
 266+ $copyright = "";
 267+ }
 268+ $wgOut->addHTML( "
 269+ <input type='hidden' name='wpIgnoreWarning' value='1' />
 270+ <input type='hidden' name='wpSessionKey' value=\"" . htmlspecialchars( $this->mSessionKey ) . "\" />
 271+ <input type='hidden' name='wpLicense' value=\"" . htmlspecialchars( $this->mLicense ) . "\" />
 272+ <input type='hidden' name='wpDestFile' value=\"" . htmlspecialchars( $this->mDestFile ) . "\" />
 273+ <input type='hidden' name='wpWatchthis' value=\"" . htmlspecialchars( intval( $this->mWatchthis ) ) . "\" />
 274+ {$copyright}
 275+ <table border='0'>
 276+ <tr>
 277+ <tr>
 278+ <td align='right'>
 279+ <input tabindex='2' type='submit' name='wpUpload' value='$save' />
 280+ </td>
 281+ <td align='left'>$iw</td>
 282+ </tr>
 283+ <tr>
 284+ <td align='right'>
 285+ <input tabindex='2' type='submit' name='wpReUpload' value='{$reupload}' />
 286+ </td>
 287+ <td align='left'>$reup</td>
 288+ </tr>
 289+ </tr>
 290+ </table></form>\n" );
 291+
 292+ }
 293+
 294+ /**
 295+ * Displays the main upload form, optionally with a highlighted
 296+ * error message up at the top.
 297+ *
 298+ * @param string $msg as HTML
 299+ * @access private
 300+ */
 301+ function mainUploadForm( $msg='' ) {
 302+ global $wgOut, $wgUser;
 303+ global $wgUseCopyrightUpload, $wgMaxUploadFiles;
 304+
 305+ if ($msg == '' && !$this->mShowUploadForm) return;
 306+ $cols = intval($wgUser->getOption( 'cols' ));
 307+ $ew = $wgUser->getOption( 'editwidth' );
 308+ if ( $ew ) $ew = " style=\"width:100%\"";
 309+ else $ew = '';
 310+
 311+ if ( '' != $msg ) {
 312+ $wgOut->addHTML( "<b>{$this->mUploadSaveName}</b>\n<br/>" );
 313+ $sub = wfMsgHtml( 'addresswarnings' );
 314+ $wgOut->addHTML( "<b>{$sub}</b><br/><span class='error'>{$msg}</span>\n" );
 315+ }
 316+ $wgOut->addHTML( '<div id="uploadtext">' );
 317+ $wgOut->addWikiText( wfMsg( 'multiuploadtext' ) );
 318+ $wgOut->addHTML( '</div>' );
 319+ $sk = $wgUser->getSkin();
 320+
 321+
 322+ $sourcefilename .= wfMsgHtml( 'sourcefilename' );
 323+ $destfilename = wfMsgHtml( 'destfilename' );
 324+ $summary = wfMsg( 'fileuploadsummary' );
 325+ $licenses = new Licenses();
 326+ $license = wfMsgHtml( 'license' );
 327+ $nolicense = wfMsgHtml( 'nolicense' );
 328+ $licenseshtml = $licenses->getHtml();
 329+ $ulb = wfMsgHtml( 'uploadbtn' );
 330+
 331+
 332+ $titleObj = Title::makeTitle( NS_SPECIAL, 'MultipleUpload' );
 333+ $action = $titleObj->escapeLocalURL();
 334+
 335+
 336+ $watchChecked = $wgUser->getOption( 'watchdefault' )
 337+ ? 'checked="checked"'
 338+ : '';
 339+
 340+ $wgOut->addHTML( "
 341+<script type=\"text/javascript\">
 342+function fillDestFilenameMulti(i) {
 343+ if (!document.getElementById)
 344+ return;
 345+ var path = document.getElementById('wpUploadFile_' + i).value;
 346+ // Find trailing part
 347+ var slash = path.lastIndexOf('/');
 348+ var backslash = path.lastIndexOf('\\\\');
 349+ var fname;
 350+ if (slash == -1 && backslash == -1) {
 351+ fname = path;
 352+ } else if (slash > backslash) {
 353+ fname = path.substring(slash+1, 10000);
 354+ } else {
 355+ fname = path.substring(backslash+1, 10000);
 356+ }
 357+
 358+ // Capitalise first letter and replace spaces by underscores
 359+ fname = fname.charAt(0).toUpperCase().concat(fname.substring(1,10000)).replace(/ /g, '_');
 360+
 361+ // Output result
 362+ var destFile = document.getElementById('wpDestFile_' + i);
 363+ if (destFile)
 364+ destFile.value = fname;
 365+}
 366+</script>
 367+
 368+ <form id='upload' method='post' enctype='multipart/form-data' action=\"$action\">
 369+ <table border='0'>
 370+ <tr>
 371+ <td align='left'><label for='wpUploadFile'><b>{$sourcefilename}:</b></label></td>
 372+ <td align='left'><label for='wpDestFile'><b>{$destfilename}:</b></label></td>
 373+ <td align='left' valign='middle'><b>{$summary}</b></td>
 374+ </tr>");
 375+ for ($i = 0; $i < $wgMaxUploadFiles; $i++) {
 376+ $encDestFile = htmlspecialchars( $this->mDestFileArray[$i] );
 377+ $wgOut->addHTML("
 378+ <tr>
 379+ <td align='left'>
 380+ <input tabindex='1' type='file' name='wpUploadFile_$i' id='wpUploadFile_$i' " . ($this->mDestFile?"":"onchange='fillDestFilenameMulti($i)' ") . "size='25' />
 381+ </td>
 382+ <td align='left'>
 383+ <input tabindex='2' type='text' name='wpDestFile_$i' id='wpDestFile_$i' size='25' value=\"$encDestFile\" />
 384+ </td>
 385+ <td align='left'>
 386+ <input tabindex='3' name='wpUploadDescription_$i' id='wpUploadDescription' value=\"". htmlspecialchars( $this->mUploadDescription ) . "\" size=25>
 387+ </td>
 388+ </tr>
 389+ <tr>" );
 390+ }
 391+
 392+ if ( $licenseshtml != '' ) {
 393+ global $wgStylePath;
 394+ $wgOut->addHTML( "
 395+ <td align='left' colspan=3>
 396+ <label for='wpLicense'>$license:</label>
 397+ <script type='text/javascript' src=\"$wgStylePath/common/upload.js\"></script>
 398+ <select name='wpLicense' id='wpLicense' tabindex='4' style='font-size: xx-small;'
 399+ onchange='licenseSelectorCheck()'>
 400+ <option value=''>$nolicense</option>
 401+ $licenseshtml
 402+ </select>
 403+ </td>
 404+ </tr>
 405+ <tr>
 406+ ");
 407+ }
 408+
 409+ if ( $wgUseCopyrightUpload ) {
 410+ $filestatus = wfMsgHtml ( 'filestatus' );
 411+ $copystatus = htmlspecialchars( $this->mUploadCopyStatus );
 412+ $filesource = wfMsgHtml ( 'filesource' );
 413+ $uploadsource = htmlspecialchars( $this->mUploadSource );
 414+
 415+ $wgOut->addHTML( "
 416+ <td align='right' nowrap='nowrap'><label for='wpUploadCopyStatus'>$filestatus:</label></td>
 417+ <td><input tabindex='5' type='text' name='wpUploadCopyStatus' id='wpUploadCopyStatus' value=\"$copystatus\" size='40' /></td>
 418+ </tr>
 419+ <tr>
 420+ <td align='right'><label for='wpUploadCopyStatus'>$filesource:</label></td>
 421+ <td><input tabindex='6' type='text' name='wpUploadSource' id='wpUploadCopyStatus' value=\"$uploadsource\" size='40' /></td>
 422+ </tr>
 423+ <tr>
 424+ ");
 425+ }
 426+
 427+
 428+ $wgOut->addHtml( "
 429+ <td>
 430+ <input tabindex='7' type='checkbox' name='wpWatchthis' id='wpWatchthis' $watchChecked value='true' />
 431+ <label for='wpWatchthis'>" . wfMsgHtml( 'watchthis' ) . "</label>
 432+ <input tabindex='8' type='checkbox' name='wpIgnoreWarning' id='wpIgnoreWarning' value='true' />
 433+ <label for='wpIgnoreWarning'>" . wfMsgHtml( 'ignorewarnings' ) . "</label>
 434+ </td>
 435+ </tr>
 436+ <tr>
 437+
 438+ </tr>
 439+ <tr>
 440+ <td align='left'><input tabindex='9' type='submit' name='wpUpload' value=\"{$ulb}\" /></td>
 441+ </tr>
 442+
 443+ <tr>
 444+ <td></td>
 445+ <td align='left'>
 446+ " );
 447+ $wgOut->addWikiText( wfMsgForContent( 'edittools' ) );
 448+ $wgOut->addHTML( "
 449+ </td>
 450+ </tr>
 451+
 452+ </table>
 453+ </form>" );
 454+ }
 455+
 456+ /* -------------------------------------------------------------- */
 457+
 458+
 459+}
 460+?>
Index: trunk/extensions/MultiUpload/README
@@ -0,0 +1,38 @@
 2+== WikiHow:MultipleUpload Extension ==
 3+
 4+This is a simple extension to upload multiple photos at once. It makes
 5+as much use of Special:Upload as it can. There are some issues when a
 6+warning and an error is encountered in one upload attempt.
 7+
 8+
 9+=== Requirements ===
 10+
 11+* PHP 5.x
 12+* This has been tested on Mediawiki 1.6.7, so it should work on later versions.
 13+
 14+
 15+=== Installation ===
 16+
 17+Download the extension from here http://www.wikihow.com/x/multipleupload.tar,
 18+in your base Mediawiki directory. It will place SpecialMultipleUpload.php
 19+in your extensions directory.
 20+
 21+Add the line
 22+
 23+ require_once("extensions/MultiUpload/SpecialMultipleUpload.php");
 24+
 25+to your LocalSettings.php file.
 26+
 27+
 28+=== Configuration ===
 29+
 30+You can change the maximum number of files a user can upload at once by
 31+changing $wgMaxUploadFiles. Then all you have to do is put a link somewhere
 32+to Special:MultipleUpload.
 33+
 34+=== License ===
 35+ * @author Travis Derouin <travis@wikihow.com>
 36+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 37+ * @homepage http://www.wikihow.com/WikiHow:MultipleUpload-Extension
 38+
 39+