Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use FormBuilder for captcha questions #6074

Open
wants to merge 2 commits into
base: 6.2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 1 addition & 60 deletions wcfsetup/install/files/acp/templates/captchaQuestionAdd.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,65 +14,6 @@
</nav>
</header>

{include file='shared_formNotice'}

<form id="adForm" method="post" action="{if $action == 'add'}{link controller='CaptchaQuestionAdd'}{/link}{else}{link controller='CaptchaQuestionEdit' id=$captchaQuestion->questionID}{/link}{/if}">
<div class="section">
<dl{if $errorField == 'question'} class="formError"{/if}>
<dt><label for="question">{lang}wcf.acp.captcha.question.question{/lang}</label></dt>
<dd>
<input type="text" id="question" name="question" value="{$i18nPlainValues[question]}" required autofocus class="long">
{if $errorField == 'question'}
<small class="innerError">
{if $errorType == 'empty'}
{lang}wcf.global.form.error.empty{/lang}
{elseif $errorType == 'multilingual'}
{lang}wcf.global.form.error.multilingual{/lang}
{else}
{lang}wcf.acp.captcha.question.question.error.{$errorType}{/lang}
{/if}
</small>
{/if}
</dd>
</dl>
{include file='shared_multipleLanguageInputJavascript' elementIdentifier='question' forceSelection=false}

<dl{if $errorField == 'answers'} class="formError"{/if}>
<dt><label for="answers">{lang}wcf.acp.captcha.question.answers{/lang}</label></dt>
<dd>
<textarea id="answers" name="answers" cols="40" rows="10">{$i18nPlainValues[answers]}</textarea>
<small>{lang}wcf.acp.captcha.question.answers.description{/lang}</small>
{if $errorField == 'answers'}
<small class="innerError">
{if $errorType == 'empty'}
{lang}wcf.global.form.error.empty{/lang}
{elseif $errorType == 'multilingual'}
{lang}wcf.global.form.error.multilingual{/lang}
{else}
{lang}wcf.acp.captcha.question.answers.error.{$errorType}{/lang}
{/if}
</small>
{/if}
</dd>
</dl>
{include file='shared_multipleLanguageInputJavascript' elementIdentifier='answers' forceSelection=false}

<dl>
<dt></dt>
<dd>
<label><input type="checkbox" name="isDisabled" value="1"{if $isDisabled} checked{/if}> {lang}wcf.acp.captcha.question.isDisabled{/lang}</label>
</dd>
</dl>

{event name='dataFields'}
</div>

{event name='sections'}

<div class="formSubmit">
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
{csrfToken}
</div>
</form>
{unsafe:$form->getHtml()}

{include file='footer'}
236 changes: 75 additions & 161 deletions wcfsetup/install/files/lib/acp/form/CaptchaQuestionAddForm.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,35 @@

namespace wcf\acp\form;

use wcf\data\captcha\question\CaptchaQuestion;
use wcf\data\captcha\question\CaptchaQuestionAction;
use wcf\data\captcha\question\CaptchaQuestionEditor;
use wcf\form\AbstractForm;
use wcf\system\exception\UserInputException;
use wcf\system\language\I18nHandler;
use wcf\data\language\Language;
use wcf\form\AbstractFormBuilderForm;
use wcf\system\form\builder\container\FormContainer;
use wcf\system\form\builder\field\BooleanFormField;
use wcf\system\form\builder\field\MultilineTextFormField;
use wcf\system\form\builder\field\TextFormField;
use wcf\system\form\builder\field\validation\FormFieldValidationError;
use wcf\system\form\builder\field\validation\FormFieldValidator;
use wcf\system\language\LanguageFactory;
use wcf\system\Regex;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\StringUtil;

/**
* Shows the form to create a new captcha question.
*
* @author Matthias Schmidt
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @author Olaf Braun, Matthias Schmidt
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @property CaptchaQuestion $formObject
*/
class CaptchaQuestionAddForm extends AbstractForm
class CaptchaQuestionAddForm extends AbstractFormBuilderForm
{
/**
* @inheritDoc
*/
public $activeMenuItem = 'wcf.acp.menu.link.captcha.question.add';

/**
* invalid regex in answers
* @var string
*/
public $invalidRegex = '';

/**
* 1 if the question is disabled
* @var int
*/
public $isDisabled = 0;

/**
* @inheritDoc
*/
Expand All @@ -46,155 +39,76 @@ class CaptchaQuestionAddForm extends AbstractForm
/**
* @inheritDoc
*/
public function assignVariables()
{
parent::assignVariables();

I18nHandler::getInstance()->assignVariables();

WCF::getTPL()->assign([
'action' => 'add',
'isDisabled' => $this->isDisabled,
'invalidRegex' => $this->invalidRegex,
]);
}

/**
* @inheritDoc
*/
public function readFormParameters()
{
parent::readFormParameters();

I18nHandler::getInstance()->readValues();

if (isset($_POST['isDisabled'])) {
$this->isDisabled = 1;
}
}
public $objectActionClass = CaptchaQuestionAction::class;

/**
* @inheritDoc
*/
public function readParameters()
{
parent::readParameters();

I18nHandler::getInstance()->register('question');
I18nHandler::getInstance()->register('answers');
}
public $objectEditLinkController = CaptchaQuestionEditForm::class;

/**
* @inheritDoc
*/
public function save()
#[\Override]
protected function createForm()
{
parent::save();

$this->objectAction = new CaptchaQuestionAction([], 'create', [
'data' => \array_merge($this->additionalFields, [
'answers' => I18nHandler::getInstance()->isPlainValue('answers') ? I18nHandler::getInstance()->getValue('answers') : '',
'isDisabled' => $this->isDisabled,
'question' => I18nHandler::getInstance()->isPlainValue('question') ? I18nHandler::getInstance()->getValue('question') : '',
]),
]);
$returnValues = $this->objectAction->executeAction();
$questionID = $returnValues['returnValues']->questionID;

// set i18n values
$questionUpdates = [];
if (!I18nHandler::getInstance()->isPlainValue('question')) {
I18nHandler::getInstance()->save(
'question',
'wcf.captcha.question.question.question' . $questionID,
'wcf.captcha.question',
1
);

$questionUpdates['question'] = 'wcf.captcha.question.question.question' . $questionID;
}
if (!I18nHandler::getInstance()->isPlainValue('answers')) {
I18nHandler::getInstance()->save(
'answers',
'wcf.captcha.question.answers.question' . $questionID,
'wcf.captcha.question',
1
);

$questionUpdates['answers'] = 'wcf.captcha.question.answers.question' . $questionID;
}

if (!empty($questionUpdates)) {
$questionEditor = new CaptchaQuestionEditor($returnValues['returnValues']);
$questionEditor->update($questionUpdates);
}

$this->saved();

// reset values
I18nHandler::getInstance()->reset();
$this->isDisabled = 0;

// show success message
WCF::getTPL()->assign([
'success' => true,
'objectEditLink' => LinkHandler::getInstance()->getControllerLink(
CaptchaQuestionEditForm::class,
['id' => $questionID]
),
parent::createForm();

$this->form->appendChildren([
FormContainer::create('general')
->appendChildren([
TextFormField::create('question')
->label('wcf.acp.captcha.question.question')
->i18n()
->languageItemPattern('wcf.captcha.question.question.question\d+')
->required(),
MultilineTextFormField::create('answers')
->label('wcf.acp.captcha.question.answers')
->i18n()
->languageItemPattern('wcf.captcha.question.answers.question\d+')
->required()
->addValidator(
new FormFieldValidator('regexValidator', function (MultilineTextFormField $formField) {
$value = $formField->getValue();

if ($formField->hasPlainValue()) {
$this->validateAnswer($value, $formField);
} else {
foreach ($value as $languageID => $languageValue) {
$this->validateAnswer(
$languageValue,
$formField,
LanguageFactory::getInstance()->getLanguage($languageID)
);
}
}
})
),
BooleanFormField::create('isDisabled')
->label('wcf.acp.captcha.question.isDisabled')
->value(false)
])
]);
}

/**
* @inheritDoc
*/
public function validate()
{
parent::validate();

// validate question
if (!I18nHandler::getInstance()->validateValue('question')) {
if (I18nHandler::getInstance()->isPlainValue('question')) {
throw new UserInputException('question');
} else {
throw new UserInputException('question', 'multilingual');
}
protected function validateAnswer(
string $answer,
MultilineTextFormField $formField,
?Language $language = null
): void {
if (!\str_starts_with('~', $answer) || !\str_ends_with('~', $answer)) {
return;
}

// validate answers
if (!I18nHandler::getInstance()->validateValue('answers')) {
if (I18nHandler::getInstance()->isPlainValue('answers')) {
throw new UserInputException('answers');
} else {
throw new UserInputException('answers', 'multilingual');
}
}

if (I18nHandler::getInstance()->isPlainValue('answers')) {
$answers = \explode("\n", StringUtil::unifyNewlines(I18nHandler::getInstance()->getValue('answers')));
foreach ($answers as $answer) {
if (\mb_substr($answer, 0, 1) == '~' && \mb_substr($answer, -1, 1) == '~') {
$regexLength = \mb_strlen($answer) - 2;
if (!$regexLength || !Regex::compile(\mb_substr($answer, 1, $regexLength))->isValid()) {
$this->invalidRegex = $answer;

throw new UserInputException('answers', 'invalidRegex');
}
}
}
}
foreach (I18nHandler::getInstance()->getValues('answers') as $languageAnswers) {
$answers = \explode("\n", StringUtil::unifyNewlines($languageAnswers));
foreach ($answers as $answer) {
if (\mb_substr($answer, 0, 1) == '~' && \mb_substr($answer, -1, 1) == '~') {
$regexLength = \mb_strlen($answer) - 2;
if (!$regexLength || !Regex::compile(\mb_substr($answer, 1, $regexLength))->isValid()) {
$this->invalidRegex = $answer;

throw new UserInputException('answers', 'invalidRegex');
}
}
}
$regexLength = \mb_strlen($answer) - 2;
if (!$regexLength || !Regex::compile(\mb_substr($answer, 1, $regexLength))->isValid()) {
$formField->addValidationError(
new FormFieldValidationError(
'invalidRegex',
'wcf.acp.captcha.question.answers.error.invalidRegex',
[
'invalidRegex' => $answer,
'language' => $language
]
)
);
}
}
}
Loading
Loading