The internal implementation of `LineBreakSeparatedTextOptionType` and `Ui/ItemList/LineBreakSeparatedText` required minor adjustments for the list to have unique ids and for the input element to be part of the template so that the user group option type works on `UserGroupOptionForm`.
<!-- Update of the Google Fonts -->
<instruction type="script" run="standalone">acp/update_com.woltlab.wcf_5.4_update_google_font.php</instruction>
+
+ <instruction type="script">acp/update_com.woltlab.wcf_5.4_deleteLanguageItems.php</instruction>
</instructions>
</package>
--- /dev/null
+<ul class="scrollableCheckboxList" {*
+ *}id="lineBreakSeparatedTextOption_{@$identifier}"{*
+ *}{if $values|empty} style="display: none"{/if}{*
+*}>
+ {foreach from=$values item=value}
+ <li data-value="{$value}">
+ <span class="icon icon16 fa-times jsDeleteItem jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}"></span>
+ <span>{$value}</span>
+ </li>
+ {/foreach}
+</ul>
+<input type="hidden" name="values[{$option->optionName}]">
+
+<script data-relocate="true">
+ require(['Language', 'WoltLabSuite/Core/Ui/ItemList/LineBreakSeparatedText'], (Language, { UiItemListLineBreakSeparatedText }) => {
+ Language.addObject({
+ 'wcf.acp.option.type.lineBreakSeparatedText.placeholder': '{jslang}wcf.acp.option.type.lineBreakSeparatedText.placeholder{/jslang}',
+ 'wcf.acp.option.type.lineBreakSeparatedText.error.duplicate': '{jslang __literal=true}wcf.acp.option.type.lineBreakSeparatedText.error.duplicate{/jslang}',
+ 'wcf.acp.option.type.lineBreakSeparatedText.clearList.confirmMessage': '{jslang}wcf.acp.option.type.lineBreakSeparatedText.clearList.confirmMessage{/jslang}',
+ });
+
+ new UiItemListLineBreakSeparatedText(
+ document.getElementById("lineBreakSeparatedTextOption_{@$identifier}")
+ );
+ });
+</script>
</option>
<option name="user.attachment.allowedExtensions">
<categoryname>user.message.attachment</categoryname>
- <optiontype>textarea</optiontype>
+ <optiontype>lineBreakSeparatedText</optiontype>
<defaultvalue>gif
jpg
jpeg
</option>
<option name="user.contactForm.attachment.allowedExtensions">
<categoryname>user.message.contactForm</categoryname>
- <optiontype>textarea</optiontype>
+ <optiontype>lineBreakSeparatedText</optiontype>
<defaultvalue>gif
jpg
jpeg
</option>
<option name="user.signature.attachment.allowedExtensions">
<categoryname>user.signature</categoryname>
- <optiontype>textarea</optiontype>
+ <optiontype>lineBreakSeparatedText</optiontype>
<defaultvalue>gif
jpg
jpeg
</option>
<option name="user.profile.avatar.allowedFileExtensions">
<categoryname>user.profile.avatar</categoryname>
- <optiontype>textarea</optiontype>
+ <optiontype>lineBreakSeparatedText</optiontype>
<defaultvalue>gif
jpg
jpeg
"formNotice",
"formSuccess",
"languageChooser",
+ "lineBreakSeparatedTextOptionType",
"mediaBBCodeTag",
"mediaManager",
"multipleLanguageInputJavascript",
import DomUtil from "../../Dom/Util";
export interface LineBreakSeparatedTextOptions {
- submitFieldName: string;
+ submitFieldName?: string;
}
export class UiItemListLineBreakSeparatedText {
protected readonly itemList: HTMLUListElement;
protected readonly items = new Set<string>();
protected readonly options: LineBreakSeparatedTextOptions;
+ protected readonly submitField?: HTMLInputElement = undefined;
- constructor(itemList: HTMLUListElement, options: LineBreakSeparatedTextOptions) {
+ constructor(itemList: HTMLUListElement, options: LineBreakSeparatedTextOptions = {}) {
this.itemList = itemList;
this.options = options;
+ if (!this.options.submitFieldName) {
+ const nextElement = this.itemList.nextElementSibling;
+ if (nextElement instanceof HTMLInputElement && nextElement.type === "hidden") {
+ this.submitField = nextElement;
+ } else {
+ throw new Error("Missing `submitFieldName` option");
+ }
+ }
+
this.itemList.closest("form")!.addEventListener("submit", () => this.submit());
this.initValues();
* Adds a hidden input field with the data to the form before it is submitted.
*/
protected submit(): void {
- const input = document.createElement("input");
- input.type = "hidden";
- input.name = this.options.submitFieldName;
- input.value = Array.from(this.items).join("\n");
- this.itemList.parentElement!.append(input);
+ const value = Array.from(this.items).join("\n");
+
+ if (this.submitField) {
+ this.submitField.value = value;
+ } else {
+ const input = document.createElement("input");
+ input.type = "hidden";
+ input.name = this.options.submitFieldName!;
+ input.value = value;
+ this.itemList.parentElement!.append(input);
+ }
}
}
<ul class="scrollableCheckboxList" {*
- *}id="lineBreakSeparatedTextOption_{@$option->optionID}"{*
+ *}id="lineBreakSeparatedTextOption_{@$identifier}"{*
*}{if $values|empty} style="display: none"{/if}{*
*}>
{foreach from=$values item=value}
</li>
{/foreach}
</ul>
+<input type="hidden" name="values[{$option->optionName}]">
<script data-relocate="true">
require(['Language', 'WoltLabSuite/Core/Ui/ItemList/LineBreakSeparatedText'], (Language, { UiItemListLineBreakSeparatedText }) => {
});
new UiItemListLineBreakSeparatedText(
- document.getElementById("lineBreakSeparatedTextOption_{@$option->optionID}"),
- {
- submitFieldName: "values[{$option->optionName}]"
- }
+ document.getElementById("lineBreakSeparatedTextOption_{@$identifier}")
);
});
</script>
--- /dev/null
+<?php
+
+use wcf\data\language\item\LanguageItemAction;
+use wcf\data\language\item\LanguageItemList;
+
+$languageItems = [
+ 'wcf.acp.group.option.user.attachment.allowedExtensions.description',
+ 'wcf.acp.group.option.user.contactForm.attachment.allowedExtensions.description',
+ 'wcf.acp.group.option.user.signature.attachment.allowedExtensions.description',
+];
+
+$languageItemList = new LanguageItemList();
+$languageItemList->getConditionBuilder()->add('languageItem IN (?)', [$languageItems]);
+$languageItemList->readObjects();
+
+(new LanguageItemAction([$languageItemList->getObjects()], 'delete'))->executeAction();
Language = tslib_1.__importStar(Language);
Util_1 = tslib_1.__importDefault(Util_1);
class UiItemListLineBreakSeparatedText {
- constructor(itemList, options) {
+ constructor(itemList, options = {}) {
this.clearButton = undefined;
this.itemInput = undefined;
this.items = new Set();
+ this.submitField = undefined;
this.itemList = itemList;
this.options = options;
+ if (!this.options.submitFieldName) {
+ const nextElement = this.itemList.nextElementSibling;
+ if (nextElement instanceof HTMLInputElement && nextElement.type === "hidden") {
+ this.submitField = nextElement;
+ }
+ else {
+ throw new Error("Missing `submitFieldName` option");
+ }
+ }
this.itemList.closest("form").addEventListener("submit", () => this.submit());
this.initValues();
this.buildUi();
* Adds a hidden input field with the data to the form before it is submitted.
*/
submit() {
- const input = document.createElement("input");
- input.type = "hidden";
- input.name = this.options.submitFieldName;
- input.value = Array.from(this.items).join("\n");
- this.itemList.parentElement.append(input);
+ const value = Array.from(this.items).join("\n");
+ if (this.submitField) {
+ this.submitField.value = value;
+ }
+ else {
+ const input = document.createElement("input");
+ input.type = "hidden";
+ input.name = this.options.submitFieldName;
+ input.value = value;
+ this.itemList.parentElement.append(input);
+ }
}
}
exports.UiItemListLineBreakSeparatedText = UiItemListLineBreakSeparatedText;
$values = ArrayUtil::trim(\explode("\n", StringUtil::unifyNewlines($value)));
\uasort($values, 'strnatcmp');
+ static $identifiers = [];
+ do {
+ $identifier = \substr(StringUtil::getRandomID(), 0, 8);
+ } while (\in_array($identifier, $identifiers));
+ $identifiers[] = $identifier;
+
return WCF::getTPL()->fetch('lineBreakSeparatedTextOptionType', 'wcf', [
+ 'identifier' => $identifier,
'option' => $option,
'values' => $values,
]);
--- /dev/null
+<?php
+
+namespace wcf\system\option\user\group;
+
+use wcf\system\option\LineBreakSeparatedTextOptionType;
+use wcf\util\StringUtil;
+
+/**
+ * User group option type implementation for separate items that are stored as line break-separated
+ * text.
+ *
+ * The merge of option values returns merge of all text values.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2021 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Option\User\Group
+ * @since 5.4
+ */
+class LineBreakSeparatedTextUserGroupOptionType extends LineBreakSeparatedTextOptionType implements IUserGroupOptionType
+{
+ /**
+ * @inheritDoc
+ */
+ public function merge($defaultValue, $groupValue)
+ {
+ $defaultValue = empty($defaultValue) ? [] : \explode("\n", StringUtil::unifyNewlines($defaultValue));
+ $groupValue = empty($groupValue) ? [] : \explode("\n", StringUtil::unifyNewlines($groupValue));
+
+ return \implode("\n", \array_unique(\array_merge($defaultValue, $groupValue)));
+ }
+}
<item name="wcf.acp.group.option.category.user.message.attachment"><![CDATA[Dateianhänge]]></item>
<item name="wcf.acp.group.option.user.attachment.maxSize"><![CDATA[Maximale Dateianhangsgröße]]></item>
<item name="wcf.acp.group.option.user.attachment.allowedExtensions"><![CDATA[Erlaubte Dateiendungen]]></item>
- <item name="wcf.acp.group.option.user.attachment.allowedExtensions.description"><![CDATA[Eine Dateiendung pro Zeile]]></item>
<item name="wcf.acp.group.option.user.attachment.maxCount"><![CDATA[Maximale Dateianhänge pro Nachricht]]></item>
<item name="wcf.acp.group.option.user.attachment.maxCount.description"/>
<item name="wcf.acp.group.option.category.admin.attachment"><![CDATA[Dateianhänge]]></item>
<item name="wcf.acp.group.option.category.user.message.contactForm"><![CDATA[Kontaktformular]]></item>
<item name="wcf.acp.group.option.user.contactForm.attachment.maxSize"><![CDATA[Maximale Dateianhangsgröße]]></item>
<item name="wcf.acp.group.option.user.contactForm.attachment.allowedExtensions"><![CDATA[Erlaubte Dateiendungen]]></item>
- <item name="wcf.acp.group.option.user.contactForm.attachment.allowedExtensions.description"><![CDATA[Eine Dateiendung pro Zeile]]></item>
<item name="wcf.acp.group.option.user.contactForm.attachment.maxCount"><![CDATA[Maximale Dateianhänge pro Nachricht]]></item>
<item name="wcf.acp.group.option.user.profile.canEditUserProfile"><![CDATA[Kann eigenes Profil bearbeiten]]></item>
<item name="wcf.acp.group.option.user.profile.canHideOnlineStatus"><![CDATA[Kann Online-Status verbergen]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.canUpload"><![CDATA[Kann Dateianhänge hochladen]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.maxSize"><![CDATA[Maximale Dateianhangsgröße]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.allowedExtensions"><![CDATA[Erlaubte Dateiendungen]]></item>
- <item name="wcf.acp.group.option.user.signature.attachment.allowedExtensions.description"><![CDATA[Eine Dateiendung pro Zeile]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.maxCount"><![CDATA[Maximale Dateianhänge]]></item>
<item name="wcf.acp.group.requireMultifactor"><![CDATA[Mehrfaktor-Authentifizierung erzwingen]]></item>
<item name="wcf.acp.group.requireMultifactor.description"><![CDATA[Benutzer, die Mitglied dieser Benutzergruppe sind, können die Mehrfaktor-Authentifizierung nicht deaktivieren und können besonders geschützte Bereiche erst betreten, wenn sie die Mehrfaktor-Authentifizierung eingerichtet haben.]]></item>
<item name="wcf.acp.group.option.category.user.message.attachment"><![CDATA[Attachments]]></item>
<item name="wcf.acp.group.option.user.attachment.maxSize"><![CDATA[Maximum Attachment File Size]]></item>
<item name="wcf.acp.group.option.user.attachment.allowedExtensions"><![CDATA[Allowed Attachment File Extensions]]></item>
- <item name="wcf.acp.group.option.user.attachment.allowedExtensions.description"><![CDATA[Enter one extension per line.]]></item>
<item name="wcf.acp.group.option.user.attachment.maxCount"><![CDATA[Maximum Attachments per Message]]></item>
<item name="wcf.acp.group.option.user.attachment.maxCount.description"><![CDATA[The maximum number of attachments allowed per message.]]></item>
<item name="wcf.acp.group.option.category.admin.attachment"><![CDATA[Attachments]]></item>
<item name="wcf.acp.group.option.category.user.message.contactForm"><![CDATA[Contact Form]]></item>
<item name="wcf.acp.group.option.user.contactForm.attachment.maxSize"><![CDATA[Maximum Attachment File Size]]></item>
<item name="wcf.acp.group.option.user.contactForm.attachment.allowedExtensions"><![CDATA[Allowed Attachment File Extensions]]></item>
- <item name="wcf.acp.group.option.user.contactForm.attachment.allowedExtensions.description"><![CDATA[Enter one extension per line.]]></item>
<item name="wcf.acp.group.option.user.contactForm.attachment.maxCount"><![CDATA[Maximum Attachments per Message]]></item>
<item name="wcf.acp.group.option.user.profile.canEditUserProfile"><![CDATA[Can edit their profile]]></item>
<item name="wcf.acp.group.option.user.profile.canHideOnlineStatus"><![CDATA[Can hide their online status]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.canUpload"><![CDATA[Can Upload Attachments]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.maxSize"><![CDATA[Maximum Attachment File Size]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.allowedExtensions"><![CDATA[Allowed Attachment File Extensions]]></item>
- <item name="wcf.acp.group.option.user.signature.attachment.allowedExtensions.description"><![CDATA[Enter one extension per line.]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.maxCount"><![CDATA[Maximum Attachments]]></item>
<item name="wcf.acp.group.requireMultifactor"><![CDATA[Require Multi-factor Authentication]]></item>
<item name="wcf.acp.group.requireMultifactor.description"><![CDATA[Users that are members of this user group may not disable multi-factor authentication. They will also be required to set up multi-factor authentication before they may enter protected areas.]]></item>