In light of religious terrorist attacks in Paris, please see Category:blasphemy!

Freedom Porn:free technology/Submission Upload

From Freedom Porn
Jump to: navigation, search

Submission Upload is a MediaWiki extension that makes it easier for those who are not familiar with the upload process to do everything correctly. It normalises the names to the form of Author - Title.ext and ensures that extension is checked and made the same for all files of the same type.

Licence

Available under the terms of GNU General Public License 3.0

Produced in the year 2013.
GPLv3
For more information please see Freedom Porn:copyrights.


Installation

Put the files from #Code into $IP/extensions/SubmissionUpload and then add the following to LocalSettings.php.

require_once("{$IP}/extensions/SubmissionUpload/SubmissionUpload.php");

Configuration

Default configuration is inside the #DefaultSettings.php. It should give one an idea of how to generate different upload forms.

Known issues

  • Configuration is rather complicated.
  • Need better look and feel.
  • Many hooks are not called.
    • Because of that LicenceOnUpload is not working. So far it's implemented into the body of this extension with the assumed default settings.

Code

SubmissionUpload.php

<?php
/**
 * @file SubmissionUpload.php
 * @author VolodyA! V Anarhist
 * @ingroup Extensions
 * @comment Eases the upload process by giving several fields that get connected to the template.
 * @copyright VolodyA! V Anarhist
 * @license GPL 3.0
**/
 
if ( !defined( 'MEDIAWIKI' ) )
{
  echo <<<EOT
To install SubmissionUpload, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/SubmissionUpload/SubmissionUpload.php" );
EOT;
  exit( 1 );
}
 
$wgExtensionCredits['specialpage'][] = array
(
  'path' => __FILE__,
  'name' => 'Submission Upload',
  'descriptionmsg' => 'submissionupload-description',
  'version' => '0.9.1',
  'author' => '[http://www.freedomporn.org/smut/User:VolodyA!_V_Anarhist VolodyA! V Anarhist]',
  'url' => 'http://www.freedomporn.org/smut/Freedom_Porn:free_technology/Submission_Upload',
);
 
// Setting up the special page
$wgSpecialPages['SubmissionUpload'] = 'SpecialSubmissionUpload'; // class
$wgAutoloadClasses['SpecialSubmissionUpload'] = __DIR__.'/SpecialSubmissionUpload.php'; // file
 
$wgSpecialPageGroups['SubmissionUpload'] = 'media'; // category of the special page
 
// Setting up the language
$wgExtensionMessagesFiles['SubmissionUpload'] = __DIR__.'/SubmissionUpload.i18n.php'; // messages
$wgExtensionMessagesFiles['SubmissionUploadAlias' ] = __DIR__.'/SubmissionUpload.alias.php'; // alias
 
// Settings (initialisation, can and should be overridden in LocalSettings.php)
require_once( __DIR__.'/DefaultSettings.php' );

SpecialSubmissionUpload.php

<?php
/**
 * @file SpecialSubmissionUpload.php
 * @author VolodyA! V Anarhist
 * @ingroup Extensions
 * @comment Eases the upload process by giving several fields that get connected to the template.
 * @copyright VolodyA! V Anarhist
 * @license GPL 3.0
**/
 
if ( !defined( 'MEDIAWIKI' ) )
{
  echo <<<EOT
To install SubmissionUpload, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/SubmissionUpload/SubmissionUpload.php" );
EOT;
  exit( 1 );
}
 
require_once(__DIR__.'/UploadFromSubmission.php');
 
/**
 * TODO:
 * 1. Make the class a subclass of SpecialUpload
 * 2. Reimplement form generation via HTMLForm
 * 2.1. Resturcture HTML to allow the correct generation of the LicenceOnUpload
 * 3. Implement AJAX warnings
 * 4. More use of the language messages, allowing for more internationalisation
 * 5. Collapsable table with some options hidden by default
 */
 
class SpecialSubmissionUpload extends SpecialPage
{
  public $mBase;
  public $mTitle;
  public $mSubmitter;
  public $mSpoiler;
  public $mLocalFile;
  public $mIgnoreWarning;
  public $mWatch;
  public $mInitialName;
  public $mPageWikiText;
 
  function __construct()
  {
    SpecialPage::__construct( 'SubmissionUpload', 'upload' );
 
    $this->mIgnoreWarning = false;
    $this->mWatch = true;
  }
 
 
  function execute( $par )
  {
    global $wgSubmissionUploadsTemplates;
 
    $request = $this->getRequest();
    $output = $this->getOutput();
 
    $this->addCSS();
 
    // Check if the user can upload
    if ( !$this->userCanExecute( $this->getUser() ) )
    {
//      $this->displayRestrictionError();
      $output->setPageTitle('Please login first');
 
      $output->addWikiText('In order to access this page you first need to [[Special:UserLogin|login]].');
      return;
    }
 
    $this->setHeaders();
 
    $result = '';
 
    if ( $par=='' )
    {
      $result = $this->generateMainMenu();
    }
    elseif ( !array_key_exists( $par, $wgSubmissionUploadsTemplates ) )
    {
      $result .= $this->sandboxParse("The type '{$par}' is not defined. Please go to [[Special:SubmissionUpload]] and select a valid one.");
    }
    elseif ( !$request->wasPosted() ) // valid, but not yet uploaded
    {
      $output->setPageTitle("{$this->getOutput()->getPageTitle()} ({$par})");
      $result .= $this->generateUploadForm( $par );
    }
    else // processing upload
    {
      // Validate
      $errors=array();
      foreach ( $wgSubmissionUploadsTemplates[$par]['attributes'] as $attr => $attrArray )
      {
        if ( $attrArray['required'] && !$request->getText($attr) )
        {
          $errors[$attr] = 'This value is required';
        }
      }
      if( !empty($errors) )
      {
        $result .= $this->generateUploadForm( $par, $errors );
      }
      else
      {
        // Compose
        wfDebug(__METHOD__.' temp file name is '.$request->getUpload('wfUploadFile')->getTempName().PHP_EOL);
 
        $this->mBase = UploadBase::createFromRequest( $request, 'Submission' );
 
        // Save
        $this->processUpload($par);
 
        // Notify
        $mail_to=$wgEmergencyContact;
        $mail_subject='=?UTF-8?B?'.base64_encode('Freedom Porn: Submission Upload').'?=';
        $mail_from=$wgPasswordSender;
        $mail_replyto=$from;
        $mail_xmailer="FreedomPorn.org Submission Upload running on PHP/".phpversion();
        $mail_headers = "From: {$mail_from}\r\n";
        $mail_headers.= "Reply-To: {$mail_replyto}\r\n";
        $mail_headers.= "MIME-Version: 1.0\r\n";
        $mail_headers.= "Content-type: text/plain; charset=utf-8\r\n";
        $mail_headers.="Content-Transfer-Encoding: 8bit\r\n";
        $mail_headers.= "X-Mailer: {$mail_xmailer}";
        $mail_url = $this->mLocalFile->getTitle()->getFullURL();
        $mail_body=<<<MAILBODY
{$this->mSubmitter} has uploaded a new file "{$this->mTitle}"
 
{$mail_url}
MAILBODY;
 
        if(!mail($mail_to, $mail_subject, $mail_body, $mail_headers))
        {
          wfDebug(__METHOD__.' Failure to send the notification e-mail.'.PHP_EOL);
        }
 
        // Cleanup
        if ( $this->mUpload )
        {
          $this->mUpload->cleanupTempFile();
        }
 
      }
    }
 
    $output->addHtml( $result );
  }
 
  protected function processUpload($par)
  {
    global $wgUser, $wgOut;
 
/* Non-action needed to fetch from URL and stuff
    // Fetch the file if required
    $status = $this->mBase->fetchFile();
    if( !$status->isOK() )
    {
      $wgOut->addWikiText($status->getWikiText());
      $this->showUploadError( $wgOut->parse( $status->getWikiText() ) );
      return;
    }
*/
 
    // Upload verification
		$details = $this->mBase->verifyUpload();
		if ( $details['status'] != UploadBase::OK )
    {
			//$this->processVerificationError( $details );
      $wgOut->addWikiText("Failed verification with status {$details['status']}");
			return;
		}
 
		// Verify permissions for this title
		$permErrors = $this->mBase->verifyTitlePermissions( $wgUser );
		if( $permErrors !== true )
    {
			$code = array_shift( $permErrors[0] );
      $wgOut->addWikiText("Permissions error Code#{$code}");
			//$this->showRecoverableUploadError( wfMsgExt( $code,
			//		'parseinline', $permErrors[0] ) );
			return;
		}
 
 
		// Check warnings if necessary
		if( !$this->mIgnoreWarning )
    {
			$warnings = $this->mBase->checkWarnings();
			if( false /*$this->showUploadWarning( $warnings )*/ )
      {
				return;
			}
		}
 
    $request = $this->getRequest();
    $upload = $request->getUpload( 'wpUploadFile');
 
    $this->mTitle = $request->getText( 'name' );
    $this->mSubmitter = $request->getText( 'submitter' );
    $this->mSpoiler = $request->getText( 'spoiler' );
    $this->mLocalFile = $this->mBase->getLocalFile();
    $this->mInitialName = $upload->getName();
    $this->mPageWikiText = $this->generatePageText($par);
 
    $comment = "[[Special:SubmissionUpload]]: {$this->mTitle} ~ {$this->mSpoiler}";
		$status = $this->mBase->performUpload( $comment, $this->mPageWikiText, $this->mWatch, $wgUser );
		if ( !$status->isGood() )
    {
      $wgOut->addWikiText( $status->getWikiText() );
//			$this->showUploadError( $wgOut->parse( $status->getWikiText() ) );
			return;
		}
 
		// Success, redirect to description page
		$this->mUploadSuccessful = true;
		wfRunHooks( 'SpecialUploadComplete', array( &$this ) );
		$wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() );
  }
 
  protected function generateMainMenu()
  {
    global $wgSubmissionUploadsTemplates;
 
    $wikitext = 'Please select:'.PHP_EOL;
    foreach ( $wgSubmissionUploadsTemplates as $type => $settings )
    {
      $wikitext .= '* <big>\'\'\'[[Special:SubmissionUpload/'.$type.'|'.$type.']]\'\'\'</big> &mdash; '.$settings['description'].PHP_EOL;
    }
    $wikitext .= 'To upload video or audio files please use [http://www.whengendarmesleeps.org/submissions/send.php media submitter].'.PHP_EOL.PHP_EOL;
    $wikitext .= 'If you are an advanced user you may also try [[Special:Upload]].'.PHP_EOL.PHP_EOL;
 
    $result = $this->sandboxParse($wikitext);
 
    return $result;
  }
 
  protected function generatePageText($par)
  {
    global $wgSubmissionUploadsTemplates;
 
    $request = $this->getRequest();
 
    $year=date('Y');
    $month=date('F');
    $day=date('j');
 
    $result = '{{'.$par.PHP_EOL;
    // TODO: find out if it's faster to run array_keys first
    foreach($wgSubmissionUploadsTemplates[$par]['attributes'] as $attribute=>$value)
    {
      $result .= '|'.$attribute.'='.$request->getText($attribute).PHP_EOL;
    }
    $result .= '}}'.PHP_EOL.PHP_EOL;
 
    $result .= <<<WIKITEXT
<!-- Initial filename={$this->mInitialName} -->
 
{{free art
|year={$year}
|month={$month}
|day={$day}
}}
 
[[Category:uploaded with Submission Upload]]
WIKITEXT;
 
    return $result;
  }
 
  private function generateJavascript( $par )
  {
    global $wgSubmissionUploadsTemplates;
    // prepare possible extensions
    $extKey = $wgSubmissionUploadsTemplates[$par]['extension'];
    $extSettings = $wgSubmissionUploadsTemplates[$par]['attributes'][$extKey]['options'];
    $exts = array();
 
    $extsJsArray = '[';
    $first=true;
    foreach($extSettings as $type)
    {
      $exts = array_merge(array($type['extension']), $type['otherextensions'] ? $type['otherextensions'] : array() );
 
      if(!$first) $extsJsArray .= ',';
      $extsJsArray .= '["'.implode('", "', $exts).'"]';
 
      $first=false;
    }
    $extsJsArray .= ']';
 
    // generate script
    // thanks to http://stackoverflow.com/questions/190852/how-can-i-get-file-extensions-with-javascript
    $result = <<<SCRIPT
<script type='text/javascript'>
function doShowHide(tableId)
{
	if ( document.getElementById(tableId).className.match(/(?:^|\s)collapsed(?!\S)/) )
	{
		document.getElementById(tableId).className='expanded';
		document.getElementById(tableId+'_collapselabel').innerHTML='Hide extra options';
	}
	else
	{
		document.getElementById(tableId).className='collapsed';
		document.getElementById(tableId+'_collapselabel').innerHTML='Show more options';
	}
}
 
function getExt(fname)
{
  var a = fname.split('.');
  if( a.length == 1 || ( a[0] == '' && a.length == 2 ) )
  {
    return '';
  }
  return a.pop();
}
 
function setTypeInDocument( selectName )
{
  var fname = document.getElementById('wpUploadFile').value;
  var extension = getExt(fname);
  var type = getType(extension);
  document.getElementById(selectName).value = type;
}
 
function getType( extension )
{
  extension = extension.toLowerCase();
 
  var exts = {$extsJsArray};
  for(var extArray in exts)
  {
    for (var key in exts[extArray])
    {
      if (exts[extArray][key] == extension)
      {
        return exts[extArray][0].toUpperCase();
      }
    }
  }
  return false;
}
</script>
SCRIPT;
    return $result;
  }
 
  protected function addCSS()
  {
    $output = $this->getOutput();
 
    $output->addStyle(__DIR__.'/SpecialSubmissionUpload.css');
  }
 
  protected function generateUploadForm( $par, array $errors=array(), array $defaults=array() )
  {
    global $wgSubmissionUploadsTemplates;
 
    if(!empty($errors))
    {
      $numErrors=count($errors);
      $result .= $this->sandboxParse("Number of errors: {$numErrors}");
      $result .= $this->sandboxParse("Please fill all fields marked red");
      $result .= '<hr/>';
    }
 
    $settings=$wgSubmissionUploadsTemplates[$par];
    $result .= $this->sandboxParse("Uploading {$par}, if you mean to upload a different type of a file please go to [[Special:SubmissionUpload]] and make another selection.");
    $result .= $this->sandboxParse("All the uploads '''must be your own work''' and licenced under [[Free Art Licence]].");
 
    $result .= $this->generateJavascript( $par );
 
    $result .= "<form enctype='multipart/form-data' method='POST' id='mw-submission-upload-form' >".
               "<input type='hidden' name='wpSourceType' value='Submission' />".
               "<input type='hidden' name='extension' value='{$wgSubmissionUploadsTemplates[$par]['extension']}' />";
 
    $result .= "<table id='specialuploadtable' width='100%' border='2' class='collapsed'><tbody>";
 
    foreach ( $settings['attributes'] as $attr => $attrArray )
    {
      if( array_key_exists($attr, $errors) )
      {
        $errorSettings = ' bgcolor=\'red\'';
      }
      else
      {
        $errorSettings = '';
      }
      if( isset($attrArray['advanced']) && $attrArray['advanced'] )
      {
        $rowclass='collapsable';
      }
      $result .= "<tr class='{$rowclass}' id='specialuploadtable'><td{$errorSettings} title='{$attr}'><strong>{$attrArray['description']}</strong></td>";
      $defValue = '';
      switch( $attrArray['type'] )
      {
        case 'input':
        case 'text':
          if( isset($attrArray['default']) && !empty($attrArray['default']) )
          {
            $attrArray['default']=str_replace('USERNAME',$this->getUser()->getName(),$attrArray['default']);
            $defValue = " value='{$attrArray['default']}'";
          }
          $result .= "<td><input name='{$attr}' type='text' size='{$attrArray['size']}' {$defValue}/></td>";
          break;
        case 'number':
          if( isset($attrArray['default']) && !empty($attrArray['default']) )
          {
            $defValue = " value='{$attrArray['default']}'";
          }
          $result .= "<td><input name='{$attr}' type='number' size='{$attrArray['size']}' min='{$attrArray['min']}' {$defValue} /></td>";
          break;
        case 'textarea':
          if( isset($attrArray['default']) && !empty($attrArray['default']) )
          {
            $defValue = $attrArray['default'];
          }
          $result .= "<td>&nbsp;</td></tr><tr><td colspan='3'>".
                     "<textarea name='{$attr}' cols='{$attrArray['cols']}' rows='{$attrArray['rows']}'>{$defValue}</textarea>".
                     "</td>";
          break;
        case 'file':
          $result .= "<td><input type='file' name='{$attr}' id='{$attr}'".
              ($attrArray['multiple']?" multiple='multiple'":"").
              " onchange='{$attrArray['onchange']}'".
              "</td>";
          break;
        case 'select':
          $result .= "<td><select name='{$attr}' id='{$attr}'>";
          foreach ( $attrArray['options'] as $option => $optionArray )
          {
            $result .= "<option title='{$optionArray['description']}'>{$option}</option>";
          }
          $result .= "</select></td>";
          break;
      }
      $result .= "</tr>";
    }
    $result .= "<tr><td colspan='2' align=center>".
        "<a href='#' id='specialuploadtable_collapselabel' onclick='doShowHide(\"specialuploadtable\"); return false;'>Show more options</a></td></tr>";
    $result .= "</tbody></table>";
    $result .= "<input width='200%' height='200%' type='submit' value='Upload' />";
    $result .= "</form>";
    return $result;
  }
 
  private function sandboxParse($wikiText) {
    global $wgTitle, $wgUser;
    $myParser = new Parser();
    $myParserOptions = ParserOptions::newFromUser($wgUser);
    $result = $myParser->parse($wikiText, $wgTitle, $myParserOptions);
    return $result->getText();
  }
}

UploadFromSubmission.php

<?php
/**
 * @file UploadFromSubmission.php
 * @author VolodyA! V Anarhist
 * @ingroup Extensions
 * @comment Eases the upload process by giving several fields that get connected to the template.
 * @copyright VolodyA! V Anarhist
 * @license GPL 3.0
**/
 
if ( !defined( 'MEDIAWIKI' ) )
{
  echo <<<EOT
To install SubmissionUpload, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/SubmissionUpload/SubmissionUpload.php" );
EOT;
  exit( 1 );
}
 
UploadBase::$uploadHandlers[] = 'Submission';
 
class UploadFromSubmission extends UploadFromFile
{
  function __construct() {}
 
  /**
   * @param $request WebRequest
   */
  function initializeFromRequest( &$request )
  {
    global $wgSubmissionUploadTypes;
 
    $upload = $request->getUpload( 'wpUploadFile' );
 
    $desiredTitle = $request->getText( 'name' );
    $desiredSubmitter = $request->getText( 'submitter' );
    $extensionField = $request->getText( 'extension' );
    $desiredExtension = $wgSubmissionUploadTypes[$request->getText( $extensionField )]['extension'];
 
    $desiredDestName = "{$desiredSubmitter} - {$desiredTitle}.{$desiredExtension}";
 
    return $this->initialize( $desiredDestName, $upload );
  }
 
  /**
   * @return string
   */
  public function getSourceType() {
    return 'submission';
  }
 
}

SpecialSubmissionUpload.css

.collapsed tr.collapsable
{
	display: none;
}

SubmissionUpload.i18n.php

<?php
/**
 * @file SubmissionUpload.i18n.php
 * @author VolodyA! V Anarhist
 * @ingroup Extensions
 * @comment Eases the upload process by giving several fields that get connected to the template.
 * @copyright VolodyA! V Anarhist
 * @license GPL 3.0
**/
 
if ( !defined( 'MEDIAWIKI' ) )
{
  echo <<<EOT
To install submissionupload, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/SubmissionUpload/SubmissionUpload.php" );
EOT;
  exit( 1 );
}
 
$messages = array();
 
/** Message documentation
 * @author VolodyA! V Anarhist
 */
$messages['qqq'] = array(
  'submissionupload-description' => "{{desc}}",
);
 
/** English
 * @author VolodyA! V Anarhist
 */
$messages['en'] = array(
  'submissionupload' => 'Submission Upload',
  'submissionupload-description' => "Provides [[Special:SubmissionUpload]] that eases the upload process by giving several fields that get connected to the template.",
);
 
/** Russian
 * @author VolodyA! V Anarhist
 */
$messages['ru'] = array(
  'submissionupload' => 'Загрузка Предоставленного',
  'submissionupload-description' => "Создаёт [[Special:ЗагрузкаПредоставленного]], которая упрощает процес загрузки, предоставляя несколько полей для подключения к конкретному шаблону.",
);

SubmissionUpload.alias.php

<?php
/**
 * @file SubmissionUpload.alias.php
 * @author VolodyA! V Anarhist
 * @ingroup Extensions
 * @comment Eases the upload process by giving several fields that get connected to the template.
 * @copyright VolodyA! V Anarhist
 * @license GPL 3.0
**/
 
if ( !defined( 'MEDIAWIKI' ) )
{
  echo <<<EOT
To install SubmissionUpload, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/SubmissionUpload/SubmissionUpload.php" );
EOT;
        exit( 1 );
}
 
$specialPageAliases = array();
 
/** English
 * @author VolodyA! V Anarhist
 */
$specialPageAliases['en'] = array(
        'SubmissionUpload' => array( 'SubmissionUpload', 'Porn Upload' ),
);
 
/** Russian
 * @author VolodyA! V Anarhist
 */
$specialPageAliases['ru'] = array(
        'SubmissionUpload' => array( 'ПорноЗагрузка', 'Порно Загрузка' ),
);

DefaultSettings.php

<?php
/**
 * @file DefaultSettings.php
 * @author VolodyA! V Anarhist
 * @ingroup Extensions
 * @comment Eases the upload process by giving several fields that get connected to the template.
 * @copyright VolodyA! V Anarhist
 * @license GPL 3.0
**/
 
if ( !defined( 'MEDIAWIKI' ) )
{
  echo <<<EOT
To install SubmissionUpload, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/SubmissionUpload/SubmissionUpload.php" );
EOT;
  exit( 1 );
}
 
  // initialising the main array
$wgSubmissionUploadsTemplates=array();
 
  // some common settings
$name = array (
  'required' => true,
  'description' => 'Title of the work',
  'type' => 'input',
  'size' => 60,
);
$submitter = array(
  'required' => true,
  'description' => 'Name of the submitter',
  'type' => 'input',
  'size' => 60,
  'default' => 'USERNAME', // Cannot subst it at this point because $wgUser isn't there yet
);
$spoiler = array(
  'required' => true,
  'description' => 'Description that will be presented in the collapsed state, it should describe the image in detail',
  'type' => 'textarea',
  'cols' => 54,
  'rows' => 3,
);
 
$wgSubmissionUploadTypes = array();
$wgSubmissionUploadTypes['JPEG'] = array(
  'description' => 'lossy format commonly used for photographs',
  'mime' => 'image/jpeg',
  'extension' => 'jpeg',
  'otherextensions' => array( 'jpe', 'jpg' ),
);
$wgSubmissionUploadTypes['PNG'] = array(
  'description' => 'lossless format, best suited for graphics',
  'mime' => 'image/png',
  'extension' => 'png',
);
$wgSubmissionUploadTypes['SVG'] = array(
  'description' => 'vector graphics format',
  'mime' => 'image/svg+xml',
  'extension' => 'svg',
);
$wgSubmissionUploadTypes['GIF'] = array(
  'description' => 'lossless format with few colours, best suited for graphics',
  'mime' => 'image/gif',
  'extension' => 'gif',
);
$wgSubmissionUploadTypes['Animated SVG'] = array(
  'description' => 'vector graphics format with animation',
  'mime' => 'image/svg+xml',
  'extension' => 'ani.svg',
);
$wgSubmissionUploadTypes['Animated GIF'] = array(
  'description' => 'lossless format with few colours with animation',
  'mime' => 'image/gif',
  'extension' => 'ani.gif',
  'otherextensions' => array('gif'),
);
 
$wgSubmissionUploadsTemplates['image'] = array(
  'description' => 'Individual images that are not a part of a sequence. [[:Category:individual images|examples]]',
  'extension' => 'imageformat',
  'attributes' => array(
    'wpUploadFile' => array(
      'required' => true,
      'description' => 'File that you wish to upload',
      'type' => 'file',
      'multiple' => false,
      'onchange' => 'setTypeInDocument("imageformat");'
    ),
    'name' => $name,
    'submitter' => $submitter,
    'spoiler' => $spoiler,
    'imageformat' => array(
      'required' => false,
      'advanced' => true,
      'description' => 'What is the format of this image?',
      'type' => 'select',
      'options' => array(
        'JPEG' => $wgSubmissionUploadTypes['JPEG'],
        'PNG' => $wgSubmissionUploadTypes['PNG'],
        'GIF' => $wgSubmissionUploadTypes['GIF'],
        'SVG' => $wgSubmissionUploadTypes['SVG'],
      ),
    ),
  ),
);
$wgSubmissionUploadsTemplates['collage'] = array(
  'description' => 'A single file which contains several images in a collage. [[:Category:collages|examples]]',
  'extension' => 'imageformat',
  'attributes' => array(
    'wpUploadFile' => array(
      'required' => true,
      'description' => 'File that you wish to upload',
      'type' => 'file',
      'multiple' => false,
      'onchange' => 'setTypeInDocument("imageformat");'
    ),
    'name' => $name,
    'submitter' => $submitter,
    'spoiler' => $spoiler,
    'imageformat' => array(
      'required' => false,
      'advanced' => true,
      'description' => 'What is the format of this image?',
      'type' => 'select',
      'options' => array(
        'JPEG' => $wgSubmissionUploadTypes['JPEG'],
        'PNG' => $wgSubmissionUploadTypes['PNG'],
        'GIF' => $wgSubmissionUploadTypes['GIF'],
        'SVG' => $wgSubmissionUploadTypes['SVG'],
      ),
    ),
  ),
);
$wgSubmissionUploadsTemplates['animation'] = array(
  'description' => 'A file which plays a silent animation, usually a special image file. [[:Category:animations|examples]]',
  'extension' => 'container',
  'attributes' => array(
    'wpUploadFile' => array(
      'required' => true,
      'description' => 'File that you wish to upload',
      'type' => 'file',
      'multiple' => false,
      'onchange' => 'setTypeInDocument("imageformat");'
    ),
    'name' => $name,
    'submitter' => $submitter,
    'spoiler' => $spoiler,
    'length' => array(
      'required' => false,
      'advanced' => true,
      'description' => 'Length of time of a single loop.',
      'type' => 'input',
      'size' => 60,
    ),
    'loop' => array(
      'required' => false,
      'advanced' => true,
      'description' => 'How many times the animation loops. Put 0 for infinite.',
      'type' => 'number',
      'size' => 60,
      'min' => 0,
    ),
    'container' => array(
      'required' => false,
      'advanced' => true,
      'description' => 'What is the format of this image?',
      'type' => 'select',
      'options' => array(
        'GIF' => $wgSubmissionUploadTypes['Animated GIF'],
        'SVG' => $wgSubmissionUploadTypes['Animated SVG'],
      ),
    ),
  ),
);

See also