2022-11-06 02:26:21 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
class UOJForm {
|
2022-11-11 23:10:34 +00:00
|
|
|
public ?string $form_name;
|
|
|
|
public ?string $succ_href;
|
2022-11-06 02:26:21 +00:00
|
|
|
public $extra_validator = null;
|
2022-11-11 23:10:34 +00:00
|
|
|
public $handle;
|
|
|
|
private $ajax_submit_js = null;
|
|
|
|
private $run_at_server_handler = [];
|
2022-11-06 02:26:21 +00:00
|
|
|
private $data = [];
|
|
|
|
private $vdata = [];
|
|
|
|
private $main_html = '';
|
|
|
|
|
|
|
|
public $config = [
|
2022-11-11 23:10:34 +00:00
|
|
|
'is_big' => false,
|
|
|
|
'has_file' => false,
|
|
|
|
'ctrl_enter_submit' => false,
|
|
|
|
'max_post_size' => 15728640, // 15M
|
|
|
|
'max_file_size_mb' => 10, // 10M
|
|
|
|
'form' => [
|
2022-11-06 02:26:21 +00:00
|
|
|
'class' => '',
|
|
|
|
],
|
2022-11-11 23:10:34 +00:00
|
|
|
'submit_container' => [
|
|
|
|
'class' => 'mt-3 text-center',
|
|
|
|
],
|
2022-11-06 02:26:21 +00:00
|
|
|
'submit_button' => [
|
2022-11-11 23:10:34 +00:00
|
|
|
'class' => 'btn btn-primary',
|
|
|
|
'text' => '提交',
|
|
|
|
],
|
|
|
|
'back_button' => [
|
|
|
|
'href' => null,
|
2022-11-06 02:26:21 +00:00
|
|
|
'class' => 'btn btn-secondary',
|
|
|
|
],
|
2022-11-11 23:10:34 +00:00
|
|
|
'confirm' => [
|
|
|
|
'smart' => false,
|
|
|
|
'text' => null,
|
|
|
|
]
|
2022-11-06 02:26:21 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
public function __construct($form_name) {
|
|
|
|
$this->form_name = $form_name;
|
|
|
|
$this->succ_href = UOJContext::requestURI();
|
|
|
|
$this->handle = function (&$vdata) {
|
|
|
|
};
|
|
|
|
|
|
|
|
$this->run_at_server_handler["check-{$this->form_name}"] = function () {
|
|
|
|
die(json_encode($this->validateAtServer()));
|
|
|
|
};
|
|
|
|
$this->run_at_server_handler["submit-{$this->form_name}"] = function () {
|
2022-11-11 23:10:34 +00:00
|
|
|
if ($this->config['no_submit']) {
|
2022-11-06 02:26:21 +00:00
|
|
|
UOJResponse::page404();
|
|
|
|
}
|
|
|
|
foreach ($this->data as $field) {
|
|
|
|
if (!isset($field['no_val']) && !isset($_POST[$field['name']])) {
|
|
|
|
UOJResponse::message('The form is incomplete.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UOJContext::requestMethod() == 'POST') {
|
|
|
|
$len = UOJContext::contentLength();
|
|
|
|
if ($len === null) {
|
|
|
|
UOJResponse::page403();
|
2022-11-11 23:10:34 +00:00
|
|
|
} elseif ($len > $this->config['max_post_size']) {
|
2022-11-06 02:26:21 +00:00
|
|
|
UOJResponse::message('The form is too large.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
crsf_defend();
|
|
|
|
$errors = $this->validateAtServer();
|
|
|
|
if ($errors) {
|
|
|
|
$err_str = '';
|
|
|
|
foreach ($errors as $name => $err) {
|
|
|
|
$esc_err = htmlspecialchars($err);
|
|
|
|
$err_str .= "$name: $esc_err<br />";
|
|
|
|
}
|
|
|
|
UOJResponse::message($err_str);
|
|
|
|
}
|
|
|
|
$fun = $this->handle;
|
|
|
|
$fun($this->vdata);
|
|
|
|
|
|
|
|
if ($this->succ_href !== 'none') {
|
|
|
|
redirectTo($this->succ_href);
|
|
|
|
}
|
|
|
|
die();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAjaxSubmit($js) {
|
|
|
|
$GLOBALS['REQUIRE_LIB']['jquery.form'] = '';
|
|
|
|
$this->ajax_submit_js = $js;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function add($name, $html, $validator_php, $validator_js) {
|
|
|
|
$this->main_html .= $html;
|
2022-11-11 23:10:34 +00:00
|
|
|
$this->data[] = [
|
2022-11-06 02:26:21 +00:00
|
|
|
'name' => $name,
|
|
|
|
'validator_php' => $validator_php,
|
|
|
|
'validator_js' => $validator_js
|
2022-11-11 23:10:34 +00:00
|
|
|
];
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function addNoVal($name, $html) {
|
|
|
|
$this->main_html .= $html;
|
|
|
|
$this->data[] = array(
|
|
|
|
'name' => $name,
|
|
|
|
'validator_js' => 'always_ok',
|
|
|
|
'no_val' => ''
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
public function appendHTML($html) {
|
|
|
|
$this->main_html .= $html;
|
|
|
|
}
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
public function addHidden($name, $default_value, $validator_php, $validator_js) {
|
|
|
|
$default_value = HTML::escape($default_value);
|
|
|
|
$html = <<<EOD
|
|
|
|
<input type="hidden" name="$name" id="input-$name" value="$default_value" />
|
|
|
|
EOD;
|
|
|
|
$this->add($name, $html, $validator_php, $validator_js);
|
|
|
|
}
|
|
|
|
|
2022-12-23 14:10:14 +00:00
|
|
|
public function addInput($name, $config) {
|
|
|
|
$config += [
|
|
|
|
'type' => 'text',
|
|
|
|
'div_class' => '',
|
|
|
|
'input_class' => 'form-control',
|
2023-02-04 13:52:59 +00:00
|
|
|
'input_attrs' => [],
|
|
|
|
'input_div_class' => null,
|
2022-12-23 14:10:14 +00:00
|
|
|
'default_value' => '',
|
|
|
|
'label' => '',
|
|
|
|
'label_class' => 'form-label',
|
|
|
|
'placeholder' => '',
|
|
|
|
'help' => '',
|
2023-01-15 00:05:00 +00:00
|
|
|
'help_class' => 'form-text',
|
2022-12-23 14:10:14 +00:00
|
|
|
'validator_php' => function ($x) {
|
|
|
|
return '';
|
|
|
|
},
|
|
|
|
'validator_js' => null,
|
|
|
|
];
|
|
|
|
|
|
|
|
$html = '';
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['div_class'], 'id' => "div-$name"]);
|
|
|
|
|
|
|
|
if ($config['label']) {
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['label_class'],
|
|
|
|
'for' => "input-$name",
|
|
|
|
'id' => "label-$name"
|
|
|
|
], $config['label']);
|
|
|
|
}
|
|
|
|
|
2023-02-04 13:52:59 +00:00
|
|
|
if ($config['input_div_class'] !== null) {
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['input_div_class']]);
|
|
|
|
}
|
|
|
|
|
2022-12-23 14:10:14 +00:00
|
|
|
$html .= HTML::empty_tag('input', [
|
|
|
|
'class' => $config['input_class'],
|
|
|
|
'type' => $config['type'],
|
|
|
|
'name' => $name,
|
|
|
|
'id' => "input-$name",
|
|
|
|
'value' => $config['default_value'],
|
|
|
|
'placeholder' => $config['placeholder'],
|
2023-02-04 13:52:59 +00:00
|
|
|
] + $config['input_attrs']);
|
2022-12-23 14:10:14 +00:00
|
|
|
$html .= HTML::tag('div', ['class' => 'invalid-feedback', 'id' => "help-$name"], '');
|
|
|
|
|
|
|
|
if ($config['help']) {
|
|
|
|
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
|
|
|
}
|
|
|
|
|
2023-02-04 13:52:59 +00:00
|
|
|
if ($config['input_div_class'] !== null) {
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
}
|
|
|
|
|
2022-12-23 14:10:14 +00:00
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
|
|
|
|
$this->add($name, $html, $config['validator_php'], $config['validator_js']);
|
|
|
|
}
|
|
|
|
|
2023-01-15 13:35:24 +00:00
|
|
|
public function addTextArea($name, $config) {
|
2023-01-15 00:48:08 +00:00
|
|
|
$config += [
|
|
|
|
'type' => 'text',
|
|
|
|
'div_class' => '',
|
|
|
|
'input_class' => 'form-control',
|
2023-02-15 08:46:47 +00:00
|
|
|
'input_attrs' => [],
|
2023-01-15 00:48:08 +00:00
|
|
|
'default_value' => '',
|
|
|
|
'label' => '',
|
|
|
|
'label_class' => 'form-label',
|
|
|
|
'placeholder' => '',
|
|
|
|
'help' => '',
|
|
|
|
'help_class' => 'form-text',
|
|
|
|
'validator_php' => function ($x) {
|
|
|
|
return '';
|
|
|
|
},
|
|
|
|
'validator_js' => null,
|
|
|
|
];
|
|
|
|
|
|
|
|
$html = '';
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['div_class'], 'id' => "div-$name"]);
|
|
|
|
|
|
|
|
if ($config['label']) {
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['label_class'],
|
|
|
|
'for' => "input-$name",
|
|
|
|
'id' => "label-$name"
|
|
|
|
], $config['label']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag('textarea', [
|
|
|
|
'class' => $config['input_class'],
|
|
|
|
'type' => $config['type'],
|
|
|
|
'name' => $name,
|
|
|
|
'id' => "input-$name",
|
|
|
|
'placeholder' => $config['placeholder'],
|
2023-02-15 08:46:47 +00:00
|
|
|
] + $config['input_attrs'], HTML::escape($config['default_value']));
|
2023-01-15 00:48:08 +00:00
|
|
|
$html .= HTML::tag('div', ['class' => 'invalid-feedback', 'id' => "help-$name"], '');
|
|
|
|
|
|
|
|
if ($config['help']) {
|
|
|
|
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
|
|
|
|
$this->add($name, $html, $config['validator_php'], $config['validator_js']);
|
|
|
|
}
|
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
public function addCheckbox($name, $config) {
|
|
|
|
$config += [
|
|
|
|
'checked' => false,
|
|
|
|
'div_class' => 'form-check',
|
|
|
|
'role' => 'checkbox',
|
|
|
|
'input_class' => 'form-check-input',
|
|
|
|
'label' => '',
|
|
|
|
'label_class' => 'form-check-label',
|
|
|
|
'help' => '',
|
|
|
|
'help_class' => 'form-text',
|
|
|
|
'disabled' => false,
|
|
|
|
];
|
|
|
|
|
|
|
|
$html = '';
|
2022-12-07 14:49:43 +00:00
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['div_class'], 'id' => "div-$name"]);
|
2022-11-11 23:10:34 +00:00
|
|
|
$html .= HTML::empty_tag('input', [
|
|
|
|
'class' => $config['input_class'],
|
|
|
|
'type' => 'checkbox',
|
|
|
|
'name' => $name,
|
|
|
|
'id' => "input-$name",
|
|
|
|
'checked' => $config['checked'] ? 'checked' : null,
|
|
|
|
'value' => '1',
|
|
|
|
'disabled' => $config['disabled'] ? 'disabled' : null,
|
|
|
|
]);
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['label_class'],
|
|
|
|
'for' => "input-$name",
|
|
|
|
], $config['label']);
|
|
|
|
|
|
|
|
if ($config['help']) {
|
|
|
|
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
|
|
|
|
$this->addNoVal($name, $html);
|
|
|
|
}
|
|
|
|
|
2022-12-04 09:27:16 +00:00
|
|
|
public function addSelect($name, $config) {
|
|
|
|
$config += [
|
|
|
|
'div_class' => '',
|
|
|
|
'select_class' => 'form-select',
|
2023-02-04 13:52:59 +00:00
|
|
|
'select_div_class' => null,
|
2022-12-04 09:27:16 +00:00
|
|
|
'options' => [],
|
|
|
|
'default_value' => '',
|
|
|
|
'label' => '',
|
2023-01-11 03:17:08 +00:00
|
|
|
'label_class' => 'form-label',
|
2022-12-04 09:27:16 +00:00
|
|
|
'help' => '',
|
|
|
|
'help_class' => 'form-text',
|
|
|
|
'disabled' => false,
|
|
|
|
];
|
|
|
|
|
|
|
|
$html = '';
|
|
|
|
$html .= HTML::tag_begin('div', ['id' => "div-$name", 'class' => $config['div_class']]);
|
|
|
|
|
|
|
|
// Label
|
|
|
|
if ($config['label']) {
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['label_class'],
|
|
|
|
'for' => "input-$name",
|
|
|
|
], $config['label']);
|
|
|
|
}
|
|
|
|
|
2023-02-04 13:52:59 +00:00
|
|
|
if ($config['select_div_class'] !== null) {
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['select_div_class']]);
|
|
|
|
}
|
|
|
|
|
2022-12-04 09:27:16 +00:00
|
|
|
// Select
|
|
|
|
$html .= HTML::tag_begin('select', ['id' => "input-$name", 'name' => $name, 'class' => $config['select_class']]);
|
|
|
|
|
|
|
|
foreach ($config['options'] as $opt_name => $opt_label) {
|
|
|
|
if ($opt_name == $config['default_value']) {
|
|
|
|
$html .= HTML::tag('option', ['value' => $opt_name, 'selected' => 'selected'], $opt_label);
|
|
|
|
} else {
|
|
|
|
$html .= HTML::tag('option', ['value' => $opt_name], $opt_label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('select');
|
|
|
|
|
|
|
|
// Help text
|
|
|
|
if ($config['help']) {
|
|
|
|
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
|
|
|
}
|
|
|
|
|
2023-02-04 13:52:59 +00:00
|
|
|
if ($config['select_div_class'] !== null) {
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
}
|
|
|
|
|
2022-12-04 09:27:16 +00:00
|
|
|
$html .= HTML::tag_end('div');
|
2022-12-24 04:06:39 +00:00
|
|
|
|
|
|
|
$this->add(
|
|
|
|
$name,
|
|
|
|
$html,
|
|
|
|
function ($opt) use ($config) {
|
|
|
|
return isset($config['options'][$opt]) ? '' : "无效选项";
|
|
|
|
},
|
|
|
|
null
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addCheckboxes($name, $config) {
|
|
|
|
$config += [
|
|
|
|
'div_class' => '',
|
|
|
|
'select_class' => '',
|
|
|
|
'label' => '',
|
|
|
|
'label_class' => 'form-check-label',
|
|
|
|
'options' => [],
|
|
|
|
'default_value' => '',
|
|
|
|
'option_div_class' => 'form-check',
|
|
|
|
'option_class' => 'form-check-input',
|
|
|
|
'option_label_class' => 'form-check-label',
|
|
|
|
'help' => '',
|
|
|
|
'help_class' => 'form-text',
|
|
|
|
'disabled' => false,
|
|
|
|
];
|
|
|
|
|
|
|
|
$html = '';
|
|
|
|
$html .= HTML::tag_begin('div', ['id' => "div-$name", 'class' => $config['div_class']]);
|
|
|
|
|
|
|
|
// Label
|
|
|
|
if ($config['label']) {
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['label_class'],
|
|
|
|
'for' => "input-$name",
|
|
|
|
], $config['label']);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['select_class']]);
|
|
|
|
|
|
|
|
foreach ($config['options'] as $opt_name => $opt_label) {
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['option_div_class']]);
|
|
|
|
|
|
|
|
if ($opt_name == $config['default_value']) {
|
|
|
|
$html .= HTML::empty_tag('input', [
|
|
|
|
'name' => $name,
|
|
|
|
'id' => "input-$name-$opt_name",
|
|
|
|
'class' => $config['option_class'],
|
|
|
|
'type' => 'radio',
|
|
|
|
'value' => $opt_name,
|
|
|
|
'checked' => 'checked',
|
|
|
|
]);
|
|
|
|
} else {
|
|
|
|
$html .= HTML::empty_tag('input', [
|
|
|
|
'name' => $name,
|
|
|
|
'id' => "input-$name-$opt_name",
|
|
|
|
'class' => $config['option_class'],
|
|
|
|
'type' => 'radio',
|
|
|
|
'value' => $opt_name,
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['option_label_class'],
|
|
|
|
'for' => "input-$name-$opt_name",
|
|
|
|
], $opt_label);
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
|
|
|
|
// Help text
|
|
|
|
if ($config['help']) {
|
|
|
|
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('div');
|
2022-12-04 09:27:16 +00:00
|
|
|
|
|
|
|
$this->add(
|
|
|
|
$name,
|
|
|
|
$html,
|
|
|
|
function ($opt) use ($config) {
|
|
|
|
return isset($config['options'][$opt]) ? '' : "无效选项";
|
|
|
|
},
|
|
|
|
null
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-02-01 10:11:26 +00:00
|
|
|
public function addSourceCodeInput($name, $config) {
|
|
|
|
$config += [
|
|
|
|
'filename' => '',
|
|
|
|
'languages' => UOJLang::getAvailableLanguages(),
|
|
|
|
'preferred_lang' => null,
|
|
|
|
];
|
|
|
|
|
|
|
|
$this->add(
|
|
|
|
"{$name}_upload_type",
|
|
|
|
'',
|
|
|
|
function ($type) use ($name) {
|
|
|
|
if ($type == 'editor') {
|
|
|
|
if (!isset($_POST["{$name}_editor"])) {
|
|
|
|
return '你在干啥……怎么什么都没交过来……?';
|
|
|
|
}
|
|
|
|
} elseif ($type == 'file') {
|
|
|
|
} else {
|
|
|
|
return '……居然既不是用编辑器上传也不是用文件上传的……= =……';
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
},
|
|
|
|
'always_ok'
|
|
|
|
);
|
|
|
|
$this->addNoVal("{$name}_editor", '');
|
|
|
|
$this->addNoVal("{$name}_file", '');
|
|
|
|
$this->add(
|
|
|
|
"{$name}_language",
|
|
|
|
'',
|
|
|
|
function ($lang) use ($config) {
|
|
|
|
if (!isset($config['languages'][$lang])) {
|
|
|
|
return '该语言不被支持';
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
},
|
|
|
|
'always_ok'
|
|
|
|
);
|
|
|
|
|
2023-02-10 13:59:22 +00:00
|
|
|
if ($config['preferred_lang'] == null || !isset($config['languages'][$config['preferred_lang']])) {
|
2023-02-10 22:31:06 +00:00
|
|
|
$config['preferred_lang'] = Cookie::get('uoj_preferred_language');
|
2023-02-01 10:11:26 +00:00
|
|
|
}
|
|
|
|
|
2023-02-10 13:59:22 +00:00
|
|
|
if ($config['preferred_lang'] == null || !isset($config['languages'][$config['preferred_lang']])) {
|
2023-02-10 22:31:06 +00:00
|
|
|
$config['preferred_lang'] = UOJLang::$default_preferred_language;
|
2023-02-01 10:11:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$langs_options_str = '';
|
|
|
|
foreach ($config['languages'] as $lang_code => $lang_display) {
|
2023-02-10 22:31:06 +00:00
|
|
|
$langs_options_str .= HTML::option($lang_code, $lang_display, $lang_code == $config['preferred_lang']);
|
2023-02-01 10:11:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$text = json_encode(UOJLocale::get('problems::source code') . ': ' . HTML::tag('code', [], $config['filename']));
|
|
|
|
$langs_options_json = json_encode($langs_options_str);
|
|
|
|
|
|
|
|
$this->appendHTML(<<<EOD
|
|
|
|
<div class="form-group mb-3" id="form-group-$name"></div>
|
|
|
|
<script type="text/javascript">
|
|
|
|
$('#form-group-$name').source_code_form_group('$name', $text, $langs_options_json);
|
|
|
|
</script>
|
|
|
|
EOD);
|
|
|
|
|
|
|
|
$this->config['is_big'] = true;
|
|
|
|
$this->config['has_file'] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addTextFileInput($name, $config) {
|
|
|
|
$config += [
|
|
|
|
'filename' => '',
|
|
|
|
];
|
|
|
|
|
|
|
|
$this->add(
|
|
|
|
"{$name}_upload_type",
|
|
|
|
'',
|
|
|
|
function ($type, &$vdata) use ($name) {
|
|
|
|
if ($type == 'editor') {
|
|
|
|
if (!isset($_POST["{$name}_editor"])) {
|
|
|
|
return '你在干啥……怎么什么都没交过来……?';
|
|
|
|
}
|
|
|
|
} elseif ($type == 'file') {
|
|
|
|
} else {
|
|
|
|
return '……居然既不是用编辑器上传也不是用文件上传的……= =……';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'always_ok'
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->addNoVal("{$name}_editor", '');
|
|
|
|
$this->addNoVal("{$name}_file", '');
|
|
|
|
|
|
|
|
$text = json_encode(UOJLocale::get('problems::text file') . ': ' . HTML::tag('code', [], $config['filename']));
|
|
|
|
|
|
|
|
$this->appendHTML(<<<EOD
|
|
|
|
<div class="form-group mb-3" id="form-group-$name"></div>
|
|
|
|
<script type="text/javascript">
|
|
|
|
$('#form-group-$name').text_file_form_group('$name', $text);
|
|
|
|
</script>
|
|
|
|
EOD);
|
|
|
|
|
|
|
|
$this->config['is_big'] = true;
|
|
|
|
$this->config['has_file'] = true;
|
|
|
|
}
|
|
|
|
|
2023-03-14 08:55:11 +00:00
|
|
|
public function addMarkdownEditor($name, $config = []) {
|
|
|
|
$config += [
|
|
|
|
'div_class' => '',
|
|
|
|
'default_value' => '',
|
|
|
|
'label' => '',
|
|
|
|
'label_class' => 'form-label',
|
|
|
|
'placeholder' => '',
|
|
|
|
'help' => '',
|
|
|
|
'help_class' => 'form-text',
|
|
|
|
'validator_php' => function ($str, &$vdata) {
|
|
|
|
return '';
|
|
|
|
},
|
|
|
|
'validator_js' => null,
|
|
|
|
];
|
|
|
|
|
|
|
|
$html = '';
|
|
|
|
$html .= HTML::tag_begin('div', ['class' => $config['div_class'], 'id' => "div-$name"]);
|
|
|
|
|
|
|
|
$default_value = json_encode($config['default_value']);
|
|
|
|
|
|
|
|
if ($config['label']) {
|
|
|
|
$html .= HTML::tag('label', [
|
|
|
|
'class' => $config['label_class'],
|
|
|
|
'for' => "input-$name",
|
|
|
|
'id' => "label-$name"
|
|
|
|
], $config['label']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= <<<EOD
|
|
|
|
<div id="{$name}-markdown-input-container"></div>
|
|
|
|
<script>
|
|
|
|
$('#{$name}-markdown-input-container').markdown_input_editor("{$name}", "default", {$default_value});
|
|
|
|
</script>
|
|
|
|
EOD;
|
|
|
|
|
|
|
|
if ($config['help']) {
|
|
|
|
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$html .= HTML::tag_end('div');
|
|
|
|
|
|
|
|
$this->add($name, $html, $config['validator_php'], $config['validator_js']);
|
|
|
|
}
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
public function printHTML() {
|
2022-11-11 23:10:34 +00:00
|
|
|
echo HTML::tag_begin('form', [
|
|
|
|
'action' => UOJContext::requestURI(),
|
|
|
|
'method' => 'POST',
|
|
|
|
'class' => $this->config['form']['class'],
|
|
|
|
'id' => "form-{$this->form_name}",
|
|
|
|
'enctype' => $this->config['is_big'] ? 'multipart/form-data' : 'application/x-www-form-urlencoded',
|
|
|
|
]);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
echo HTML::hiddenToken();
|
2022-11-11 23:10:34 +00:00
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
echo $this->main_html;
|
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
if (!$this->config['no_submit']) {
|
|
|
|
echo HTML::tag_begin('div', ['class' => $this->config['submit_container']['class']]);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
2023-02-04 13:52:59 +00:00
|
|
|
if ($this->config['back_button']['href'] !== null) {
|
|
|
|
echo HTML::tag('a', [
|
|
|
|
'class' => $this->config['back_button']['class'],
|
|
|
|
'href' => $this->config['back_button']['href']
|
|
|
|
], '返回');
|
|
|
|
}
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
echo HTML::tag('button', [
|
2022-11-11 23:10:34 +00:00
|
|
|
'type' => 'submit',
|
|
|
|
'id' => "button-submit-{$this->form_name}",
|
|
|
|
'name' => "submit-{$this->form_name}",
|
|
|
|
'value' => $this->form_name,
|
|
|
|
'class' => $this->config['submit_button']['class']
|
|
|
|
], $this->config['submit_button']['text']);
|
|
|
|
|
|
|
|
echo HTML::tag_end('div');
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
echo HTML::tag_end('form');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
if ($this->config['no_submit']) {
|
2022-11-06 02:26:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
<script type="text/javascript">
|
|
|
|
$(document).ready(function() {
|
|
|
|
EOD;
|
|
|
|
if ($this->config['ctrl_enter_submit']) {
|
2022-11-06 02:26:21 +00:00
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
$('#form-{$this->form_name}').keydown(function(e) {
|
|
|
|
if (e.keyCode == 13 && e.ctrlKey) {
|
|
|
|
$('#button-submit-{$this->form_name}').click();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
$('#form-{$this->form_name}').submit(function(e) {
|
|
|
|
var ok = true;
|
2022-11-06 02:26:21 +00:00
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
$need_ajax = false;
|
|
|
|
if ($this->extra_validator) {
|
|
|
|
$need_ajax = true;
|
|
|
|
}
|
|
|
|
foreach ($this->data as $field) {
|
|
|
|
if ($field['validator_js'] != null) {
|
|
|
|
if ($field['validator_js'] != 'always_ok') {
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
var {$field['name']}_err = ({$field['validator_js']})($('#input-{$field['name']}').val());
|
2022-11-06 02:26:21 +00:00
|
|
|
EOD;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$need_ajax = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($need_ajax) {
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
var post_data = {};
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
foreach ($this->data as $field) {
|
|
|
|
if ($field['validator_js'] == null) {
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
var {$field['name']}_err = 'Unknown error';
|
|
|
|
post_data.{$field['name']} = $('#input-{$field['name']}').val();
|
2022-11-06 02:26:21 +00:00
|
|
|
EOD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
post_data['check-{$this->form_name}'] = "";
|
|
|
|
$.ajax({
|
|
|
|
url: '{$_SERVER['REQUEST_URI']}',
|
|
|
|
type: 'POST',
|
|
|
|
dataType: 'json',
|
|
|
|
async: false,
|
|
|
|
|
|
|
|
data: post_data,
|
|
|
|
success: function(data) {
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
foreach ($this->data as $field) {
|
|
|
|
if ($field['validator_js'] == null) {
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
{$field['name']}_err = data.${field['name']};
|
2022-11-06 02:26:21 +00:00
|
|
|
EOD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
if (data.extra != undefined) {
|
|
|
|
alert(data.extra);
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($this->data as $field) {
|
|
|
|
if ($field['validator_js'] != 'always_ok') {
|
|
|
|
echo <<<EOD
|
2023-02-01 10:11:26 +00:00
|
|
|
if ({$field['name']}_err) {
|
|
|
|
$('#div-{$field['name']}').addClass('has-validation has-error');
|
|
|
|
$('#div-{$field['name']}').addClass('is-invalid');
|
|
|
|
$('#input-{$field['name']}').addClass('is-invalid');
|
|
|
|
$('#help-{$field['name']}').text({$field['name']}_err);
|
2022-11-11 23:10:34 +00:00
|
|
|
ok = false;
|
|
|
|
} else {
|
2023-02-01 10:11:26 +00:00
|
|
|
$('#div-{$field['name']}').removeClass('has-validation has-error');
|
|
|
|
$('#div-{$field['name']}').removeClass('is-invalid');
|
|
|
|
$('#input-{$field['name']}').removeClass('is-invalid');
|
|
|
|
$('#help-{$field['name']}').text('');
|
2022-11-11 23:10:34 +00:00
|
|
|
}
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-11 23:10:34 +00:00
|
|
|
if ($this->config['confirm']['smart']) {
|
2022-12-23 14:10:14 +00:00
|
|
|
$this->config['confirm']['text'] = '你真的要' . $this->config['submit_button']['text'] . '吗?';
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
2022-11-11 23:10:34 +00:00
|
|
|
if ($this->config['confirm']['text']) {
|
2022-11-06 02:26:21 +00:00
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
if (!confirm('{$this->config['confirm']['text']}')) {
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
2022-11-11 23:10:34 +00:00
|
|
|
if ($this->config['has_file']) {
|
2022-11-06 02:26:21 +00:00
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
$(this).find("input[type='file']").each(function() {
|
|
|
|
for (var i = 0; i < this.files.length; i++) {
|
|
|
|
if (this.files[i].size > {$this->config['max_file_size_mb']} * 1024 * 1024) {
|
|
|
|
$('#div-' + $(this).attr('name')).addClass('has-validation has-error');
|
|
|
|
$('#div-' + $(this).attr('name')).addClass('is-invalid');
|
|
|
|
$('#input-' + $(this).attr('name')).addClass('is-invalid');
|
|
|
|
$('#help-' + $(this).attr('name')).text('文件大小不能超过 {$this->config['max_file_size_mb']} MB');
|
|
|
|
ok = false;
|
|
|
|
} else {
|
|
|
|
$('#div-' + $(this).attr('name')).removeClass('has-validation has-error');
|
|
|
|
$('#div-' + $(this).attr('name')).removeClass('is-invalid');
|
|
|
|
$('#input-' + $(this).attr('name')).removeClass('is-invalid');
|
|
|
|
$('#help-' + $(this).attr('name')).text('');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->ajax_submit_js !== null) {
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
e.preventDefault();
|
|
|
|
if (ok) {
|
|
|
|
$(this).ajaxSubmit({
|
|
|
|
beforeSubmit: function(formData) {
|
|
|
|
formData.push({name: 'submit-{$this->form_name}', value: '{$this->form_name}', type: 'submit'});
|
|
|
|
},
|
|
|
|
success: {$this->ajax_submit_js}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
} else {
|
|
|
|
echo <<<EOD
|
2023-02-03 09:16:01 +00:00
|
|
|
if (ok) {
|
2023-02-14 11:15:08 +00:00
|
|
|
$("#button-submit-{$this->form_name}")
|
|
|
|
.addClass('disabled')
|
|
|
|
.css('width', $("#button-submit-{$this->form_name}").outerWidth())
|
|
|
|
.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>');
|
|
|
|
|
2023-02-03 09:16:01 +00:00
|
|
|
$(this).submit(function () {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
2022-11-11 23:10:34 +00:00
|
|
|
return ok;
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
echo <<<EOD
|
2022-11-11 23:10:34 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
EOD;
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private function validateAtServer() {
|
|
|
|
$errors = array();
|
|
|
|
if ($this->extra_validator) {
|
|
|
|
$fun = $this->extra_validator;
|
|
|
|
$err = $fun();
|
|
|
|
if ($err) {
|
|
|
|
$errors['extra'] = $err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach ($this->data as $field) {
|
|
|
|
if (!isset($field['no_val']) && isset($_POST[$field['name']])) {
|
|
|
|
$fun = $field['validator_php'];
|
|
|
|
$ret = $fun($_POST[$field['name']], $this->vdata, $field['name']);
|
|
|
|
if (is_array($ret) && isset($ret['error'])) {
|
|
|
|
$err = $ret['error'];
|
|
|
|
} else {
|
|
|
|
$err = $ret;
|
|
|
|
}
|
|
|
|
if ($err) {
|
|
|
|
$errors[$field['name']] = $err;
|
|
|
|
}
|
|
|
|
if (is_array($ret) && isset($ret['store'])) {
|
|
|
|
$this->vdata[$field['name']] = $ret['store'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function runAtServer() {
|
|
|
|
foreach ($this->run_at_server_handler as $type => $handler) {
|
|
|
|
if (isset($_POST[$type])) {
|
|
|
|
$handler();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-01 10:11:26 +00:00
|
|
|
|
|
|
|
static public function uploadedFileTmpName($name) {
|
|
|
|
if (isset($_FILES[$name]) && is_uploaded_file($_FILES[$name]['tmp_name'])) {
|
|
|
|
return $_FILES[$name]['tmp_name'];
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|