Upload folder via GUI - inc
This commit is contained in:
348
inc/classes/class-admin.php
Normal file
348
inc/classes/class-admin.php
Normal file
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
class WMF_Admin {
|
||||
private static $instance=null;
|
||||
public static function instance() {
|
||||
if(is_null(self::$instance)){self::$instance=new self();self::$instance->hook();}
|
||||
return self::$instance;
|
||||
}
|
||||
public function hook() {
|
||||
add_action('admin_menu', array($this,'register_menu'));
|
||||
add_action('admin_enqueue_scripts', array($this,'enqueue_assets'));
|
||||
add_action('admin_init', array($this,'handle_actions'));
|
||||
add_action('admin_notices', array($this,'admin_notices'));
|
||||
}
|
||||
public function register_menu() {
|
||||
add_menu_page('WP Multi Formular','Formulare','manage_options','wp-multi-formular',
|
||||
array($this,'page_router'),'dashicons-feedback',25);
|
||||
add_submenu_page('wp-multi-formular','Alle Formulare','Alle Formulare','manage_options','wp-multi-formular',array($this,'page_router'));
|
||||
add_submenu_page('wp-multi-formular','Neues Formular','+ Neues Formular','manage_options','wmf-new-form',array($this,'page_builder'));
|
||||
// Neue Einreichungen zaehlen fuer Badge
|
||||
$new_count = 0;
|
||||
$forms = get_posts(array('post_type'=>'wmf-form','post_status'=>'publish','numberposts'=>-1,'fields'=>'ids'));
|
||||
foreach($forms as $fid) $new_count += wmf_count_submissions($fid,'neu');
|
||||
$badge = $new_count > 0 ? ' <span class="awaiting-mod update-plugins count-'.intval($new_count).'"><span class="pending-count">'.intval($new_count).'</span></span>' : '';
|
||||
add_submenu_page('wp-multi-formular','Einreichungen','Einreichungen'.$badge,'manage_options','wmf-submissions',array($this,'page_submissions'));
|
||||
}
|
||||
public function page_router() {
|
||||
// Einzelne Einreichung anzeigen
|
||||
if(!empty($_GET['view_submission']) && !empty($_GET['form_id'])) {
|
||||
$sid = intval($_GET['view_submission']);
|
||||
$form_id = intval($_GET['form_id']);
|
||||
require WMF_TPL.'admin/page-submission-detail.php';
|
||||
return;
|
||||
}
|
||||
// Einreichung löschen
|
||||
if(!empty($_GET['wmf_action'])&&$_GET['wmf_action']==='delete_submission'&&!empty($_GET['submission_id'])) {
|
||||
if(wp_verify_nonce($_GET['_wpnonce']??'','wmf_delete_submission')) {
|
||||
WMF_Submission::delete(intval($_GET['submission_id']));
|
||||
$this->safe_redirect(add_query_arg('wmf_notice','deleted',admin_url('admin.php?page=wmf-submissions')));
|
||||
}
|
||||
}
|
||||
// CSV Export
|
||||
if(!empty($_GET['wmf_action'])&&$_GET['wmf_action']==='export_csv'&&!empty($_GET['form_id'])) {
|
||||
WMF_Submissions_List::maybe_export(intval($_GET['form_id']));
|
||||
}
|
||||
// Einreichungen anzeigen
|
||||
if(!empty($_GET['view_submissions'])) {
|
||||
$form_id=intval($_GET['view_submissions']);
|
||||
require WMF_TPL.'admin/page-submissions.php'; return;
|
||||
}
|
||||
// Builder (Bearbeiten)
|
||||
if(!empty($_GET['edit'])) {
|
||||
require WMF_TPL.'admin/page-builder.php'; return;
|
||||
}
|
||||
require WMF_TPL.'admin/page-forms-list.php';
|
||||
}
|
||||
public function page_builder() {
|
||||
require WMF_TPL.'admin/page-builder.php';
|
||||
}
|
||||
|
||||
public function page_submissions() {
|
||||
// Einzelne Einreichung anzeigen
|
||||
if(!empty($_GET['view_submission']) && !empty($_GET['form_id'])) {
|
||||
$sid = intval($_GET['view_submission']);
|
||||
$form_id = intval($_GET['form_id']);
|
||||
$form = get_post($form_id);
|
||||
?>
|
||||
<div class="wrap wmf-admin-wrap">
|
||||
<h1 class="wmf-page-title">
|
||||
Einreichung #<?php echo intval($sid); ?>
|
||||
<span style="font-size:14px;font-weight:normal;color:#646970;margin-left:8px;">
|
||||
aus: <?php echo esc_html($form ? $form->post_title : ''); ?>
|
||||
</span>
|
||||
</h1>
|
||||
<?php WMF_Submissions_List::render_single($sid, $form_id); ?>
|
||||
</div>
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
|
||||
// Einreichungen eines Formulars anzeigen
|
||||
if(!empty($_GET['form_id'])) {
|
||||
$form_id = intval($_GET['form_id']);
|
||||
$form = get_post($form_id);
|
||||
WMF_Submissions_List::maybe_export($form_id);
|
||||
?>
|
||||
<div class="wrap wmf-admin-wrap">
|
||||
<h1 class="wmf-page-title">
|
||||
Einreichungen:
|
||||
<span style="color:#646970;"><?php echo esc_html($form ? $form->post_title : ''); ?></span>
|
||||
<a href="<?php echo esc_url(admin_url('admin.php?page=wmf-submissions')); ?>"
|
||||
class="page-title-action">← Alle Formulare</a>
|
||||
</h1>
|
||||
<?php WMF_Submissions_List::render($form_id); ?>
|
||||
</div>
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
|
||||
// Übersicht aller Formulare mit Einreichungszahlen
|
||||
?>
|
||||
<div class="wrap wmf-admin-wrap">
|
||||
<h1>Einreichungen</h1>
|
||||
<?php
|
||||
$forms = get_posts(array(
|
||||
'post_type' => 'wmf-form',
|
||||
'post_status' => 'publish',
|
||||
'numberposts' => -1,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
));
|
||||
|
||||
if(empty($forms)): ?>
|
||||
<div class="wmf-empty-state">
|
||||
<span class="dashicons dashicons-email-alt wmf-empty-icon"></span>
|
||||
<h2>Noch keine Formulare vorhanden</h2>
|
||||
<p>Erstellen Sie zuerst ein Formular und binden Sie es auf einer Seite ein.</p>
|
||||
<a href="<?php echo esc_url(admin_url('admin.php?page=wmf-new-form')); ?>"
|
||||
class="button button-primary button-hero">Formular erstellen</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<table class="wp-list-table widefat fixed striped wmf-submissions-overview">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Formular</th>
|
||||
<th style="width:100px;text-align:center;">Gesamt</th>
|
||||
<th style="width:80px;text-align:center;">Neu</th>
|
||||
<th style="width:100px;text-align:center;">Gelesen</th>
|
||||
<th style="width:110px;text-align:center;">Archiviert</th>
|
||||
<th style="width:130px;text-align:center;">Letzte Einreichung</th>
|
||||
<th style="width:120px;">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($forms as $form):
|
||||
$total = wmf_count_submissions($form->ID);
|
||||
$count_new = wmf_count_submissions($form->ID, 'neu');
|
||||
$count_read = wmf_count_submissions($form->ID, 'gelesen');
|
||||
$count_arch = wmf_count_submissions($form->ID, 'archiviert');
|
||||
global $wpdb;
|
||||
$last = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT created_at FROM {$wpdb->prefix}wmf_submissions WHERE form_id=%d ORDER BY created_at DESC LIMIT 1",
|
||||
$form->ID
|
||||
));
|
||||
$view_url = add_query_arg(array('page'=>'wmf-submissions','form_id'=>$form->ID), admin_url('admin.php'));
|
||||
$export_url = WMF_Submissions_List::export_url($form->ID);
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>
|
||||
<a href="<?php echo esc_url($view_url); ?>">
|
||||
<?php echo esc_html($form->post_title); ?>
|
||||
</a>
|
||||
</strong>
|
||||
<div style="font-size:11px;color:#646970;margin-top:2px;">
|
||||
<?php echo esc_html(wmf_get_shortcode($form->ID)); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
<a href="<?php echo esc_url($view_url); ?>" style="font-size:18px;font-weight:700;color:#2271b1;text-decoration:none;">
|
||||
<?php echo intval($total); ?>
|
||||
</a>
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
<?php if($count_new > 0): ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('sub_status','neu',$view_url)); ?>"
|
||||
style="display:inline-block;background:#2271b1;color:#fff;border-radius:10px;padding:2px 9px;font-size:12px;font-weight:700;text-decoration:none;">
|
||||
<?php echo intval($count_new); ?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span style="color:#a7aaad;">0</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td style="text-align:center;color:#646970;"><?php echo intval($count_read); ?></td>
|
||||
<td style="text-align:center;color:#a7aaad;"><?php echo intval($count_arch); ?></td>
|
||||
<td style="text-align:center;font-size:12px;color:#646970;">
|
||||
<?php echo $last ? esc_html(date_i18n('d.m.Y H:i', strtotime($last))) : '—'; ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="<?php echo esc_url($view_url); ?>" class="button button-small">Anzeigen</a>
|
||||
<?php if($total > 0): ?>
|
||||
<a href="<?php echo esc_url($export_url); ?>" class="button button-small">CSV</a>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
/**
|
||||
* Sicherer Redirect: funktioniert auch wenn bereits Output gesendet wurde
|
||||
* (z.B. durch andere Plugins wie wp-multi-ticket)
|
||||
*/
|
||||
private function safe_redirect($url) {
|
||||
$url = esc_url_raw($url);
|
||||
if(!headers_sent()) {
|
||||
wp_redirect($url);
|
||||
exit;
|
||||
}
|
||||
// Fallback: JavaScript-Redirect wenn Header bereits gesendet
|
||||
echo '<script>window.location.href=' . wp_json_encode($url) . ';</script>';
|
||||
echo '<noscript><meta http-equiv="refresh" content="0;url=' . esc_attr($url) . '"></noscript>';
|
||||
exit;
|
||||
}
|
||||
|
||||
public function handle_actions() {
|
||||
// Globale Einstellungen speichern (via admin-post.php)
|
||||
add_action('admin_post_wmf_save_global_settings', array($this, 'save_global_settings'));
|
||||
add_action('admin_post_wmf_update_submission_status', array($this, 'update_submission_status'));
|
||||
|
||||
if(empty($_POST['wmf_admin_action'])||!current_user_can('manage_options')) return;
|
||||
if($_POST['wmf_admin_action']==='save_form') {
|
||||
check_admin_referer('wmf_save_form'); $this->save_form();
|
||||
}
|
||||
if($_POST['wmf_admin_action']==='delete_form'&&!empty($_POST['form_id'])) {
|
||||
check_admin_referer('wmf_delete_form_'.intval($_POST['form_id']));
|
||||
wp_delete_post(intval($_POST['form_id']),true);
|
||||
$this->safe_redirect(add_query_arg('wmf_notice','form_deleted',admin_url('admin.php?page=wp-multi-formular')));
|
||||
}
|
||||
}
|
||||
private function save_form() {
|
||||
$form_id=intval($_POST['form_id']??0);
|
||||
$title=sanitize_text_field($_POST['form_title']??'Neues Formular');
|
||||
$fields_raw=stripslashes($_POST['wmf_form_fields']??'[]');
|
||||
$fields=json_decode($fields_raw,true);
|
||||
if(!is_array($fields)) $fields=array();
|
||||
|
||||
// Felder bereinigen
|
||||
$clean_fields=array();
|
||||
foreach($fields as $f) {
|
||||
if(empty($f['id'])||empty($f['type'])) continue;
|
||||
$f['name']=sanitize_key($f['name']??$f['id']);
|
||||
$f['label']=sanitize_text_field($f['label']??'');
|
||||
$f['placeholder']=sanitize_text_field($f['placeholder']??'');
|
||||
$f['description']=sanitize_text_field($f['description']??'');
|
||||
$f['required']=in_array($f['required']??'0',array('0','1'))?$f['required']:'0';
|
||||
$f['width']=in_array($f['width']??'full',array('full','half','third'))?$f['width']:'full';
|
||||
$clean_fields[]=$f;
|
||||
}
|
||||
|
||||
$step_labels=array();
|
||||
if(!empty($_POST['step_labels'])&&is_array($_POST['step_labels'])) {
|
||||
$step_labels=array_map('sanitize_text_field',$_POST['step_labels']);
|
||||
}
|
||||
|
||||
$data=array(
|
||||
'fields' => $clean_fields,
|
||||
'submit_label' => sanitize_text_field($_POST['submit_label']??'Absenden'),
|
||||
'success_message' => sanitize_textarea_field($_POST['success_message']??''),
|
||||
'error_message' => sanitize_textarea_field($_POST['error_message']??''),
|
||||
'notify_admin' => !empty($_POST['notify_admin'])?'1':'0',
|
||||
'admin_email' => sanitize_email($_POST['admin_email']??''),
|
||||
'admin_subject' => sanitize_text_field($_POST['admin_subject']??''),
|
||||
'admin_reply_to' => !empty($_POST['admin_reply_to'])?'1':'0',
|
||||
'notify_sender' => !empty($_POST['notify_sender'])?'1':'0',
|
||||
'sender_subject' => sanitize_text_field($_POST['sender_subject']??''),
|
||||
'sender_message' => sanitize_textarea_field($_POST['sender_message']??''),
|
||||
'from_name' => sanitize_text_field($_POST['from_name']??''),
|
||||
'from_email' => sanitize_email($_POST['from_email']??''),
|
||||
'save_submissions' => !empty($_POST['save_submissions'])?'1':'0',
|
||||
'recaptcha_enabled' => !empty($_POST['recaptcha_enabled'])?'1':'0',
|
||||
'honeypot_enabled' => !empty($_POST['honeypot_enabled'])?'1':'0',
|
||||
'redirect_url' => esc_url_raw($_POST['redirect_url']??''),
|
||||
'css_class' => sanitize_html_class($_POST['css_class']??''),
|
||||
'multi_step' => !empty($_POST['multi_step'])?'1':'0',
|
||||
'step_labels' => $step_labels,
|
||||
'show_progress' => !empty($_POST['show_progress'])?'1':'0',
|
||||
);
|
||||
|
||||
if($form_id) {
|
||||
wp_update_post(array('ID'=>$form_id,'post_title'=>$title,'post_status'=>'publish'));
|
||||
} else {
|
||||
$form_id=wp_insert_post(array('post_type'=>'wmf-form','post_title'=>$title,'post_status'=>'publish'));
|
||||
}
|
||||
wmf_save_form_meta($form_id,$data);
|
||||
$this->safe_redirect(add_query_arg(array('page'=>'wp-multi-formular','edit'=>$form_id,'wmf_notice'=>'saved'),admin_url('admin.php')));
|
||||
}
|
||||
public function admin_notices() {
|
||||
$n=$_GET['wmf_notice']??'';
|
||||
$msgs=array('saved'=>array('success','Formular gespeichert.'),'deleted'=>array('success','Einreichung gelöscht.'),'form_deleted'=>array('success','Formular gelöscht.'),'global_saved'=>array('success','Globale E-Mail-Einstellungen gespeichert.'));
|
||||
if(isset($msgs[$n])) printf('<div class="notice notice-%s is-dismissible"><p>%s</p></div>',esc_attr($msgs[$n][0]),esc_html($msgs[$n][1]));
|
||||
}
|
||||
public function enqueue_assets($hook) {
|
||||
$page=$_GET['page']??'';
|
||||
if(!in_array($page,array('wp-multi-formular','wmf-new-form','wmf-integrations'))&&strpos($hook,'wmf')=== false) return;
|
||||
wp_enqueue_style('wmf-admin',WMF_URL.'assets/css/admin.css',array(),WMF_VERSION);
|
||||
wp_enqueue_script('wmf-admin',WMF_URL.'assets/js/admin.js',array('jquery','jquery-ui-sortable','jquery-ui-draggable'),WMF_VERSION,true);
|
||||
wp_enqueue_style('dashicons');
|
||||
wp_localize_script('wmf-admin','WMF',array(
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('wmf_admin'),
|
||||
'fields' => $this->fields_for_js(),
|
||||
'i18n' => array(
|
||||
'confirm_delete' => 'Feld wirklich löschen?',
|
||||
'confirm_delete_form' => 'Formular und alle Einreichungen wirklich löschen?',
|
||||
'no_label' => '(kein Titel)',
|
||||
'loading' => 'Lade …',
|
||||
'preview' => 'Vorschau',
|
||||
'close_preview' => 'Vorschau schließen',
|
||||
),
|
||||
));
|
||||
}
|
||||
public function update_submission_status() {
|
||||
if(!wp_verify_nonce($_POST['_wpnonce'] ?? '', 'wmf_update_status') || !current_user_can('manage_options')) wp_die('Fehler.');
|
||||
$sid = intval($_POST['submission_id'] ?? 0);
|
||||
$status = sanitize_text_field($_POST['status'] ?? 'neu');
|
||||
$form_id = intval($_POST['form_id'] ?? 0);
|
||||
$redirect = esc_url_raw($_POST['redirect_url'] ?? admin_url('admin.php?page=wp-multi-formular'));
|
||||
if($sid && in_array($status, array('neu','gelesen','archiviert'))) {
|
||||
WMF_Submission::update_status($sid, $status);
|
||||
}
|
||||
$this->safe_redirect($redirect);
|
||||
}
|
||||
|
||||
public function save_global_settings() {
|
||||
if(!wp_verify_nonce($_POST['wmf_global_nonce'] ?? '', 'wmf_global_settings_save')) {
|
||||
wp_die('Sicherheitsfehler.');
|
||||
}
|
||||
if(!current_user_can('manage_options')) wp_die('Keine Berechtigung.');
|
||||
|
||||
$settings = array(
|
||||
'from_name' => sanitize_text_field($_POST['wmf_from_name'] ?? ''),
|
||||
'from_email' => sanitize_email( $_POST['wmf_from_email'] ?? ''),
|
||||
'smtp_enabled' => !empty($_POST['wmf_smtp_enabled']) ? '1' : '0',
|
||||
'smtp_host' => sanitize_text_field($_POST['wmf_smtp_host'] ?? ''),
|
||||
'smtp_port' => intval( $_POST['wmf_smtp_port'] ?? 587),
|
||||
'smtp_enc' => sanitize_text_field($_POST['wmf_smtp_enc'] ?? 'tls'),
|
||||
'smtp_user' => sanitize_text_field($_POST['wmf_smtp_user'] ?? ''),
|
||||
'smtp_pass' => $_POST['wmf_smtp_pass'] ?? '', // Passwort nicht strippen
|
||||
);
|
||||
|
||||
update_option('wmf_global_settings', $settings);
|
||||
|
||||
$this->safe_redirect(add_query_arg(array('page'=>'wmf-integrations','wmf_notice'=>'global_saved'), admin_url('admin.php')));
|
||||
}
|
||||
|
||||
private function fields_for_js() {
|
||||
$r=array();
|
||||
foreach(wmf_get_fields() as $type=>$f) {
|
||||
$r[]=array('type'=>$type,'label'=>$f->label,'icon'=>$f->icon,'category'=>$f->category,'defaults'=>$f->defaults());
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
44
inc/classes/class-builder.php
Normal file
44
inc/classes/class-builder.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
class WMF_Builder {
|
||||
private static $instance=null;
|
||||
public static function instance() {
|
||||
if(is_null(self::$instance)){self::$instance=new self();self::$instance->hook();}
|
||||
return self::$instance;
|
||||
}
|
||||
public function hook() {
|
||||
add_action('wp_ajax_wmf_get_field_settings',array($this,'ajax_field_settings'));
|
||||
add_action('wp_ajax_wmf_preview_form', array($this,'ajax_preview'));
|
||||
}
|
||||
public function ajax_field_settings() {
|
||||
check_ajax_referer('wmf_admin','nonce');
|
||||
if(!current_user_can('manage_options')) wp_die();
|
||||
$type=sanitize_text_field($_POST['field_type']??'');
|
||||
$field=json_decode(stripslashes($_POST['field_data']??'{}'),true);
|
||||
$obj=wmf_get_field($type);
|
||||
if(!$obj) wp_send_json_error('Unbekannter Feldtyp: '.$type);
|
||||
ob_start(); $obj->settings_panel($field); $html=ob_get_clean();
|
||||
wp_send_json_success(array('html'=>$html));
|
||||
}
|
||||
public function ajax_preview() {
|
||||
check_ajax_referer('wmf_admin','nonce');
|
||||
if(!current_user_can('manage_options')) wp_die();
|
||||
$form_id=intval($_POST['form_id']??0);
|
||||
$fields=json_decode(stripslashes($_POST['fields']??'[]'),true);
|
||||
$meta=wmf_get_form_meta($form_id);
|
||||
$meta['fields']=$fields;
|
||||
ob_start();
|
||||
echo '<div class="wmf-preview-wrap">';
|
||||
foreach($fields as $field) {
|
||||
$obj=wmf_get_field($field['type']??'');
|
||||
if(!$obj) continue;
|
||||
echo '<div class="wmf-field-wrap">';
|
||||
$obj->render($field,'');
|
||||
echo '</div>';
|
||||
}
|
||||
echo '<div class="wmf-submit-wrap"><button type="button" class="wmf-submit-button" disabled>'.esc_html($meta['submit_label']?:'Absenden').'</button></div>';
|
||||
echo '</div>';
|
||||
$html=ob_get_clean();
|
||||
wp_send_json_success(array('html'=>$html));
|
||||
}
|
||||
}
|
||||
21
inc/classes/class-field-registry.php
Normal file
21
inc/classes/class-field-registry.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
class WMF_Field_Registry {
|
||||
private static $instance=null;
|
||||
private $fields=array();
|
||||
public static function instance() {
|
||||
if(is_null(self::$instance)){self::$instance=new self();self::$instance->register_defaults();}
|
||||
return self::$instance;
|
||||
}
|
||||
private function register_defaults() {
|
||||
foreach(array('WMF_Field_Text','WMF_Field_Email','WMF_Field_Textarea','WMF_Field_Select',
|
||||
'WMF_Field_Checkbox','WMF_Field_Radio','WMF_Field_Number','WMF_Field_Phone',
|
||||
'WMF_Field_URL','WMF_Field_Date','WMF_Field_File','WMF_Field_Rating',
|
||||
'WMF_Field_Range','WMF_Field_GDPR','WMF_Field_Signature',
|
||||
'WMF_Field_Hidden','WMF_Field_HTML','WMF_Field_Divider') as $cls) {
|
||||
$f=new $cls(); $this->fields[$f->type]=$f;
|
||||
}
|
||||
}
|
||||
public function get_fields() { return $this->fields; }
|
||||
public function get_field($type) { return $this->fields[$type]??null; }
|
||||
}
|
||||
105
inc/classes/class-form-processor.php
Normal file
105
inc/classes/class-form-processor.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
class WMF_Form_Processor {
|
||||
private static $instance=null;
|
||||
public static function instance() {
|
||||
if(is_null(self::$instance)){self::$instance=new self();self::$instance->hook();}
|
||||
return self::$instance;
|
||||
}
|
||||
public function hook() {
|
||||
add_action('init',array($this,'maybe_process'),20);
|
||||
}
|
||||
public function maybe_process() {
|
||||
if(empty($_POST['wmf_action'])||$_POST['wmf_action']!=='submit') return;
|
||||
if(empty($_POST['wmf_form_id'])) return;
|
||||
if(!session_id()) session_start();
|
||||
|
||||
$form_id=intval($_POST['wmf_form_id']);
|
||||
if(!wp_verify_nonce($_POST['wmf_nonce']??'','wmf_submit_'.$form_id)) {
|
||||
$this->fail($form_id,'Sicherheitsüberprüfung fehlgeschlagen.'); return;
|
||||
}
|
||||
$form=get_post($form_id);
|
||||
if(!$form||$form->post_type!=='wmf-form') return;
|
||||
|
||||
$meta = wmf_get_form_meta($form_id);
|
||||
$fields = $meta['fields']??array();
|
||||
|
||||
// Honeypot prüfen
|
||||
if(!empty($meta['honeypot_enabled'])&&$meta['honeypot_enabled']==='1') {
|
||||
if(!empty($_POST['wmf_hp_'.md5($form_id)])) { $this->ok($form_id,$meta); return; } // stille Ablehnung
|
||||
}
|
||||
|
||||
// Werte sammeln + validieren
|
||||
$values=array(); $errors=array();
|
||||
foreach($fields as $field) {
|
||||
$type=$field['type']??'';
|
||||
$obj=wmf_get_field($type);
|
||||
if(!$obj) continue;
|
||||
if(in_array($type,array('html','divider'))) continue;
|
||||
|
||||
$raw=$_POST['wmf_fields'][$field['id']]??'';
|
||||
$val=$obj->sanitize($raw,$field);
|
||||
$valid=$obj->validate($val,$field);
|
||||
$values[$field['id']]=$val;
|
||||
if($valid!==true) $errors[$field['id']]=$valid;
|
||||
}
|
||||
|
||||
// Datei-Uploads
|
||||
$file_values=array();
|
||||
if(!empty($_FILES['wmf_files'])) {
|
||||
foreach($fields as $field) {
|
||||
if(($field['type']??'')!=='file') continue;
|
||||
$uploaded=WMF_Field_File::handle_upload($field,$form_id);
|
||||
if(!empty($uploaded)) $file_values[$field['id']]=$uploaded;
|
||||
// Validierung nochmal mit Upload-Ergebnis
|
||||
$valid=wmf_get_field('file')->validate('',$field);
|
||||
if($valid!==true&&!isset($errors[$field['id']])) $errors[$field['id']]=$valid;
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($errors)) {
|
||||
$_SESSION['wmf_values_'.$form_id]=$values;
|
||||
$_SESSION['wmf_errors_'.$form_id]=$errors;
|
||||
wp_redirect($this->current_url()); exit;
|
||||
}
|
||||
|
||||
// Datei-URLs in Werte mergen
|
||||
foreach($file_values as $fid=>$uploads) {
|
||||
$urls=array_map(fn($u)=>$u['url'],$uploads);
|
||||
$values[$fid]=implode(', ',$urls);
|
||||
}
|
||||
|
||||
// Speichern
|
||||
$submission_id=null;
|
||||
if(!empty($meta['save_submissions'])&&$meta['save_submissions']==='1') {
|
||||
$submission_id=WMF_Submission::save($form_id,$values);
|
||||
}
|
||||
|
||||
// E-Mails
|
||||
if(!empty($meta['notify_admin'])&&$meta['notify_admin']==='1') {
|
||||
WMF_Mailer::notify_admin($form_id,$meta,$fields,$values,$file_values);
|
||||
}
|
||||
if(!empty($meta['notify_sender'])&&$meta['notify_sender']==='1') {
|
||||
WMF_Mailer::notify_sender($form_id,$meta,$fields,$values);
|
||||
}
|
||||
|
||||
do_action('wmf_form_submitted',$form_id,$meta,$fields,$values,$submission_id);
|
||||
$this->ok($form_id,$meta);
|
||||
}
|
||||
|
||||
private function ok($form_id,$meta) {
|
||||
if(!empty($meta['redirect_url'])) { wp_redirect(esc_url_raw($meta['redirect_url'])); exit; }
|
||||
if(!session_id()) session_start();
|
||||
$_SESSION['wmf_success_'.$form_id]=true;
|
||||
wp_redirect($this->current_url()); exit;
|
||||
}
|
||||
private function fail($form_id,$msg) {
|
||||
if(!session_id()) session_start();
|
||||
$_SESSION['wmf_errors_'.$form_id]=array('_global'=>$msg);
|
||||
wp_redirect($this->current_url()); exit;
|
||||
}
|
||||
private function current_url() {
|
||||
return (is_ssl()?'https':'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
||||
}
|
||||
}
|
||||
145
inc/classes/class-form-renderer.php
Normal file
145
inc/classes/class-form-renderer.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
class WMF_Form_Renderer {
|
||||
|
||||
public static function render($form_id,$args=array()) {
|
||||
$form=get_post($form_id);
|
||||
if(!$form||$form->post_type!=='wmf-form'||$form->post_status!=='publish')
|
||||
return '<p class="wmf-error">Formular nicht gefunden.</p>';
|
||||
|
||||
if(!session_id()) session_start();
|
||||
|
||||
$meta = wmf_get_form_meta($form_id);
|
||||
$fields = $meta['fields']??array();
|
||||
$saved_values = $_SESSION['wmf_values_'.$form_id]??array();
|
||||
$errors = $_SESSION['wmf_errors_'.$form_id]??array();
|
||||
$success = $_SESSION['wmf_success_'.$form_id]??false;
|
||||
|
||||
unset($_SESSION['wmf_values_'.$form_id],$_SESSION['wmf_errors_'.$form_id],$_SESSION['wmf_success_'.$form_id]);
|
||||
|
||||
ob_start();
|
||||
|
||||
if($success) {
|
||||
echo '<div class="wmf-notice wmf-notice-success" role="alert">'.esc_html($meta['success_message']).'</div>';
|
||||
if(empty($args['always_show'])) return ob_get_clean();
|
||||
}
|
||||
if(!empty($errors['_global']))
|
||||
echo '<div class="wmf-notice wmf-notice-error" role="alert">'.esc_html($errors['_global']).'</div>';
|
||||
|
||||
$multi_step=!empty($meta['multi_step'])&&$meta['multi_step']==='1';
|
||||
// Schritte ermitteln
|
||||
$steps=array();
|
||||
foreach($fields as $f) { $s=intval($f['step']??0); if(!isset($steps[$s])) $steps[$s]=array(); $steps[$s][]=$f; }
|
||||
ksort($steps);
|
||||
$total_steps=count($steps);
|
||||
if($total_steps<2) $multi_step=false;
|
||||
|
||||
$form_cls='wmf-form'.(!empty($meta['css_class'])?' '.esc_attr($meta['css_class']):'');
|
||||
$field_json=wp_json_encode($fields);
|
||||
?>
|
||||
<div class="wmf-form-wrap" id="wmf-wrap-<?php echo intval($form_id); ?>">
|
||||
|
||||
<?php if($multi_step&&!empty($meta['show_progress'])&&$meta['show_progress']==='1'): ?>
|
||||
<div class="wmf-progress-bar" data-steps="<?php echo $total_steps; ?>">
|
||||
<?php $step_labels=$meta['step_labels']??array();
|
||||
foreach(array_keys($steps) as $si=>$snum): $lbl=$step_labels[$si]??'Schritt '.($si+1); ?>
|
||||
<div class="wmf-step-indicator <?php echo $si===0?'active':''; ?>" data-step="<?php echo $si; ?>">
|
||||
<span class="wmf-step-num"><?php echo $si+1; ?></span>
|
||||
<span class="wmf-step-lbl"><?php echo esc_html($lbl); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form class="<?php echo $form_cls; ?>"
|
||||
id="wmf-form-<?php echo intval($form_id); ?>"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
novalidate
|
||||
data-form-id="<?php echo intval($form_id); ?>"
|
||||
data-multi-step="<?php echo $multi_step?'1':'0'; ?>"
|
||||
data-total-steps="<?php echo $total_steps; ?>"
|
||||
data-fields='<?php echo esc_attr($field_json); ?>'>
|
||||
|
||||
<?php wp_nonce_field('wmf_submit_'.$form_id,'wmf_nonce'); ?>
|
||||
<input type="hidden" name="wmf_form_id" value="<?php echo intval($form_id); ?>">
|
||||
<input type="hidden" name="wmf_action" value="submit">
|
||||
|
||||
<?php // Honeypot
|
||||
if(!empty($meta['honeypot_enabled'])&&$meta['honeypot_enabled']==='1'):
|
||||
$hp_name='wmf_hp_'.md5($form_id); ?>
|
||||
<div class="wmf-hp-field" aria-hidden="true" style="position:absolute;left:-9999px;opacity:0;pointer-events:none;">
|
||||
<label for="<?php echo esc_attr($hp_name); ?>">Bitte leer lassen</label>
|
||||
<input type="text" id="<?php echo esc_attr($hp_name); ?>" name="<?php echo esc_attr($hp_name); ?>" value="" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if($multi_step): ?>
|
||||
<?php foreach(array_values($steps) as $si=>$step_fields): ?>
|
||||
<div class="wmf-step" data-step="<?php echo $si; ?>" <?php echo $si>0?'style="display:none;"':''; ?>>
|
||||
<div class="wmf-fields">
|
||||
<?php self::render_fields($step_fields,$errors,$saved_values); ?>
|
||||
</div>
|
||||
<div class="wmf-step-nav">
|
||||
<?php if($si>0): ?><button type="button" class="wmf-prev-step button button-secondary">← Zurück</button><?php endif; ?>
|
||||
<?php if($si<$total_steps-1): ?>
|
||||
<button type="button" class="wmf-next-step button button-primary">Weiter →</button>
|
||||
<?php else: ?>
|
||||
<?php self::render_submit($meta,$form_id); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<div class="wmf-fields">
|
||||
<?php self::render_fields($fields,$errors,$saved_values); ?>
|
||||
</div>
|
||||
<?php self::render_submit($meta,$form_id); ?>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
private static function render_fields($fields,$errors,$saved_values) {
|
||||
foreach($fields as $field) {
|
||||
$obj=wmf_get_field($field['type']??'');
|
||||
if(!$obj) continue;
|
||||
$value=$saved_values[$field['id']]??'';
|
||||
$err=$errors[$field['id']]??'';
|
||||
$wrap_cls='wmf-field-wrap'.($err?' wmf-has-error':'');
|
||||
echo '<div class="'.esc_attr($wrap_cls).'">';
|
||||
$obj->render($field,$value);
|
||||
if($err) echo '<p class="wmf-field-error">'.esc_html($err).'</p>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
private static function render_submit($meta,$form_id) {
|
||||
// reCAPTCHA
|
||||
$integrations=wmf_get_integrations();
|
||||
if(!empty($meta['recaptcha_enabled'])&&$meta['recaptcha_enabled']==='1') {
|
||||
$rv3=$integrations->get_service('recaptchav3');
|
||||
$rv2=$integrations->get_service('recaptcha');
|
||||
if($rv3&&$rv3->is_connected()) {
|
||||
$creds=$rv3->get_credentials();
|
||||
echo '<input type="hidden" name="wmf_recaptcha_token" id="wmf-rctoken-'.intval($form_id).'">';
|
||||
echo '<script>if(typeof grecaptcha!=="undefined"){grecaptcha.ready(function(){grecaptcha.execute("'.esc_js($creds['site_key']).'",{action:"submit"}).then(function(t){document.getElementById("wmf-rctoken-'.intval($form_id).'").value=t;});});}</script>';
|
||||
} elseif($rv2&&$rv2->is_connected()) {
|
||||
$creds=$rv2->get_credentials();
|
||||
echo '<div class="wmf-recaptcha g-recaptcha" data-sitekey="'.esc_attr($creds['site_key']).'"></div>';
|
||||
echo '<script async defer src="https://www.google.com/recaptcha/api.js"></script>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="wmf-submit-wrap">
|
||||
<button type="submit" class="wmf-submit-button">
|
||||
<?php echo esc_html($meta['submit_label']?:'Absenden'); ?>
|
||||
</button>
|
||||
<span class="wmf-spinner" aria-hidden="true"></span>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
102
inc/classes/class-mailer.php
Normal file
102
inc/classes/class-mailer.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class WMF_Mailer {
|
||||
|
||||
/**
|
||||
* Admin-Benachrichtigung
|
||||
*/
|
||||
public static function notify_admin($form_id, $meta, $fields, $values, $file_values = array()) {
|
||||
$global = get_option('wmf_global_settings', array());
|
||||
$from_name = !empty($meta['from_name']) ? $meta['from_name'] : ($global['from_name'] ?? get_bloginfo('name'));
|
||||
$from_email = !empty($meta['from_email']) ? $meta['from_email'] : ($global['from_email'] ?? get_option('admin_email'));
|
||||
$to = !empty($meta['admin_email']) ? $meta['admin_email'] : get_option('admin_email');
|
||||
$subject = !empty($meta['admin_subject']) ? $meta['admin_subject'] : 'Neue Formulareinreichung';
|
||||
|
||||
$headers = array(
|
||||
'Content-Type: text/html; charset=UTF-8',
|
||||
'From: ' . $from_name . ' <' . $from_email . '>',
|
||||
);
|
||||
|
||||
// Reply-To auf Absender-E-Mail-Feld setzen
|
||||
if(!empty($meta['admin_reply_to']) && $meta['admin_reply_to'] === '1') {
|
||||
foreach($fields as $f) {
|
||||
if(($f['type'] ?? '') === 'email' && !empty($values[$f['id']]) && is_email($values[$f['id']])) {
|
||||
$headers[] = 'Reply-To: ' . $values[$f['id']];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wp_mail($to, $subject, self::build_body($fields, $values, $file_values), $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Absender-Bestaetigung
|
||||
*/
|
||||
public static function notify_sender($form_id, $meta, $fields, $values) {
|
||||
$global = get_option('wmf_global_settings', array());
|
||||
$from_name = !empty($meta['from_name']) ? $meta['from_name'] : ($global['from_name'] ?? get_bloginfo('name'));
|
||||
$from_email = !empty($meta['from_email']) ? $meta['from_email'] : ($global['from_email'] ?? get_option('admin_email'));
|
||||
|
||||
$email = '';
|
||||
foreach($fields as $f) {
|
||||
if(($f['type'] ?? '') === 'email' && !empty($values[$f['id']]) && is_email($values[$f['id']])) {
|
||||
$email = $values[$f['id']];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$email) return;
|
||||
|
||||
$headers = array(
|
||||
'Content-Type: text/html; charset=UTF-8',
|
||||
'From: ' . $from_name . ' <' . $from_email . '>',
|
||||
);
|
||||
|
||||
$body = '<html><body style="font-family:sans-serif;color:#1d2327;max-width:600px;margin:0 auto;">'
|
||||
. wpautop(esc_html($meta['sender_message'] ?? ''))
|
||||
. '<p style="color:#888;font-size:12px;margin-top:24px;">Gesendet ueber ' . get_bloginfo('name') . '</p>'
|
||||
. '</body></html>';
|
||||
|
||||
wp_mail($email, $meta['sender_subject'] ?? 'Ihre Nachricht wurde empfangen', $body, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* E-Mail-Body aufbauen
|
||||
*/
|
||||
private static function build_body($fields, $values, $file_values) {
|
||||
$rows = '';
|
||||
foreach($fields as $f) {
|
||||
if(in_array($f['type'] ?? '', array('html','divider','hidden'))) continue;
|
||||
$lbl = $f['label'] ?? $f['id'];
|
||||
$val = $values[$f['id']] ?? '';
|
||||
if(is_array($val)) $val = implode(', ', $val);
|
||||
if(($f['type'] ?? '') === 'gdpr')
|
||||
$val = ($val === '1') ? '✓ Zugestimmt' : '✗ Nicht zugestimmt';
|
||||
if(($f['type'] ?? '') === 'signature' && !empty($val))
|
||||
$val = '<img src="' . esc_attr($val) . '" style="max-width:300px;border:1px solid #ddd;">';
|
||||
if(isset($file_values[$f['id']])) {
|
||||
$links = array_map(
|
||||
fn($u) => '<a href="' . esc_url($u['url']) . '">' . esc_html($u['name']) . '</a>',
|
||||
$file_values[$f['id']]
|
||||
);
|
||||
$val = implode('<br>', $links);
|
||||
}
|
||||
$rows .= '<tr>'
|
||||
. '<th style="text-align:left;padding:8px 14px;background:#f6f7f7;border-bottom:1px solid #eee;white-space:nowrap;font-weight:600;">' . esc_html($lbl) . '</th>'
|
||||
. '<td style="padding:8px 14px;border-bottom:1px solid #eee;">' . $val . '</td>'
|
||||
. '</tr>';
|
||||
}
|
||||
|
||||
return '<html><body style="font-family:Arial,sans-serif;color:#1d2327;max-width:600px;margin:0 auto;">'
|
||||
. '<div style="background:#2271b1;padding:20px 24px;border-radius:4px 4px 0 0;">'
|
||||
. '<h2 style="color:#fff;margin:0;font-size:18px;">Neue Formulareinreichung</h2>'
|
||||
. '<p style="color:rgba(255,255,255,.8);margin:4px 0 0;font-size:13px;">' . get_bloginfo('name') . ' · ' . current_time('d.m.Y H:i') . '</p>'
|
||||
. '</div>'
|
||||
. '<div style="border:1px solid #dcdcde;border-top:none;border-radius:0 0 4px 4px;padding:0;">'
|
||||
. '<table style="border-collapse:collapse;width:100%;">' . $rows . '</table>'
|
||||
. '</div>'
|
||||
. '<p style="color:#888;font-size:11px;margin-top:16px;text-align:center;">Diese E-Mail wurde automatisch gesendet von WP Multi Formular</p>'
|
||||
. '</body></html>';
|
||||
}
|
||||
}
|
||||
43
inc/classes/class-post-type.php
Normal file
43
inc/classes/class-post-type.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
class WMF_Post_Type {
|
||||
private static $instance = null;
|
||||
public static function instance() {
|
||||
if ( is_null( self::$instance ) ) { self::$instance = new self(); self::$instance->hook(); }
|
||||
return self::$instance;
|
||||
}
|
||||
public function hook() {
|
||||
add_action( 'init', array( $this, 'register' ) );
|
||||
add_action( 'admin_init', array( $this, 'redirect_cpt' ) );
|
||||
}
|
||||
public static function register() {
|
||||
register_post_type( 'wmf-form', array(
|
||||
'labels' => array(
|
||||
'name' => 'Formulare',
|
||||
'singular_name' => 'Formular',
|
||||
'not_found' => 'Keine Formulare gefunden.',
|
||||
),
|
||||
'public' => false,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'supports' => array( 'title' ),
|
||||
'capability_type' => 'post',
|
||||
'has_archive' => false,
|
||||
'rewrite' => false,
|
||||
) );
|
||||
}
|
||||
public function redirect_cpt() {
|
||||
if ( ! is_admin() ) return;
|
||||
$pt = $_GET['post_type'] ?? '';
|
||||
if ( $pt === 'wmf-form' && basename( $_SERVER['PHP_SELF'] ) === 'edit.php' ) {
|
||||
wp_redirect( admin_url( 'admin.php?page=wp-multi-formular' ) ); exit;
|
||||
}
|
||||
if ( isset( $_GET['post'], $_GET['action'] ) && $_GET['action'] === 'edit' ) {
|
||||
$p = get_post( intval( $_GET['post'] ) );
|
||||
if ( $p && $p->post_type === 'wmf-form' ) {
|
||||
wp_redirect( admin_url( 'admin.php?page=wp-multi-formular&edit=' . $p->ID ) ); exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
inc/classes/class-shortcode.php
Normal file
36
inc/classes/class-shortcode.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
class WMF_Shortcode {
|
||||
private static $instance=null;
|
||||
public static function instance() {
|
||||
if(is_null(self::$instance)){self::$instance=new self();self::$instance->hook();}
|
||||
return self::$instance;
|
||||
}
|
||||
public function hook() {
|
||||
add_shortcode('wp_multi_formular',array($this,'render'));
|
||||
add_action('wp_enqueue_scripts',array($this,'enqueue_assets'));
|
||||
add_action('init',array($this,'start_session'),1);
|
||||
}
|
||||
public function start_session() { if(!session_id()&&!headers_sent()) session_start(); }
|
||||
public function render($atts) {
|
||||
$atts=shortcode_atts(array('id'=>0),$atts,'wp_multi_formular');
|
||||
$id=intval($atts['id']);
|
||||
if(!$id) return '<p class="wmf-error">Bitte geben Sie eine Formular-ID an.</p>';
|
||||
return WMF_Form_Renderer::render($id);
|
||||
}
|
||||
public function enqueue_assets() {
|
||||
wp_enqueue_style('wp-multi-formular',WMF_URL.'assets/css/frontend.css',array(),WMF_VERSION);
|
||||
wp_enqueue_script('wp-multi-formular',WMF_URL.'assets/js/frontend.js',array('jquery'),WMF_VERSION,true);
|
||||
wp_localize_script('wp-multi-formular','WMF_Frontend',array(
|
||||
'ajax_url'=>admin_url('admin-ajax.php'),
|
||||
'i18n'=>array(
|
||||
'required' =>'Dieses Feld ist ein Pflichtfeld.',
|
||||
'email' =>'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
|
||||
'url' =>'Bitte geben Sie eine gültige URL ein.',
|
||||
'step_of' =>'Schritt %1 von %2',
|
||||
'next' =>'Weiter',
|
||||
'prev' =>'Zurück',
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
54
inc/classes/class-smtp.php
Normal file
54
inc/classes/class-smtp.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class WMF_SMTP {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function instance() {
|
||||
if(is_null(self::$instance)) {
|
||||
self::$instance = new self();
|
||||
self::$instance->hook();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function hook() {
|
||||
$opts = get_option('wmf_global_settings', array());
|
||||
if(!empty($opts['smtp_enabled']) && $opts['smtp_enabled'] === '1' && !empty($opts['smtp_host'])) {
|
||||
add_action('phpmailer_init', array($this, 'configure_smtp'));
|
||||
}
|
||||
}
|
||||
|
||||
public function configure_smtp($phpmailer) {
|
||||
$opts = get_option('wmf_global_settings', array());
|
||||
if(empty($opts['smtp_host'])) return;
|
||||
|
||||
$phpmailer->isSMTP();
|
||||
$phpmailer->Host = $opts['smtp_host'];
|
||||
$phpmailer->Port = intval($opts['smtp_port'] ?? 587);
|
||||
$phpmailer->SMTPSecure = $opts['smtp_enc'] ?? 'tls';
|
||||
|
||||
if(!empty($opts['smtp_user'])) {
|
||||
$phpmailer->SMTPAuth = true;
|
||||
$phpmailer->Username = $opts['smtp_user'];
|
||||
$phpmailer->Password = $opts['smtp_pass'] ?? '';
|
||||
} else {
|
||||
$phpmailer->SMTPAuth = false;
|
||||
}
|
||||
|
||||
// From-Adresse global setzen falls nicht per Mail-Header gesetzt
|
||||
if(!empty($opts['from_email'])) {
|
||||
$phpmailer->From = $opts['from_email'];
|
||||
$phpmailer->FromName = $opts['from_name'] ?? get_bloginfo('name');
|
||||
}
|
||||
|
||||
$phpmailer->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
18
inc/classes/class-submission.php
Normal file
18
inc/classes/class-submission.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
class WMF_Submission {
|
||||
public static function save($form_id,$values) {
|
||||
global $wpdb;
|
||||
$wpdb->insert($wpdb->prefix.'wmf_submissions',array(
|
||||
'form_id'=>$form_id,'data'=>wp_json_encode($values),
|
||||
'ip'=>wmf_get_client_ip(),'user_agent'=>$_SERVER['HTTP_USER_AGENT']??'',
|
||||
'status'=>'neu','created_at'=>current_time('mysql'),
|
||||
),array('%d','%s','%s','%s','%s','%s'));
|
||||
return $wpdb->insert_id;
|
||||
}
|
||||
public static function delete($id) { global $wpdb; $wpdb->delete($wpdb->prefix.'wmf_submissions',array('id'=>$id),array('%d')); }
|
||||
public static function update_status($id,$status) {
|
||||
global $wpdb;
|
||||
$wpdb->update($wpdb->prefix.'wmf_submissions',array('status'=>sanitize_text_field($status)),array('id'=>$id),array('%s'),array('%d'));
|
||||
}
|
||||
}
|
||||
481
inc/classes/class-submissions-list.php
Normal file
481
inc/classes/class-submissions-list.php
Normal file
@@ -0,0 +1,481 @@
|
||||
<?php
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class WMF_Submissions_List {
|
||||
|
||||
/* ================================================================
|
||||
LISTE ALLER EINREICHUNGEN EINES FORMULARS
|
||||
================================================================ */
|
||||
public static function render($form_id) {
|
||||
$meta = wmf_get_form_meta($form_id);
|
||||
$fields = self::get_display_fields($meta);
|
||||
$per_page = 25;
|
||||
$current_page= max(1, intval($_GET['paged'] ?? 1));
|
||||
$offset = ($current_page - 1) * $per_page;
|
||||
$status_filter = sanitize_text_field($_GET['sub_status'] ?? '');
|
||||
$search = sanitize_text_field($_GET['sub_search'] ?? '');
|
||||
|
||||
$submissions = wmf_get_submissions($form_id, array(
|
||||
'limit' => $per_page,
|
||||
'offset' => $offset,
|
||||
'status' => $status_filter,
|
||||
'search' => $search,
|
||||
));
|
||||
$total = wmf_count_submissions($form_id, $status_filter, $search);
|
||||
$total_pages = ceil($total / $per_page);
|
||||
|
||||
$base_url = add_query_arg(array(
|
||||
'page' => 'wp-multi-formular',
|
||||
'view_submissions' => $form_id,
|
||||
), admin_url('admin.php'));
|
||||
?>
|
||||
|
||||
<div class="wmf-submissions-wrap">
|
||||
|
||||
<!-- Header -->
|
||||
<div class="wmf-subs-header">
|
||||
<h2 class="wmf-subs-title">
|
||||
Einreichungen
|
||||
<span class="wmf-subs-count"><?php echo intval($total); ?></span>
|
||||
</h2>
|
||||
<div class="wmf-subs-actions">
|
||||
<?php if($submissions): ?>
|
||||
<a href="<?php echo esc_url(self::export_url($form_id)); ?>"
|
||||
class="button">⬇ CSV exportieren</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter-Leiste -->
|
||||
<div class="wmf-subs-filter-bar">
|
||||
<form method="get" action="<?php echo esc_url(admin_url('admin.php')); ?>">
|
||||
<input type="hidden" name="page" value="wp-multi-formular">
|
||||
<input type="hidden" name="view_submissions" value="<?php echo intval($form_id); ?>">
|
||||
|
||||
<!-- Status-Tabs -->
|
||||
<div class="wmf-status-tabs">
|
||||
<?php
|
||||
$statuses = array('' => 'Alle', 'neu' => 'Neu', 'gelesen' => 'Gelesen', 'archiviert' => 'Archiviert');
|
||||
foreach($statuses as $s_key => $s_label):
|
||||
$cnt = ($s_key === '') ? wmf_count_submissions($form_id) : wmf_count_submissions($form_id, $s_key);
|
||||
$active = ($status_filter === $s_key) ? 'current' : '';
|
||||
?>
|
||||
<a href="<?php echo esc_url(add_query_arg(array('sub_status'=>$s_key,'paged'=>1), $base_url)); ?>"
|
||||
class="wmf-status-tab <?php echo $active; ?>">
|
||||
<?php echo esc_html($s_label); ?>
|
||||
<span class="count">(<?php echo intval($cnt); ?>)</span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Suche -->
|
||||
<div class="wmf-subs-search">
|
||||
<input type="search" name="sub_search" value="<?php echo esc_attr($search); ?>"
|
||||
placeholder="Einreichungen durchsuchen …" class="wmf-search-input">
|
||||
<button type="submit" class="button">Suchen</button>
|
||||
<?php if($search): ?>
|
||||
<a href="<?php echo esc_url($base_url); ?>" class="button">✕ Zurücksetzen</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if(empty($submissions)): ?>
|
||||
<div class="wmf-empty-submissions">
|
||||
<span class="dashicons dashicons-email-alt" style="font-size:48px;width:48px;height:48px;color:#c3c4c7;margin-bottom:12px;display:block;"></span>
|
||||
<?php if($search||$status_filter): ?>
|
||||
<p>Keine Einreichungen gefunden.</p>
|
||||
<a href="<?php echo esc_url($base_url); ?>" class="button">Filter zurücksetzen</a>
|
||||
<?php else: ?>
|
||||
<p>Noch keine Einreichungen vorhanden.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
|
||||
<!-- Tabelle -->
|
||||
<div class="wmf-table-wrap">
|
||||
<table class="wp-list-table widefat fixed striped wmf-submissions-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="wmf-col-id">#</th>
|
||||
<th class="wmf-col-date">Datum</th>
|
||||
<?php foreach(array_slice($fields, 0, 4) as $f): ?>
|
||||
<th><?php echo esc_html($f['label']); ?></th>
|
||||
<?php endforeach; ?>
|
||||
<th class="wmf-col-status">Status</th>
|
||||
<th class="wmf-col-actions">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($submissions as $row):
|
||||
$data = json_decode($row->data, true) ?? array();
|
||||
$view_url = add_query_arg(array(
|
||||
'page' => 'wp-multi-formular',
|
||||
'view_submission' => $row->id,
|
||||
'form_id' => $form_id,
|
||||
), admin_url('admin.php'));
|
||||
?>
|
||||
<tr class="wmf-sub-row <?php echo $row->status === 'neu' ? 'wmf-sub-new' : ''; ?>">
|
||||
<td class="wmf-col-id">
|
||||
<a href="<?php echo esc_url($view_url); ?>" class="wmf-sub-id-link">
|
||||
#<?php echo intval($row->id); ?>
|
||||
</a>
|
||||
</td>
|
||||
<td class="wmf-col-date">
|
||||
<a href="<?php echo esc_url($view_url); ?>">
|
||||
<?php echo esc_html(date_i18n('d.m.Y', strtotime($row->created_at))); ?>
|
||||
<span class="wmf-time"><?php echo esc_html(date_i18n('H:i', strtotime($row->created_at))); ?></span>
|
||||
</a>
|
||||
</td>
|
||||
<?php foreach(array_slice($fields, 0, 4) as $f):
|
||||
$v = $data[$f['id']] ?? '';
|
||||
if(is_array($v)) $v = implode(', ', $v);
|
||||
if(($f['type']??'') === 'signature') $v = '(Unterschrift)';
|
||||
$v_short = mb_strlen($v) > 60 ? mb_substr($v, 0, 60).'…' : $v;
|
||||
?>
|
||||
<td>
|
||||
<a href="<?php echo esc_url($view_url); ?>" title="<?php echo esc_attr($v); ?>">
|
||||
<?php echo esc_html($v_short); ?>
|
||||
</a>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
<td class="wmf-col-status">
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="wmf-status-form">
|
||||
<?php wp_nonce_field('wmf_update_status'); ?>
|
||||
<input type="hidden" name="action" value="wmf_update_submission_status">
|
||||
<input type="hidden" name="submission_id" value="<?php echo intval($row->id); ?>">
|
||||
<input type="hidden" name="form_id" value="<?php echo intval($form_id); ?>">
|
||||
<input type="hidden" name="redirect_url" value="<?php echo esc_attr(add_query_arg(array('page'=>'wp-multi-formular','view_submissions'=>$form_id,'paged'=>$current_page,'sub_status'=>$status_filter), admin_url('admin.php'))); ?>">
|
||||
<select name="status" class="wmf-status-select wmf-status-<?php echo esc_attr($row->status); ?>" onchange="this.form.submit()">
|
||||
<option value="neu" <?php selected($row->status,'neu'); ?>>Neu</option>
|
||||
<option value="gelesen" <?php selected($row->status,'gelesen'); ?>>Gelesen</option>
|
||||
<option value="archiviert" <?php selected($row->status,'archiviert'); ?>>Archiviert</option>
|
||||
</select>
|
||||
</form>
|
||||
</td>
|
||||
<td class="wmf-col-actions">
|
||||
<a href="<?php echo esc_url($view_url); ?>" class="button button-small">
|
||||
👁 Ansehen
|
||||
</a>
|
||||
<a href="<?php echo esc_url(wp_nonce_url(
|
||||
add_query_arg(array('wmf_action'=>'delete_submission','submission_id'=>$row->id,'form_id'=>$form_id,'page'=>'wp-multi-formular'), admin_url('admin.php')),
|
||||
'wmf_delete_submission'
|
||||
)); ?>"
|
||||
class="button button-small wmf-btn-delete"
|
||||
onclick="return confirm('Einreichung #<?php echo intval($row->id); ?> wirklich löschen?')">
|
||||
🗑 Löschen
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<?php if($total_pages > 1): ?>
|
||||
<div class="wmf-pagination">
|
||||
<?php if($current_page > 1): ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('paged', $current_page-1, $base_url)); ?>" class="button">« Zurück</a>
|
||||
<?php endif; ?>
|
||||
<span class="wmf-page-info">
|
||||
Seite <?php echo $current_page; ?> von <?php echo $total_pages; ?>
|
||||
</span>
|
||||
<?php if($current_page < $total_pages): ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('paged', $current_page+1, $base_url)); ?>" class="button">Weiter »</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
DETAILANSICHT EINER EINZELNEN EINREICHUNG
|
||||
================================================================ */
|
||||
public static function render_single($submission_id, $form_id) {
|
||||
global $wpdb;
|
||||
$row = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}wmf_submissions WHERE id = %d AND form_id = %d",
|
||||
$submission_id, $form_id
|
||||
));
|
||||
|
||||
if(!$row) {
|
||||
echo '<div class="notice notice-error"><p>Einreichung nicht gefunden.</p></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Als gelesen markieren
|
||||
if($row->status === 'neu') {
|
||||
WMF_Submission::update_status($submission_id, 'gelesen');
|
||||
$row->status = 'gelesen';
|
||||
}
|
||||
|
||||
$data = json_decode($row->data, true) ?? array();
|
||||
$meta = wmf_get_form_meta($form_id);
|
||||
$fields = self::get_display_fields($meta);
|
||||
$form = get_post($form_id);
|
||||
|
||||
$back_url = add_query_arg(array(
|
||||
'page' => 'wp-multi-formular',
|
||||
'view_submissions' => $form_id,
|
||||
), admin_url('admin.php'));
|
||||
|
||||
$prev_url = self::get_adjacent_url($submission_id, $form_id, 'prev');
|
||||
$next_url = self::get_adjacent_url($submission_id, $form_id, 'next');
|
||||
?>
|
||||
|
||||
<div class="wmf-submission-detail">
|
||||
|
||||
<!-- Navigation -->
|
||||
<div class="wmf-detail-nav">
|
||||
<a href="<?php echo esc_url($back_url); ?>" class="button">
|
||||
← Alle Einreichungen
|
||||
</a>
|
||||
<div class="wmf-detail-nav-arrows">
|
||||
<?php if($prev_url): ?>
|
||||
<a href="<?php echo esc_url($prev_url); ?>" class="button" title="Vorherige Einreichung">« Vorherige</a>
|
||||
<?php else: ?>
|
||||
<button class="button" disabled>« Vorherige</button>
|
||||
<?php endif; ?>
|
||||
<?php if($next_url): ?>
|
||||
<a href="<?php echo esc_url($next_url); ?>" class="button" title="Nächste Einreichung">Nächste »</a>
|
||||
<?php else: ?>
|
||||
<button class="button" disabled>Nächste »</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Meta-Karte -->
|
||||
<div class="wmf-detail-meta-card">
|
||||
<div class="wmf-detail-meta-item">
|
||||
<span class="wmf-detail-meta-label">Einreichung</span>
|
||||
<span class="wmf-detail-meta-value">#<?php echo intval($row->id); ?></span>
|
||||
</div>
|
||||
<div class="wmf-detail-meta-item">
|
||||
<span class="wmf-detail-meta-label">Formular</span>
|
||||
<span class="wmf-detail-meta-value"><?php echo esc_html($form ? $form->post_title : 'Unbekannt'); ?></span>
|
||||
</div>
|
||||
<div class="wmf-detail-meta-item">
|
||||
<span class="wmf-detail-meta-label">Datum</span>
|
||||
<span class="wmf-detail-meta-value"><?php echo esc_html(date_i18n('d.m.Y H:i', strtotime($row->created_at))); ?></span>
|
||||
</div>
|
||||
<div class="wmf-detail-meta-item">
|
||||
<span class="wmf-detail-meta-label">IP-Adresse</span>
|
||||
<span class="wmf-detail-meta-value"><?php echo esc_html($row->ip ?: '—'); ?></span>
|
||||
</div>
|
||||
<div class="wmf-detail-meta-item">
|
||||
<span class="wmf-detail-meta-label">Status</span>
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;">
|
||||
<?php wp_nonce_field('wmf_update_status'); ?>
|
||||
<input type="hidden" name="action" value="wmf_update_submission_status">
|
||||
<input type="hidden" name="submission_id" value="<?php echo intval($row->id); ?>">
|
||||
<input type="hidden" name="form_id" value="<?php echo intval($form_id); ?>">
|
||||
<input type="hidden" name="redirect_url" value="<?php echo esc_attr(add_query_arg(array('page'=>'wp-multi-formular','view_submission'=>$row->id,'form_id'=>$form_id), admin_url('admin.php'))); ?>">
|
||||
<select name="status" class="wmf-status-select wmf-status-<?php echo esc_attr($row->status); ?>" onchange="this.form.submit()">
|
||||
<option value="neu" <?php selected($row->status,'neu'); ?>>Neu</option>
|
||||
<option value="gelesen" <?php selected($row->status,'gelesen'); ?>>Gelesen</option>
|
||||
<option value="archiviert" <?php selected($row->status,'archiviert'); ?>>Archiviert</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div class="wmf-detail-meta-item wmf-detail-meta-actions">
|
||||
<a href="<?php echo esc_url(wp_nonce_url(
|
||||
add_query_arg(array('wmf_action'=>'delete_submission','submission_id'=>$row->id,'form_id'=>$form_id,'page'=>'wp-multi-formular'), admin_url('admin.php')),
|
||||
'wmf_delete_submission'
|
||||
)); ?>"
|
||||
class="button wmf-btn-delete"
|
||||
onclick="return confirm('Einreichung #<?php echo intval($row->id); ?> wirklich löschen?')">
|
||||
🗑 Löschen
|
||||
</a>
|
||||
<button onclick="window.print()" class="button">🖶 Drucken</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Felder-Inhalt -->
|
||||
<div class="wmf-detail-fields">
|
||||
<h3 class="wmf-detail-section-title">Eingereichte Daten</h3>
|
||||
<div class="wmf-detail-fields-grid">
|
||||
<?php foreach($fields as $field):
|
||||
$val = $data[$field['id']] ?? '';
|
||||
$type = $field['type'] ?? 'text';
|
||||
?>
|
||||
<div class="wmf-detail-field <?php echo 'wmf-detail-field-' . esc_attr($type); ?>">
|
||||
<div class="wmf-detail-field-label">
|
||||
<?php echo esc_html($field['label']); ?>
|
||||
<span class="wmf-detail-field-type"><?php echo esc_html($type); ?></span>
|
||||
</div>
|
||||
<div class="wmf-detail-field-value">
|
||||
<?php self::render_field_value($val, $field); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Technische Infos (aufklappbar) -->
|
||||
<details class="wmf-detail-technical">
|
||||
<summary>Technische Informationen</summary>
|
||||
<table class="widefat" style="margin-top:12px;">
|
||||
<tr><th>User-Agent</th><td><?php echo esc_html($row->user_agent ?: '—'); ?></td></tr>
|
||||
<tr><th>Erstellt am</th><td><?php echo esc_html($row->created_at); ?></td></tr>
|
||||
<tr><th>Datenbank-ID</th><td><?php echo intval($row->id); ?></td></tr>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@media print {
|
||||
#adminmenumain,#wpadminbar,.wmf-detail-nav,.wmf-detail-meta-actions,
|
||||
#screen-meta,#wpfooter,.notice { display:none!important; }
|
||||
.wmf-submission-detail { margin:0; padding:0; }
|
||||
.wmf-detail-fields { border:none; }
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
FELDINHALTE RENDERN (je nach Typ)
|
||||
================================================================ */
|
||||
private static function render_field_value($val, $field) {
|
||||
$type = $field['type'] ?? 'text';
|
||||
|
||||
if($val === '' || $val === null || $val === array()) {
|
||||
echo '<span class="wmf-empty-value">—</span>';
|
||||
return;
|
||||
}
|
||||
|
||||
switch($type) {
|
||||
case 'checkbox':
|
||||
$vals = is_array($val) ? $val : explode(', ', $val);
|
||||
echo '<ul class="wmf-val-list">';
|
||||
foreach($vals as $v) echo '<li>' . esc_html($v) . '</li>';
|
||||
echo '</ul>';
|
||||
break;
|
||||
|
||||
case 'gdpr':
|
||||
$icon = $val === '1' ? '✅' : '❌';
|
||||
echo $icon . ' ' . ($val === '1' ? 'Zugestimmt' : 'Nicht zugestimmt');
|
||||
break;
|
||||
|
||||
case 'signature':
|
||||
if(strpos($val, 'data:image') === 0) {
|
||||
echo '<img src="' . esc_attr($val) . '" style="max-width:300px;border:1px solid #dcdcde;border-radius:4px;background:#fff;">';
|
||||
} else {
|
||||
echo '<span class="wmf-empty-value">Keine Unterschrift</span>';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
$urls = is_array($val) ? $val : explode(', ', $val);
|
||||
echo '<div class="wmf-val-files">';
|
||||
foreach($urls as $url) {
|
||||
$url = trim($url);
|
||||
if(!$url) continue;
|
||||
$filename = basename(parse_url($url, PHP_URL_PATH));
|
||||
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
$is_image = in_array($ext, array('jpg','jpeg','png','gif','webp'));
|
||||
if($is_image) {
|
||||
echo '<div class="wmf-val-file-img"><a href="' . esc_url($url) . '" target="_blank">';
|
||||
echo '<img src="' . esc_url($url) . '" style="max-width:200px;max-height:150px;border-radius:4px;"></a></div>';
|
||||
} else {
|
||||
echo '<a href="' . esc_url($url) . '" target="_blank" class="wmf-val-file-link">📎 ' . esc_html($filename) . '</a>';
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
break;
|
||||
|
||||
case 'rating':
|
||||
$stars = intval($val);
|
||||
$max = intval($field['max_stars'] ?? 5);
|
||||
echo '<div class="wmf-val-stars">';
|
||||
for($i = 1; $i <= $max; $i++) {
|
||||
echo '<span style="color:' . ($i <= $stars ? '#f0b429' : '#ddd') . ';font-size:20px;">★</span>';
|
||||
}
|
||||
echo ' <span style="color:#646970;font-size:13px;">' . $stars . '/' . $max . '</span></div>';
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
echo '<a href="' . esc_url($val) . '" target="_blank">' . esc_html($val) . '</a>';
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
echo '<a href="mailto:' . esc_attr($val) . '">' . esc_html($val) . '</a>';
|
||||
break;
|
||||
|
||||
case 'textarea':
|
||||
echo '<div class="wmf-val-textarea">' . nl2br(esc_html($val)) . '</div>';
|
||||
break;
|
||||
|
||||
default:
|
||||
if(is_array($val)) {
|
||||
echo '<ul class="wmf-val-list">';
|
||||
foreach($val as $v) echo '<li>' . esc_html($v) . '</li>';
|
||||
echo '</ul>';
|
||||
} else {
|
||||
echo '<span class="wmf-val-text">' . esc_html($val) . '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
HILFSFUNKTIONEN
|
||||
================================================================ */
|
||||
private static function get_display_fields($meta) {
|
||||
return array_values(array_filter($meta['fields'] ?? array(), function($f) {
|
||||
return !in_array($f['type'] ?? '', array('html','divider','hidden'));
|
||||
}));
|
||||
}
|
||||
|
||||
private static function get_adjacent_url($submission_id, $form_id, $direction) {
|
||||
global $wpdb;
|
||||
$op = $direction === 'prev' ? '>' : '<';
|
||||
$order = $direction === 'prev' ? 'ASC' : 'DESC';
|
||||
$adj = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT id FROM {$wpdb->prefix}wmf_submissions WHERE form_id = %d AND id {$op} %d ORDER BY id {$order} LIMIT 1",
|
||||
$form_id, $submission_id
|
||||
));
|
||||
if(!$adj) return null;
|
||||
return add_query_arg(array('page'=>'wp-multi-formular','view_submission'=>$adj,'form_id'=>$form_id), admin_url('admin.php'));
|
||||
}
|
||||
|
||||
public static function status_label($s) {
|
||||
return array('neu'=>'Neu','gelesen'=>'Gelesen','archiviert'=>'Archiviert')[$s] ?? $s;
|
||||
}
|
||||
|
||||
public static function export_url($form_id) {
|
||||
return wp_nonce_url(add_query_arg(array('wmf_action'=>'export_csv','form_id'=>$form_id,'page'=>'wp-multi-formular'), admin_url('admin.php')), 'wmf_export_csv');
|
||||
}
|
||||
|
||||
public static function maybe_export($form_id) {
|
||||
if(empty($_GET['wmf_action']) || $_GET['wmf_action'] !== 'export_csv') return;
|
||||
if(!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'wmf_export_csv')) return;
|
||||
$meta = wmf_get_form_meta($form_id);
|
||||
$fields = self::get_display_fields($meta);
|
||||
$rows = wmf_get_submissions($form_id, array('limit'=>9999));
|
||||
header('Content-Type: text/csv; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="formular-' . $form_id . '-einreichungen.csv"');
|
||||
$out = fopen('php://output', 'w');
|
||||
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
$header = array('ID','Datum','Status','IP');
|
||||
foreach($fields as $f) $header[] = $f['label'];
|
||||
fputcsv($out, $header, ';');
|
||||
foreach($rows as $row) {
|
||||
$data = json_decode($row->data, true) ?? array();
|
||||
$line = array($row->id, date_i18n('d.m.Y H:i', strtotime($row->created_at)), self::status_label($row->status), $row->ip);
|
||||
foreach($fields as $f) {
|
||||
$v = $data[$f['id']] ?? '';
|
||||
if(is_array($v)) $v = implode(', ', $v);
|
||||
if(($f['type']??'') === 'signature') $v = '(Unterschrift)';
|
||||
$line[] = $v;
|
||||
}
|
||||
fputcsv($out, $line, ';');
|
||||
}
|
||||
fclose($out);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user