{js application='wcf' file='WCF.ColorPicker' bundle='WCF.Combined'}
<script data-relocate="true">
require([
- 'WoltLabSuite/Core/Acp/Ui/Style/CoverPhoto/Delete', 'WoltLabSuite/Core/Acp/Ui/Style/CoverPhoto/Upload', 'WoltLabSuite/Core/Acp/Ui/Style/Favicon/Upload',
+ 'WoltLabSuite/Core/Acp/Ui/Style/Favicon/Upload',
'WoltLabSuite/Core/Acp/Ui/Style/Editor', 'WoltLabSuite/Core/Ui/Toggle/Input', 'Language'
], function(
- AcpUiStyleCoverPhotoDelete, AcpUiStyleCoverPhotoUpload, AcpUiStyleFaviconUpload,
+ AcpUiStyleFaviconUpload,
AcpUiStyleEditor, UiToggleInput, Language
) {
AcpUiStyleEditor.setup({
{if $action === 'edit'}
new AcpUiStyleFaviconUpload({@$style->styleID});
-
- {if MODULE_USER_COVER_PHOTO}
- Language.addObject({
- 'wcf.acp.style.coverPhoto.delete.confirmMessage': '{lang}wcf.acp.style.coverPhoto.delete.confirmMessage{/lang}',
- 'wcf.user.coverPhoto.upload.error.invalidExtension': '{lang}wcf.user.coverPhoto.upload.error.invalidExtension{/lang}',
- 'wcf.user.coverPhoto.upload.error.minHeight': '{lang}wcf.user.coverPhoto.upload.error.minHeight{/lang}',
- 'wcf.user.coverPhoto.upload.error.minWidth': '{lang}wcf.user.coverPhoto.upload.error.minWidth{/lang}',
- 'wcf.user.coverPhoto.upload.error.uploadFailed': '{lang}wcf.user.coverPhoto.upload.error.uploadFailed{/lang}'
- });
-
- AcpUiStyleCoverPhotoDelete.init({@$style->styleID});
- new AcpUiStyleCoverPhotoUpload({@$style->styleID});
- {/if}
{/if}
});
{event name='faviconFields'}
</section>
-
- <section class="section">
- <header class="sectionHeader">
- <h2 class="sectionTitle">{lang}wcf.acp.style.general.coverPhoto{/lang}</h2>
- <p class="sectionDescription">{lang}wcf.acp.style.general.coverPhoto.description{/lang}</p>
- </header>
-
- <dl>
- <dt><label for="coverPhoto">{lang}wcf.acp.style.coverPhoto{/lang}</label></dt>
- <dd>
- <div id="coverPhotoPreview" style="background-image: url({@$__wcf->getPath()}images/coverPhotos/{@$style->getCoverPhoto()})"></div>
- <div id="uploadCoverPhoto">
- <a href="#" class="button jsButtonDeleteCoverPhoto"{if !$style->coverPhotoExtension} style="display:none"{/if}>{lang}wcf.global.button.delete{/lang}</a>
- </div>
- <small>{lang}wcf.acp.style.coverPhoto.description{/lang}</small>
- </dd>
- </dl>
-
- {event name='coverPhotoFields'}
- </section>
{/if}
+
+ <section class="section">
+ <header class="sectionHeader">
+ <h2 class="sectionTitle">{lang}wcf.acp.style.general.coverPhoto{/lang}</h2>
+ <p class="sectionDescription">{lang}wcf.acp.style.general.coverPhoto.description{/lang}</p>
+ </header>
+
+ <dl{if $errorField == 'coverPhoto'} class="formError"{/if}>
+ <dt><label for="coverPhoto">{lang}wcf.acp.style.coverPhoto{/lang}</label></dt>
+ <dd>
+ {@$__wcf->getUploadHandler()->renderField('coverPhoto')}
+ {if $errorField == 'coverPhoto'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {elseif $errorType == 'minWidth' || $errorType == 'minHeight'}
+ {lang}wcf.image.coverPhoto.upload.error.{$errorType}{/lang}
+ {else}
+ {lang}wcf.acp.style.coverPhoto.error.{$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.acp.style.coverPhoto.description{/lang}</small>
+ </dd>
+ </dl>
+
+ {event name='coverPhotoFields'}
+ </section>
{event name='generalFieldsets'}
</div>
+++ /dev/null
-/**
- * Deletes the current style's default cover photo.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Acp/Ui/Style/CoverPhoto/Delete
- */
-define(['Ajax', 'Language', 'Ui/Confirmation', 'Ui/Notification'], function (Ajax, Language, UiConfirmation, UiNotification) {
- "use strict";
-
- var _button, _styleId;
-
- /**
- * @exports WoltLabSuite/Core/Acp/Ui/Style/CoverPhoto/Delete
- */
- return {
- /**
- * Initializes the delete handler and enables the delete button on upload.
- *
- * @param {int} styleId
- */
- init: function (styleId) {
- _styleId = styleId;
-
- _button = elBySel('.jsButtonDeleteCoverPhoto');
- _button.addEventListener(WCF_CLICK_EVENT, this._click.bind(this));
- },
-
- /**
- * Handles clicks on the delete button.
- *
- * @param {Event} event
- * @protected
- */
- _click: function (event) {
- event.preventDefault();
-
- UiConfirmation.show({
- confirm: Ajax.api.bind(Ajax, this),
- message: Language.get('wcf.acp.style.coverPhoto.delete.confirmMessage')
- });
- },
-
- _ajaxSuccess: function (data) {
- elById('coverPhotoPreview').style.setProperty('background-image', 'url(' + data.returnValues.url + ')', '');
-
- elHide(_button);
-
- UiNotification.show();
- },
-
- _ajaxSetup: function () {
- return {
- data: {
- actionName: 'deleteCoverPhoto',
- className: 'wcf\\data\\style\\StyleAction',
- objectIDs: [_styleId]
- }
- };
- }
- };
-});
+++ /dev/null
-/**
- * Handles uploading the style's cover photo.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Acp/Ui/Style/CoverPhoto/Upload
- */
-define(['Core', 'Dom/Traverse', 'Language', 'Ui/Notification', 'Upload'], function(Core, DomTraverse, Language, UiNotification, Upload) {
- "use strict";
-
- /**
- * @constructor
- */
- function AcpUiStyleCoverPhotoUpload(styleId) {
- this._styleId = ~~styleId;
-
- Upload.call(this, 'uploadCoverPhoto', 'coverPhotoPreview', {
- action: 'uploadCoverPhoto',
- className: 'wcf\\data\\style\\StyleAction'
- });
- }
- Core.inherit(AcpUiStyleCoverPhotoUpload, Upload, {
- /**
- * @see WoltLabSuite/Core/Upload#_createFileElement
- */
- _createFileElement: function(file) {
- return this._target;
- },
-
- /**
- * @see WoltLabSuite/Core/Upload#_getParameters
- */
- _getParameters: function() {
- return {
- styleID: this._styleId
- };
- },
-
- /**
- * @see WoltLabSuite/Core/Upload#_success
- */
- _success: function(uploadId, data) {
- var errorMessage = '';
- if (data.returnValues.url) {
- this._target.style.setProperty('background-image', 'url(' + data.returnValues.url + '?timestamp=' + Date.now() + ')', '');
-
- UiNotification.show();
- }
- else if (data.returnValues.errorType) {
- errorMessage = Language.get('wcf.user.coverPhoto.upload.error.' + data.returnValues.errorType);
- }
-
- elInnerError(this._button, errorMessage);
- }
- });
-
- return AcpUiStyleCoverPhotoUpload;
-});
use wcf\data\style\StyleAction;
use wcf\data\style\StyleEditor;
use wcf\data\template\group\TemplateGroup;
+use wcf\data\user\cover\photo\UserCoverPhoto;
use wcf\form\AbstractForm;
use wcf\system\event\EventHandler;
use wcf\system\exception\SystemException;
$field->setAllowSvgImage(true);
$field->maxFiles = 1;
$handler->registerUploadField($field);
+
+ if ($handler->isRegisteredFieldId('coverPhoto')) {
+ $handler->unregisterUploadField('coverPhoto');
+ }
+ $field = new UploadField('coverPhoto');
+ $field->setImageOnly(true);
+ $field->maxFiles = 1;
+ $handler->registerUploadField($field);
}
/**
if (isset($_POST['scrollOffsets']) && is_array($_POST['scrollOffsets'])) $this->scrollOffsets = ArrayUtil::toIntegerArray($_POST['scrollOffsets']);
$this->uploads = [];
- foreach (['image', 'image2x', 'pageLogo', 'pageLogoMobile'] as $field) {
+ foreach (['image', 'image2x', 'pageLogo', 'pageLogoMobile', 'coverPhoto'] as $field) {
$removedFiles = UploadHandler::getInstance()->getRemovedFiledByFieldId($field);
if (!empty($removedFiles)) {
$this->uploads[$field] = null;
if (count($files) > 1) {
throw new UserInputException($field, 'invalid');
}
+
+ // coverPhoto
+ $field = 'coverPhoto';
+ $files = UploadHandler::getInstance()->getFilesByFieldId($field);
+ if (count($files) > 1) {
+ throw new UserInputException($field, 'invalid');
+ }
+ if (!empty($files)) {
+ $fileLocation = $files[0]->getLocation();
+ if (($imageData = getimagesize($fileLocation)) === false) {
+ throw new UserInputException($field, 'invalid');
+ }
+ switch ($imageData[2]) {
+ case IMAGETYPE_PNG:
+ case IMAGETYPE_JPEG:
+ case IMAGETYPE_GIF:
+ // fine
+ break;
+ default:
+ throw new UserInputException($field, 'invalid');
+ }
+
+ if ($imageData[0] < UserCoverPhoto::MIN_WIDTH) {
+ throw new UserInputException('coverPhoto', 'minWidth');
+ }
+ if ($imageData[1] < UserCoverPhoto::MIN_HEIGHT) {
+ throw new UserInputException('coverPhoto', 'minHeight');
+ }
+ }
}
/**
'supportedApiVersions' => Style::$supportedApiVersions,
'newVariables' => $this->newVariables,
'scrollOffsets' => $this->scrollOffsets,
+ 'coverPhotoMinHeight' => UserCoverPhoto::MIN_HEIGHT,
+ 'coverPhotoMinWidth' => UserCoverPhoto::MIN_WIDTH,
]);
}
$this->styleVersion = $this->style->styleVersion;
$this->templateGroupID = $this->style->templateGroupID;
if ($this->style->image) {
- $file = new UploadFile(WCF_DIR.'images/'.$this->style->image, $this->style->image, true, true, true);
+ $file = new UploadFile(WCF_DIR.'images/'.$this->style->image, $this->style->image, true, true, false);
UploadHandler::getInstance()->registerFilesByField('image', [
$file,
]);
}
if ($this->style->image2x) {
- $file = new UploadFile(WCF_DIR.'images/'.$this->style->image2x, $this->style->image2x, true, true, true);
+ $file = new UploadFile(WCF_DIR.'images/'.$this->style->image2x, $this->style->image2x, true, true, false);
UploadHandler::getInstance()->registerFilesByField('image2x', [
$file,
]);
}
+ if ($this->style->coverPhotoExtension) {
+ $file = new UploadFile($this->style->getCoverPhotoLocation(), $this->style->getCoverPhoto(), true, true, false);
+ UploadHandler::getInstance()->registerFilesByField('coverPhoto', [
+ $file,
+ ]);
+ }
}
}
'isTainted' => $this->style->isTainted,
'style' => $this->style,
'styleID' => $this->styleID,
- 'coverPhotoMinHeight' => UserCoverPhoto::MIN_HEIGHT,
- 'coverPhotoMinWidth' => UserCoverPhoto::MIN_WIDTH
]);
}
}
*/
public function getCoverPhoto() {
if ($this->coverPhotoExtension) {
- return $this->styleID . '.' . $this->coverPhotoExtension;
+ return 'coverPhoto.'.$this->coverPhotoExtension;
}
return 'default.jpg';
* @since 5.2
*/
public function getCoverPhotoLocation() {
- return WCF_DIR . 'images/coverPhotos/' . $this->getCoverPhoto();
+ if ($this->coverPhotoExtension) {
+ return $this->getAssetPath().'coverPhoto.'.$this->coverPhotoExtension;
+ }
+ return WCF_DIR . 'images/coverPhotos/default.jpg';
}
/**
* @since 5.2
*/
public function getCoverPhotoUrl() {
+ if ($this->coverPhotoExtension) {
+ return FileUtil::getRelativePath(WCF_DIR, $this->getAssetPath()).'coverPhoto.'.$this->coverPhotoExtension;
+ }
return WCF::getPath() . 'images/coverPhotos/' . $this->getCoverPhoto();
}
<?php
namespace wcf\data\style;
use wcf\data\TDatabaseObjectToggle;
-use wcf\data\user\cover\photo\UserCoverPhoto;
use wcf\data\user\UserAction;
use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\IToggleAction;
/**
* @inheritDoc
*/
- protected $requireACP = ['copy', 'delete', 'deleteCoverPhoto', 'markAsTainted', 'setAsDefault', 'toggle', 'update', 'upload', 'uploadCoverPhoto',];
+ protected $requireACP = ['copy', 'delete', 'markAsTainted', 'setAsDefault', 'toggle', 'update', 'upload',];
/**
* style object
// handle style preview image
$this->updateStylePreviewImage($style);
+ // handle the cover photo
+ $this->updateCoverPhoto($style);
+
return $style;
}
* @since 3.1
*/
protected function updateCoverPhoto(Style $style) {
- $styleID = $style->styleID;
- $fileExtension = WCF::getSession()->getVar('styleCoverPhoto-'.$styleID);
- if ($fileExtension) {
- // remove old image
- if ($style->coverPhotoExtension) {
- @unlink(WCF_DIR . 'images/coverPhotos/' . $style->getCoverPhoto());
- }
-
- rename(
- WCF_DIR . 'images/coverPhotos/' . $styleID . '.tmp.' . $fileExtension,
- WCF_DIR . 'images/coverPhotos/' . $styleID . '.' . $fileExtension
- );
+ $type = 'coverPhoto';
+
+ if (array_key_exists('coverPhoto', $this->parameters['uploads'])) {
+ /** @var \wcf\system\file\upload\UploadFile $file */
+ $file = $this->parameters['uploads']['coverPhoto'];
- (new StyleEditor($style))->update(['coverPhotoExtension' => $fileExtension]);
- WCF::getSession()->unregister('styleCoverPhoto-'.$style->styleID);
+ if ($style->coverPhotoExtension && file_exists($style->getCoverPhotoLocation())) {
+ if (!$file || $style->getCoverPhotoLocation() !== $file->getLocation()) {
+ unlink($style->getCoverPhotoLocation());
+ }
+ }
+ if ($file !== null) {
+ $fileLocation = $file->getLocation();
+ if (($imageData = getimagesize($fileLocation)) === false) {
+ throw new \InvalidArgumentException('The given '.$type.' is not an image');
+ }
+ $extension = ImageUtil::getExtensionByMimeType($imageData['mime']);
+ $newLocation = $style->getAssetPath().'coverPhoto.'.$extension;
+ rename($fileLocation, $newLocation);
+ (new StyleEditor($style))->update([
+ 'coverPhotoExtension' => $extension,
+ ]);
+
+ $file->setProcessed($newLocation);
+ }
+ else {
+ (new StyleEditor($style))->update([
+ 'coverPhotoExtension' => '',
+ ]);
+ }
}
}
return ['errorType' => $file->getValidationErrorType()];
}
- /**
- * Validates parameters to upload a cover photo.
- *
- * @since 3.1
- */
- public function validateUploadCoverPhoto() {
- if (!MODULE_USER_COVER_PHOTO) {
- throw new PermissionDeniedException();
- }
-
- // ignore tmp hash, uploading is supported for existing styles only
- // and files will be finally processed on form submit
- $this->parameters['tmpHash'] = '@@@WCF_INVALID_TMP_HASH@@@';
-
- $this->validateUpload();
- }
-
- /**
- * Handles the cover photo upload.
- *
- * @return string[]
- * @since 3.1
- */
- public function uploadCoverPhoto() {
- // save files
- /** @noinspection PhpUndefinedMethodInspection */
- /** @var UploadFile[] $files */
- $files = $this->parameters['__files']->getFiles();
- $file = $files[0];
-
- try {
- if (!$file->getValidationErrorType()) {
- $fileLocation = $file->getLocation();
- try {
- if (($imageData = getimagesize($fileLocation)) === false) {
- throw new UserInputException('coverPhoto');
- }
- switch ($imageData[2]) {
- case IMAGETYPE_PNG:
- case IMAGETYPE_JPEG:
- case IMAGETYPE_GIF:
- // fine
- break;
- default:
- throw new UserInputException('coverPhoto');
- }
-
- if ($imageData[0] < UserCoverPhoto::MIN_WIDTH) {
- throw new UserInputException('coverPhoto', 'minWidth');
- }
- else if ($imageData[1] < UserCoverPhoto::MIN_HEIGHT) {
- throw new UserInputException('coverPhoto', 'minHeight');
- }
- }
- catch (SystemException $e) {
- throw new UserInputException('coverPhoto');
- }
-
- // move uploaded file
- if (@copy($fileLocation, WCF_DIR.'images/coverPhotos/'.$this->style->styleID.'.tmp.'.$file->getFileExtension())) {
- @unlink($fileLocation);
-
- // store extension within session variables
- WCF::getSession()->register('styleCoverPhoto-'.$this->style->styleID, $file->getFileExtension());
-
- // return result
- return [
- 'url' => WCF::getPath().'images/coverPhotos/'.$this->style->styleID.'.tmp.'.$file->getFileExtension()
- ];
- }
- else {
- throw new UserInputException('coverPhoto', 'uploadFailed');
- }
- }
- }
- catch (UserInputException $e) {
- $file->setValidationErrorType($e->getType());
- }
-
- return ['errorType' => $file->getValidationErrorType()];
- }
-
- /**
- * Validates the parameters to delete a style's default cover photo.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- * @since 3.1
- */
- public function validateDeleteCoverPhoto() {
- if (!MODULE_USER_COVER_PHOTO) {
- throw new PermissionDeniedException();
- }
-
- $this->styleEditor = $this->getSingleObject();
- if (!$this->styleEditor->coverPhotoExtension) {
- throw new UserInputException('objectIDs');
- }
- }
-
- /**
- * Deletes a style's default cover photo.
- *
- * @return string[]
- * @since 3.1
- */
- public function deleteCoverPhoto() {
- $this->styleEditor->deleteCoverPhoto();
-
- return [
- 'url' => WCF::getPath().'images/coverPhotos/'.(new Style($this->styleEditor->styleID))->getCoverPhoto()
- ];
- }
-
/**
* Validates parameters to assign a new default style.
*/