Upload via GUI (30 Dateien)
This commit is contained in:
@@ -157,7 +157,7 @@ class Deskhub_Tickets_Form
|
||||
$texts = [];
|
||||
foreach ($forms as $tid => $fm) {
|
||||
$texts[$tid] = ['title' => $fm['title'], 'intro' => $fm['intro'], 'subjectShow' => $fm['subject']['show'], 'subjectLabel' => $fm['subject']['label'],
|
||||
'messageShow' => $fm['message']['show'], 'messageLabel' => $fm['message']['label'], 'messageHint' => $fm['message']['hint'], 'submitLabel' => $fm['submitLabel']];
|
||||
'messageShow' => $fm['message']['show'], 'messageLabel' => $fm['message']['label'], 'messageHint' => $fm['message']['hint'], 'submitLabel' => $fm['submitLabel'], 'attachments' => $fm['attachments']['enabled']];
|
||||
}
|
||||
if ($unsupported && current_user_can('manage_options')) {
|
||||
echo '<p class="dht-notice dht-error">' . esc_html__('Der DeskHub-Server kennt die Formular-Schnittstelle noch nicht (bitte DeskHub aktualisieren). Bis dahin wird das einfache Formular ohne eigene Felder gezeigt. (Diese Meldung sehen nur Administratoren.)', 'deskhub-tickets') . '</p>';
|
||||
@@ -175,7 +175,7 @@ class Deskhub_Tickets_Form
|
||||
$showSubject = (bool) $active['subject']['show'];
|
||||
$showMessage = (bool) $active['message']['show'];
|
||||
?>
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="dht-form" data-dht-forms="<?php echo esc_attr((string) wp_json_encode($texts)); ?>">
|
||||
<form method="post" enctype="multipart/form-data" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="dht-form" data-dht-forms="<?php echo esc_attr((string) wp_json_encode($texts)); ?>">
|
||||
<input type="hidden" name="action" value="deskhub_ticket_submit">
|
||||
<input type="hidden" name="dht_cfg" value="<?php echo esc_attr($cfgB64); ?>">
|
||||
<input type="hidden" name="dht_sig" value="<?php echo esc_attr(deskhub_tickets_sign('cfg|' . $cfgB64)); ?>">
|
||||
@@ -219,6 +219,31 @@ class Deskhub_Tickets_Form
|
||||
</p>
|
||||
<?php echo self::render_slot($forms, ['issue'], $multi, $selected, $values['fields']); ?>
|
||||
<?php echo self::render_slot($forms, [], $multi, $selected, $values['fields'], true); ?>
|
||||
<?php
|
||||
// Dateien anhängen: ein Feld für das ganze Formular; form.js blendet es aus, wenn das gewählte Thema keine Anhänge erlaubt
|
||||
$attPolicy = null;
|
||||
foreach ($forms as $fm) {
|
||||
if (!empty($fm['attachments']['enabled'])) {
|
||||
$attPolicy = $fm['attachments'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($attPolicy !== null):
|
||||
$attOn = !empty($active['attachments']['enabled']);
|
||||
?>
|
||||
<p class="dht-attach"<?php echo $attOn ? '' : ' hidden'; ?>>
|
||||
<label for="dht-files"><?php echo esc_html__('Dateien anhängen (optional)', 'deskhub-tickets'); ?></label>
|
||||
<input type="file" id="dht-files" name="dht_files[]" multiple accept="<?php echo esc_attr('.' . implode(',.', $attPolicy['allowed'])); ?>" <?php echo $attOn ? '' : 'disabled'; ?>>
|
||||
<span class="dht-help"><?php echo esc_html(sprintf(
|
||||
/* translators: 1: Anzahl Dateien, 2: Größe je Datei, 3: Größe insgesamt, 4: Dateitypen */
|
||||
__('Bis zu %1$d Dateien, je höchstens %2$s, zusammen höchstens %3$s. Erlaubt: %4$s', 'deskhub-tickets'),
|
||||
$attPolicy['maxFiles'],
|
||||
self::format_bytes($attPolicy['maxFileBytes']),
|
||||
self::format_bytes($attPolicy['maxTotalBytes']),
|
||||
implode(', ', $attPolicy['allowed'])
|
||||
)); ?></span>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (trim((string) $opts['consent_text']) !== ''): ?>
|
||||
<p class="dht-consent">
|
||||
<label><input type="checkbox" name="dht_consent" value="1" required> <span><?php echo wp_kses((string) $opts['consent_text'], ['a' => ['href' => [], 'target' => [], 'rel' => []], 'strong' => [], 'em' => []]); ?></span></label>
|
||||
@@ -247,6 +272,104 @@ class Deskhub_Tickets_Form
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Angebot für Dateianhänge aus dem Formular von DeskHub. Ohne Angabe (ältere DeskHub-Version) oder wenn die Option des Plugins
|
||||
* ausgeschaltet ist, gibt es keine Anhänge.
|
||||
*
|
||||
* @param mixed $a
|
||||
* @return array{enabled:bool,maxFiles:int,maxFileBytes:int,maxTotalBytes:int,allowed:string[]}
|
||||
*/
|
||||
public static function normalize_attachments($a): array
|
||||
{
|
||||
$off = ['enabled' => false, 'maxFiles' => 0, 'maxFileBytes' => 0, 'maxTotalBytes' => 0, 'allowed' => []];
|
||||
$opts = deskhub_tickets_options();
|
||||
if (!is_array($a) || empty($a['enabled']) || empty($opts['attachments'])) {
|
||||
return $off;
|
||||
}
|
||||
$allowed = [];
|
||||
foreach ((array) ($a['allowedExtensions'] ?? []) as $e) {
|
||||
$e = strtolower(ltrim(trim((string) $e), '.'));
|
||||
if ($e !== '' && preg_match('/^[a-z0-9]{1,8}$/', $e)) {
|
||||
$allowed[] = $e;
|
||||
}
|
||||
}
|
||||
$files = max(0, min(10, (int) ($a['maxFiles'] ?? 0)));
|
||||
$perFile = max(0, (int) ($a['maxFileBytes'] ?? 0));
|
||||
$total = max(0, (int) ($a['maxTotalBytes'] ?? 0));
|
||||
if ($files < 1 || $perFile < 1 || $total < 1 || !$allowed) {
|
||||
return $off;
|
||||
}
|
||||
return ['enabled' => true, 'maxFiles' => $files, 'maxFileBytes' => $perFile, 'maxTotalBytes' => $total, 'allowed' => $allowed];
|
||||
}
|
||||
|
||||
/** Menschenlesbare Größe ("5 MB"). */
|
||||
private static function format_bytes(int $b): string
|
||||
{
|
||||
return $b >= 1048576 ? rtrim(rtrim(number_format($b / 1048576, 1, ',', ''), '0'), ',') . ' MB' : max(1, (int) round($b / 1024)) . ' KB';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft die hochgeladenen Dateien gegen das Angebot und gibt sie fertig für die Schnittstelle zurück.
|
||||
*
|
||||
* @param array<string,mixed> $files $_FILES['dht_files']
|
||||
* @return array{0:string[],1:array<int,array{name:string,data:string}>} [Fehler, Anhänge]
|
||||
*/
|
||||
public static function collect_attachments(array $files, array $policy): array
|
||||
{
|
||||
$names = isset($files['name']) ? (array) $files['name'] : [];
|
||||
$errors = [];
|
||||
$out = [];
|
||||
$total = 0;
|
||||
$dangerous = ['php', 'php3', 'php4', 'php5', 'php7', 'php8', 'phtml', 'phar', 'exe', 'bat', 'cmd', 'sh', 'js', 'html', 'htm', 'svg'];
|
||||
foreach ($names as $i => $rawName) {
|
||||
$err = (int) ($files['error'][$i] ?? UPLOAD_ERR_NO_FILE);
|
||||
if ($err === UPLOAD_ERR_NO_FILE) {
|
||||
continue; // nichts ausgewählt
|
||||
}
|
||||
$name = sanitize_file_name(wp_unslash((string) $rawName));
|
||||
if (!$policy['enabled']) {
|
||||
return [[__('Bei diesem Formular können keine Dateien angehängt werden.', 'deskhub-tickets')], []];
|
||||
}
|
||||
if (count($out) >= $policy['maxFiles']) {
|
||||
$errors[] = sprintf(__('Bitte hängen Sie höchstens %d Dateien an.', 'deskhub-tickets'), $policy['maxFiles']);
|
||||
break;
|
||||
}
|
||||
if ($err !== UPLOAD_ERR_OK) {
|
||||
$errors[] = ($err === UPLOAD_ERR_INI_SIZE || $err === UPLOAD_ERR_FORM_SIZE)
|
||||
? sprintf(__('Die Datei „%s“ ist zu groß (höchstens %s).', 'deskhub-tickets'), $name, self::format_bytes($policy['maxFileBytes']))
|
||||
: sprintf(__('Die Datei „%s“ konnte nicht hochgeladen werden.', 'deskhub-tickets'), $name);
|
||||
continue;
|
||||
}
|
||||
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
|
||||
if ($name === '' || $ext === '' || in_array($ext, $dangerous, true) || !in_array($ext, $policy['allowed'], true)) {
|
||||
$errors[] = sprintf(__('Der Dateityp von „%1$s“ ist nicht erlaubt. Erlaubt: %2$s', 'deskhub-tickets'), $name, implode(', ', $policy['allowed']));
|
||||
continue;
|
||||
}
|
||||
$size = (int) ($files['size'][$i] ?? 0);
|
||||
$tmp = (string) ($files['tmp_name'][$i] ?? '');
|
||||
if ($size < 1 || $tmp === '' || !(is_uploaded_file($tmp) || (defined('DESKHUB_TICKETS_TESTS') && is_file($tmp)))) {
|
||||
$errors[] = sprintf(__('Die Datei „%s“ konnte nicht gelesen werden.', 'deskhub-tickets'), $name);
|
||||
continue;
|
||||
}
|
||||
if ($size > $policy['maxFileBytes']) {
|
||||
$errors[] = sprintf(__('Die Datei „%1$s“ ist zu groß (höchstens %2$s).', 'deskhub-tickets'), $name, self::format_bytes($policy['maxFileBytes']));
|
||||
continue;
|
||||
}
|
||||
$total += $size;
|
||||
if ($total > $policy['maxTotalBytes']) {
|
||||
$errors[] = sprintf(__('Die Dateien sind zusammen zu groß (höchstens %s).', 'deskhub-tickets'), self::format_bytes($policy['maxTotalBytes']));
|
||||
break;
|
||||
}
|
||||
$content = file_get_contents($tmp);
|
||||
if ($content === false || $content === '') {
|
||||
$errors[] = sprintf(__('Die Datei „%s“ konnte nicht gelesen werden.', 'deskhub-tickets'), $name);
|
||||
continue;
|
||||
}
|
||||
$out[] = ['name' => $name, 'data' => base64_encode($content)];
|
||||
}
|
||||
return [$errors, $out];
|
||||
}
|
||||
|
||||
/** Bringt ein Formular von DeskHub (oder null) in eine feste Form mit Standardwerten, Feldern nach Plätzen sortiert. */
|
||||
public static function normalize_form(?array $f): array
|
||||
{
|
||||
@@ -268,6 +391,7 @@ class Deskhub_Tickets_Form
|
||||
],
|
||||
'submitLabel' => $own ? $str($f['submitLabel'] ?? '', __('Ticket absenden', 'deskhub-tickets')) : __('Ticket absenden', 'deskhub-tickets'),
|
||||
'fields' => [],
|
||||
'attachments' => self::normalize_attachments($f['attachments'] ?? null),
|
||||
];
|
||||
$allowed = ['text', 'textarea', 'select', 'radio', 'checkbox', 'number', 'date'];
|
||||
foreach ((array) ($f['fields'] ?? []) as $fd) {
|
||||
@@ -528,6 +652,13 @@ class Deskhub_Tickets_Form
|
||||
[$fieldErrors, $fieldValues] = self::validate_fields($form['fields'], $postedFields);
|
||||
$errors = array_merge($errors, $fieldErrors);
|
||||
}
|
||||
// Dateianhänge (nur wenn das Formular sie anbietet)
|
||||
$attachments = [];
|
||||
if (!empty($_FILES['dht_files']) && is_array($_FILES['dht_files'])) {
|
||||
$policy = $form !== null ? $form['attachments'] : self::normalize_attachments(null);
|
||||
[$attErrors, $attachments] = self::collect_attachments($_FILES['dht_files'], $policy);
|
||||
$errors = array_merge($errors, $attErrors);
|
||||
}
|
||||
if (trim((string) $opts['consent_text']) !== '' && empty($_POST['dht_consent'])) {
|
||||
$errors[] = __('Bitte stimmen Sie der Verarbeitung Ihrer Angaben zu.', 'deskhub-tickets');
|
||||
}
|
||||
@@ -563,6 +694,9 @@ class Deskhub_Tickets_Form
|
||||
if ($form !== null) {
|
||||
$payload['fields'] = $fieldValues;
|
||||
}
|
||||
if ($attachments) {
|
||||
$payload['attachments'] = $attachments;
|
||||
}
|
||||
$payload = apply_filters('deskhub_tickets_payload', $payload, $values);
|
||||
$result = $client->create_ticket($payload);
|
||||
if (is_wp_error($result)) {
|
||||
|
||||
Reference in New Issue
Block a user