diff options
Diffstat (limited to 'www/wiki/extensions/UploadWizard/includes/specials/SpecialUploadWizard.php')
-rw-r--r-- | www/wiki/extensions/UploadWizard/includes/specials/SpecialUploadWizard.php | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/www/wiki/extensions/UploadWizard/includes/specials/SpecialUploadWizard.php b/www/wiki/extensions/UploadWizard/includes/specials/SpecialUploadWizard.php new file mode 100644 index 00000000..676f3a9f --- /dev/null +++ b/www/wiki/extensions/UploadWizard/includes/specials/SpecialUploadWizard.php @@ -0,0 +1,366 @@ +<?php +/** + * Special:UploadWizard + * + * Easy to use multi-file upload page. + * + * @file + * @ingroup SpecialPage + * @ingroup Upload + */ + +class SpecialUploadWizard extends SpecialPage { + /** + * The name of the upload wizard campaign, or null when none is specified. + * + * @since 1.2 + * @var string|null + */ + protected $campaign = null; + + /** + * @param WebRequest $request the request (usually wgRequest) + * @param string|null $par everything in the URL after Special:UploadWizard. + * Not sure what we can use it for + */ + public function __construct( $request = null, $par = null ) { + parent::__construct( 'UploadWizard', 'upload' ); + } + + /** + * Replaces default execute method + * Checks whether uploading enabled, user permissions okay, + * @param string|null $subPage subpage, e.g. the "foo" in Special:UploadWizard/foo. + */ + public function execute( $subPage ) { + // side effects: if we can't upload, will print error page to wgOut + // and return false + if ( !( $this->isUploadAllowed() && $this->isUserUploadAllowed( $this->getUser() ) ) ) { + return; + } + + $this->setHeaders(); + $this->outputHeader(); + + $req = $this->getRequest(); + + $urlArgs = [ 'caption', 'description', 'lat', 'lon', 'alt' ]; + + $urlDefaults = []; + foreach ( $urlArgs as $arg ) { + $value = $req->getText( $arg ); + if ( $value ) { + $urlDefaults[$arg] = $value; + } + } + + $categories = $req->getText( 'categories' ); + if ( $categories ) { + $urlDefaults['categories'] = explode( '|', $categories ); + } + + $urlDefaults['objref'] = $req->getText( 'objref' ) ?: ''; + $urlDefaults['updateList'] = $req->getText( 'updateList' ) ?: ''; + + UploadWizardConfig::setUrlSetting( 'defaults', $urlDefaults ); + + $fields = $req->getArray( 'fields' ); + $fieldDefaults = []; + + # Support id and id2 for field0 and field1 + # Legacy support for old URL structure. They override fields[] + if ( $req->getText( 'id' ) ) { + $fields[0] = $req->getText( 'id' ); + } + + if ( $req->getText( 'id2' ) ) { + $fields[1] = $req->getText( 'id2' ); + } + + if ( $fields ) { + foreach ( $fields as $index => $value ) { + $fieldDefaults[$index]['initialValue'] = $value; + } + } + + UploadWizardConfig::setUrlSetting( 'fields', $fieldDefaults ); + + $this->handleCampaign(); + + $out = $this->getOutput(); + + // fallback for non-JS + $out->addHTML( '<div class="mwe-upwiz-unavailable">' ); + $out->addHTML( '<p class="errorbox">' . $this->msg( 'mwe-upwiz-unavailable' )->parse() . '</p>' ); + // create a simple form for non-JS fallback, which targets the old Special:Upload page. + // at some point, if we completely subsume its functionality, change that to point here again, + // but then we'll need to process non-JS uploads in the same way Special:Upload does. + $derivativeContext = new DerivativeContext( $this->getContext() ); + $derivativeContext->setTitle( SpecialPage::getTitleFor( 'Upload' ) ); + $simpleForm = new UploadWizardSimpleForm( [], $derivativeContext, $this->getLinkRenderer() ); + $simpleForm->show(); + $out->addHTML( '</div>' ); + + // global javascript variables + $this->addJsVars( $subPage ); + + // dependencies (css, js) + $out->addModules( 'uw.EventFlowLogger' ); + $out->addModules( 'ext.uploadWizard.page' ); + $out->addModuleStyles( 'ext.uploadWizard.page.styles' ); + + // where the uploadwizard will go + // TODO import more from UploadWizard's createInterface call. + $out->addHTML( $this->getWizardHtml() ); + } + + /** + * Handles the campaign parameter. + * + * @since 1.2 + */ + protected function handleCampaign() { + $campaignName = $this->getRequest()->getVal( 'campaign' ); + if ( is_null( $campaignName ) ) { + $campaignName = UploadWizardConfig::getSetting( 'defaultCampaign' ); + } + + if ( !is_null( $campaignName ) && $campaignName !== '' ) { + $campaign = UploadWizardCampaign::newFromName( $campaignName ); + + if ( $campaign === false ) { + $this->displayError( $this->msg( 'mwe-upwiz-error-nosuchcampaign', $campaignName )->text() ); + } else { + if ( $campaign->getIsEnabled() ) { + $this->campaign = $campaignName; + } else { + $this->displayError( $this->msg( 'mwe-upwiz-error-campaigndisabled', $campaignName )->text() ); + } + } + } + } + + /** + * Display an error message. + * + * @since 1.2 + * + * @param string $message + */ + protected function displayError( $message ) { + $this->getOutput()->addHTML( Html::element( + 'span', + [ 'class' => 'errorbox' ], + $message + ) . '<br /><br /><br />' ); + } + + /** + * Adds some global variables for our use, as well as initializes the UploadWizard + * + * TODO once bug https://bugzilla.wikimedia.org/show_bug.cgi?id=26901 + * is fixed we should package configuration with the upload wizard instead of + * in uploadWizard output page. + * + * @param string $subPage subpage, e.g. the "foo" in Special:UploadWizard/foo + */ + public function addJsVars( $subPage ) { + $config = UploadWizardConfig::getConfig( $this->campaign ); + + if ( array_key_exists( 'trackingCategory', $config ) ) { + if ( array_key_exists( 'campaign', $config['trackingCategory'] ) ) { + if ( $this->campaign !== null ) { + $config['trackingCategory']['campaign'] = str_replace( + '$1', + $this->campaign, + $config['trackingCategory']['campaign'] + ); + } else { + unset( $config['trackingCategory']['campaign'] ); + } + } + } + // UploadFromUrl parameter set to true only if the user is allowed to upload a file + // from a URL which we need to check in our Javascript implementation. + if ( UploadFromUrl::isEnabled() && UploadFromUrl::isAllowed( $this->getUser() ) === true ) { + $config['UploadFromUrl'] = true; + } else { + $config['UploadFromUrl'] = false; + } + + // Get the user's default license. This will usually be 'default', but + // can be a specific license like 'ownwork-cc-zero'. + $userDefaultLicense = $this->getUser()->getOption( 'upwiz_deflicense' ); + + if ( $userDefaultLicense !== 'default' ) { + $licenseParts = explode( '-', $userDefaultLicense, 2 ); + $userLicenseType = $licenseParts[0]; + $userDefaultLicense = $licenseParts[1]; + + // Determine if the user's default license is valid for this campaign + switch ( $config['licensing']['ownWorkDefault'] ) { + case "own": + $defaultInAllowedLicenses = in_array( + $userDefaultLicense, $config['licensing']['ownWork']['licenses'] + ); + break; + case "notown": + $defaultInAllowedLicenses = in_array( + $userDefaultLicense, UploadWizardConfig::getThirdPartyLicenses() + ); + break; + case "choice": + $defaultInAllowedLicenses = ( in_array( + $userDefaultLicense, $config['licensing']['ownWork']['licenses'] + ) || + in_array( $userDefaultLicense, UploadWizardConfig::getThirdPartyLicenses() ) ); + break; + } + + if ( $defaultInAllowedLicenses ) { + if ( $userLicenseType === 'ownwork' ) { + $userLicenseGroup = 'ownWork'; + } else { + $userLicenseGroup = 'thirdParty'; + } + $config['licensing'][$userLicenseGroup]['defaults'] = [ $userDefaultLicense ]; + $config['licensing']['defaultType'] = $userLicenseType; + + if ( $userDefaultLicense === 'custom' ) { + $config['licenses']['custom']['defaultText'] = + $this->getUser()->getOption( 'upwiz_deflicense_custom' ); + } + } + } + + // add an 'uploadwizard' tag, but only if it'll be allowed + UploadWizardHooks::onListDefinedTags( $tags ); + $status = ChangeTags::canAddTagsAccompanyingChange( $tags, $this->getUser() ); + $config['CanAddTags'] = $status->isOK(); + + $bitmapHandler = new BitmapHandler(); + $this->getOutput()->addJsConfigVars( + [ + 'UploadWizardConfig' => $config, + 'wgFileCanRotate' => $bitmapHandler->canRotate(), + ] + ); + } + + /** + * Check if anyone can upload (or if other sitewide config prevents this) + * Side effect: will print error page to wgOut if cannot upload. + * @return boolean -- true if can upload + */ + private function isUploadAllowed() { + // Check uploading enabled + if ( !UploadBase::isEnabled() ) { + $this->getOutput()->showErrorPage( 'uploaddisabled', 'uploaddisabledtext' ); + return false; + } + + // Check whether we actually want to allow changing stuff + if ( wfReadOnly() ) { + throw new ReadOnlyError; + } + + // we got all the way here, so it must be okay to upload + return true; + } + + /** + * Check if the user can upload + * Side effect: will print error page to wgOut if cannot upload. + * @param User $user + * @throws PermissionsError + * @throws UserBlockedError + * @return boolean -- true if can upload + */ + private function isUserUploadAllowed( User $user ) { + // Check permissions + $permissionRequired = UploadBase::isAllowed( $user ); + if ( $permissionRequired !== true ) { + throw new PermissionsError( $permissionRequired ); + } + + // Check blocks + if ( $user->isBlocked() ) { + throw new UserBlockedError( $user->getBlock() ); + } + + // Global blocks + if ( $user->isBlockedGlobally() ) { + throw new UserBlockedError( $user->getGlobalBlock() ); + } + + // we got all the way here, so it must be okay to upload + return true; + } + + /** + * Return the basic HTML structure for the entire page + * Will be enhanced by the javascript to actually do stuff + * @return string html + */ + protected function getWizardHtml() { + global $wgExtensionAssetsPath; + + $config = UploadWizardConfig::getConfig( $this->campaign ); + + if ( array_key_exists( + 'display', $config ) && array_key_exists( 'headerLabel', $config['display'] ) + ) { + $this->getOutput()->addHtml( $config['display']['headerLabel'] ); + } + + if ( array_key_exists( 'fallbackToAltUploadForm', $config ) + && array_key_exists( 'altUploadForm', $config ) + && $config['altUploadForm'] != '' + && $config[ 'fallbackToAltUploadForm' ] + ) { + $linkHtml = ''; + $altUploadForm = Title::newFromText( $config[ 'altUploadForm' ] ); + if ( $altUploadForm instanceof Title ) { + $linkHtml = Html::rawElement( 'p', [ 'style' => 'text-align: center;' ], + Html::rawElement( 'a', [ 'href' => $altUploadForm->getLocalURL() ], + $config['altUploadForm'] + ) + ); + } + + return Html::rawElement( + 'div', + [], + Html::rawElement( + 'p', + [ 'style' => 'text-align: center' ], + wfMessage( 'mwe-upwiz-extension-disabled' )->text() + ) . $linkHtml + ); + } + + // always load the html: even if the tutorial is skipped, users can + // still move back to view it + $tutorialHtml = UploadWizardTutorial::getHtml( $this->campaign ); + + // TODO move this into UploadWizard.js or some other javascript resource so the upload wizard + // can be dynamically included ( for example the add media wizard ) + // @codingStandardsIgnoreStart + return '<div id="upload-wizard" class="upload-section">' . + '<div id="mwe-upwiz-tutorial-html" style="display:none;">' . + $tutorialHtml . + '</div>' . + // if loading takes > 2 seconds display spinner. Note we are evading Resource Loader here, and linking directly. Because we want an image to appear if RL's package is late. + // using some 's which is a bit of superstition, to make sure jQuery will hide this (it seems that it doesn't sometimes, when it has no content) + // the min-width & max-width is copied from the #uploadWizard properties, so in nice browsers the spinner is right where the button will go. + '<div id="mwe-first-spinner" style="min-width:750px; max-width:900px; height:200px; line-height:200px; text-align:center;">' . + ' <img src="' . $wgExtensionAssetsPath . '/UploadWizard/resources/images/24px-spinner-0645ad.gif" width="24" height="24" /> ' . + '</div>' . + '</div>'; + // @codingStandardsIgnoreEnd + } + + protected function getGroupName() { + return 'media'; + } +} |