<dl{if $errorField == 'rankImage'} class="formError"{/if}>
<dt><label for="rankImage">{lang}wcf.acp.user.rank.image{/lang}</label></dt>
<dd>
- <input type="text" id="rankImage" name="rankImage" value="{$rankImage}" class="long">
+ {@$__wcf->getUploadHandler()->renderField('rankImage')}
{if $errorField == 'rankImage'}
<small class="innerError">
- {lang}wcf.acp.user.rank.image.error.{@$errorType}{/lang}
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.user.rank.image.error.{$errorType}{/lang}
+ {/if}
</small>
{/if}
- <small>{lang}wcf.acp.user.rank.rankImage.description{/lang}</small>
</dd>
</dl>
</dd>
</dl>
- {if $action == 'edit' && $rank->rankImage}
- <dl>
- <dt><label>{lang}wcf.acp.user.rank.currentImage{/lang}</label></dt>
- <dd>{@$rank->getImage()}</dd>
- </dl>
- {/if}
-
<dl{if $errorField == 'hideTitle'} class="formError"{/if}>
<dt></dt>
<dd>
use wcf\data\user\UserProfile;
use wcf\form\AbstractForm;
use wcf\system\exception\UserInputException;
+use wcf\system\file\upload\UploadField;
+use wcf\system\file\upload\UploadFile;
+use wcf\system\file\upload\UploadHandler;
use wcf\system\language\I18nHandler;
use wcf\system\Regex;
use wcf\system\request\LinkHandler;
public $requiredPoints = 0;
/**
- * path to user rank image
- * @var string
+ * @deprecated since 5.4
*/
public $rankImage = '';
'custom' /* not a real value */
];
+ /**
+ * @var UploadFile[]
+ */
+ public $removedRankImages;
+
+ /**
+ * @var UploadFile|bool
+ */
+ public $rankImageFile;
+
/**
* @inheritDoc
*/
parent::readParameters();
I18nHandler::getInstance()->register('rankTitle');
+
+ $this->rebuildUploadField();
+ }
+
+ protected function rebuildUploadField(): void {
+ if (UploadHandler::getInstance()->isRegisteredFieldId('rankImage')) {
+ UploadHandler::getInstance()->unregisterUploadField('rankImage');
+ }
+ $field = new UploadField('rankImage');
+ $field->setImageOnly(true);
+ $field->setAllowSvgImage(true);
+ $field->maxFiles = 1;
+ UploadHandler::getInstance()->registerUploadField($field);
}
/**
if (isset($_POST['customCssClassName'])) $this->customCssClassName = StringUtil::trim($_POST['customCssClassName']);
if (isset($_POST['groupID'])) $this->groupID = intval($_POST['groupID']);
if (isset($_POST['requiredPoints'])) $this->requiredPoints = intval($_POST['requiredPoints']);
- if (isset($_POST['rankImage'])) $this->rankImage = StringUtil::trim($_POST['rankImage']);
if (isset($_POST['repeatImage'])) $this->repeatImage = intval($_POST['repeatImage']);
if (isset($_POST['requiredGender'])) $this->requiredGender = intval($_POST['requiredGender']);
if (isset($_POST['hideTitle'])) $this->hideTitle = intval($_POST['hideTitle']);
+
+ $this->removedRankImages = UploadHandler::getInstance()->getRemovedFiledByFieldId('rankImage');
+ $rankImageFiles = UploadHandler::getInstance()->getFilesByFieldId('rankImage');
+ $this->rankImageFile = reset($rankImageFiles);
}
/**
$this->requiredGender = 0;
}
- if ($this->hideTitle && !$this->rankImage) {
+ if ($this->hideTitle && !$this->rankImageFile) {
throw new UserInputException('hideTitle', 'rankImage');
}
}
parent::save();
// save label
- $this->objectAction = new UserRankAction([], 'create', ['data' => array_merge($this->additionalFields, [
- 'rankTitle' => $this->rankTitle,
- 'cssClassName' => $this->cssClassName == 'custom' ? $this->customCssClassName : $this->cssClassName,
- 'groupID' => $this->groupID,
- 'requiredPoints' => $this->requiredPoints,
- 'rankImage' => $this->rankImage,
- 'repeatImage' => $this->repeatImage,
- 'requiredGender' => $this->requiredGender,
- 'hideTitle' => ($this->hideTitle ? 1 : 0)
- ])]);
+ $this->objectAction = new UserRankAction([], 'create', [
+ 'data' => array_merge($this->additionalFields, [
+ 'rankTitle' => $this->rankTitle,
+ 'cssClassName' => $this->cssClassName == 'custom' ? $this->customCssClassName : $this->cssClassName,
+ 'groupID' => $this->groupID,
+ 'requiredPoints' => $this->requiredPoints,
+ 'repeatImage' => $this->repeatImage,
+ 'requiredGender' => $this->requiredGender,
+ 'hideTitle' => ($this->hideTitle ? 1 : 0)
+ ]),
+ 'rankImageFile' => $this->rankImageFile,
+ ]);
$returnValues = $this->objectAction->executeAction();
$rankID = $returnValues['returnValues']->rankID;
$this->repeatImage = 1;
I18nHandler::getInstance()->reset();
+ $this->rebuildUploadField();
// show success message
WCF::getTPL()->assign([
use wcf\data\user\rank\UserRankAction;
use wcf\form\AbstractForm;
use wcf\system\exception\IllegalLinkException;
+use wcf\system\file\upload\UploadHandler;
use wcf\system\language\I18nHandler;
use wcf\system\WCF;
}
// update label
- $this->objectAction = new UserRankAction([$this->rank], 'update', ['data' => array_merge($this->additionalFields, [
- 'rankTitle' => $this->rankTitle,
- 'cssClassName' => $this->cssClassName == 'custom' ? $this->customCssClassName : $this->cssClassName,
- 'groupID' => $this->groupID,
- 'requiredPoints' => $this->requiredPoints,
- 'rankImage' => $this->rankImage,
- 'repeatImage' => $this->repeatImage,
- 'requiredGender' => $this->requiredGender,
- 'hideTitle' => $this->hideTitle
- ])]);
+ $this->objectAction = new UserRankAction([$this->rank], 'update', [
+ 'data' => array_merge($this->additionalFields, [
+ 'rankTitle' => $this->rankTitle,
+ 'cssClassName' => $this->cssClassName == 'custom' ? $this->customCssClassName : $this->cssClassName,
+ 'groupID' => $this->groupID,
+ 'requiredPoints' => $this->requiredPoints,
+ 'repeatImage' => $this->repeatImage,
+ 'requiredGender' => $this->requiredGender,
+ 'hideTitle' => $this->hideTitle
+ ]),
+ 'rankImageFile' => $this->rankImageFile,
+ 'rankImageFile__removedFiles' => $this->removedRankImages,
+ ]);
$this->objectAction->executeAction();
$this->saved();
$this->repeatImage = $this->rank->repeatImage;
$this->rankImage = $this->rank->rankImage;
$this->hideTitle = $this->rank->hideTitle;
+
+ if ($this->rank->getImageFile()) {
+ UploadHandler::getInstance()->registerFilesByField('rankImage', [
+ $this->rank->getImageFile()
+ ]);
+ }
}
}
namespace wcf\data\user\rank;
use wcf\data\DatabaseObject;
use wcf\data\ITitledObject;
+use wcf\system\file\upload\UploadFile;
use wcf\system\WCF;
use wcf\util\StringUtil;
* @property-read integer $hideTitle hides the generic title of the rank, but not custom titles, `0` to show the title at all times
*/
class UserRank extends DatabaseObject implements ITitledObject {
+
+ public const RANK_IMAGE_DIR = 'images/rank/';
+
/**
* Returns the image of this user rank.
*
*/
public function getImage() {
if ($this->rankImage) {
- $image = '<img src="'.(!preg_match('~^(/|https?://)~i', $this->rankImage) ? WCF::getPath() : '').StringUtil::encodeHTML($this->rankImage).'" alt="">';
+ $image = '<img src="'. WCF::getPath() . self::RANK_IMAGE_DIR . StringUtil::encodeHTML($this->rankImage) .'" alt="">';
if ($this->repeatImage > 1) $image = str_repeat($image, $this->repeatImage);
return $image;
}
public function showTitle() {
return !$this->rankImage || !$this->hideTitle;
}
+
+ /**
+ * Returns the currently uploaded rank image or null, if the rank has no image.
+ *
+ * @since 5.4
+ */
+ public function getImageFile(): ?UploadFile {
+ if ($this->rankImage) {
+ return new UploadFile(WCF_DIR . self::RANK_IMAGE_DIR . $this->rankImage, $this->rankImage, true, true, true);
+ }
+
+ return null;
+ }
}
<?php
namespace wcf\data\user\rank;
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\exception\InvalidObjectArgument;
+use wcf\system\file\upload\UploadFile;
/**
* Executes user rank-related actions.
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package WoltLabSuite\Core\Data\User\Rank
*
- * @method UserRank create()
* @method UserRankEditor[] getObjects()
* @method UserRankEditor getSingleObject()
*/
* @inheritDoc
*/
protected $requireACP = ['delete'];
+
+ /**
+ * @inheritDoc
+ */
+ public function create() {
+ /** @var UserRank $rank */
+ $rank = parent::create();
+
+ if (isset($this->parameters['rankImageFile']) && $this->parameters['rankImageFile']) {
+ if (!($this->parameters['rankImageFile'] instanceof UploadFile)) {
+ throw new InvalidObjectArgument($this->parameters['rankImageFile'], UploadFile::class, "The parameter 'rankImageFile'");
+ }
+
+ if (!$this->parameters['rankImageFile']->isProcessed()) {
+ $fileName = $rank->rankID . '-' . $this->parameters['rankImageFile']->getFilename();
+
+ rename($this->parameters['rankImageFile']->getLocation(), WCF_DIR . UserRank::RANK_IMAGE_DIR . $fileName);
+ $this->parameters['rankImageFile']->setProcessed(WCF_DIR . UserRank::RANK_IMAGE_DIR . $fileName);
+
+ $updateData['rankImage'] = $fileName;
+
+ $rankEditor = new UserRankEditor($rank);
+ $rankEditor->update($updateData);
+ }
+ }
+
+ return $rank;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update() {
+ if (isset($this->parameters['rankImageFile__removedFiles']) && is_array($this->parameters['rankImageFile__removedFiles'])) {
+ foreach ($this->parameters['rankImageFile__removedFiles'] as $file) {
+ if (!($file instanceof UploadFile)) {
+ throw new InvalidObjectArgument($this->parameters['rankImageFile__removedFiles'], UploadFile::class, "An array values of 'rankImageFile__removedFiles'");
+ }
+
+ @unlink($file->getLocation());
+ }
+ }
+
+ if (isset($this->parameters['rankImageFile'])) {
+ if (count($this->objects) > 1) {
+ throw new \BadMethodCallException("The parameter 'rankImageFile' can only be processed, if there is only one object to update.");
+ }
+
+ $object = reset($this->objects);
+
+ if (!$this->parameters['rankImageFile']) {
+ $this->parameters['data']['rankImage'] = "";
+ }
+ else {
+ if (!($this->parameters['rankImageFile'] instanceof UploadFile)) {
+ throw new InvalidObjectArgument($this->parameters['rankImageFile'], UploadFile::class, "The parameter 'rankImageFile'");
+ }
+
+ if (!$this->parameters['rankImageFile']->isProcessed()) {
+ $fileName = $object->rankID . '-' . $this->parameters['rankImageFile']->getFilename();
+
+ rename($this->parameters['rankImageFile']->getLocation(), WCF_DIR . UserRank::RANK_IMAGE_DIR . $fileName);
+ $this->parameters['rankImageFile']->setProcessed(WCF_DIR . UserRank::RANK_IMAGE_DIR . $fileName);
+
+ $this->parameters['data']['rankImage'] = $fileName;
+ }
+ }
+ }
+
+ parent::update();
+ }
}
<item name="wcf.acp.user.rank.hideTitle.error.rankImage"><![CDATA[Diese Option erfordert eine gültige Ranggrafik.]]></item>
<item name="wcf.acp.user.rank.image"><![CDATA[Ranggrafik]]></item>
<item name="wcf.acp.user.rank.list"><![CDATA[Benutzerränge]]></item>
- <item name="wcf.acp.user.rank.rankImage.description"><![CDATA[Der Pfad zur Ranggrafik kann relativ zum WCF-Verzeichnis oder absolut angegeben werden.]]></item>
<item name="wcf.acp.user.rank.requiredGender.description"><![CDATA[Optional {if LANGUAGE_USE_INFORMAL_VARIANT}kannst du{else}können Sie{/if} diesen Benutzerrang auf Benutzer mit einem bestimmten Geschlecht einschränken.]]></item>
<item name="wcf.acp.user.rank.requiredPoints"><![CDATA[Punkte]]></item>
<item name="wcf.acp.user.rank.requiredPoints.description"><![CDATA[Benötigte Menge an Aktivitätspunkten, die ein Benutzer erreichen muss, um in diesen Rang aufzusteigen.]]></item>
<item name="wcf.acp.user.rank.hideTitle.error.rankImage"><![CDATA[This option requires a valid rank image.]]></item>
<item name="wcf.acp.user.rank.image"><![CDATA[Rank Image]]></item>
<item name="wcf.acp.user.rank.list"><![CDATA[User Ranks]]></item>
- <item name="wcf.acp.user.rank.rankImage.description"><![CDATA[The path must be either relative to WCF’s directory or absolute.]]></item>
<item name="wcf.acp.user.rank.requiredGender.description"><![CDATA[The rank can be restricted to a specific gender.]]></item>
<item name="wcf.acp.user.rank.requiredPoints"><![CDATA[Points]]></item>
<item name="wcf.acp.user.rank.requiredPoints.description"><![CDATA[The required number of activity points to obtain this rank.]]></item>